initial commit

This commit is contained in:
Bloxx12 2025-05-03 13:04:07 +02:00
commit 35524b5e6e
7 changed files with 412 additions and 0 deletions

37
Bar.qml Normal file
View file

@ -0,0 +1,37 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
PanelWindow {
id: root
color: "transparent"
anchors {
top: true
bottom: true
right: true
}
width: 60
ColumnLayout {
// anchors.fill: parent
anchors.margins: 2
spacing: 2
anchors {
left: parent.left
right: parent.right
top: parent.top
margins: 2
}
ClockWidget {}
WorkspaceWidget {
bar: root
}
// SysTray {
// bar: root
// }
}
}

39
ClockWidget.qml Normal file
View file

@ -0,0 +1,39 @@
import QtQuick
import QtQuick.Layouts
Rectangle {
width: parent.width
height: width
border.color: "black"
border.width: 1
radius: 5
// color: "green"
Item {
width: parent.width
height: text.height * 2
anchors.centerIn: parent
Text {
id: text
anchors.centerIn: parent
property var date: Date()
text: Qt.formatDateTime(date, "hh\nmm")
font.family: "Iosevka NF"
font.weight: Font.ExtraBold
font.pointSize: 18
color: "black"
}
}
Timer {
interval: 1000 * 60
running: true
repeat: true
onTriggered: text.date = new Date()
}
}

34
Launcher.qml Normal file
View file

@ -0,0 +1,34 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Widgets
import Quickshell.Services.SystemTray
Singleton {
PersistentProperties {
id: persist
property bool launcherOpen: false
}
IpcHandler {
target: "launcher"
function open(): void {
persist.launcherOpen = true;
}
function close(): void {
persist.launcherOpen = false;
}
function toggle(): void {
persist.launcherOpen = !persist.launcherOpen;
}
}
}

127
ReloadPopup.qml Normal file
View file

@ -0,0 +1,127 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
Scope {
id: root
property bool failed
property string errorString
// Connect to the Quickshell global to listen for the reload signals.
Connections {
target: Quickshell
function onReloadCompleted() {
root.failed = false;
popupLoader.loading = true;
}
function onReloadFailed(error: string) {
// Close any existing popup before making a new one.
popupLoader.active = false;
root.failed = true;
root.errorString = error;
popupLoader.loading = true;
}
}
// Keep the popup in a loader because it isn't needed most of the timeand will take up
// memory that could be used for something else.
LazyLoader {
id: popupLoader
PanelWindow {
id: popup
anchors {
top: true
right: true
}
margins {
top: 25
left: 25
}
width: rect.width
height: rect.height
// color blending is a bit odd as detailed in the type reference.
color: "transparent"
Rectangle {
id: rect
color: root.failed ? "#40802020" : "#40009020"
implicitHeight: layout.implicitHeight + 50
implicitWidth: layout.implicitWidth + 30
// Fills the whole area of the rectangle, making any clicks go to it,
// which dismiss the popup.
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: popupLoader.active = false
// makes the mouse area track mouse hovering, so the hide animation
// can be paused when hovering.
hoverEnabled: true
}
ColumnLayout {
id: layout
anchors {
top: parent.top
topMargin: 20
horizontalCenter: parent.horizontalCenter
}
Text {
text: root.failed ? "Reload failed." : "Reloaded completed!"
color: "white"
}
Text {
text: root.errorString
color: "white"
// When visible is false, it also takes up no space.
visible: root.errorString != ""
}
}
// A progress bar on the bottom of the screen, showing how long until the
// popup is removed.
Rectangle {
id: bar
color: "#20ffffff"
anchors.bottom: parent.bottom
anchors.left: parent.left
height: 20
PropertyAnimation {
id: anim
target: bar
property: "width"
from: rect.width
to: 0
duration: failed ? 10000 : 800
onFinished: popupLoader.active = false
// Pause the animation when the mouse is hovering over the popup,
// so it stays onscreen while reading. This updates reactively
// when the mouse moves on and off the popup.
paused: mouseArea.containsMouse
}
}
// We could set `running: true` inside the animation, but the width of the
// rectangle might not be calculated yet, due to the layout.
// In the `Component.onCompleted` event handler, all of the component's
// properties and children have been initialized.
Component.onCompleted: anim.start()
}
}
}
}

35
SysTray.qml Normal file
View file

@ -0,0 +1,35 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import QtQuick.Effects
import Quickshell
import Quickshell.Services.SystemTray
Rectangle {
id: root
required property var bar
Column {
id: column
spacing: 5
anchors {
fill: parent
margins: 5
}
Repeater {
model: SystemTray.items
Item {
id: item
required property SystemTrayItem modelData
implicitHeight: width
}
}
}
}

118
WorkspaceWidget.qml Normal file
View file

@ -0,0 +1,118 @@
// A workspace indicator.
// This is in big parts taken from outfoxxed, the creator of quickshell.
// Please make sure to check out his setup.
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Hyprland
Rectangle {
id: root
required property var bar
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(bar.screen)
// Amount of workspaces
property int wsCount: 10
// Base index for the workspaces
property int wsBaseIndex: 1
// index of the current workspace
property int currentIndex: 0
// count how many workspaces currently exist
property int existsCount: 0
implicitHeight: column.implicitHeight + 10
width: parent.width
height: width
border.color: "black"
// color: "blue"
border.width: 1
radius: 5
// destructor takes care of nulling
signal workspaceAdded(workspace: HyprlandWorkspace)
Column {
id: column
spacing: 0
anchors {
fill: parent
margins: 5
}
Repeater {
model: root.wsCount
Item {
id: wsItem
implicitHeight: 15
anchors {
right: parent.right
left: parent.left
}
// index of the current workspace
required property int index
property int wsIndex: root.wsBaseIndex + index
property HyprlandWorkspace workspace: null
// check if workspace exists
property bool exists: workspace != null
property bool active: (root.monitor?.activeWorkspace ?? false) && root.monitor.activeWorkspace == workspace
Connections {
target: root
function onWorkspaceAdded(workspace: HyprlandWorkspace) {
if (workspace.id == wsItem.wsIndex) {
wsItem.workspace = workspace;
}
}
}
property real animActive: active ? 1 : 0.65
Behavior on animActive {
NumberAnimation {
duration: 150
}
}
property real animExists: exists ? 1 : 0
Behavior on animExists {
NumberAnimation {
duration: 100
}
}
Rectangle {
anchors.centerIn: parent
height: 10
// width: (wsItem.active ? parent.width : parent.width - 20)
width: parent.width * wsItem.animActive
radius: height / 2
border.color: "black"
border.width: 1
color: "black"
}
}
}
}
Connections {
target: Hyprland.workspaces
function onObjectInsertedPost(workspace) {
root.workspaceAdded(workspace);
}
}
Component.onCompleted: {
Hyprland.workspaces.values.forEach(workspace => {
root.workspaceAdded(workspace);
});
}
}

22
shell.qml Normal file
View file

@ -0,0 +1,22 @@
import Quickshell
import Quickshell.Io
import QtQuick
import QtQuick.Layouts
ShellRoot {
id: shellroot
Variants {
model: Quickshell.screens
Scope {
property var modelData
Bar {
screen: modelData
}
ReloadPopup {}
}
}
}