Inital commit checkpoint
This commit is contained in:
80
bar/Bar.qml
Normal file
80
bar/Bar.qml
Normal file
@@ -0,0 +1,80 @@
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell.Wayland
|
||||
import qs.common
|
||||
import qs.common.widgets
|
||||
|
||||
Scope {
|
||||
Variants {
|
||||
model: Quickshell.screens;
|
||||
PanelWindow {
|
||||
required property var modelData
|
||||
screen: modelData
|
||||
WlrLayershell.layer: WlrLayer.Bottom
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
id: barBackground
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: Config.options.bar.cornerStyle === 1 ? (Appearance.sizes.hyprlandGapsOut) : 0
|
||||
}
|
||||
color: Config.options.bar.showBackground ? Appearance.colors.colLayer1 : "transparent"
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: true
|
||||
}
|
||||
|
||||
implicitHeight: 45
|
||||
|
||||
RowLayout { // Left Section
|
||||
id: leftSection
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
leftMargin: 5
|
||||
}
|
||||
spacing: Config.options?.bar.borderless ? 4 : 8
|
||||
Workspaces {}
|
||||
}
|
||||
|
||||
RowLayout { // Middle section
|
||||
id: middleSection
|
||||
anchors.centerIn: parent
|
||||
spacing: Config.options?.bar.borderless ? 4 : 8
|
||||
|
||||
Media {
|
||||
visible: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout { // Right Section
|
||||
id: rightSection
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: 5
|
||||
}
|
||||
spacing: Config.options?.bar.borderless ? 4 : 8
|
||||
SysTray {
|
||||
Layout.fillWidth: false
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
NotificationIcon {
|
||||
Layout.fillWidth: false
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
ClockWidget {
|
||||
id: clock
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
bar/BarGroup.qml
Normal file
9
bar/BarGroup.qml
Normal file
@@ -0,0 +1,9 @@
|
||||
import qs.modules.common
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property real padding: 5
|
||||
implicitHeight: Appearance.sizes.baseBarHeight
|
||||
}
|
||||
8
bar/ClockWidget.qml
Normal file
8
bar/ClockWidget.qml
Normal file
@@ -0,0 +1,8 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.common
|
||||
import qs.common.widgets
|
||||
|
||||
StyledText {
|
||||
text: Time.time
|
||||
}
|
||||
81
bar/Media.qml
Normal file
81
bar/Media.qml
Normal file
@@ -0,0 +1,81 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Services.Mpris
|
||||
|
||||
import qs
|
||||
import qs.common
|
||||
import qs.common.widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property bool borderless: Config.options.bar.borderless
|
||||
|
||||
Layout.fillHeight: true
|
||||
implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2
|
||||
implicitHeight: Appearance.sizes.barHeight
|
||||
|
||||
Timer {
|
||||
running: MprisController.hasPlayers && MprisController.activePlayer().isPlaying && MprisController.activePlayer().lengthSupported
|
||||
interval: 1000
|
||||
repeat: true
|
||||
onTriggered: MprisController.activePlayer().positionChanged()
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.MiddleButton | Qt.BackButton | Qt.ForwardButton | Qt.RightButton | Qt.LeftButton
|
||||
onPressed: (event) => {
|
||||
if (event.button === Qt.MiddleButton) {
|
||||
MprisController.activePlayer().togglePlaying();
|
||||
} else if (event.button === Qt.BackButton) {
|
||||
MprisController.shiftPlayer(-1);
|
||||
} else if (event.button === Qt.ForwardButton) {
|
||||
MprisController.shiftPlayer(1);
|
||||
} else if (event.button === Qt.LeftButton) {
|
||||
GlobalStates.mediaControlsOpen = !GlobalStates.mediaControlsOpen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: rowLayout
|
||||
|
||||
spacing: 4
|
||||
anchors.fill: parent
|
||||
visible: MprisController.hasPlayers
|
||||
CircularProgress {
|
||||
id: circularProgress
|
||||
visible: MprisController.hasPlayers && MprisController.activePlayer().lengthSupported
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.leftMargin: rowLayout.spacing
|
||||
lineWidth: 2
|
||||
value: MprisController.activePlayer().lengthSupported ? MprisController.activePlayer()?.position / MprisController.activePlayer()?.length : 0
|
||||
implicitSize: 26
|
||||
colSecondary: Appearance.colors.colSecondaryContainer
|
||||
colPrimary: Appearance.m3colors.m3onSecondaryContainer
|
||||
enableAnimation: false
|
||||
|
||||
MaterialSymbol {
|
||||
visible: MprisController.hasPlayers && MprisController.activePlayer().lengthSupported
|
||||
anchors.centerIn: parent
|
||||
fill: 1
|
||||
text: MprisController.activePlayer()?.isPlaying ? "music_note" : "pause"
|
||||
iconSize: Appearance.font.pixelSize.normal
|
||||
color: Appearance.m3colors.m3onSecondaryContainer
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
visible: Config.options.bar.verbose
|
||||
width: rowLayout.width - (circularProgress.size + rowLayout.spacing * 2)
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: rowLayout.spacing
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
color: Appearance.colors.colOnLayer1
|
||||
text: `${MprisController.activePlayer()?.trackTitle}${MprisController.activePlayer()?.trackArtist ? ' • ' + MprisController.activePlayer().trackArtist : ''}`
|
||||
}
|
||||
}
|
||||
}
|
||||
45
bar/NotificationIcon.qml
Normal file
45
bar/NotificationIcon.qml
Normal file
@@ -0,0 +1,45 @@
|
||||
import qs.common
|
||||
import qs.common.widgets
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
height: parent.height
|
||||
implicitWidth: rowLayout.implicitWidth
|
||||
Layout.leftMargin: Appearance.rounding.screenRounding
|
||||
|
||||
RowLayout {
|
||||
id: rowLayout
|
||||
|
||||
anchors.fill: parent
|
||||
spacing: 15
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
font.pixelSize: Appearance.font.pixelSize.larger
|
||||
color: Appearance.m3colors.m3error
|
||||
text: NotificationServer.amountNotifications
|
||||
visible: {
|
||||
NotificationServer.amountNotifications > 0
|
||||
}
|
||||
}
|
||||
|
||||
MaterialSymbol {
|
||||
visible: true
|
||||
anchors.centerIn: parent
|
||||
text: NotificationServer.amountNotifications > 0 ? "notifications_unread" : "notifications"
|
||||
iconSize: Appearance.font.pixelSize.larger
|
||||
color: NotificationServer.amountNotifications > 0 ? Appearance.m3colors.m3error : Appearance.m3colors.m3onSecondaryContainer
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
font.pixelSize: Appearance.font.pixelSize.larger
|
||||
color: Appearance.colors.colSubtext
|
||||
text: "•"
|
||||
visible: true
|
||||
}
|
||||
}
|
||||
}
|
||||
39
bar/SysTray.qml
Normal file
39
bar/SysTray.qml
Normal file
@@ -0,0 +1,39 @@
|
||||
import qs.common
|
||||
import qs.common.widgets
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell.Services.SystemTray
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
height: parent.height
|
||||
implicitWidth: rowLayout.implicitWidth
|
||||
Layout.leftMargin: Appearance.rounding.screenRounding
|
||||
|
||||
RowLayout {
|
||||
id: rowLayout
|
||||
|
||||
anchors.fill: parent
|
||||
spacing: 15
|
||||
|
||||
Repeater {
|
||||
model: SystemTray.items
|
||||
|
||||
SysTrayItem {
|
||||
required property SystemTrayItem modelData
|
||||
item: modelData
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
font.pixelSize: Appearance.font.pixelSize.larger
|
||||
color: Appearance.colors.colSubtext
|
||||
text: "•"
|
||||
visible: {
|
||||
SystemTray.items.values.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
52
bar/SysTrayItem.qml
Normal file
52
bar/SysTrayItem.qml
Normal file
@@ -0,0 +1,52 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Services.SystemTray
|
||||
import qs.common
|
||||
|
||||
MouseArea {
|
||||
id: root
|
||||
|
||||
required property SystemTrayItem item
|
||||
property bool targetMenuOpen: false
|
||||
property int trayItemWidth: Appearance.font.pixelSize.larger
|
||||
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
Layout.fillHeight: true
|
||||
implicitWidth: trayItemWidth
|
||||
onClicked: (event) => {
|
||||
switch (event.button) {
|
||||
case Qt.LeftButton:
|
||||
item.activate();
|
||||
break;
|
||||
case Qt.RightButton:
|
||||
if (item.hasMenu) {
|
||||
menu.open();
|
||||
}
|
||||
break;
|
||||
}
|
||||
event.accepted = true;
|
||||
}
|
||||
|
||||
QsMenuAnchor {
|
||||
id: menu
|
||||
menu: root.item.menu
|
||||
anchor {
|
||||
item: root // Works instead of using window
|
||||
edges: Edges.Bottom | Edges.Right
|
||||
gravity: Edges.Bottom | Edges.Left
|
||||
margins {
|
||||
top: 30
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IconImage {
|
||||
id: trayIcon
|
||||
source: root.item.icon
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
}
|
||||
}
|
||||
16
bar/Time.qml
Normal file
16
bar/Time.qml
Normal file
@@ -0,0 +1,16 @@
|
||||
pragma Singleton
|
||||
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
readonly property string time: {
|
||||
Qt.formatDateTime(clock.date, "ddd, MMM dd hh:mm:ss AP")
|
||||
}
|
||||
|
||||
SystemClock {
|
||||
id: clock
|
||||
precision: SystemClock.Seconds
|
||||
}
|
||||
}
|
||||
180
bar/Workspaces.qml
Normal file
180
bar/Workspaces.qml
Normal file
@@ -0,0 +1,180 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls // button
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import qs.common
|
||||
import qs.common.functions
|
||||
import qs.common.widgets
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property bool borderless: Config.options.bar.borderless
|
||||
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(QsWindow.window?.screen)
|
||||
readonly property list<HyprlandMonitor> monitors: Hyprland.monitors.values
|
||||
readonly property HyprlandToplevel activeWindow: Hyprland.activeToplevel
|
||||
|
||||
readonly property int workspaceGroup: Math.floor((monitor?.activeWorkspace?.id - 1) / Config.options.bar.workspaces.shown)
|
||||
property list<bool> workspaceOccupied: []
|
||||
|
||||
property int widgetPadding: 4
|
||||
property int workspaceButtonWidth: 26
|
||||
property real workspaceIconSizeShrinked: workspaceButtonWidth * 0.55
|
||||
property real workspaceIconOpacityShrinked: 1
|
||||
property real workspaceIconMarginShrinked: -4
|
||||
property int workspaceIndexInGroup: (monitor?.activeWorkspace?.id - 1) % Config.options.bar.workspaces.shown
|
||||
|
||||
function updateWorkspaceOccupied() {
|
||||
workspaceOccupied = Array.from({ length: Config.options.bar.workspaces.shown }, (_, i) => {
|
||||
return Hyprland.workspaces.values.some(ws => ws.id === workspaceGroup * Config.options.bar.workspaces.shown + i + 1);
|
||||
});
|
||||
}
|
||||
|
||||
function isMonitorWorkspace(id) {
|
||||
for (var i = 0; i < monitors.length; i++){
|
||||
if (id === monitors[i].id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: updateWorkspaceOccupied()
|
||||
|
||||
Connections {
|
||||
target: Hyprland.workspaces
|
||||
function onValuesChanged() {
|
||||
root.updateWorkspaceOccupied();
|
||||
}
|
||||
}
|
||||
|
||||
implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2
|
||||
implicitHeight: Appearance.sizes.barHeight
|
||||
// Workspaces - background
|
||||
RowLayout {
|
||||
id: rowLayout
|
||||
z: 1
|
||||
|
||||
spacing: 0
|
||||
anchors.fill: parent
|
||||
implicitHeight: Appearance.sizes.barHeight
|
||||
|
||||
// https://doc.qt.io/qt-6/qml-qtquick-repeater.html
|
||||
Repeater {
|
||||
model: Config.options.bar.workspaces.shown
|
||||
|
||||
Rectangle {
|
||||
z: 1
|
||||
implicitHeight: root.workspaceButtonWidth
|
||||
implicitWidth: root.workspaceButtonWidth
|
||||
radius: Appearance.rounding.full
|
||||
property var leftOccupied: index - 1 >= 0 && (root.workspaceOccupied[index-1] || root.isMonitorWorkspace(index))
|
||||
property var rightOccupied: index + 1 < workspaceOccupied.length && (root.workspaceOccupied[index+1] || root.isMonitorWorkspace(index+2))
|
||||
|
||||
property var radiusLeft: leftOccupied ? 0 : Appearance.rounding.full
|
||||
property var radiusRight: rightOccupied ? 0 : Appearance.rounding.full
|
||||
|
||||
topLeftRadius: radiusLeft
|
||||
bottomLeftRadius: radiusLeft
|
||||
topRightRadius: radiusRight
|
||||
bottomRightRadius: radiusRight
|
||||
|
||||
color: ColorUtils.transparentize(Appearance.m3colors.m3secondaryContainer, 0.4)
|
||||
opacity: (root.workspaceOccupied[index] || root.isMonitorWorkspace(index+1)) ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
||||
}
|
||||
Behavior on radiusLeft {
|
||||
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
Behavior on radiusRight {
|
||||
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Active workspace
|
||||
Rectangle {
|
||||
z: 2
|
||||
property real activeWorkspaceMargin: 2
|
||||
implicitHeight: root.workspaceButtonWidth - activeWorkspaceMargin * 2
|
||||
radius: Appearance.rounding.full
|
||||
color: Appearance.colors.colPrimary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
property real idx1: root.workspaceIndexInGroup
|
||||
property real idx2: root.workspaceIndexInGroup
|
||||
x: Math.min(idx1, idx2) * root.workspaceButtonWidth + activeWorkspaceMargin
|
||||
implicitWidth: Math.abs(idx1 - idx2) * root.workspaceButtonWidth + root.workspaceButtonWidth - activeWorkspaceMargin * 2
|
||||
|
||||
Behavior on activeWorkspaceMargin {
|
||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
}
|
||||
Behavior on idx1 { // leading animation
|
||||
NumberAnimation {
|
||||
duration: 100
|
||||
easing.type: Easing.OutSine
|
||||
}
|
||||
}
|
||||
/*
|
||||
Behavior on idx2 { // following animation
|
||||
NumberAnimation {
|
||||
duration: 100
|
||||
easing.type: Easing.OutSine
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// workspaces - numbers
|
||||
RowLayout {
|
||||
id: rowLayoutNumbers
|
||||
z: 3
|
||||
|
||||
spacing: 0
|
||||
anchors.fill: parent
|
||||
implicitHeight: Appearance.sizes.barHeight
|
||||
|
||||
Repeater {
|
||||
model: Config.options.bar.workspaces.shown
|
||||
|
||||
Button {
|
||||
id: button
|
||||
property int workspaceValue: workspaceGroup * Config.options.bar.workspaces.shown + index + 1
|
||||
Layout.fillHeight: true
|
||||
onPressed: Hyprland.dispatch(`workspace ${workspaceValue}`)
|
||||
width: root.workspaceButtonWidth
|
||||
|
||||
background: Item {
|
||||
id: workspaceButtonBackground
|
||||
implicitWidth: root.workspaceButtonWidth
|
||||
implicitHeight: root.workspaceButtonWidth
|
||||
|
||||
StyledText { // Workspace number text
|
||||
opacity: (Config.options?.bar.workspaces.alwaysShowNumbers) ? 1 : 0
|
||||
z: 3
|
||||
|
||||
anchors.centerIn: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: Appearance.font.pixelSize.small - ((text.length - 1) * (text !== "10") * 2)
|
||||
text: `${button.workspaceValue}`
|
||||
elide: Text.ElideRight
|
||||
color: (monitor?.activeWorkspace?.id == button.workspaceValue) ?
|
||||
Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer1Inactive
|
||||
|
||||
Behavior on opacity {
|
||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user