battery stuff and fixed the weird workspace nonsense

This commit is contained in:
2026-06-11 16:09:16 +01:00
parent eafc417a17
commit 1356456ab0
7 changed files with 507 additions and 291 deletions

View File

@@ -1,2 +1,26 @@
require("nvim-treesitter").install({ "qmljs" }) require("nvim-treesitter").install({ "qmljs" })
vim.lsp.enable("qmlls") vim.lsp.enable("qmlls")
-- Disable semantic tokens when any LSP client attaches to a buffer
vim.api.nvim_create_autocmd("LspAttach", {
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
if client then
client.server_capabilities.semanticTokensProvider = nil
end
end,
})
vim.api.nvim_create_autocmd("FileType", {
pattern = { "qml" },
callback = function()
vim.treesitter.start()
end,
})
require("conform").setup({
formatters_by_ft = {
qml = { "qmlformat" },
},
format_on_save = true,
})

12
.qmlformat.ini Normal file
View File

@@ -0,0 +1,12 @@
[General]
FunctionsSpacing=true
GroupAttributesTogether=false
IndentWidth=2
MaxColumnWidth=100
NewlineType=unix
NormalizeOrder=true
ObjectsSpacing=true
SemicolonRule=always
SingleLineEmptyObjects=true
SortImports=true
UseTabs=true

45
Bar.qml
View File

@@ -1,11 +1,10 @@
import Quickshell
import Quickshell.Hyprland
import QtQuick import QtQuick
import QtQuick.Effects import QtQuick.Effects
import Quickshell
import Quickshell.Hyprland
import "Components/Color.js" as Colors
import "Components" import "Components"
import "Components/Color.js" as Colors
Scope { Scope {
Variants { Variants {
@@ -14,60 +13,70 @@ Scope {
delegate: Component { delegate: Component {
PanelWindow { PanelWindow {
id: win id: win
required property var modelData required property var modelData
screen: modelData
Behavior on implicitHeight {
NumberAnimation { duration: 0; easing.type: Easing.InOutQuad }
}
property HyprlandMonitor monitor: Hyprland.monitorFor(modelData) property HyprlandMonitor monitor: Hyprland.monitorFor(modelData)
color: "transparent" color: "transparent"
exclusionMode: ExclusionMode.Normal exclusionMode: ExclusionMode.Normal
exclusiveZone: 20
implicitHeight: 1000
screen: modelData
Behavior on implicitHeight {
NumberAnimation {
duration: 0
easing.type: Easing.InOutQuad
}
}
mask: Region { mask: Region {
Region { Region {
item: workspaceSwitcher item: workspaceSwitcher
} }
Region { Region {
item: pillItem item: pillItem
} }
Region {
item: utilsItem
}
} }
anchors { anchors {
top: true
left: true left: true
right: true right: true
top: true
} }
implicitHeight: 1000
exclusiveZone: 20
Workspace { Workspace {
id: workspaceSwitcher id: workspaceSwitcher
monitor: win.monitor monitor: win.monitor
} }
RectangularShadow { RectangularShadow {
anchors.fill: pillItem anchors.fill: pillItem
blur: 20
color: Colors.crust
offset.x: 3 offset.x: 3
offset.y: 3 offset.y: 3
radius: pillItem.radius radius: pillItem.radius
blur: 20
spread: 7 spread: 7
color: Colors.crust
} }
Pill { Pill {
id: pillItem id: pillItem
monitor: win.monitor monitor: win.monitor
} }
Item { Item {
anchors.fill: parent anchors.fill: parent
Utils { Utils {
id: utilsItem
monitor: win.monitor monitor: win.monitor
} }
} }

View File

@@ -1,41 +1,45 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Hyprland import Quickshell.Hyprland
import QtQuick
import QtQuick.Layouts
import "./Utils" import "./Utils"
RowLayout { RowLayout {
id: utilsContainer id: utilsContainer
required property HyprlandMonitor monitor required property HyprlandMonitor monitor
property bool shown: monitor !== null && monitor.focused
opacity: shown ? 1 : 0
state: "" state: ""
anchors { Behavior on anchors.topMargin {
right: parent.right SmoothedAnimation {
top: parent.top duration: 300
}
}
Behavior on opacity {
NumberAnimation {
duration: 50
}
} }
states: [ states: [
State { State {
name: "" name: ""
} }
] ]
Rectangle { anchors {
color: "red" right: parent.right
implicitWidth: 40 rightMargin: 7
implicitHeight: 40 top: parent.top
} topMargin: shown ? -33 : -40
Rectangle {
color: "blue"
implicitWidth: 40
implicitHeight: 40
} }
// Battery {} Battery {}
// Mpris {} // Mpris {}
} }

View File

@@ -1,8 +1,46 @@
import Quickshell
import QtQuick import QtQuick
import Quickshell
import Quickshell.Services.UPower
import "../Color.js" as Colors
import "./"
Container {
id: batteryRoot
boxColor: Colors.green
boxState: ""
sourceComponent: batteryClosed
visible: UPower.devices[0] ? true : false
MouseArea {
anchors.fill: parent
enabled: true
hoverEnabled: true
propagateComposedEvents: true
onClicked: batteryRoot.boxState == "" ? batteryRoot.boxState = "open" : batteryRoot.boxState = ""
onExited: batteryRoot.boxState = ""
}
Component {
id: batteryClosed
Item { Item {
id: batteryRoot
anchors.fill: parent
Text { Text {
text: "some" color: Colors.base
text: "something"
anchors {
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
}
}
}
} }
} }

View File

@@ -0,0 +1,64 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
Item {
id: container
required property color boxColor
property double boxHeight
property double boxRadius
required property string boxState
property double boxWidth
property double openHeight
property double openWidth
required property Component sourceComponent
Layout.topMargin: 0
implicitHeight: boxHeight || 50
implicitWidth: boxWidth || 30
state: boxState
Behavior on anchors.topMargin {
SmoothAnim {}
}
Behavior on implicitHeight {
SmoothAnim {}
}
Behavior on implicitWidth {
SmoothAnim {}
}
states: [
State {
name: ""
},
State {
name: "open"
PropertyChanges {
container.Layout.topMargin: 35
container.implicitHeight: openHeight || 150
container.implicitWidth: openWidth || 200
}
}
]
Rectangle {
id: mainBackground
anchors.fill: parent
color: container.boxColor
radius: container.boxRadius || 10
Loader {
anchors.fill: parent
sourceComponent: container.sourceComponent
}
}
component SmoothAnim: SpringAnimation {
damping: 0.18
mass: 0.5
spring: 3
}
}

View File

@@ -1,17 +1,18 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Hyprland import Quickshell.Hyprland
import QtQuick
import QtQuick.Layouts
import QtQuick.Effects
import "Color.js" as Colors import "Color.js" as Colors
Item { Item {
id: workspaceRowContainer id: workspaceRowContainer
required property HyprlandMonitor monitor required property HyprlandMonitor monitor
state: "" property int textBottomMargin: 0
function getNextEmptyWorkspaceId() { function getNextEmptyWorkspaceId() {
let maxId = 0; let maxId = 0;
@@ -26,14 +27,53 @@ Item {
} }
// Returns the next global workspace ID (e.g., if max is 3, returns 4) // Returns the next global workspace ID (e.g., if max is 3, returns 4)
console.log(maxId + 1) console.log(maxId + 1);
return maxId === 0 ? 1 : maxId + 1; return maxId === 0 ? 1 : maxId + 1;
} }
implicitHeight: 65
implicitWidth: 200
state: ""
Behavior on anchors.topMargin {
NumberAnimation {
duration: 100
}
}
states: [
State {
name: ""
// When not hovered, stay at default
when: !workspaceHoverHandler.hovered
PropertyChanges {
workspaceRowContainer.anchors.topMargin: -33
}
},
State {
name: "hovered"
// Keep the workspace dropped whenever hovered is true
when: workspaceHoverHandler.hovered
PropertyChanges {
workspaceRowContainer.anchors.topMargin: -20
}
PropertyChanges {
workspaceRowContainer.textBottomMargin: 7
}
}
]
Behavior on textBottomMargin {
NumberAnimation {
duration: 80
}
}
anchors { anchors {
top: parent.top
left: parent.left left: parent.left
leftMargin: 15 leftMargin: 15
top: parent.top
topMargin: -33 topMargin: -33
} }
@@ -41,62 +81,100 @@ Item {
id: workspaceHoverHandler id: workspaceHoverHandler
} }
Behavior on anchors.topMargin {
NumberAnimation { duration: 100 }
}
property int textBottomMargin: 0
Behavior on textBottomMargin {
NumberAnimation {duration: 80}
}
states: [
State {
name: ""
// When not hovered, stay at default
when: !workspaceHoverHandler.hovered
PropertyChanges { workspaceRowContainer.anchors.topMargin: -33 }
},
State {
name: "hovered"
// Keep the workspace dropped whenever hovered is true
when: workspaceHoverHandler.hovered
PropertyChanges { workspaceRowContainer.anchors.topMargin: -20 }
PropertyChanges { workspaceRowContainer.textBottomMargin: 7 }
}
]
implicitWidth: 200
implicitHeight: 65
Row { Row {
id: workspaceRow id: workspaceRow
spacing: 5
spacing: 5
Repeater { Repeater {
model: Hyprland.workspaces.values model: Hyprland.workspaces.values
Item { Item {
id: selectorContainer id: selectorContainer
required property int index
property HyprlandWorkspace activeWorkspace: workspaceRowContainer.monitor.activeWorkspace
property HyprlandWorkspace currentWorkspace: Hyprland.workspaces.values[index] property HyprlandWorkspace currentWorkspace: Hyprland.workspaces.values[index]
property HyprlandWorkspace globalFocusedWorkspace: Hyprland.focusedWorkspace property HyprlandWorkspace globalFocusedWorkspace: Hyprland.focusedWorkspace
implicitHeight: 50 required property int index
implicitWidth: currentWorkspace.focused && workspaceRowContainer.state == "hovered" ? 50 : workspaceRowContainer.state == "hovered" ? 30 : 25
function getImplicitWidth() {
let implicitWidth = 25;
if (workspaceRowContainer.state == "hovered") {
implicitWidth += 5;
if (currentWorkspace.focused) {
implicitWidth += 20;
}
}
return implicitWidth;
}
function shouldBeVisible() {
let isSpecialWorkspace = !selectorContainer.currentWorkspace.name.includes("special:");
let isCurrentMonitor = Hyprland.workspaces.values[index].monitor
== workspaceRowContainer.monitor;
return isSpecialWorkspace && isCurrentMonitor;
}
implicitHeight: 50
implicitWidth: getImplicitWidth()
visible: shouldBeVisible()
Behavior on anchors.topMargin {
NumberAnimation {
duration: 100
}
}
Behavior on implicitWidth {
NumberAnimation {
duration: 100
}
}
states: [
State {
name: ""
when: !selectorHoverHandler.hovered
PropertyChanges {
selectorContainer.anchors.topMargin: 0
}
},
State {
name: "individualHovered"
when: selectorHoverHandler.hovered
PropertyChanges {
selectorContainer.anchors.topMargin: 10
}
},
State {
name: "workspaceSwitched"
PropertyChanges {
selectorContainer.anchors.topMargin: 5
}
}
]
// onActiveWorkspaceChanged: {
// if (workspaceRowContainer.monitor.activeWorkspace.id == "1") {}
// if (workspaceRowContainer.monitor.activeWorkspace.id == "4") {}
// }
onGlobalFocusedWorkspaceChanged: { onGlobalFocusedWorkspaceChanged: {
if (globalFocusedWorkspace.id === currentWorkspace.id) { if (globalFocusedWorkspace.name === currentWorkspace.name && globalFocusedWorkspace.monitor
selectorContainer.state = "workspaceSwitched" === workspaceRowContainer.monitor && workspaceRowContainer.monitor.activeWorkspace.name
switchFeedbackTimer.restart() === currentWorkspace.name) {
selectorContainer.state = "workspaceSwitched";
switchFeedbackTimer.restart();
} }
} }
Timer { Timer {
id: switchFeedbackTimer id: switchFeedbackTimer
interval: 200 interval: 200
repeat: false repeat: false
onTriggered: selectorContainer.state = "" onTriggered: selectorContainer.state = ""
} }
@@ -111,6 +189,7 @@ Item {
MouseArea { MouseArea {
id: selectorMouseArea id: selectorMouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
propagateComposedEvents: true propagateComposedEvents: true
@@ -118,102 +197,88 @@ Item {
onClicked: selectorContainer.currentWorkspace.activate() onClicked: selectorContainer.currentWorkspace.activate()
} }
Behavior on anchors.topMargin {
NumberAnimation {duration: 100}
}
Behavior on implicitWidth {
NumberAnimation {duration: 100}
}
states: [
State {
name: ""
when: !selectorHoverHandler.hovered
PropertyChanges { selectorContainer.anchors.topMargin: 0 }
},
State {
name: "individualHovered"
when: selectorHoverHandler.hovered
PropertyChanges { selectorContainer.anchors.topMargin: 10 }
},
State {
name: "workspaceSwitched"
PropertyChanges { selectorContainer.anchors.topMargin: 5 }
}
]
visible: Hyprland.workspaces.values[index].monitor == monitor && index > 0 && selectorContainer.currentWorkspace.name != "special:scratch" && selectorContainer.currentWorkspace.name != "special:music"
RectangularShadow { RectangularShadow {
anchors.fill: selector anchors.fill: selector
blur: 20
color: Colors.crust
offset.x: 3 offset.x: 3
offset.y: 3 offset.y: 3
radius: selector.radius radius: selector.radius
blur: 20
z: -1
spread: 7 spread: 7
color: Colors.crust z: -1
} }
Rectangle {
z: 1
id: selector
state: ""
color: selectorContainer.currentWorkspace.focused ? Colors.mauve : workspaceRowContainer.monitor.activeWorkspace.id == selectorContainer.currentWorkspace.id ? Colors.lavender : Colors.overlay1 Rectangle {
radius: 8 id: selector
anchors.fill: parent anchors.fill: parent
color: selectorContainer.currentWorkspace.focused ? Colors.mauve :
workspaceRowContainer.monitor.activeWorkspace
== selectorContainer.currentWorkspace ? Colors.lavender : Colors.overlay1
radius: 8
state: ""
z: 1
Behavior on color { Behavior on color {
ColorAnimation {duration: 100} ColorAnimation {
duration: 100
}
} }
Text { Text {
id: workspaceIdentifier id: workspaceIdentifier
text: selectorContainer.currentWorkspace.name
font.family: "FiraMono Nerd Font" font.family: "FiraMono Nerd Font"
font.pixelSize: workspaceRowContainer.state == "hovered" ? 15 : 13 font.pixelSize: workspaceRowContainer.state == "hovered" ? 15 : 13
text: selectorContainer.currentWorkspace.name
anchors { anchors {
bottom: parent.bottom bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
bottomMargin: workspaceRowContainer.textBottomMargin bottomMargin: workspaceRowContainer.textBottomMargin
horizontalCenter: parent.horizontalCenter
}
}
}
} }
} }
}
}
}
Item { Item {
implicitHeight: 40 implicitHeight: 40
implicitWidth: 20 implicitWidth: 20
Behavior on anchors.topMargin {
NumberAnimation {
duration: 100
}
}
anchors { anchors {
top: parent.top top: parent.top
topMargin: workspaceRowContainer.state == "hovered" ? 0 : -10 topMargin: workspaceRowContainer.state == "hovered" ? 0 : -10
} }
Behavior on anchors.topMargin {
NumberAnimation {duration: 100}
}
MouseArea { MouseArea {
id: newWorkspaceButton id: newWorkspaceButton
anchors.fill: parent anchors.fill: parent
onClicked: Hyprland.dispatch(`hl.dsp.focus({workspace = ${workspaceRowContainer.getNextEmptyWorkspaceId()}})`) onClicked: Hyprland.dispatch(`hl.dsp.focus({workspace =
${workspaceRowContainer.getNextEmptyWorkspaceId()}})`)
} }
Rectangle { Rectangle {
color: Colors.surface2
anchors.fill: parent anchors.fill: parent
radius: 10
border.color: Colors.text border.color: Colors.text
border.width: 2 border.width: 2
color: Colors.surface2
radius: 10
Text { Text {
text: "+"
color: Colors.text color: Colors.text
font.family: "FiraMono Nerd Font" font.family: "FiraMono Nerd Font"
font.pixelSize: 20 font.pixelSize: 20
text: "+"
anchors { anchors {
bottom: parent.bottom bottom: parent.bottom
horizontalCenter: parent.horizontalCenter horizontalCenter: parent.horizontalCenter