first commit

This commit is contained in:
Zacharias-Brohn
2025-10-07 13:53:18 +02:00
commit 0da7e57a64
13 changed files with 520 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
.qmlls.ini
+86
View File
@@ -0,0 +1,86 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Quickshell.Io
import Quickshell.Wayland
import Qt5Compat.GraphicalEffects
import Quickshell.Hyprland
import qs.Modules
Scope {
Variants {
model: Quickshell.screens
PanelWindow {
id: bar
required property var modelData
screen: modelData
anchors {
top: true
left: true
right: true
}
implicitHeight: 34
color: "transparent"
Rectangle {
anchors.fill: parent
color: "#801a1a1a"
radius: 0
RowLayout {
anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
RowLayout {
id: leftSection
Layout.fillHeight: true
Layout.preferredWidth: 100
Workspaces {
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.fillHeight: true
Layout.topMargin: 6
Layout.bottomMargin: 6
}
}
RowLayout {
id: centerSection
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
}
RowLayout {
id: rightSection
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
TrayWidget {
id: systemTrayModule
bar: bar
Layout.alignment: Qt.AlignVCenter
}
Clock {
Layout.alignment: Qt.AlignVCenter
}
SwayNC {
Layout.alignment: Qt.AlignVCenter
}
}
}
WindowTitle {
anchors.centerIn: parent
width: Math.min( 300, parent.width * 0.4 )
height: parent.height
z: 1
}
}
}
}
}
+6
View File
@@ -0,0 +1,6 @@
import QtQuick
Text {
text: Time.time
color: "white"
}
+9
View File
@@ -0,0 +1,9 @@
pragma Singleton
import Quickshell
import Quickshell.Hyprland
Singleton {
id: root
property string activeWindow: Hyprland.activeToplevel?.lastIpcObject.class || ""
}
+86
View File
@@ -0,0 +1,86 @@
// CustomTrayMenu.qml
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import QtQuick.Window // for Window, flags
PopupWindow {
id: popup
property QsMenuHandle menuHandle
property alias entries: menuModel
QsMenuOpener {
id: menu
menu: popup.menuHandle
}
ListModel { id: menuModel }
implicitWidth: contentColumn.implicitWidth + 16
implicitHeight: contentColumn.implicitHeight + 16
Rectangle {
color: "#202020CC"
radius: 4
anchors.fill: parent
}
Column {
id: contentColumn
anchors.fill: parent
spacing: 4
Repeater {
id: repeater
model: menuModel
Row {
id: entryRow
height: 30
width: parent.implicitWidth
property var entry: modelData
MouseArea {
anchors.fill: parent
onClicked: {
if (entryRow.entry.triggered) {
entryRow.entry.triggered()
}
popup.visible = false
}
}
Image {
source: entryRow.entry.icon
width: 20; height: 20
visible: entryRow.entry.icon !== ""
}
Text {
text: entryRow.entry.text
color: "white"
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
function rebuild() {
menuModel.clear()
console.log(menu.children.count)
if (!menu) return
for (let i = 0; i < menu.children.count; ++i) {
let e = menu.children.get(i)
menuModel.append({
text: e.text,
icon: e.icon,
triggered: e.triggered,
entryObject: e
})
}
}
onMenuHandleChanged: rebuild
Connections {
target: menu
function onCountChanged() {
popup.rebuild
}
}
}
+94
View File
@@ -0,0 +1,94 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
Item {
id: root
implicitWidth: notificationButton.implicitWidth
implicitHeight: notificationButton.implicitHeight
property var notificationState: ({})
function updateState(output) {
try {
notificationState = JSON.parse(output.trim())
} catch (e) {
console.error("Failed to parse swaync state:", e)
}
}
function getIcon() {
let count = notificationState["text"] || 0
let hasNotification = count > 0
if (hasNotification) return "notification"
return "none"
}
function getDisplayText() {
let icon = getIcon()
let count = notificationState["count"] || 0
if (icon.includes("notification")) {
return ""
}
return ""
}
Process {
id: swayNcMonitor
running: true
command: ["swaync-client", "-swb"]
stdout: SplitParser {
onRead: data => root.updateState(data)
}
}
Process {
id: swayncProcess
command: ["swaync-client", "-t", "-sw"]
running: false
}
Button {
id: notificationButton
flat: true
background: Rectangle {
color: "transparent"
radius: 4
}
contentItem: RowLayout {
spacing: 0
Text {
text: root.getDisplayText()
color: "white"
font.pixelSize: 16
Layout.alignment: Qt.AlignVCenter
}
Text {
text: "●"
color: "red"
font.pixelSize: 6
visible: root.getIcon().includes("notification")
Layout.alignment: Qt.AlignTop | Qt.AlignRight
Layout.topMargin: 0
Layout.rightMargin: -6
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
swayncProcess.running = true
}
}
}
}
+52
View File
@@ -0,0 +1,52 @@
import QtQuick
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.SystemTray
import qs.Modules
IconImage {
id: root
required property SystemTrayItem item
property var customMenu
source: root.item.icon
implicitSize: 15
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: event => {
switch (event.button) {
case Qt.LeftButton: root.item.activate(); break;
case Qt.RightButton:
if (root.item.hasMenu) {
root.customMenu = menuComponent.createObject(root);
root.customMenu.menuHandle = root.item.menu;
const window = QsWindow.window;
const widgetRect = window.contentItem.mapFromItem(root, 0, root.height + 4, root.width, root.height);
root.customMenu.anchor.rect = widgetRect
root.customMenu.anchor.window = window
root.customMenu.anchor.adjustment = PopupAdjustment.Flip
root.customMenu.visible = true;
root.customMenu.rebuild();
// menuAnchor.anchor.rect = widgetRect;
// menuAnchor.open();
}
break;
}
}
}
Component {
id: menuComponent
CustomTrayMenu {}
}
// QsMenuAnchor {
// id: menuAnchor
// menu: root.item.menu
// anchor.window: root.QsWindow.window?? null
// anchor.adjustment: PopupAdjustment.Flip
// }
}
+25
View File
@@ -0,0 +1,25 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Services.SystemTray
Rectangle {
required property PanelWindow bar
implicitHeight: parent.height
implicitWidth: rowL.implicitWidth + 20
color: "transparent"
RowLayout {
spacing: 10
id: rowL
anchors.centerIn: parent
Repeater {
model: SystemTray.items
TrayItem {
required property SystemTrayItem modelData
item: modelData
}
}
}
}
+53
View File
@@ -0,0 +1,53 @@
import QtQuick
import QtQuick.Layouts
Item {
id: root
Layout.fillHeight: true
Layout.preferredWidth: Math.max( titleText1.implicitWidth, titleText2.implicitWidth ) + 10
clip: true
property string currentTitle: ActiveWindow.activeWindow
property bool showFirst: true
onCurrentTitleChanged: {
if (showFirst) {
titleText2.text = currentTitle
showFirst = false
} else {
titleText1.text = currentTitle
showFirst = true
}
}
Text {
id: titleText1
anchors.fill: parent
anchors.margins: 5
text: root.currentTitle
color: "white"
elide: Text.ElideRight
font.pixelSize: 16
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: root.showFirst ? 1 : 0
Behavior on opacity {
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
}
}
Text {
id: titleText2
anchors.fill: parent
anchors.margins: 5
color: "white"
elide: Text.ElideRight
font.pixelSize: 16
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: root.showFirst ? 0 : 1
Behavior on opacity {
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
}
}
}
+84
View File
@@ -0,0 +1,84 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Hyprland
Rectangle {
id: root
implicitWidth: workspacesRow.implicitWidth + 12
implicitHeight: workspacesRow.implicitHeight + 8
color: "#40000000"
radius: height / 2
Behavior on implicitWidth {
NumberAnimation {
duration: 100
easing.type: Easing.InOutQuad
}
}
RowLayout {
id: workspacesRow
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 6
spacing: 8
Repeater {
model: Hyprland.workspaces
Rectangle {
required property var modelData
width: 12
height: 12
radius: 6
color: modelData.id === Hyprland.focusedWorkspace.id ? "#4080ff" : "#606060"
border.color: modelData.id === Hyprland.focusedWorkspace.id ? "#60a0ff" : "#808080"
border.width: 1
scale: 1.0
opacity: 1.0
Behavior on color {
ColorAnimation {
duration: 150
easing.type: Easing.InOutQuad
}
}
Behavior on border.color {
ColorAnimation {
duration: 150
easing.type: Easing.InOutQuad
}
}
NumberAnimation on scale {
from: 0.0
to: 1.0
duration: 300
easing.type: Easing.OutBack
}
NumberAnimation on opacity {
from: 0.0
to: 1.0
duration: 200
}
MouseArea {
anchors.fill: parent
onClicked: {
Hyprland.dispatch("workspace " + modelData.id)
}
}
}
}
}
}
+1
View File
@@ -0,0 +1 @@
# z-bar-qt
+17
View File
@@ -0,0 +1,17 @@
// Time.qml
pragma Singleton
import Quickshell
import QtQuick
Singleton {
id: root
readonly property string time: {
Qt.formatDateTime(clock.date, "ddd d MMM - hh:mm:ss")
}
SystemClock {
id: clock
precision: SystemClock.Seconds
}
}
+6
View File
@@ -0,0 +1,6 @@
//@ pragma UseQApplication
import Quickshell
Scope {
Bar {}
}