updated config

This commit is contained in:
2026-08-31 12:13:13 -05:00
parent b7bf86aab7
commit d3cbe74a4f
27 changed files with 2087 additions and 1394 deletions
@@ -7,222 +7,241 @@ import QtQuick.Layouts
import Quickshell
Item {
id: root
id: root
property var pluginApi: null
property var pluginApi: null
property ShellScreen screen
property string widgetId: ""
property string section: ""
property int sectionWidgetIndex: -1
property int sectionWidgetsCount: 0
property ShellScreen screen
property string widgetId: ""
property string section: ""
property int sectionWidgetIndex: -1
property int sectionWidgetsCount: 0
// ── Configuration ──
property string txSpeed: (SystemStatService.formatSpeed(SystemStatService.txSpeed).replace(/([0-9.]+)([A-Za-z]+)/, "$1 $2") + "/s").padStart(8, " ")
property string rxSpeed: (SystemStatService.formatSpeed(SystemStatService.rxSpeed).replace(/([0-9.]+)([A-Za-z]+)/, "$1 $2") + "/s").padStart(8, " ")
property var cfg: pluginApi?.pluginSettings || ({})
property var defaults: pluginApi?.manifest?.metadata?.defaultSettings || ({})
// ── Configuration ──
property string arrowType: cfg.arrowType ?? defaults.arrowType
property var cfg: pluginApi?.pluginSettings || ({})
property var defaults: pluginApi?.manifest?.metadata?.defaultSettings || ({})
property bool useCustomColors: cfg.useCustomColors ?? defaults.useCustomColors
property bool showNumbers: cfg.showNumbers ?? defaults.showNumbers
property string iconType: cfg.iconType ?? defaults.iconType
property int byteThresholdActive: cfg.byteThresholdActive ?? defaults.byteThresholdActive
property string layout: cfg.layout ?? defaults.layout
property var slots: cfg.slots ?? defaults.slots
property color colorSilent: root.useCustomColors && cfg.colorSilent || Color.mSurfaceVariant
property color colorTx: root.useCustomColors && cfg.colorTx || Color.mSecondary
property color colorRx: root.useCustomColors && cfg.colorRx || Color.mPrimary
property color colorText: root.useCustomColors && cfg.colorText || Color.mOnSurfaceVariant
property real fontSizeModifier: cfg.fontSizeModifier ?? defaults.fontSizeModifier
property real iconSizeModifier: cfg.iconSizeModifier ?? defaults.iconSizeModifier
property int byteThresholdActive: cfg.byteThresholdActive ?? defaults.byteThresholdActive
property real fontSizeModifier: cfg.fontSizeModifier ?? defaults.fontSizeModifier
property real iconSizeModifier: cfg.iconSizeModifier ?? defaults.iconSizeModifier
property real spacingInbetween: cfg.spacingInbetween ?? defaults.spacingInbetween
property real contentMargin: cfg.contentMargin ?? defaults.contentMargin ?? Style.marginS
property real columnSpacing: cfg.columnSpacing ?? defaults.columnSpacing
property real rowSpacing: cfg.rowSpacing ?? defaults.rowSpacing
property real paddingLeft: cfg.paddingLeft ?? defaults.paddingLeft
property real paddingRight: cfg.paddingRight ?? defaults.paddingRight
property bool useCustomFont: cfg.useCustomFont ?? defaults.useCustomFont
property string customFontFamily: cfg.customFontFamily ?? defaults.customFontFamily
property bool customFontBold: cfg.customFontBold ?? defaults.customFontBold
property bool customFontItalic: cfg.customFontItalic ?? defaults.customFontItalic
property bool useCustomColors: cfg.useCustomColors ?? defaults.useCustomColors
property color colorSilent: root.useCustomColors && cfg.colorSilent || Color.mSurfaceVariant
property color colorTx: root.useCustomColors && cfg.colorTx || Color.mSecondary
property color colorRx: root.useCustomColors && cfg.colorRx || Color.mPrimary
property color colorText: root.useCustomColors && cfg.colorText || Color.mOnSurfaceVariant
property bool horizontalNumbers: cfg.horizontalLayout ?? defaults.horizontalLayout
property bool useCustomFont: cfg.useCustomFont ?? defaults.useCustomFont
property string customFontFamily: cfg.customFontFamily ?? defaults.customFontFamily
property bool customFontBold: cfg.customFontBold ?? defaults.customFontBold
property bool customFontItalic: cfg.customFontItalic ?? defaults.customFontItalic
readonly property string resolvedFontFamily: {
if (root.useCustomFont && root.customFontFamily)
return root.customFontFamily;
return Settings.data.ui.fontDefault;
readonly property string resolvedFontFamily: {
if (root.useCustomFont && root.customFontFamily)
return root.customFontFamily;
return Settings.data.ui.fontDefault;
}
readonly property int resolvedFontWeight: {
if (root.useCustomFont && root.customFontBold)
return Font.Bold;
return Style.fontWeightMedium;
}
readonly property bool resolvedFontItalic: root.useCustomFont && root.customFontItalic
// ── Widget ──
property bool txActive: SystemStatService.txSpeed >= root.byteThresholdActive
property bool rxActive: SystemStatService.rxSpeed >= root.byteThresholdActive
property string barPosition: Settings.data.bar.position || "top"
property string barDensity: Settings.data.bar.density || "compact"
property bool barIsSpacious: barDensity != "mini"
property bool barIsVertical: barPosition === "left" || barPosition === "right"
readonly property real contentWidth: barIsVertical ? Style.capsuleHeight : content.implicitWidth + root.paddingLeft + root.paddingRight
readonly property real contentHeight: barIsVertical ? Math.round(content.implicitHeight + Style.marginM * 2) : Style.capsuleHeight
implicitWidth: contentWidth
implicitHeight: contentHeight
NIcon {
id: txIconElement
icon: root.iconType + "-up"
color: root.txActive ? root.colorTx : root.colorSilent
pointSize: Style.fontSizeL * root.iconSizeModifier
}
NIcon {
id: rxIconElement
icon: root.iconType + "-down"
color: root.rxActive ? root.colorRx : root.colorSilent
pointSize: Style.fontSizeL * root.iconSizeModifier
}
NText {
id: txSpeedElement
text: root.txSpeed
color: root.colorText
pointSize: Style.barFontSize * root.fontSizeModifier
font.family: root.resolvedFontFamily
font.weight: root.resolvedFontWeight
font.italic: root.resolvedFontItalic
}
NText {
id: rxSpeedElement
text: root.rxSpeed
color: root.colorText
pointSize: Style.barFontSize * root.fontSizeModifier
font.family: root.resolvedFontFamily
font.weight: root.resolvedFontWeight
font.italic: root.resolvedFontItalic
}
function getElement(name) {
switch (name) {
case "txIcon":
return txIconElement;
case "rxIcon":
return rxIconElement;
case "txSpeed":
return txSpeedElement;
case "rxSpeed":
return rxSpeedElement;
default:
return null;
}
}
readonly property var spacers: [spacer0, spacer1, spacer2, spacer3]
Item {
id: spacer0
}
Item {
id: spacer1
}
Item {
id: spacer2
}
Item {
id: spacer3
}
Rectangle {
id: visualCapsule
x: Style.pixelAlignCenter(parent.width, width)
y: Style.pixelAlignCenter(parent.height, height)
width: root.contentWidth
height: root.contentHeight
color: Style.capsuleColor
radius: Style.radiusM
border.color: Style.capsuleBorderColor
border.width: Style.capsuleBorderWidth
GridLayout {
id: content
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: root.paddingLeft
anchors.right: parent.right
anchors.rightMargin: root.paddingRight
rows: root.layout === "horizontal" ? 1 : 2
columns: root.layout === "horizontal" ? 4 : 2
columnSpacing: root.columnSpacing
rowSpacing: root.rowSpacing
}
}
function rebuildLayout() {
rxIconElement.parent = root;
rxIconElement.visible = false;
rxSpeedElement.parent = root;
rxSpeedElement.visible = false;
txIconElement.parent = root;
txIconElement.visible = false;
txSpeedElement.parent = root;
txSpeedElement.visible = false;
for (let s of spacers) {
s.parent = root;
s.visible = false;
}
readonly property int resolvedFontWeight: {
if (root.useCustomFont && root.customFontBold)
return Font.Bold;
return Style.fontWeightMedium;
for (let idx = 0; idx < root.slots.length; idx++) {
const elem = root.getElement(root.slots[idx]);
if (elem) {
elem.parent = content;
elem.visible = true;
} else {
const s = spacers[idx];
s.parent = content;
s.visible = true;
}
}
}
onSlotsChanged: rebuildLayout()
onLayoutChanged: rebuildLayout()
Component.onCompleted: rebuildLayout()
// ── Interaction ──
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onPressed: mouse => {
if (mouse.button == Qt.LeftButton)
pluginApi.togglePanel(root.screen, root);
if (mouse.button == Qt.RightButton)
PanelService.showContextMenu(contextMenu, root, screen);
}
readonly property bool resolvedFontItalic: root.useCustomFont && root.customFontItalic
NPopupContextMenu {
id: contextMenu
readonly property bool numbersVisible: root.showNumbers && barIsSpacious && !barIsVertical
model: [
{
"label": root.pluginApi?.tr("actions.toggle-panel"),
"action": "toggle-panel",
"icon": "activity"
},
{
"label": root.pluginApi?.tr("actions.widget-settings"),
"action": "widget-settings",
"icon": "settings"
},
]
property string barPosition: Settings.data.bar.position || "top"
property string barDensity: Settings.data.bar.density || "compact"
property bool barIsSpacious: barDensity != "mini"
property bool barIsVertical: barPosition === "left" || barPosition === "right"
onTriggered: action => {
contextMenu.close();
PanelService.closeContextMenu(screen);
readonly property real contentWidth: barIsVertical ? Style.capsuleHeight : contentRow.implicitWidth + root.contentMargin * 2
readonly property real contentHeight: barIsVertical ? Math.round(contentRow.implicitHeight + Style.marginM * 2) : Style.capsuleHeight
implicitWidth: contentWidth
implicitHeight: contentHeight
// ── Widget ──
property string txSpeed: (SystemStatService.formatSpeed(SystemStatService.txSpeed).replace(/([0-9.]+)([A-Za-z]+)/, "$1 $2") + "/s").padStart(8, " ")
property string rxSpeed: (SystemStatService.formatSpeed(SystemStatService.rxSpeed).replace(/([0-9.]+)([A-Za-z]+)/, "$1 $2") + "/s").padStart(8, " ")
Rectangle {
id: visualCapsule
x: Style.pixelAlignCenter(parent.width, width)
y: Style.pixelAlignCenter(parent.height, height)
width: root.contentWidth
height: root.contentHeight
color: Style.capsuleColor
radius: Style.radiusM
border.color: Style.capsuleBorderColor
border.width: Style.capsuleBorderWidth
RowLayout {
id: contentRow
anchors.centerIn: parent
spacing: Style.marginS
// Vertical layout: stacked values to the left
Column {
visible: root.numbersVisible && !root.horizontalNumbers
spacing: root.spacingInbetween
NText {
horizontalAlignment: Text.AlignRight
text: root.txSpeed
color: root.colorText
pointSize: Style.barFontSize * root.fontSizeModifier
font.family: root.resolvedFontFamily
font.weight: root.resolvedFontWeight
font.italic: root.resolvedFontItalic
}
NText {
horizontalAlignment: Text.AlignRight
text: root.rxSpeed
color: root.colorText
pointSize: Style.barFontSize * root.fontSizeModifier
font.family: root.resolvedFontFamily
font.weight: root.resolvedFontWeight
font.italic: root.resolvedFontItalic
}
}
// Horizontal layout: TX value left
NText {
visible: root.numbersVisible && root.horizontalNumbers
horizontalAlignment: Text.AlignRight
text: root.rxSpeed
color: root.colorText
pointSize: Style.barFontSize * root.fontSizeModifier
font.family: root.resolvedFontFamily
font.weight: root.resolvedFontWeight
font.italic: root.resolvedFontItalic
}
// Icons
Column {
spacing: -10.0 + root.spacingInbetween
NIcon {
icon: arrowType + "-up"
color: SystemStatService.txSpeed >= root.byteThresholdActive ? root.colorTx : root.colorSilent
pointSize: Style.fontSizeL * root.iconSizeModifier
}
NIcon {
icon: arrowType + "-down"
color: SystemStatService.rxSpeed >= root.byteThresholdActive ? root.colorRx : root.colorSilent
pointSize: Style.fontSizeL * root.iconSizeModifier
}
}
// Horizontal layout: RX value right
NText {
visible: root.numbersVisible && root.horizontalNumbers
horizontalAlignment: Text.AlignLeft
text: root.txSpeed
color: root.colorText
pointSize: Style.barFontSize * root.fontSizeModifier
font.family: root.resolvedFontFamily
font.weight: root.resolvedFontWeight
font.italic: root.resolvedFontItalic
}
}
}
// ── Interaction ──
HoverHandler {
id: hoverHandler
onHoveredChanged: {
if (hovered) {
closeTimer.stop();
hoverTimer.start();
} else {
hoverTimer.stop();
closeTimer.start();
}
}
}
Timer {
id: hoverTimer
interval: 500
onTriggered: {
if (hoverHandler.hovered && root.pluginApi && !pluginApi.panelOpenScreen)
pluginApi.openPanel(root.screen, root);
}
}
Timer {
id: closeTimer
interval: 250
onTriggered: {
if (!hoverHandler.hovered && root.pluginApi && pluginApi.panelOpenScreen)
pluginApi.togglePanel(root.screen, root);
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onPressed: mouse => {
if (mouse.button == Qt.RightButton)
PanelService.showContextMenu(contextMenu, root, screen);
}
NPopupContextMenu {
id: contextMenu
model: [
{
"label": root.pluginApi?.tr("actions.widget-settings"),
"action": "widget-settings",
"icon": "settings"
},
]
onTriggered: action => {
contextMenu.close();
PanelService.closeContextMenu(screen);
if (action === "widget-settings") {
BarService.openPluginSettings(screen, pluginApi.manifest);
}
}
if (action === "toggle-panel")
pluginApi.togglePanel(root.screen, root);
else if (action === "widget-settings") {
BarService.openPluginSettings(screen, pluginApi.manifest);
}
}
}
}
}