commit 7a9756e0e1bd256c2b7622fa2a2d6cc6a2d438df Author: Teo Date: Wed Nov 26 16:16:42 2025 +0100 Initial commit diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml new file mode 100644 index 0000000..8f51166 --- /dev/null +++ b/modules/bar/Bar.qml @@ -0,0 +1,69 @@ +import QtQuick +import Quickshell +import Quickshell.Hyprland +import "./widgets" + +PanelWindow { + id: panel + + anchors.top: true + anchors.left: true + anchors.right: true + + implicitHeight: 40 + + exclusiveZone: height // this is so context menus don't clip into the bar + + property HyprlandMonitor barThisMonitor: Hyprland.monitorFor(screen) + + margins { + top: 0 + left: 0 + right: 0 + } + + Rectangle { // Bar + id: bar + anchors.fill: parent + color: "#1a1a1a" + radius: 0 + + Row { // bar widgets left + id: widgetsLeft + + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 16 + spacing: 8 + + MenuButton {} + + Workspaces { + thisMonitor: barThisMonitor + anchors.verticalCenter: parent.verticalCenter + } + + + } + + Row { // bar widgets center + id: widgetsCenter + + anchors.centerIn: parent + + Clock {} + + } + + Row { // bar widgets right + id: widgetsRight + + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 16 + spacing: 8 + + } + + } +} \ No newline at end of file diff --git a/modules/bar/BarLoader.qml b/modules/bar/BarLoader.qml new file mode 100644 index 0000000..3ad7db7 --- /dev/null +++ b/modules/bar/BarLoader.qml @@ -0,0 +1,14 @@ +import QtQuick +import Quickshell + + +Item { + id: root + Repeater { // Bars + model: Quickshell.screens + delegate: Loader { + active: true // loads object + sourceComponent: Bar {screen: modelData} // creates instance of bar component + } + } +} \ No newline at end of file diff --git a/modules/bar/widgets/Clock.qml b/modules/bar/widgets/Clock.qml new file mode 100644 index 0000000..c12eae0 --- /dev/null +++ b/modules/bar/widgets/Clock.qml @@ -0,0 +1,25 @@ +import QtQuick +import Quickshell +import Quickshell.Hyprland + +Text { + id: timeDisplay + + property string currentTime: "" + + text: currentTime + color: "#ffffff" + font.pixelSize: 14 + font.family: "Inter, sans-serif" + + //Update time every second + Timer { + interval: 1000 + running: true + repeat: true + onTriggered: { + var now = new Date() + timeDisplay.currentTime = Qt.formatTime(now, "hh:mm:ss") + } + } +} \ No newline at end of file diff --git a/modules/bar/widgets/MenuButton.qml b/modules/bar/widgets/MenuButton.qml new file mode 100644 index 0000000..457bc5e --- /dev/null +++ b/modules/bar/widgets/MenuButton.qml @@ -0,0 +1,25 @@ +import QtQuick +import Quickshell +import Quickshell.Hyprland + +MouseArea { + id: archButton + width: 30 + height: 28 + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + + Rectangle { + anchors.fill: parent + color: archButton.containsMouse ? "#2a2a2a" : "transparent" + radius: 6 + + Text { + anchors.centerIn: parent + text: "󰣇" + font.pixelSize: 26 + font.family: "Nerd Font" + color: "#ffffff" + } + } +} \ No newline at end of file diff --git a/modules/bar/widgets/Workspaces.qml b/modules/bar/widgets/Workspaces.qml new file mode 100644 index 0000000..bb5794d --- /dev/null +++ b/modules/bar/widgets/Workspaces.qml @@ -0,0 +1,47 @@ +import QtQuick +import Quickshell +import Quickshell.Hyprland + + +Row { // Workspace Row + id: workspacesRow + + required property HyprlandMonitor thisMonitor + spacing: 8 + + Repeater { // repeats workspaces + model: Hyprland.workspaces + + Rectangle { //workspace + visible: modelData.monitor === thisMonitor + width: 32 + height: 24 + radius: 4 + color: modelData.active ? "#4a93ff": "#333333" + border.color: "#555555" + border.width: 2 + + MouseArea { + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + anchors.fill: parent + onClicked: Hyprland.dispatch("workspace " + modelData.id) + } + + Text { + text: modelData.id + anchors.centerIn: parent + color: modelData.active ? "#ffffff" : "#cccccc" + font.pixelSize: 12 + font.family: "Inter, sans-serif" + } + } + } + + Text { + visible: Hyprland.workspaces.length === 0 + text: "No Workspaces" + color: "#ffffff" + font.pixelSize: 12 + } +} diff --git a/modules/wp/WallpaperPicker.qml b/modules/wp/WallpaperPicker.qml new file mode 100644 index 0000000..0bd56e0 --- /dev/null +++ b/modules/wp/WallpaperPicker.qml @@ -0,0 +1,145 @@ +import QtQuick +import Quickshell +import QtQuick.Controls +import Quickshell.Hyprland +import Quickshell.Io +import Qt.labs.folderlistmodel + + +PanelWindow { + id: picker + implicitWidth: screen.width * 0.75 + implicitHeight: screen.height * 0.5 + color: "transparent" + visible: true + + Rectangle { + anchors.fill: parent + radius: 10 + color: "black" + + border.width: 2 + border.color: "white" + + + //Wallpaper space + Rectangle { + id: wallpaperContainer + + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 20 + + width: parent.width - 35 + height: parent.height - 100 + color: "black" + radius: 10 + + clip: true + + + // get folder url + FolderListModel { + id: imagesModel + folder: "file://" + Quickshell.workingDirectory + "/Pictures/Wallpapers" + nameFilters: ["*.png", "*.jpg", "*.jpeg"] + showDirs: false + } + + // grid + Item { + anchors.fill: parent + anchors.margins: 15 + + GridView { + id: grid + anchors.fill: parent + cellWidth: parent.width/6 + cellHeight: parent.height/2 + 15 + model: imagesModel + + boundsBehavior: Flickable.StopAtBounds + + + // pictures + text + delegate: Item { + width: grid.cellWidth + height: grid.cellHeight + + Column { + spacing: 20 + + Image { // Image + source: filePath + fillMode: Image.PreserveAspectCrop + + width: grid.cellWidth -10 + height: grid.cellHeight * 0.7 + + asynchronous: true + cache: true + } + + Rectangle { // highlight of text + id: textHighlight + width: parent.width - 10 + height: 24 + color: mouseArea.containsMouse ? "#4a90e2" : "transparent" + anchors.horizontalCenter: parent.horizontalCenter + + Text { + text: fileName + elide: Text.ElideRight + width: parent.width + horizontalAlignment: Text.AlignHCenter + + font.pixelSize: 15 + font.family: "Fira Sans" + color: "white" + } + } + } + Item { + anchors.fill: parent + Process { + id: wallpaperProcess + command: ["sh", "-c", Quickshell.workingDirectory + "/.config/quickshell/modules/wp/set-wallpaper.sh" + " " + model.filePath + " &"] + stdout: StdioCollector { + onStreamFinished: console.log(`line read: ${this.text}`) + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + console.log("Setting wallpaper to:", model.fileName) + wallpaperProcess.startDetached() + + wLoader.closeWallpaperPicker() + } + } + } + } + + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AlwaysOn + } + } + } + + Rectangle { // border of wallpaper container + id: borderOverlay + anchors.fill: parent + radius: 10 + color: "transparent" + border.color: "white" + border.width: 1 + z: 999 + } + + } + } +} \ No newline at end of file diff --git a/modules/wp/WallpaperPickerLoader.qml b/modules/wp/WallpaperPickerLoader.qml new file mode 100644 index 0000000..70a9f6a --- /dev/null +++ b/modules/wp/WallpaperPickerLoader.qml @@ -0,0 +1,26 @@ +import QtQuick +import Quickshell +import Quickshell.Hyprland + +Item { // container, invisible + id: wLoader + + Loader { + id: wallpaperLoader + active: false + sourceComponent: WallpaperPicker { id: wPicker } + } + + GlobalShortcut { + name: "Wallpaper" + description: "Open wallpaper picker" + onPressed: { + wallpaperLoader.active = !wallpaperLoader.active + console.log("Pressed Meta+Shift+W (Hyprland global shortcut)") + } + } + + function closeWallpaperPicker() { + wallpaperLoader.active = false + } +} \ No newline at end of file diff --git a/modules/wp/set-wallpaper.sh b/modules/wp/set-wallpaper.sh new file mode 100755 index 0000000..df1ac2f --- /dev/null +++ b/modules/wp/set-wallpaper.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Path to the image is the first argument +IMAGE="$1" + +echo "start" + +# Check if an image was provided +if [[ -z "$IMAGE" ]]; then + echo "Usage: $0 /path/to/image" + exit 1 +fi + +# Check if swww daemon is running +if ! pgrep -x "swww-daemon" > /dev/null; then + echo "Starting swww daemon..." + swww-daemon & + + # Give the daemon a moment to start + sleep 0.2 + echo "daemon started" +fi + +# Set the wallpaper +echo "running" +swww img "$IMAGE" -t grow --transition-duration 1 + diff --git a/shell.qml b/shell.qml new file mode 100644 index 0000000..0b82f33 --- /dev/null +++ b/shell.qml @@ -0,0 +1,18 @@ +//@ pragma UseQApplication + +import Quickshell //for PanelWindow +import Quickshell.Hyprland +import QtQuick //for Text +import "./modules/bar" +import "./modules/wp" + +ShellRoot { + id: root + + // Bar + BarLoader {} + + //Wallpaper picker + WallpaperPickerLoader {} + +} \ No newline at end of file