fedora
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Modules.Bar.Extras
|
||||
import qs.Services.Media
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
import qs.Widgets.AudioSpectrum
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property ShellScreen screen
|
||||
|
||||
// Widget properties passed from Bar.qml for per-instance settings
|
||||
property string widgetId: ""
|
||||
property string section: ""
|
||||
property int sectionWidgetIndex: -1
|
||||
property int sectionWidgetsCount: 0
|
||||
|
||||
// Explicit screenName property ensures reactive binding when screen changes
|
||||
readonly property string screenName: screen ? screen.name : ""
|
||||
readonly property string barPosition: Settings.getBarPositionForScreen(screenName)
|
||||
readonly property bool isVerticalBar: barPosition === "left" || barPosition === "right"
|
||||
readonly property real capsuleHeight: Style.getCapsuleHeightForScreen(screenName)
|
||||
|
||||
property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] ?? {}
|
||||
property var widgetSettings: {
|
||||
if (section && sectionWidgetIndex >= 0 && screenName) {
|
||||
var widgets = Settings.getBarWidgetsForScreen(screenName)[section];
|
||||
if (widgets && sectionWidgetIndex < widgets.length) {
|
||||
return widgets[sectionWidgetIndex];
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// Resolve settings: try user settings or defaults from BarWidgetRegistry
|
||||
readonly property int visualizerWidth: widgetSettings.width !== undefined ? widgetSettings.width : widgetMetadata.width
|
||||
readonly property bool hideWhenIdle: widgetSettings.hideWhenIdle !== undefined ? widgetSettings.hideWhenIdle : widgetMetadata.hideWhenIdle
|
||||
readonly property string colorName: widgetSettings.colorName !== undefined ? widgetSettings.colorName : widgetMetadata.colorName
|
||||
|
||||
readonly property color fillColor: Color.resolveColorKey(colorName)
|
||||
|
||||
readonly property bool shouldShow: (currentVisualizerType !== "" && currentVisualizerType !== "none") && (!hideWhenIdle || MediaService.isPlaying)
|
||||
|
||||
// Register/unregister with SpectrumService based on visibility (use screenName — screen can be null after DPMS/output changes)
|
||||
readonly property string spectrumComponentId: "bar:audiovisualizer:" + screenName + ":" + root.section + ":" + root.sectionWidgetIndex
|
||||
|
||||
onShouldShowChanged: {
|
||||
if (root.shouldShow) {
|
||||
SpectrumService.registerComponent(root.spectrumComponentId);
|
||||
} else {
|
||||
SpectrumService.unregisterComponent(root.spectrumComponentId);
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
if (root.shouldShow) {
|
||||
SpectrumService.unregisterComponent(root.spectrumComponentId);
|
||||
}
|
||||
}
|
||||
|
||||
// Content dimensions for implicit sizing
|
||||
readonly property real contentWidth: !shouldShow ? 0 : isVerticalBar ? capsuleHeight : visualizerWidth
|
||||
readonly property real contentHeight: !shouldShow ? 0 : isVerticalBar ? visualizerWidth : capsuleHeight
|
||||
|
||||
implicitWidth: contentWidth
|
||||
implicitHeight: contentHeight
|
||||
visible: shouldShow
|
||||
opacity: shouldShow ? 1.0 : 0.0
|
||||
|
||||
Behavior on implicitWidth {
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.InOutCubic
|
||||
}
|
||||
}
|
||||
Behavior on implicitHeight {
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.InOutCubic
|
||||
}
|
||||
}
|
||||
|
||||
// Store visualizer type to force re-evaluation
|
||||
readonly property string currentVisualizerType: Settings.data.audio.visualizerType
|
||||
|
||||
// Visual capsule centered in parent
|
||||
Rectangle {
|
||||
id: background
|
||||
width: root.contentWidth
|
||||
height: root.contentHeight
|
||||
anchors.centerIn: parent
|
||||
radius: Style.radiusS
|
||||
color: Style.capsuleColor
|
||||
border.color: Style.capsuleBorderColor
|
||||
border.width: Style.capsuleBorderWidth
|
||||
|
||||
// When visualizer type or playback changes, shouldShow updates automatically
|
||||
// The Loader dynamically loads the appropriate visualizer based on settings
|
||||
Loader {
|
||||
id: visualizerLoader
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginS
|
||||
active: shouldShow
|
||||
asynchronous: true
|
||||
|
||||
sourceComponent: {
|
||||
switch (currentVisualizerType) {
|
||||
case "linear":
|
||||
return linearComponent;
|
||||
case "mirrored":
|
||||
return mirroredComponent;
|
||||
case "wave":
|
||||
return waveComponent;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NPopupContextMenu {
|
||||
id: contextMenu
|
||||
|
||||
model: [
|
||||
{
|
||||
"label": I18n.tr("actions.cycle-visualizer"),
|
||||
"action": "cycle-visualizer",
|
||||
"icon": "chart-column"
|
||||
},
|
||||
{
|
||||
"label": I18n.tr("actions.widget-settings"),
|
||||
"action": "widget-settings",
|
||||
"icon": "settings"
|
||||
},
|
||||
]
|
||||
|
||||
onTriggered: action => {
|
||||
contextMenu.close();
|
||||
if (screen) {
|
||||
PanelService.closeContextMenu(screen);
|
||||
}
|
||||
|
||||
if (action === "cycle-visualizer") {
|
||||
const types = ["linear", "mirrored", "wave"];
|
||||
const currentIndex = types.indexOf(currentVisualizerType);
|
||||
const nextIndex = (currentIndex + 1) % types.length;
|
||||
Settings.data.audio.visualizerType = types[nextIndex];
|
||||
} else if (action === "widget-settings" && screen) {
|
||||
BarService.openWidgetSettings(screen, section, sectionWidgetIndex, widgetId, widgetSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Click to cycle through visualizer types
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onClicked: mouse => {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
if (screen) {
|
||||
PanelService.showContextMenu(contextMenu, root, screen);
|
||||
}
|
||||
} else {
|
||||
const types = ["linear", "mirrored", "wave"];
|
||||
const currentIndex = types.indexOf(currentVisualizerType);
|
||||
const nextIndex = (currentIndex + 1) % types.length;
|
||||
Settings.data.audio.visualizerType = types[nextIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: linearComponent
|
||||
NLinearSpectrum {
|
||||
anchors.fill: parent
|
||||
values: SpectrumService.values
|
||||
fillColor: root.fillColor
|
||||
showMinimumSignal: true
|
||||
vertical: root.isVerticalBar
|
||||
barPosition: root.barPosition
|
||||
mirrored: Settings.data.audio.spectrumMirrored
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: mirroredComponent
|
||||
NMirroredSpectrum {
|
||||
anchors.fill: parent
|
||||
values: SpectrumService.values
|
||||
fillColor: root.fillColor
|
||||
showMinimumSignal: true
|
||||
vertical: root.isVerticalBar
|
||||
mirrored: Settings.data.audio.spectrumMirrored
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: waveComponent
|
||||
NWaveSpectrum {
|
||||
anchors.fill: parent
|
||||
values: SpectrumService.values
|
||||
fillColor: root.fillColor
|
||||
showMinimumSignal: true
|
||||
vertical: root.isVerticalBar
|
||||
mirrored: Settings.data.audio.spectrumMirrored
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user