feat: settings is now json, refactor panels to be able to dismiss by clicking outside

This commit is contained in:
ferreo 2025-07-18 15:43:22 +01:00
parent 8a3d610d22
commit a498671ef1
36 changed files with 1282 additions and 1300 deletions

View file

@ -16,7 +16,7 @@ Item {
height: usableOuter * 2
onOuterRadiusChanged: () => {
usableOuter = Settings.visualizerType === "fire" ? outerRadius * 0.85 : outerRadius;
usableOuter = Settings.settings.visualizerType === "fire" ? outerRadius * 0.85 : outerRadius;
}
Repeater {
@ -25,25 +25,25 @@ Item {
property real value: root.values[index]
property real angle: (index / root.values.length) * 360
width: Math.max(2, (root.innerRadius * 2 * Math.PI) / root.values.length - 4)
height: Settings.visualizerType === "diamond" ? value * 2 * (usableOuter - root.innerRadius) : value * (usableOuter - root.innerRadius)
height: Settings.settings.visualizerType === "diamond" ? value * 2 * (usableOuter - root.innerRadius) : value * (usableOuter - root.innerRadius)
radius: width / 2
color: root.fillColor
border.color: root.strokeColor
border.width: root.strokeWidth
antialiasing: true
x: Settings.visualizerType === "radial" ? root.width / 2 - width / 2 : root.width / 2 + root.innerRadius * Math.cos(Math.PI / 2 + 2 * Math.PI * index / root.values.length) - width / 2
x: Settings.settings.visualizerType === "radial" ? root.width / 2 - width / 2 : root.width / 2 + root.innerRadius * Math.cos(Math.PI / 2 + 2 * Math.PI * index / root.values.length) - width / 2
y: Settings.visualizerType === "radial" ? root.height / 2 - height : Settings.visualizerType === "diamond" ? root.height / 2 - root.innerRadius * Math.sin(Math.PI / 2 + 2 * Math.PI * index / root.values.length) - height / 2 : root.height / 2 - root.innerRadius * Math.sin(Math.PI / 2 + 2 * Math.PI * index / root.values.length) - height
y: Settings.settings.visualizerType === "radial" ? root.height / 2 - height : Settings.settings.visualizerType === "diamond" ? root.height / 2 - root.innerRadius * Math.sin(Math.PI / 2 + 2 * Math.PI * index / root.values.length) - height / 2 : root.height / 2 - root.innerRadius * Math.sin(Math.PI / 2 + 2 * Math.PI * index / root.values.length) - height
transform: [
Rotation {
origin.x: width / 2
origin.y: Settings.visualizerType === "diamond" ? height / 2 : height
angle: Settings.visualizerType === "radial" ? (index / root.values.length) * 360 : Settings.visualizerType === "fire" ? 0 : (index / root.values.length) * 360 - 90
origin.y: Settings.settings.visualizerType === "diamond" ? height / 2 : height
angle: Settings.settings.visualizerType === "radial" ? (index / root.values.length) * 360 : Settings.settings.visualizerType === "fire" ? 0 : (index / root.values.length) * 360 - 90
},
Translate {
x: Settings.visualizerType === "radial" ? root.innerRadius * Math.cos(2 * Math.PI * index / root.values.length) : 0
y: Settings.visualizerType === "radial" ? root.innerRadius * Math.sin(2 * Math.PI * index / root.values.length) : 0
x: Settings.settings.visualizerType === "radial" ? root.innerRadius * Math.cos(2 * Math.PI * index / root.values.length) : 0
y: Settings.settings.visualizerType === "radial" ? root.innerRadius * Math.sin(2 * Math.PI * index / root.values.length) : 0
}
]

View file

@ -0,0 +1,44 @@
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Settings
PanelWindow {
id: outerPanel
property bool showOverlay: true
property int topMargin: 36
property color overlayColor: showOverlay ? Theme.overlay : "transparent"
function dismiss() {
visible = false;
}
function show() {
visible = true;
}
implicitWidth: screen.width
implicitHeight: screen.height
color: visible ? overlayColor : "transparent"
visible: false
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
screen: (typeof modelData !== 'undefined' ? modelData : null)
anchors.top: true
anchors.left: true
anchors.right: true
anchors.bottom: true
margins.top: topMargin
MouseArea {
anchors.fill: parent
onClicked: outerPanel.dismiss()
}
Behavior on color {
ColorAnimation {
duration: 350
easing.type: Easing.InOutCubic
}
}
}

View file

@ -1,5 +1,4 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick
import QtQuick.Window 2.15
import qs.Settings
@ -12,8 +11,9 @@ Window {
flags: Qt.ToolTip | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
color: "transparent"
visible: false
minimumWidth: Math.max(minimumWidth, tooltipText.implicitWidth + 24)
minimumHeight: Math.max(minimumHeight, tooltipText.implicitHeight + 16)
minimumWidth: tooltipText.implicitWidth + 24
minimumHeight: tooltipText.implicitHeight + 16
property var _timerObj: null
onTooltipVisibleChanged: {
if (tooltipVisible) {
@ -33,26 +33,32 @@ Window {
x = pos.x - width / 2 + targetItem.width / 2;
y = pos.y + 12;
visible = true;
console.log("StyledTooltip _showNow called");
console.log("StyledTooltip Theme.textPrimary:", Theme.textPrimary);
}
function _hideNow() {
visible = false;
if (_timerObj) { _timerObj.destroy(); _timerObj = null; }
}
Connections {
target: targetItem
onXChanged: if (tooltipWindow.visible) tooltipWindow._showNow()
onYChanged: if (tooltipWindow.visible) tooltipWindow._showNow()
onWidthChanged: if (tooltipWindow.visible) tooltipWindow._showNow()
onHeightChanged: if (tooltipWindow.visible) tooltipWindow._showNow()
target: tooltipWindow.targetItem
function onXChanged() {
if (tooltipWindow.visible) tooltipWindow._showNow()
}
function onYChanged() {
if (tooltipWindow.visible) tooltipWindow._showNow()
}
function onWidthChanged() {
if (tooltipWindow.visible) tooltipWindow._showNow()
}
function onHeightChanged() {
if (tooltipWindow.visible) tooltipWindow._showNow()
}
}
Component.onCompleted: console.log("Tooltip window loaded")
Rectangle {
anchors.fill: parent
radius: 6
color: "#222"
border.color: Theme.border || "#444"
border.color: Theme.backgroundTertiary || "#444"
border.width: 1
opacity: 0.97
z: 1

View file

@ -1,11 +1,10 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick
import QtQuick.Layouts
import qs.Settings
Item {
id: root
property var tabsModel: [] // [{icon: "videocam", label: "Video"}, ...]
property var tabsModel: []
property int currentIndex: 0
signal tabChanged(int index)
@ -16,17 +15,20 @@ Item {
Repeater {
model: root.tabsModel
delegate: Column {
width: 56
spacing: 2
delegate: Rectangle {
id: tabWrapper
implicitHeight: tab.height
implicitWidth: 56
color: "transparent"
property bool hovered: false
MouseArea {
anchors.fill: parent
onClicked: {
if (root.currentIndex !== index) {
root.currentIndex = index;
root.tabChanged(index);
if (currentIndex !== index) {
currentIndex = index;
tabChanged(index);
}
}
cursorShape: Qt.PointingHandCursor
@ -35,43 +37,41 @@ Item {
onExited: parent.hovered = false
}
// Icon
Text {
text: modelData.icon
font.family: "Material Symbols Outlined"
font.pixelSize: 22
color: index === root.currentIndex
? (Theme ? Theme.accentPrimary : "#7C3AED")
: parent.hovered
? (Theme ? Theme.accentPrimary : "#7C3AED")
: (Theme ? Theme.textSecondary : "#444")
anchors.horizontalCenter: parent.horizontalCenter
}
ColumnLayout {
id: tab
spacing: 2
anchors.centerIn: parent
Layout.fillWidth: true
Layout.fillHeight: true
// Label
Text {
text: modelData.label
font.pixelSize: 12
font.bold: index === root.currentIndex
color: index === root.currentIndex
? (Theme ? Theme.accentPrimary : "#7C3AED")
: parent.hovered
? (Theme ? Theme.accentPrimary : "#7C3AED")
: (Theme ? Theme.textSecondary : "#444")
anchors.horizontalCenter: parent.horizontalCenter
}
// Icon
Text {
text: modelData.icon
font.family: "Material Symbols Outlined"
font.pixelSize: 22
color: index === root.currentIndex ? (Theme ? Theme.accentPrimary : "#7C3AED") : tabWrapper.hovered ? (Theme ? Theme.accentPrimary : "#7C3AED") : (Theme ? Theme.textSecondary : "#444")
Layout.alignment: Qt.AlignCenter
}
// Underline for active tab
Rectangle {
width: 24
height: 2
radius: 1
color: index === root.currentIndex
? (Theme ? Theme.accentPrimary : "#7C3AED")
: "transparent"
anchors.horizontalCenter: parent.horizontalCenter
// Label
Text {
text: modelData.label
font.pixelSize: 12
font.bold: index === root.currentIndex
color: index === root.currentIndex ? (Theme ? Theme.accentPrimary : "#7C3AED") : tabWrapper.hovered ? (Theme ? Theme.accentPrimary : "#7C3AED") : (Theme ? Theme.textSecondary : "#444")
Layout.alignment: Qt.AlignCenter
}
// Underline for active tab
Rectangle {
width: 24
height: 2
radius: 1
color: index === root.currentIndex ? (Theme ? Theme.accentPrimary : "#7C3AED") : "transparent"
Layout.alignment: Qt.AlignCenter
}
}
}
}
}
}
}