180 lines
5.9 KiB
QML
180 lines
5.9 KiB
QML
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |