mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2026-08-15 18:43:59 +00:00
Merge branch 'noctalia-dev:main' into main
This commit is contained in:
@@ -102,6 +102,7 @@ Variants {
|
||||
model: Settings.data.bar.widgets.left
|
||||
delegate: BarWidgetLoader {
|
||||
widgetId: (modelData.id !== undefined ? modelData.id : "")
|
||||
barDensity: Settings.data.bar.density
|
||||
widgetProps: {
|
||||
"screen": root.modelData || null,
|
||||
"widgetId": modelData.id,
|
||||
@@ -124,6 +125,7 @@ Variants {
|
||||
model: Settings.data.bar.widgets.center
|
||||
delegate: BarWidgetLoader {
|
||||
widgetId: (modelData.id !== undefined ? modelData.id : "")
|
||||
barDensity: Settings.data.bar.density
|
||||
widgetProps: {
|
||||
"screen": root.modelData || null,
|
||||
"widgetId": modelData.id,
|
||||
@@ -147,6 +149,7 @@ Variants {
|
||||
model: Settings.data.bar.widgets.right
|
||||
delegate: BarWidgetLoader {
|
||||
widgetId: (modelData.id !== undefined ? modelData.id : "")
|
||||
barDensity: Settings.data.bar.density
|
||||
widgetProps: {
|
||||
"screen": root.modelData || null,
|
||||
"widgetId": modelData.id,
|
||||
@@ -180,6 +183,7 @@ Variants {
|
||||
model: Settings.data.bar.widgets.left
|
||||
delegate: BarWidgetLoader {
|
||||
widgetId: (modelData.id !== undefined ? modelData.id : "")
|
||||
barDensity: Settings.data.bar.density
|
||||
widgetProps: {
|
||||
"screen": root.modelData || null,
|
||||
"widgetId": modelData.id,
|
||||
@@ -204,6 +208,7 @@ Variants {
|
||||
model: Settings.data.bar.widgets.center
|
||||
delegate: BarWidgetLoader {
|
||||
widgetId: (modelData.id !== undefined ? modelData.id : "")
|
||||
barDensity: Settings.data.bar.density
|
||||
widgetProps: {
|
||||
"screen": root.modelData || null,
|
||||
"widgetId": modelData.id,
|
||||
@@ -229,6 +234,7 @@ Variants {
|
||||
model: Settings.data.bar.widgets.right
|
||||
delegate: BarWidgetLoader {
|
||||
widgetId: (modelData.id !== undefined ? modelData.id : "")
|
||||
barDensity: Settings.data.bar.density
|
||||
widgetProps: {
|
||||
"screen": root.modelData || null,
|
||||
"widgetId": modelData.id,
|
||||
|
||||
@@ -109,7 +109,7 @@ ColumnLayout {
|
||||
|
||||
NIcon {
|
||||
visible: modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked
|
||||
text: BluetoothService.getSignalIcon(modelData)
|
||||
icon: BluetoothService.getSignalIcon(modelData)
|
||||
pointSize: Style.fontSizeXS
|
||||
color: getContentColor(Color.mOnSurface)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ NPanel {
|
||||
|
||||
readonly property int firstDayOfWeek: Qt.locale().firstDayOfWeek
|
||||
property bool isCurrentMonth: checkIsCurrentMonth()
|
||||
readonly property bool weatherReady: (LocationService.data.weather !== null)
|
||||
readonly property bool weatherReady: Settings.data.location.weatherEnabled && (LocationService.data.weather !== null)
|
||||
|
||||
function checkIsCurrentMonth() {
|
||||
return (Time.date.getMonth() === grid.month) && (Time.date.getFullYear() === grid.year)
|
||||
@@ -78,12 +78,13 @@ NPanel {
|
||||
|
||||
// Weather icon and temperature
|
||||
ColumnLayout {
|
||||
visible: Settings.data.location.weatherEnabled && weatherReady
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
spacing: Style.marginXXS
|
||||
|
||||
NIcon {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
icon: weatherReady ? LocationService.weatherSymbolFromCode(LocationService.data.weather.current_weather.weathercode) : "cloud"
|
||||
icon: Settings.data.location.weatherEnabled && weatherReady ? LocationService.weatherSymbolFromCode(LocationService.data.weather.current_weather.weathercode) : ""
|
||||
pointSize: Style.fontSizeXXL
|
||||
color: Color.mOnPrimary
|
||||
}
|
||||
@@ -91,6 +92,8 @@ NPanel {
|
||||
NText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: {
|
||||
if (!Settings.data.location.weatherEnabled)
|
||||
return ""
|
||||
if (!weatherReady)
|
||||
return ""
|
||||
var temp = LocationService.data.weather.current_weather.temperature
|
||||
@@ -168,6 +171,8 @@ NPanel {
|
||||
|
||||
NText {
|
||||
text: {
|
||||
if (!Settings.data.location.weatherEnabled)
|
||||
return ""
|
||||
if (!weatherReady)
|
||||
return I18n.tr("calendar.weather.loading")
|
||||
const chunks = Settings.data.location.name.split(",")
|
||||
@@ -323,7 +328,7 @@ NPanel {
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
visible: !weatherReady
|
||||
visible: Settings.data.location.weatherEnabled && !weatherReady
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
NBusyIndicator {}
|
||||
|
||||
@@ -67,7 +67,9 @@ Item {
|
||||
Connections {
|
||||
target: root
|
||||
function onTooltipTextChanged() {
|
||||
TooltipService.updateText(root.tooltipText)
|
||||
if (hovered) {
|
||||
TooltipService.updateText(root.tooltipText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,9 @@ Item {
|
||||
Connections {
|
||||
target: root
|
||||
function onTooltipTextChanged() {
|
||||
TooltipService.updateText(root.tooltipText)
|
||||
if (hovered) {
|
||||
TooltipService.updateText(root.tooltipText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ Item {
|
||||
property string section: widgetProps && widgetProps.section || ""
|
||||
property int sectionIndex: widgetProps && widgetProps.sectionWidgetIndex || 0
|
||||
|
||||
property string barDensity: "default"
|
||||
readonly property real scaling: barDensity === "mini" ? 0.8 : (barDensity === "compact" ? 0.9 : 1.0)
|
||||
|
||||
// Don't reserve space unless the loaded widget is really visible
|
||||
implicitWidth: getImplicitSize(loader.item, "implicitWidth")
|
||||
implicitHeight: getImplicitSize(loader.item, "implicitHeight")
|
||||
@@ -40,6 +43,12 @@ Item {
|
||||
item[prop] = widgetProps[prop]
|
||||
}
|
||||
}
|
||||
// Explicitly set scaling property
|
||||
if (item.hasOwnProperty("scaling")) {
|
||||
item.scaling = Qt.binding(function () {
|
||||
return root.scaling
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Register this widget instance with BarService
|
||||
@@ -51,7 +60,7 @@ Item {
|
||||
item.onLoaded()
|
||||
}
|
||||
|
||||
//Logger.log("BarWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name)
|
||||
//Logger.i("BarWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name)
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
@@ -67,7 +76,7 @@ Item {
|
||||
// Error handling
|
||||
onWidgetIdChanged: {
|
||||
if (widgetId && !BarWidgetRegistry.hasWidget(widgetId)) {
|
||||
Logger.warn("BarWidgetLoader", "Widget not found in registry:", widgetId)
|
||||
Logger.w("BarWidgetLoader", "Widget not found in registry:", widgetId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,12 +30,12 @@ PopupWindow {
|
||||
|
||||
function showAt(item, x, y) {
|
||||
if (!item) {
|
||||
Logger.warn("TrayMenu", "anchorItem is undefined, won't show menu.")
|
||||
Logger.w("TrayMenu", "anchorItem is undefined, won't show menu.")
|
||||
return
|
||||
}
|
||||
|
||||
if (!opener.children || opener.children.values.length === 0) {
|
||||
//Logger.warn("TrayMenu", "Menu not ready, delaying show")
|
||||
//Logger.w("TrayMenu", "Menu not ready, delaying show")
|
||||
Qt.callLater(() => showAt(item, x, y))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ Item {
|
||||
property string section: ""
|
||||
property int sectionWidgetIndex: -1
|
||||
property int sectionWidgetsCount: 0
|
||||
property real scaling: 1.0
|
||||
|
||||
property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId]
|
||||
property var widgetSettings: {
|
||||
@@ -34,7 +35,10 @@ Item {
|
||||
readonly property bool showIcon: (widgetSettings.showIcon !== undefined) ? widgetSettings.showIcon : widgetMetadata.showIcon
|
||||
readonly property string hideMode: (widgetSettings.hideMode !== undefined) ? widgetSettings.hideMode : widgetMetadata.hideMode
|
||||
readonly property string scrollingMode: (widgetSettings.scrollingMode !== undefined) ? widgetSettings.scrollingMode : (widgetMetadata.scrollingMode !== undefined ? widgetMetadata.scrollingMode : "hover")
|
||||
readonly property int widgetWidth: (widgetSettings.width !== undefined) ? widgetSettings.width : Math.max(widgetMetadata.width, screen.width * 0.06)
|
||||
|
||||
// Maximum widget width with user settings support
|
||||
readonly property real maxWidth: (widgetSettings.maxWidth !== undefined) ? widgetSettings.maxWidth : Math.max(widgetMetadata.maxWidth, screen ? screen.width * 0.06 : 0)
|
||||
readonly property bool useFixedWidth: (widgetSettings.useFixedWidth !== undefined) ? widgetSettings.useFixedWidth : widgetMetadata.useFixedWidth
|
||||
|
||||
readonly property bool isVerticalBar: (Settings.data.bar.position === "left" || Settings.data.bar.position === "right")
|
||||
readonly property bool hasFocusedWindow: CompositorService.getFocusedWindow() !== null
|
||||
@@ -42,7 +46,7 @@ Item {
|
||||
readonly property string fallbackIcon: "user-desktop"
|
||||
|
||||
implicitHeight: visible ? (isVerticalBar ? calculatedVerticalDimension() : Style.barHeight) : 0
|
||||
implicitWidth: visible ? (isVerticalBar ? calculatedVerticalDimension() : widgetWidth) : 0
|
||||
implicitWidth: visible ? (isVerticalBar ? calculatedVerticalDimension() : dynamicWidth) : 0
|
||||
|
||||
// "visible": Always Visible, "hidden": Hide When Empty, "transparent": Transparent When Empty
|
||||
visible: hideMode !== "hidden" || hasFocusedWindow
|
||||
@@ -55,8 +59,44 @@ Item {
|
||||
}
|
||||
|
||||
function calculatedVerticalDimension() {
|
||||
const ratio = (Settings.data.bar.density === "mini") ? 0.67 : 0.8
|
||||
return Math.round(Style.baseWidgetSize * ratio)
|
||||
return Math.round((Style.baseWidgetSize - 5) * scaling)
|
||||
}
|
||||
|
||||
function calculateContentWidth() {
|
||||
// Calculate the actual content width based on visible elements
|
||||
var contentWidth = 0
|
||||
var margins = Style.marginS * scaling * 2 // Left and right margins
|
||||
|
||||
// Icon width (if visible)
|
||||
if (showIcon) {
|
||||
contentWidth += 18 * scaling
|
||||
contentWidth += Style.marginS * scaling // Spacing after icon
|
||||
}
|
||||
|
||||
// Text width (use the measured width)
|
||||
contentWidth += fullTitleMetrics.contentWidth
|
||||
|
||||
// Additional small margin for text
|
||||
contentWidth += Style.marginXXS * 2
|
||||
|
||||
// Add container margins
|
||||
contentWidth += margins
|
||||
|
||||
return Math.ceil(contentWidth)
|
||||
}
|
||||
|
||||
// Dynamic width: adapt to content but respect maximum width setting
|
||||
readonly property real dynamicWidth: {
|
||||
// If using fixed width mode, always use maxWidth
|
||||
if (useFixedWidth) {
|
||||
return maxWidth
|
||||
}
|
||||
// Otherwise, adapt to content
|
||||
if (!hasFocusedWindow) {
|
||||
return maxWidth
|
||||
}
|
||||
// Use content width but don't exceed user-set maximum width
|
||||
return Math.min(calculateContentWidth(), maxWidth)
|
||||
}
|
||||
|
||||
function getAppIcon() {
|
||||
@@ -72,7 +112,7 @@ Item {
|
||||
return iconResult
|
||||
}
|
||||
} catch (iconError) {
|
||||
Logger.warn("ActiveWindow", "Error getting icon from CompositorService:", iconError)
|
||||
Logger.w("ActiveWindow", "Error getting icon from CompositorService:", iconError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,14 +130,14 @@ Item {
|
||||
}
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
Logger.warn("ActiveWindow", "Error getting icon from ToplevelManager:", fallbackError)
|
||||
Logger.w("ActiveWindow", "Error getting icon from ToplevelManager:", fallbackError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ThemeIcons.iconFromName(fallbackIcon)
|
||||
} catch (e) {
|
||||
Logger.warn("ActiveWindow", "Error in getAppIcon:", e)
|
||||
Logger.w("ActiveWindow", "Error in getAppIcon:", e)
|
||||
return ThemeIcons.iconFromName(fallbackIcon)
|
||||
}
|
||||
}
|
||||
@@ -107,7 +147,7 @@ Item {
|
||||
id: fullTitleMetrics
|
||||
visible: false
|
||||
text: windowTitle
|
||||
pointSize: Style.fontSizeS
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
applyUiScale: false
|
||||
font.weight: Style.fontWeightMedium
|
||||
}
|
||||
@@ -117,29 +157,37 @@ Item {
|
||||
visible: root.visible
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: isVerticalBar ? root.width : widgetWidth
|
||||
width: isVerticalBar ? root.width : dynamicWidth
|
||||
height: isVerticalBar ? width : Style.capsuleHeight
|
||||
radius: isVerticalBar ? width / 2 : Style.radiusM
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
// Smooth width transition
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.InOutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: mainContainer
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: isVerticalBar ? 0 : Style.marginS
|
||||
anchors.rightMargin: isVerticalBar ? 0 : Style.marginS
|
||||
anchors.leftMargin: isVerticalBar ? 0 : Style.marginS * scaling
|
||||
anchors.rightMargin: isVerticalBar ? 0 : Style.marginS * scaling
|
||||
|
||||
// Horizontal layout for top/bottom bars
|
||||
RowLayout {
|
||||
id: rowLayout
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Style.marginS
|
||||
spacing: Style.marginS * scaling
|
||||
visible: !isVerticalBar
|
||||
z: 1
|
||||
|
||||
// Window icon
|
||||
Item {
|
||||
Layout.preferredWidth: 18
|
||||
Layout.preferredHeight: 18
|
||||
Layout.preferredWidth: 18 * scaling
|
||||
Layout.preferredHeight: 18 * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: showIcon
|
||||
|
||||
@@ -254,7 +302,7 @@ Item {
|
||||
NText {
|
||||
id: titleText
|
||||
text: windowTitle
|
||||
pointSize: Style.fontSizeS
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
applyUiScale: false
|
||||
font.weight: Style.fontWeightMedium
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -265,7 +313,7 @@ Item {
|
||||
NText {
|
||||
text: windowTitle
|
||||
font: titleText.font
|
||||
pointSize: Style.fontSizeS
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
applyUiScale: false
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mOnSurface
|
||||
@@ -316,7 +364,7 @@ Item {
|
||||
|
||||
// Window icon
|
||||
Item {
|
||||
width: Style.baseWidgetSize * 0.5
|
||||
width: Style.baseWidgetSize * 0.5 * scaling
|
||||
height: width
|
||||
anchors.centerIn: parent
|
||||
visible: windowTitle !== ""
|
||||
@@ -367,7 +415,7 @@ Item {
|
||||
windowIcon.source = Qt.binding(getAppIcon)
|
||||
windowIconVertical.source = Qt.binding(getAppIcon)
|
||||
} catch (e) {
|
||||
Logger.warn("ActiveWindow", "Error in onActiveWindowChanged:", e)
|
||||
Logger.w("ActiveWindow", "Error in onActiveWindowChanged:", e)
|
||||
}
|
||||
}
|
||||
function onWindowListChanged() {
|
||||
@@ -375,7 +423,7 @@ Item {
|
||||
windowIcon.source = Qt.binding(getAppIcon)
|
||||
windowIconVertical.source = Qt.binding(getAppIcon)
|
||||
} catch (e) {
|
||||
Logger.warn("ActiveWindow", "Error in onWindowListChanged:", e)
|
||||
Logger.w("ActiveWindow", "Error in onWindowListChanged:", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,28 +103,41 @@ Item {
|
||||
return lines.join("\n")
|
||||
}
|
||||
if (!isReady || !battery.isLaptopBattery) {
|
||||
return "No battery detected."
|
||||
return I18n.tr("battery.no-battery-detected")
|
||||
}
|
||||
if (battery.timeToEmpty > 0) {
|
||||
lines.push(`Time left: ${Time.formatVagueHumanReadableDuration(battery.timeToEmpty)}.`)
|
||||
lines.push(I18n.tr("battery.time-left", {
|
||||
"time": Time.formatVagueHumanReadableDuration(battery.timeToEmpty)
|
||||
}))
|
||||
}
|
||||
if (battery.timeToFull > 0) {
|
||||
lines.push(`Time until full: ${Time.formatVagueHumanReadableDuration(battery.timeToFull)}.`)
|
||||
lines.push(I18n.tr("battery.time-until-full", {
|
||||
"time": Time.formatVagueHumanReadableDuration(battery.timeToFull)
|
||||
}))
|
||||
}
|
||||
if (battery.changeRate !== undefined) {
|
||||
const rate = battery.changeRate
|
||||
if (rate > 0) {
|
||||
lines.push(charging ? "Charging rate: " + rate.toFixed(2) + " W." : "Discharging rate: " + rate.toFixed(2) + " W.")
|
||||
lines.push(charging ? I18n.tr("battery.charging-rate", {
|
||||
"rate": rate.toFixed(2)
|
||||
}) : I18n.tr("battery.discharging-rate", {
|
||||
"rate": rate.toFixed(2)
|
||||
}))
|
||||
} else if (rate < 0) {
|
||||
lines.push("Discharging rate: " + Math.abs(rate).toFixed(2) + " W.")
|
||||
lines.push(I18n.tr("battery.discharging-rate", {
|
||||
"rate": Math.abs(rate).toFixed(2)
|
||||
}))
|
||||
} else {
|
||||
lines.push("Estimating...")
|
||||
// Rate is 0 - check if plugged in (charging state) or idle
|
||||
lines.push(charging ? I18n.tr("battery.plugged-in") : I18n.tr("battery.idle"))
|
||||
}
|
||||
} else {
|
||||
lines.push(charging ? "Charging." : "Discharging.")
|
||||
lines.push(charging ? I18n.tr("battery.charging") : I18n.tr("battery.discharging"))
|
||||
}
|
||||
if (battery.healthPercentage !== undefined && battery.healthPercentage > 0) {
|
||||
lines.push("Health: " + Math.round(battery.healthPercentage) + "%")
|
||||
lines.push(I18n.tr("battery.health", {
|
||||
"percent": Math.round(battery.healthPercentage)
|
||||
}))
|
||||
}
|
||||
return lines.join("\n")
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ Rectangle {
|
||||
property string section: ""
|
||||
property int sectionWidgetIndex: -1
|
||||
property int sectionWidgetsCount: 0
|
||||
property real scaling: 1.0
|
||||
|
||||
property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId]
|
||||
property var widgetSettings: {
|
||||
@@ -66,11 +67,13 @@ Rectangle {
|
||||
visible: text !== ""
|
||||
text: modelData
|
||||
family: useCustomFont && customFont ? customFont : Settings.data.ui.fontDefault
|
||||
pointSize: {
|
||||
if (repeater.model.length == 1) {
|
||||
return Style.fontSizeS
|
||||
} else {
|
||||
return (index == 0) ? Style.fontSizeXS : Style.fontSizeXXS
|
||||
Binding on pointSize {
|
||||
value: {
|
||||
if (repeater.model.length == 1) {
|
||||
return Style.fontSizeS * scaling
|
||||
} else {
|
||||
return (index == 0) ? Style.fontSizeXS * scaling : Style.fontSizeXXS * scaling
|
||||
}
|
||||
}
|
||||
}
|
||||
applyUiScale: false
|
||||
@@ -97,8 +100,11 @@ Rectangle {
|
||||
visible: text !== ""
|
||||
text: modelData
|
||||
family: useCustomFont && customFont ? customFont : Settings.data.ui.fontDefault
|
||||
pointSize: Style.fontSizeS
|
||||
Binding on pointSize {
|
||||
value: Style.fontSizeS * scaling
|
||||
}
|
||||
applyUiScale: false
|
||||
|
||||
font.weight: Style.fontWeightBold
|
||||
color: usePrimaryColor ? Color.mPrimary : Color.mOnSurface
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
@@ -56,7 +56,7 @@ NIconButton {
|
||||
if (customIconPath !== "")
|
||||
return customIconPath.startsWith("file://") ? customIconPath : "file://" + customIconPath
|
||||
if (useDistroLogo)
|
||||
return DistroLogoService.osLogo
|
||||
return DistroService.osLogo
|
||||
return ""
|
||||
}
|
||||
visible: source !== ""
|
||||
|
||||
@@ -112,7 +112,7 @@ Item {
|
||||
function onClicked() {
|
||||
if (leftClickExec) {
|
||||
Quickshell.execDetached(["sh", "-c", leftClickExec])
|
||||
Logger.log("CustomButton", `Executing command: ${leftClickExec}`)
|
||||
Logger.i("CustomButton", `Executing command: ${leftClickExec}`)
|
||||
} else if (!hasExec) {
|
||||
// No script was defined, open settings
|
||||
var settingsPanel = PanelService.getPanel("settingsPanel")
|
||||
@@ -124,14 +124,14 @@ Item {
|
||||
function onRightClicked() {
|
||||
if (rightClickExec) {
|
||||
Quickshell.execDetached(["sh", "-c", rightClickExec])
|
||||
Logger.log("CustomButton", `Executing command: ${rightClickExec}`)
|
||||
Logger.i("CustomButton", `Executing command: ${rightClickExec}`)
|
||||
}
|
||||
}
|
||||
|
||||
function onMiddleClicked() {
|
||||
if (middleClickExec) {
|
||||
Quickshell.execDetached(["sh", "-c", middleClickExec])
|
||||
Logger.log("CustomButton", `Executing command: ${middleClickExec}`)
|
||||
Logger.i("CustomButton", `Executing command: ${middleClickExec}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ Item {
|
||||
property string section: ""
|
||||
property int sectionWidgetIndex: -1
|
||||
property int sectionWidgetsCount: 0
|
||||
property real scaling: 1.0
|
||||
|
||||
property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId]
|
||||
property var widgetSettings: {
|
||||
@@ -37,8 +38,9 @@ Item {
|
||||
readonly property string visualizerType: (widgetSettings.visualizerType !== undefined && widgetSettings.visualizerType !== "") ? widgetSettings.visualizerType : widgetMetadata.visualizerType
|
||||
readonly property string scrollingMode: (widgetSettings.scrollingMode !== undefined) ? widgetSettings.scrollingMode : widgetMetadata.scrollingMode
|
||||
|
||||
// Fixed width - no expansion
|
||||
readonly property real widgetWidth: Math.max(145, screen.width * 0.06)
|
||||
// Maximum widget width with user settings support
|
||||
readonly property real maxWidth: (widgetSettings.maxWidth !== undefined) ? widgetSettings.maxWidth : Math.max(widgetMetadata.maxWidth, screen ? screen.width * 0.06 : 0)
|
||||
readonly property bool useFixedWidth: (widgetSettings.useFixedWidth !== undefined) ? widgetSettings.useFixedWidth : widgetMetadata.useFixedWidth
|
||||
|
||||
readonly property bool hasActivePlayer: MediaService.currentPlayer !== null
|
||||
readonly property string placeholderText: I18n.tr("bar.widget-settings.media-mini.no-active-player")
|
||||
@@ -59,7 +61,7 @@ Item {
|
||||
}
|
||||
|
||||
implicitHeight: visible ? (isVerticalBar ? calculatedVerticalDimension() : Style.barHeight) : 0
|
||||
implicitWidth: visible ? (isVerticalBar ? calculatedVerticalDimension() : widgetWidth) : 0
|
||||
implicitWidth: visible ? (isVerticalBar ? calculatedVerticalDimension() : dynamicWidth) : 0
|
||||
|
||||
// "visible": Always Visible, "hidden": Hide When Empty, "transparent": Transparent When Empty
|
||||
visible: hideMode !== "hidden" || hasActivePlayer
|
||||
@@ -76,8 +78,50 @@ Item {
|
||||
}
|
||||
|
||||
function calculatedVerticalDimension() {
|
||||
const ratio = (Settings.data.bar.density === "mini") ? 0.67 : 0.8
|
||||
return Math.round(Style.baseWidgetSize * ratio)
|
||||
return Math.round((Style.baseWidgetSize - 5) * scaling)
|
||||
}
|
||||
|
||||
function calculateContentWidth() {
|
||||
// Calculate the actual content width based on visible elements
|
||||
var contentWidth = 0
|
||||
var margins = Style.marginS * scaling * 2 // Left and right margins
|
||||
|
||||
// Icon or album art width
|
||||
if (!hasActivePlayer || !showAlbumArt) {
|
||||
// Icon width
|
||||
contentWidth += Style.fontSizeL * scaling
|
||||
} else if (showAlbumArt && hasActivePlayer) {
|
||||
// Album art width
|
||||
contentWidth += 21 * scaling
|
||||
}
|
||||
|
||||
// Spacing between icon/art and text
|
||||
contentWidth += Style.marginS * scaling
|
||||
|
||||
// Text width (use the measured width)
|
||||
contentWidth += fullTitleMetrics.contentWidth
|
||||
|
||||
// Additional small margin for text
|
||||
contentWidth += Style.marginXXS * 2
|
||||
|
||||
// Add container margins
|
||||
contentWidth += margins
|
||||
|
||||
return Math.ceil(contentWidth)
|
||||
}
|
||||
|
||||
// Dynamic width: adapt to content but respect maximum width setting
|
||||
readonly property real dynamicWidth: {
|
||||
// If using fixed width mode, always use maxWidth
|
||||
if (useFixedWidth) {
|
||||
return maxWidth
|
||||
}
|
||||
// Otherwise, adapt to content
|
||||
if (!hasActivePlayer) {
|
||||
return maxWidth
|
||||
}
|
||||
// Use content width but don't exceed user-set maximum width
|
||||
return Math.min(calculateContentWidth(), maxWidth)
|
||||
}
|
||||
|
||||
// A hidden text element to safely measure the full title width
|
||||
@@ -87,6 +131,7 @@ Item {
|
||||
text: titleText.text
|
||||
font: titleText.font
|
||||
applyUiScale: false
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -94,16 +139,24 @@ Item {
|
||||
visible: root.visible
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: isVerticalBar ? root.width : (widgetWidth)
|
||||
width: isVerticalBar ? root.width : dynamicWidth
|
||||
height: isVerticalBar ? width : Style.capsuleHeight
|
||||
radius: isVerticalBar ? width / 2 : Style.radiusM
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
// Smooth width transition
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.InOutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: mainContainer
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: isVerticalBar ? 0 : Style.marginS
|
||||
anchors.rightMargin: isVerticalBar ? 0 : Style.marginS
|
||||
anchors.leftMargin: isVerticalBar ? 0 : Style.marginS * scaling
|
||||
anchors.rightMargin: isVerticalBar ? 0 : Style.marginS * scaling
|
||||
|
||||
Loader {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -155,7 +208,7 @@ Item {
|
||||
id: rowLayout
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Style.marginS
|
||||
spacing: Style.marginS * scaling
|
||||
visible: !isVerticalBar
|
||||
z: 1 // Above the visualizer
|
||||
|
||||
@@ -163,7 +216,7 @@ Item {
|
||||
id: windowIcon
|
||||
icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "disc"
|
||||
color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant
|
||||
pointSize: Style.fontSizeL
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: !hasActivePlayer || (!showAlbumArt && !trackArt.visible)
|
||||
@@ -175,8 +228,8 @@ Item {
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: Math.round(21 * Style.uiScaleRatio)
|
||||
Layout.preferredHeight: Math.round(21 * Style.uiScaleRatio)
|
||||
Layout.preferredWidth: Math.round(21 * scaling)
|
||||
Layout.preferredHeight: Math.round(21 * scaling)
|
||||
|
||||
NImageCircled {
|
||||
id: trackArt
|
||||
@@ -288,7 +341,7 @@ Item {
|
||||
NText {
|
||||
id: titleText
|
||||
text: hasActivePlayer ? getTitle() : placeholderText
|
||||
pointSize: Style.fontSizeS
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
applyUiScale: false
|
||||
font.weight: Style.fontWeightMedium
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -300,6 +353,7 @@ Item {
|
||||
text: hasActivePlayer ? getTitle() : placeholderText
|
||||
font: titleText.font
|
||||
applyUiScale: false
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: hasActivePlayer ? Text.AlignLeft : Text.AlignHCenter
|
||||
color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant
|
||||
@@ -359,7 +413,7 @@ Item {
|
||||
anchors.fill: parent
|
||||
icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "disc"
|
||||
color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant
|
||||
pointSize: Style.fontSizeL
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ Item {
|
||||
Connections {
|
||||
target: AudioService.source?.audio ? AudioService.source?.audio : null
|
||||
function onVolumeChanged() {
|
||||
// Logger.log("Bar:Microphone", "onInputVolumeChanged")
|
||||
// Logger.i("Bar:Microphone", "onInputVolumeChanged")
|
||||
if (!firstInputVolumeReceived) {
|
||||
// Ignore the first volume change
|
||||
firstInputVolumeReceived = true
|
||||
@@ -66,7 +66,7 @@ Item {
|
||||
Connections {
|
||||
target: AudioService.source?.audio ? AudioService.source?.audio : null
|
||||
function onMutedChanged() {
|
||||
// Logger.log("Bar:Microphone", "onInputMutedChanged")
|
||||
// Logger.i("Bar:Microphone", "onInputMutedChanged")
|
||||
if (!firstInputVolumeReceived) {
|
||||
// Ignore the first mute change
|
||||
firstInputVolumeReceived = true
|
||||
|
||||
@@ -168,13 +168,13 @@ Rectangle {
|
||||
try {
|
||||
CompositorService.focusWindow(taskbarItem.modelData)
|
||||
} catch (error) {
|
||||
Logger.error("Taskbar", "Failed to activate toplevel: " + error)
|
||||
Logger.e("Taskbar", "Failed to activate toplevel: " + error)
|
||||
}
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
try {
|
||||
CompositorService.closeWindow(taskbarItem.modelData)
|
||||
} catch (error) {
|
||||
Logger.error("Taskbar", "Failed to close toplevel: " + error)
|
||||
Logger.e("Taskbar", "Failed to close toplevel: " + error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ Rectangle {
|
||||
if (!str || !rule) {
|
||||
return false
|
||||
}
|
||||
Logger.log("Tray", "wildCardMatch - Input str:", str, "rule:", rule)
|
||||
Logger.i("Tray", "wildCardMatch - Input str:", str, "rule:", rule)
|
||||
|
||||
// Escape all special regex characters in the rule
|
||||
let escapedRule = rule.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||
@@ -52,15 +52,15 @@ Rectangle {
|
||||
// Add ^ and $ to match the entire string
|
||||
pattern = '^' + pattern + '$'
|
||||
|
||||
Logger.log("Tray", "wildCardMatch - Generated pattern:", pattern)
|
||||
Logger.i("Tray", "wildCardMatch - Generated pattern:", pattern)
|
||||
|
||||
try {
|
||||
const regex = new RegExp(pattern, 'i')
|
||||
// 'i' for case-insensitive
|
||||
Logger.log("Tray", "wildCardMatch - Regex test result:", regex.test(str))
|
||||
Logger.i("Tray", "wildCardMatch - Regex test result:", regex.test(str))
|
||||
return regex.test(str)
|
||||
} catch (e) {
|
||||
Logger.warn("Tray", "Invalid regex pattern for wildcard match:", rule, e.message)
|
||||
Logger.w("Tray", "Invalid regex pattern for wildcard match:", rule, e.message)
|
||||
return false // If regex is invalid, it won't match
|
||||
}
|
||||
}
|
||||
@@ -252,7 +252,7 @@ Rectangle {
|
||||
trayMenu.item.menu = modelData.menu
|
||||
trayMenu.item.showAt(parent, menuX, menuY)
|
||||
} else {
|
||||
Logger.log("Tray", "No menu available for", modelData.id, "or trayMenu not set")
|
||||
Logger.i("Tray", "No menu available for", modelData.id, "or trayMenu not set")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ Item {
|
||||
Connections {
|
||||
target: AudioService.sink?.audio ? AudioService.sink?.audio : null
|
||||
function onVolumeChanged() {
|
||||
// Logger.log("Bar:Volume", "onVolumeChanged")
|
||||
// Logger.i("Bar:Volume", "onVolumeChanged")
|
||||
if (!firstVolumeReceived) {
|
||||
// Ignore the first volume change
|
||||
firstVolumeReceived = true
|
||||
|
||||
@@ -37,7 +37,7 @@ NIconButton {
|
||||
}
|
||||
return connected ? NetworkService.signalIcon(signalStrength) : "wifi-off"
|
||||
} catch (error) {
|
||||
Logger.error("Wi-Fi", "Error getting icon:", error)
|
||||
Logger.e("Wi-Fi", "Error getting icon:", error)
|
||||
return "signal_wifi_bad"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user