mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2025-12-06 06:36:15 +00:00
358 lines
12 KiB
QML
358 lines
12 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import Quickshell
|
|
import Quickshell.Services.UPower
|
|
import Quickshell.Wayland
|
|
import qs.Commons
|
|
import qs.Modules.Bar.Extras
|
|
import qs.Modules.Notification
|
|
import qs.Services.UI
|
|
import qs.Widgets
|
|
|
|
// Bar Component
|
|
Item {
|
|
id: root
|
|
|
|
// This property will be set by MainScreen
|
|
property ShellScreen screen: null
|
|
|
|
// Expose bar region for click-through mask
|
|
readonly property var barRegion: barContentLoader.item?.children[0] || null
|
|
|
|
// Expose the actual bar Item for unified background system
|
|
readonly property var barItem: barRegion
|
|
|
|
// Bar positioning properties
|
|
readonly property string barPosition: Settings.data.bar.position || "top"
|
|
readonly property bool barIsVertical: barPosition === "left" || barPosition === "right"
|
|
readonly property bool barFloating: Settings.data.bar.floating || false
|
|
|
|
// Fill the parent (the Loader)
|
|
anchors.fill: parent
|
|
|
|
// Register bar when screen becomes available
|
|
onScreenChanged: {
|
|
if (screen && screen.name) {
|
|
Logger.d("Bar", "Bar screen set to:", screen.name);
|
|
Logger.d("Bar", " Position:", barPosition, "Floating:", barFloating);
|
|
BarService.registerBar(screen.name);
|
|
}
|
|
}
|
|
|
|
// Wait for screen to be set before loading bar content
|
|
Loader {
|
|
id: barContentLoader
|
|
anchors.fill: parent
|
|
active: {
|
|
if (root.screen === null || root.screen === undefined) {
|
|
return false;
|
|
}
|
|
|
|
var monitors = Settings.data.bar.monitors || [];
|
|
var result = monitors.length === 0 || monitors.includes(root.screen.name);
|
|
return result;
|
|
}
|
|
|
|
sourceComponent: Item {
|
|
anchors.fill: parent
|
|
|
|
// Bar container - Content
|
|
Item {
|
|
id: bar
|
|
|
|
// Position and size the bar content based on orientation
|
|
x: (root.barPosition === "right") ? (parent.width - Style.barHeight) : 0
|
|
y: (root.barPosition === "bottom") ? (parent.height - Style.barHeight) : 0
|
|
width: root.barIsVertical ? Style.barHeight : parent.width
|
|
height: root.barIsVertical ? parent.height : Style.barHeight
|
|
|
|
// Corner states for new unified background system
|
|
// State -1: No radius (flat/square corner)
|
|
// State 0: Normal (inner curve)
|
|
// State 1: Horizontal inversion (outer curve on X-axis)
|
|
// State 2: Vertical inversion (outer curve on Y-axis)
|
|
readonly property int topLeftCornerState: {
|
|
// Floating bar: always simple rounded corners
|
|
if (barFloating)
|
|
return 0;
|
|
// Top bar: top corners against screen edge = no radius
|
|
if (barPosition === "top")
|
|
return -1;
|
|
// Left bar: top-left against screen edge = no radius
|
|
if (barPosition === "left")
|
|
return -1;
|
|
// Bottom/Right bar with outerCorners: inverted corner
|
|
if (Settings.data.bar.outerCorners && (barPosition === "bottom" || barPosition === "right")) {
|
|
return barIsVertical ? 1 : 2; // horizontal invert for vertical bars, vertical invert for horizontal
|
|
}
|
|
// No outerCorners = square
|
|
return -1;
|
|
}
|
|
|
|
readonly property int topRightCornerState: {
|
|
// Floating bar: always simple rounded corners
|
|
if (barFloating)
|
|
return 0;
|
|
// Top bar: top corners against screen edge = no radius
|
|
if (barPosition === "top")
|
|
return -1;
|
|
// Right bar: top-right against screen edge = no radius
|
|
if (barPosition === "right")
|
|
return -1;
|
|
// Bottom/Left bar with outerCorners: inverted corner
|
|
if (Settings.data.bar.outerCorners && (barPosition === "bottom" || barPosition === "left")) {
|
|
return barIsVertical ? 1 : 2;
|
|
}
|
|
// No outerCorners = square
|
|
return -1;
|
|
}
|
|
|
|
readonly property int bottomLeftCornerState: {
|
|
// Floating bar: always simple rounded corners
|
|
if (barFloating)
|
|
return 0;
|
|
// Bottom bar: bottom corners against screen edge = no radius
|
|
if (barPosition === "bottom")
|
|
return -1;
|
|
// Left bar: bottom-left against screen edge = no radius
|
|
if (barPosition === "left")
|
|
return -1;
|
|
// Top/Right bar with outerCorners: inverted corner
|
|
if (Settings.data.bar.outerCorners && (barPosition === "top" || barPosition === "right")) {
|
|
return barIsVertical ? 1 : 2;
|
|
}
|
|
// No outerCorners = square
|
|
return -1;
|
|
}
|
|
|
|
readonly property int bottomRightCornerState: {
|
|
// Floating bar: always simple rounded corners
|
|
if (barFloating)
|
|
return 0;
|
|
// Bottom bar: bottom corners against screen edge = no radius
|
|
if (barPosition === "bottom")
|
|
return -1;
|
|
// Right bar: bottom-right against screen edge = no radius
|
|
if (barPosition === "right")
|
|
return -1;
|
|
// Top/Left bar with outerCorners: inverted corner
|
|
if (Settings.data.bar.outerCorners && (barPosition === "top" || barPosition === "left")) {
|
|
return barIsVertical ? 1 : 2;
|
|
}
|
|
// No outerCorners = square
|
|
return -1;
|
|
}
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
acceptedButtons: Qt.RightButton
|
|
hoverEnabled: false
|
|
preventStealing: true
|
|
onClicked: function (mouse) {
|
|
if (mouse.button === Qt.RightButton) {
|
|
var controlCenterPanel = PanelService.getPanel("controlCenterPanel", screen);
|
|
if (Settings.data.controlCenter.position === "close_to_bar_button") {
|
|
// Will attempt to open the panel next to the bar button if any.
|
|
controlCenterPanel?.toggle(null, "ControlCenter");
|
|
} else {
|
|
controlCenterPanel?.toggle();
|
|
}
|
|
mouse.accepted = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
anchors.fill: parent
|
|
sourceComponent: (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? verticalBarComponent : horizontalBarComponent
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// For vertical bars
|
|
Component {
|
|
id: verticalBarComponent
|
|
Item {
|
|
anchors.fill: parent
|
|
clip: true
|
|
|
|
// Top section (left widgets)
|
|
ColumnLayout {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.top: parent.top
|
|
anchors.topMargin: Style.marginM
|
|
spacing: Style.marginS
|
|
|
|
Repeater {
|
|
model: Settings.data.bar.widgets.left
|
|
delegate: BarWidgetLoader {
|
|
required property var modelData
|
|
required property int index
|
|
|
|
widgetId: modelData.id || ""
|
|
barDensity: Settings.data.bar.density
|
|
widgetScreen: root.screen
|
|
widgetProps: ({
|
|
"widgetId": modelData.id,
|
|
"section": "left",
|
|
"sectionWidgetIndex": index,
|
|
"sectionWidgetsCount": Settings.data.bar.widgets.left.length
|
|
})
|
|
Layout.alignment: Qt.AlignHCenter
|
|
}
|
|
}
|
|
}
|
|
|
|
// Center section (center widgets)
|
|
ColumnLayout {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: Style.marginS
|
|
|
|
Repeater {
|
|
model: Settings.data.bar.widgets.center
|
|
delegate: BarWidgetLoader {
|
|
required property var modelData
|
|
required property int index
|
|
|
|
widgetId: modelData.id || ""
|
|
barDensity: Settings.data.bar.density
|
|
widgetScreen: root.screen
|
|
widgetProps: ({
|
|
"widgetId": modelData.id,
|
|
"section": "center",
|
|
"sectionWidgetIndex": index,
|
|
"sectionWidgetsCount": Settings.data.bar.widgets.center.length
|
|
})
|
|
Layout.alignment: Qt.AlignHCenter
|
|
}
|
|
}
|
|
}
|
|
|
|
// Bottom section (right widgets)
|
|
ColumnLayout {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.bottom: parent.bottom
|
|
anchors.bottomMargin: Style.marginM
|
|
spacing: Style.marginS
|
|
|
|
Repeater {
|
|
model: Settings.data.bar.widgets.right
|
|
delegate: BarWidgetLoader {
|
|
required property var modelData
|
|
required property int index
|
|
|
|
widgetId: modelData.id || ""
|
|
barDensity: Settings.data.bar.density
|
|
widgetScreen: root.screen
|
|
widgetProps: ({
|
|
"widgetId": modelData.id,
|
|
"section": "right",
|
|
"sectionWidgetIndex": index,
|
|
"sectionWidgetsCount": Settings.data.bar.widgets.right.length
|
|
})
|
|
Layout.alignment: Qt.AlignHCenter
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// For horizontal bars
|
|
Component {
|
|
id: horizontalBarComponent
|
|
Item {
|
|
anchors.fill: parent
|
|
clip: true
|
|
|
|
// Left Section
|
|
RowLayout {
|
|
id: leftSection
|
|
objectName: "leftSection"
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: Style.marginS
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: Style.marginS
|
|
|
|
Repeater {
|
|
model: Settings.data.bar.widgets.left
|
|
delegate: BarWidgetLoader {
|
|
required property var modelData
|
|
required property int index
|
|
|
|
widgetId: modelData.id || ""
|
|
barDensity: Settings.data.bar.density
|
|
widgetScreen: root.screen
|
|
widgetProps: ({
|
|
"widgetId": modelData.id,
|
|
"section": "left",
|
|
"sectionWidgetIndex": index,
|
|
"sectionWidgetsCount": Settings.data.bar.widgets.left.length
|
|
})
|
|
Layout.alignment: Qt.AlignVCenter
|
|
}
|
|
}
|
|
}
|
|
|
|
// Center Section
|
|
RowLayout {
|
|
id: centerSection
|
|
objectName: "centerSection"
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: Style.marginS
|
|
|
|
Repeater {
|
|
model: Settings.data.bar.widgets.center
|
|
delegate: BarWidgetLoader {
|
|
required property var modelData
|
|
required property int index
|
|
|
|
widgetId: modelData.id || ""
|
|
barDensity: Settings.data.bar.density
|
|
widgetScreen: root.screen
|
|
widgetProps: ({
|
|
"widgetId": modelData.id,
|
|
"section": "center",
|
|
"sectionWidgetIndex": index,
|
|
"sectionWidgetsCount": Settings.data.bar.widgets.center.length
|
|
})
|
|
Layout.alignment: Qt.AlignVCenter
|
|
}
|
|
}
|
|
}
|
|
|
|
// Right Section
|
|
RowLayout {
|
|
id: rightSection
|
|
objectName: "rightSection"
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: Style.marginS
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: Style.marginS
|
|
|
|
Repeater {
|
|
model: Settings.data.bar.widgets.right
|
|
delegate: BarWidgetLoader {
|
|
required property var modelData
|
|
required property int index
|
|
|
|
widgetId: modelData.id || ""
|
|
barDensity: Settings.data.bar.density
|
|
widgetScreen: root.screen
|
|
widgetProps: ({
|
|
"widgetId": modelData.id,
|
|
"section": "right",
|
|
"sectionWidgetIndex": index,
|
|
"sectionWidgetsCount": Settings.data.bar.widgets.right.length
|
|
})
|
|
Layout.alignment: Qt.AlignVCenter
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|