:Merge tag 'v2.11.0'
This commit is contained in:
commit
67fed691d1
54 changed files with 776 additions and 794 deletions
Binary file not shown.
|
|
@ -121,6 +121,12 @@ Singleton {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Upgrade the density of the bar so the look stay the same for people who upgrade.
|
||||
if (adapter.settingsVersion == 2) {
|
||||
adapter.bar.density = "comfortable"
|
||||
adapter.settingsVersion++
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
|
|
@ -259,13 +265,15 @@ Singleton {
|
|||
JsonAdapter {
|
||||
id: adapter
|
||||
|
||||
property int settingsVersion: 2
|
||||
property int settingsVersion: 3
|
||||
|
||||
// bar
|
||||
property JsonObject bar: JsonObject {
|
||||
property string position: "top" // "top", "bottom", "left", or "right"
|
||||
property real backgroundOpacity: 1.0
|
||||
property list<string> monitors: []
|
||||
property string density: "default" // "compact", "default", "comfortable"
|
||||
property bool showCapsule: true
|
||||
|
||||
// Floating bar settings
|
||||
property bool floating: false
|
||||
|
|
@ -320,7 +328,7 @@ Singleton {
|
|||
// general
|
||||
property JsonObject general: JsonObject {
|
||||
property string avatarImage: defaultAvatar
|
||||
property bool dimDesktop: false
|
||||
property bool dimDesktop: true
|
||||
property bool showScreenCorners: false
|
||||
property bool forceBlackScreenCorners: false
|
||||
property real radiusRatio: 1.0
|
||||
|
|
|
|||
|
|
@ -65,14 +65,36 @@ Singleton {
|
|||
property int animationSlow: Math.round(450 / Settings.data.general.animationSpeed)
|
||||
property int animationSlowest: Math.round(750 / Settings.data.general.animationSpeed)
|
||||
|
||||
// Dimensions
|
||||
property int barHeight: (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 39 : 37
|
||||
property int capsuleHeight: (barHeight * 0.73)
|
||||
property int baseWidgetSize: (barHeight * 0.9)
|
||||
property int sliderWidth: 200
|
||||
|
||||
// Delays
|
||||
property int tooltipDelay: 300
|
||||
property int tooltipDelayLong: 1200
|
||||
property int pillDelay: 500
|
||||
|
||||
// Settings widgets base size
|
||||
property real baseWidgetSize: 33
|
||||
property real sliderWidth: 200
|
||||
|
||||
// Bar Dimensions
|
||||
property real barHeight: {
|
||||
if (Settings.data.bar.density === "compact") {
|
||||
return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 27 : 25
|
||||
}
|
||||
if (Settings.data.bar.density === "default") {
|
||||
return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 33 : 31
|
||||
}
|
||||
if (Settings.data.bar.density === "comfortable") {
|
||||
return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 39 : 37
|
||||
}
|
||||
}
|
||||
property real capsuleHeight: {
|
||||
if (Settings.data.bar.density === "compact") {
|
||||
return barHeight * 0.85
|
||||
}
|
||||
if (Settings.data.bar.density === "default") {
|
||||
return barHeight * 0.82
|
||||
}
|
||||
if (Settings.data.bar.density === "comfortable") {
|
||||
return barHeight * 0.73
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,23 +68,12 @@ Variants {
|
|||
radius: Settings.data.bar.floating ? Style.radiusL : 0
|
||||
}
|
||||
|
||||
// For vertical bars, use a single column layout
|
||||
Loader {
|
||||
id: verticalBarLayout
|
||||
anchors.fill: parent
|
||||
visible: Settings.data.bar.position === "left" || Settings.data.bar.position === "right"
|
||||
sourceComponent: verticalBarComponent
|
||||
sourceComponent: (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? verticalBarComponent : horizontalBarComponent
|
||||
}
|
||||
|
||||
// For horizontal bars, use the original three-section layout
|
||||
Loader {
|
||||
id: horizontalBarLayout
|
||||
anchors.fill: parent
|
||||
visible: Settings.data.bar.position === "top" || Settings.data.bar.position === "bottom"
|
||||
sourceComponent: horizontalBarComponent
|
||||
}
|
||||
|
||||
// Main layout components
|
||||
// For vertical bars
|
||||
Component {
|
||||
id: verticalBarComponent
|
||||
Item {
|
||||
|
|
@ -163,6 +152,7 @@ Variants {
|
|||
}
|
||||
}
|
||||
|
||||
// For horizontal bars
|
||||
Component {
|
||||
id: horizontalBarComponent
|
||||
Item {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import QtQuick
|
|||
import QtQuick.Controls
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -10,13 +11,13 @@ Item {
|
|||
property string text: ""
|
||||
property string suffix: ""
|
||||
property string tooltipText: ""
|
||||
property real sizeRatio: 0.8
|
||||
property bool autoHide: false
|
||||
property bool forceOpen: false
|
||||
property bool forceClose: false
|
||||
property bool disableOpen: false
|
||||
property bool rightOpen: false
|
||||
property bool hovered: false
|
||||
property bool compact: false
|
||||
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool isVerticalBar: barPosition === "left" || barPosition === "right"
|
||||
|
|
@ -41,18 +42,18 @@ Item {
|
|||
|
||||
Component {
|
||||
id: verticalPillComponent
|
||||
NPillVertical {
|
||||
BarPillVertical {
|
||||
icon: root.icon
|
||||
text: root.text
|
||||
suffix: root.suffix
|
||||
tooltipText: root.tooltipText
|
||||
sizeRatio: root.sizeRatio
|
||||
autoHide: root.autoHide
|
||||
forceOpen: root.forceOpen
|
||||
forceClose: root.forceClose
|
||||
disableOpen: root.disableOpen
|
||||
rightOpen: root.rightOpen
|
||||
hovered: root.hovered
|
||||
compact: root.compact
|
||||
onShown: root.shown()
|
||||
onHidden: root.hidden()
|
||||
onEntered: root.entered()
|
||||
|
|
@ -66,18 +67,18 @@ Item {
|
|||
|
||||
Component {
|
||||
id: horizontalPillComponent
|
||||
NPillHorizontal {
|
||||
BarPillHorizontal {
|
||||
icon: root.icon
|
||||
text: root.text
|
||||
suffix: root.suffix
|
||||
tooltipText: root.tooltipText
|
||||
sizeRatio: root.sizeRatio
|
||||
autoHide: root.autoHide
|
||||
forceOpen: root.forceOpen
|
||||
forceClose: root.forceClose
|
||||
disableOpen: root.disableOpen
|
||||
rightOpen: root.rightOpen
|
||||
hovered: root.hovered
|
||||
compact: root.compact
|
||||
onShown: root.shown()
|
||||
onHidden: root.hidden()
|
||||
onEntered: root.entered()
|
||||
|
|
@ -2,6 +2,7 @@ import QtQuick
|
|||
import QtQuick.Controls
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -10,13 +11,13 @@ Item {
|
|||
property string text: ""
|
||||
property string suffix: ""
|
||||
property string tooltipText: ""
|
||||
property real sizeRatio: 0.8
|
||||
property bool autoHide: false
|
||||
property bool forceOpen: false
|
||||
property bool forceClose: false
|
||||
property bool disableOpen: false
|
||||
property bool rightOpen: false
|
||||
property bool hovered: false
|
||||
property bool compact: false
|
||||
|
||||
// Effective shown state (true if hovered/animated open or forced)
|
||||
readonly property bool revealed: forceOpen || showPill
|
||||
|
|
@ -34,26 +35,27 @@ Item {
|
|||
property bool showPill: false
|
||||
property bool shouldAnimateHide: false
|
||||
|
||||
// Exposed width logic
|
||||
readonly property int iconSize: Math.round(Style.baseWidgetSize * sizeRatio * scaling)
|
||||
readonly property int pillHeight: iconSize
|
||||
readonly property int pillPaddingHorizontal: 3 * 2 * scaling // Very precise adjustment don't replace by Style.margin
|
||||
readonly property int pillOverlap: iconSize * 0.5
|
||||
readonly property int maxPillWidth: Math.max(1, textItem.implicitWidth + pillPaddingHorizontal * 2 + pillOverlap)
|
||||
readonly property int pillHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
readonly property int pillPaddingHorizontal: Math.round(Style.capsuleHeight * 0.2 * scaling)
|
||||
readonly property int pillOverlap: Math.round(Style.capsuleHeight * 0.5 * scaling)
|
||||
readonly property int pillMaxWidth: Math.max(1, textItem.implicitWidth + pillPaddingHorizontal * 2 + pillOverlap)
|
||||
|
||||
width: iconSize + Math.max(0, pill.width - pillOverlap)
|
||||
readonly property real iconSize: Math.max(1, compact ? pillHeight * 0.65 : pillHeight * 0.48)
|
||||
readonly property real textSize: Math.max(1, compact ? pillHeight * 0.45 : pillHeight * 0.33)
|
||||
|
||||
width: pillHeight + Math.max(0, pill.width - pillOverlap)
|
||||
height: pillHeight
|
||||
|
||||
Rectangle {
|
||||
id: pill
|
||||
width: revealed ? maxPillWidth : 1
|
||||
width: revealed ? pillMaxWidth : 1
|
||||
height: pillHeight
|
||||
|
||||
x: rightOpen ? (iconCircle.x + iconCircle.width / 2) : // Opens right
|
||||
(iconCircle.x + iconCircle.width / 2) - width // Opens left
|
||||
|
||||
opacity: revealed ? Style.opacityFull : Style.opacityNone
|
||||
color: Color.mSurfaceVariant
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
topLeftRadius: rightOpen ? 0 : pillHeight * 0.5
|
||||
bottomLeftRadius: rightOpen ? 0 : pillHeight * 0.5
|
||||
|
|
@ -76,7 +78,7 @@ Item {
|
|||
}
|
||||
text: root.text + root.suffix
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
font.pointSize: textSize
|
||||
font.weight: Style.fontWeightBold
|
||||
color: forceOpen ? Color.mOnSurface : Color.mPrimary
|
||||
visible: revealed
|
||||
|
|
@ -100,10 +102,10 @@ Item {
|
|||
|
||||
Rectangle {
|
||||
id: iconCircle
|
||||
width: iconSize
|
||||
height: iconSize
|
||||
width: pillHeight
|
||||
height: pillHeight
|
||||
radius: width * 0.5
|
||||
color: hovered ? Color.mTertiary : Color.mSurfaceVariant
|
||||
color: hovered ? Color.mTertiary : Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
x: rightOpen ? 0 : (parent.width - width)
|
||||
|
|
@ -117,7 +119,7 @@ Item {
|
|||
|
||||
NIcon {
|
||||
icon: root.icon
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.pointSize: iconSize
|
||||
color: hovered ? Color.mOnTertiary : Color.mOnSurface
|
||||
// Center horizontally
|
||||
x: (iconCircle.width - width) / 2
|
||||
|
|
@ -133,7 +135,7 @@ Item {
|
|||
target: pill
|
||||
property: "width"
|
||||
from: 1
|
||||
to: maxPillWidth
|
||||
to: pillMaxWidth
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
|
@ -173,7 +175,7 @@ Item {
|
|||
NumberAnimation {
|
||||
target: pill
|
||||
property: "width"
|
||||
from: maxPillWidth
|
||||
from: pillMaxWidth
|
||||
to: 1
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.InCubic
|
||||
|
|
@ -2,6 +2,7 @@ import QtQuick
|
|||
import QtQuick.Controls
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -10,13 +11,13 @@ Item {
|
|||
property string text: ""
|
||||
property string suffix: ""
|
||||
property string tooltipText: ""
|
||||
property real sizeRatio: 0.8
|
||||
property bool autoHide: false
|
||||
property bool forceOpen: false
|
||||
property bool forceClose: false
|
||||
property bool disableOpen: false
|
||||
property bool rightOpen: false
|
||||
property bool hovered: false
|
||||
property bool compact: false
|
||||
|
||||
// Bar position detection for pill direction
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
|
|
@ -43,16 +44,19 @@ Item {
|
|||
property bool shouldAnimateHide: false
|
||||
|
||||
// Sizing logic for vertical bars
|
||||
readonly property int iconSize: Math.round(Style.baseWidgetSize * sizeRatio * scaling)
|
||||
readonly property int pillHeight: iconSize
|
||||
readonly property int buttonSize: Math.round(Style.capsuleHeight * scaling)
|
||||
readonly property int pillHeight: buttonSize
|
||||
readonly property int pillPaddingVertical: 3 * 2 * scaling // Very precise adjustment don't replace by Style.margin
|
||||
readonly property int pillOverlap: iconSize * 0.5
|
||||
readonly property int maxPillWidth: iconSize
|
||||
readonly property int pillOverlap: buttonSize * 0.5
|
||||
readonly property int maxPillWidth: buttonSize
|
||||
readonly property int maxPillHeight: Math.max(1, textItem.implicitHeight + pillPaddingVertical * 4)
|
||||
|
||||
readonly property real iconSize: Math.max(1, compact ? pillHeight * 0.65 : pillHeight * 0.48)
|
||||
readonly property real textSize: Math.max(1, compact ? pillHeight * 0.38 : pillHeight * 0.33)
|
||||
|
||||
// For vertical bars: width is just icon size, height includes pill space
|
||||
width: iconSize
|
||||
height: revealed ? (iconSize + maxPillHeight - pillOverlap) : iconSize
|
||||
width: buttonSize
|
||||
height: revealed ? (buttonSize + maxPillHeight - pillOverlap) : buttonSize
|
||||
|
||||
Rectangle {
|
||||
id: pill
|
||||
|
|
@ -64,13 +68,13 @@ Item {
|
|||
y: openUpward ? (iconCircle.y + iconCircle.height / 2 - height) : (iconCircle.y + iconCircle.height / 2)
|
||||
|
||||
opacity: revealed ? Style.opacityFull : Style.opacityNone
|
||||
color: Color.mSurfaceVariant
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
// Radius logic for vertical expansion - rounded on the side that connects to icon
|
||||
topLeftRadius: openUpward ? iconSize * 0.5 : 0
|
||||
bottomLeftRadius: openDownward ? iconSize * 0.5 : 0
|
||||
topRightRadius: openUpward ? iconSize * 0.5 : 0
|
||||
bottomRightRadius: openDownward ? iconSize * 0.5 : 0
|
||||
topLeftRadius: openUpward ? buttonSize * 0.5 : 0
|
||||
bottomLeftRadius: openDownward ? buttonSize * 0.5 : 0
|
||||
topRightRadius: openUpward ? buttonSize * 0.5 : 0
|
||||
bottomRightRadius: openDownward ? buttonSize * 0.5 : 0
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
|
|
@ -88,7 +92,7 @@ Item {
|
|||
}
|
||||
text: root.text + root.suffix
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
font.pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
|
@ -121,10 +125,10 @@ Item {
|
|||
|
||||
Rectangle {
|
||||
id: iconCircle
|
||||
width: iconSize
|
||||
height: iconSize
|
||||
width: buttonSize
|
||||
height: buttonSize
|
||||
radius: width * 0.5
|
||||
color: hovered ? Color.mTertiary : Color.mSurfaceVariant
|
||||
color: hovered ? Color.mTertiary : Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
// Icon positioning based on direction
|
||||
x: 0
|
||||
|
|
@ -140,7 +144,7 @@ Item {
|
|||
|
||||
NIcon {
|
||||
icon: root.icon
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.pointSize: iconSize
|
||||
color: hovered ? Color.mOnTertiary : Color.mOnSurface
|
||||
// Center horizontally
|
||||
x: (iconCircle.width - width) / 2
|
||||
|
|
@ -37,8 +37,18 @@ Item {
|
|||
readonly property real maxWidth: minWidth * 2
|
||||
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool isVertical: barPosition === "left" || barPosition === "right"
|
||||
readonly property bool compact: (Settings.data.bar.density === "compact")
|
||||
|
||||
implicitHeight: (barPosition === "left" || barPosition === "right") ? calculatedVerticalHeight() : Math.round(Style.barHeight * scaling)
|
||||
implicitWidth: (barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (horizontalLayout.implicitWidth + Style.marginM * 2 * scaling)
|
||||
implicitWidth: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * 0.8 * scaling) : (horizontalLayout.implicitWidth + Style.marginM * 2 * scaling)
|
||||
|
||||
readonly property real textSize: {
|
||||
var base = isVertical ? width : height
|
||||
return Math.max(1, compact ? base * 0.43 : base * 0.33)
|
||||
}
|
||||
|
||||
readonly property real iconSize: textSize * 1.25
|
||||
|
||||
function getTitle() {
|
||||
try {
|
||||
|
|
@ -60,7 +70,7 @@ Item {
|
|||
let total = Style.marginM * 2 * scaling // internal padding
|
||||
|
||||
if (showIcon) {
|
||||
total += Style.baseWidgetSize * 0.5 * scaling + 2 * scaling // icon + spacing
|
||||
total += Style.capsuleHeight * 0.5 * scaling + 2 * scaling // icon + spacing
|
||||
}
|
||||
|
||||
// Calculate actual text width more accurately
|
||||
|
|
@ -129,12 +139,14 @@ Item {
|
|||
Rectangle {
|
||||
id: windowTitleRect
|
||||
visible: root.visible
|
||||
anchors.left: parent.left
|
||||
anchors.left: (barPosition === "top" || barPosition === "bottom") ? parent.left : undefined
|
||||
anchors.top: (barPosition === "left" || barPosition === "right") ? parent.top : undefined
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * scaling) : (horizontalLayout.implicitWidth + Style.marginM * 2 * scaling)
|
||||
height: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * scaling) : Math.round(Style.capsuleHeight * scaling)
|
||||
radius: Math.round(Style.radiusM * scaling)
|
||||
color: Color.mSurfaceVariant
|
||||
radius: width / 2
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
Item {
|
||||
id: mainContainer
|
||||
|
|
@ -152,8 +164,8 @@ Item {
|
|||
|
||||
// Window icon
|
||||
Item {
|
||||
Layout.preferredWidth: Style.baseWidgetSize * 0.5 * scaling
|
||||
Layout.preferredHeight: Style.baseWidgetSize * 0.5 * scaling
|
||||
Layout.preferredWidth: Style.capsuleHeight * 0.75 * scaling
|
||||
Layout.preferredHeight: Style.capsuleHeight * 0.75 * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: getTitle() !== "" && showIcon
|
||||
|
||||
|
|
@ -217,10 +229,9 @@ Item {
|
|||
|
||||
// Window icon
|
||||
Item {
|
||||
width: Style.baseWidgetSize * 0.5 * scaling
|
||||
height: Style.baseWidgetSize * 0.5 * scaling
|
||||
width: Style.capsuleHeight * 0.75 * scaling
|
||||
height: Style.capsuleHeight * 0.75 * scaling
|
||||
anchors.centerIn: parent
|
||||
visible: getTitle() !== "" && showIcon
|
||||
|
||||
IconImage {
|
||||
id: windowIconVertical
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import QtQuick.Layouts
|
|||
import qs.Commons
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.Bar.Extras
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -81,10 +82,11 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
NPill {
|
||||
BarPill {
|
||||
id: pill
|
||||
|
||||
rightOpen: BarWidgetRegistry.getNPillDirection(root)
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
rightOpen: BarWidgetRegistry.getPillDirection(root)
|
||||
icon: testMode ? BatteryService.getIcon(testPercent, testCharging, true) : BatteryService.getIcon(percent, charging, isReady)
|
||||
text: (isReady || testMode) ? Math.round(percent) : "-"
|
||||
suffix: "%"
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ NIconButton {
|
|||
property ShellScreen screen
|
||||
property real scaling: 1.0
|
||||
|
||||
sizeRatio: 0.8
|
||||
colorBg: Color.mSurfaceVariant
|
||||
baseSize: Style.capsuleHeight
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
colorBg: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
colorFg: Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.transparent
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import qs.Commons
|
|||
import qs.Modules.SettingsPanel
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.Bar.Extras
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -73,10 +74,11 @@ Item {
|
|||
onTriggered: pill.hide()
|
||||
}
|
||||
|
||||
NPill {
|
||||
BarPill {
|
||||
id: pill
|
||||
|
||||
rightOpen: BarWidgetRegistry.getNPillDirection(root)
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
rightOpen: BarWidgetRegistry.getPillDirection(root)
|
||||
icon: getIcon()
|
||||
autoHide: false // Important to be false so we can hover as long as we want
|
||||
text: {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ Rectangle {
|
|||
}
|
||||
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool compact: (Settings.data.bar.density === "compact")
|
||||
|
||||
// Resolve settings: try user settings or defaults from BarWidgetRegistry
|
||||
readonly property bool use12h: widgetSettings.use12HourClock !== undefined ? widgetSettings.use12HourClock : widgetMetadata.use12HourClock
|
||||
|
|
@ -39,15 +40,15 @@ Rectangle {
|
|||
readonly property bool verticalMode: barPosition === "left" || barPosition === "right"
|
||||
|
||||
implicitWidth: verticalMode ? Math.round(Style.capsuleHeight * scaling) : Math.round(layout.implicitWidth + Style.marginM * 2 * scaling)
|
||||
implicitHeight: verticalMode ? Math.round(Style.capsuleHeight * 2.5 * scaling) : Math.round(Style.baseWidgetSize * 0.8 * scaling) // Match NPill
|
||||
implicitHeight: verticalMode ? Math.round(Style.capsuleHeight * 2.5 * scaling) : Math.round(Style.capsuleHeight * scaling) // Match BarPill
|
||||
|
||||
radius: Math.round(Style.radiusS * scaling)
|
||||
color: Color.mSurfaceVariant
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
Item {
|
||||
id: clockContainer
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginXS * scaling
|
||||
anchors.margins: compact ? 0 : Style.marginXS * scaling
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import qs.Commons
|
|||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.SettingsPanel
|
||||
import qs.Modules.Bar.Extras
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -43,12 +44,13 @@ Item {
|
|||
implicitWidth: pill.width
|
||||
implicitHeight: pill.height
|
||||
|
||||
NPill {
|
||||
BarPill {
|
||||
id: pill
|
||||
|
||||
rightOpen: BarWidgetRegistry.getNPillDirection(root)
|
||||
rightOpen: BarWidgetRegistry.getPillDirection(root)
|
||||
icon: customIcon
|
||||
text: _dynamicText
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
autoHide: false
|
||||
forceOpen: _dynamicText !== ""
|
||||
forceClose: false
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ NIconButton {
|
|||
property real scaling: 1.0
|
||||
|
||||
icon: "dark-mode"
|
||||
tooltipText: "Toggle light/dark mode"
|
||||
sizeRatio: 0.8
|
||||
|
||||
colorBg: Settings.data.colorSchemes.darkMode ? Color.mSurfaceVariant : Color.mPrimary
|
||||
tooltipText: "Toggle light/dark mode."
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
baseSize: Style.capsuleHeight
|
||||
colorBg: Settings.data.colorSchemes.darkMode ? (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) : Color.mPrimary
|
||||
colorFg: Settings.data.colorSchemes.darkMode ? Color.mOnSurface : Color.mOnPrimary
|
||||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.transparent
|
||||
|
|
|
|||
|
|
@ -11,14 +11,12 @@ NIconButton {
|
|||
property ShellScreen screen
|
||||
property real scaling: 1.0
|
||||
|
||||
sizeRatio: 0.8
|
||||
|
||||
baseSize: Style.capsuleHeight
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off"
|
||||
tooltipText: IdleInhibitorService.isInhibited ? "Disable keep awake" : "Enable keep awake"
|
||||
colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : Color.mSurfaceVariant
|
||||
colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: IdleInhibitorService.isInhibited ? Color.mOnPrimary : Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
onClicked: {
|
||||
IdleInhibitorService.manualToggle()
|
||||
}
|
||||
onClicked: IdleInhibitorService.manualToggle()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import Quickshell.Io
|
|||
import qs.Commons
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.Bar.Extras
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -38,11 +39,12 @@ Item {
|
|||
implicitWidth: pill.width
|
||||
implicitHeight: pill.height
|
||||
|
||||
NPill {
|
||||
BarPill {
|
||||
id: pill
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
rightOpen: BarWidgetRegistry.getNPillDirection(root)
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
rightOpen: BarWidgetRegistry.getPillDirection(root)
|
||||
icon: "keyboard"
|
||||
autoHide: false // Important to be false so we can hover as long as we want
|
||||
text: currentLayout.toUpperCase()
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ Item {
|
|||
}
|
||||
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool compact: (Settings.data.bar.density === "compact")
|
||||
|
||||
readonly property bool showAlbumArt: (widgetSettings.showAlbumArt !== undefined) ? widgetSettings.showAlbumArt : widgetMetadata.showAlbumArt
|
||||
readonly property bool showVisualizer: (widgetSettings.showVisualizer !== undefined) ? widgetSettings.showVisualizer : widgetMetadata.showVisualizer
|
||||
|
|
@ -81,7 +82,7 @@ Item {
|
|||
width: (barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (rowLayout.implicitWidth + Style.marginM * 2 * scaling)
|
||||
height: (barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : Math.round(Style.capsuleHeight * scaling)
|
||||
radius: (barPosition === "left" || barPosition === "right") ? width / 2 : Math.round(Style.radiusM * scaling)
|
||||
color: Color.mSurfaceVariant
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
// Used to anchor the tooltip, so the tooltip does not move when the content expands
|
||||
Item {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import qs.Commons
|
|||
import qs.Modules.SettingsPanel
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.Bar.Extras
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -86,10 +87,11 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
NPill {
|
||||
BarPill {
|
||||
id: pill
|
||||
rightOpen: BarWidgetRegistry.getNPillDirection(root)
|
||||
rightOpen: BarWidgetRegistry.getPillDirection(root)
|
||||
icon: getIcon()
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
autoHide: false // Important to be false so we can hover as long as we want
|
||||
text: Math.floor(AudioService.inputVolume * 100)
|
||||
suffix: "%"
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@ NIconButton {
|
|||
property ShellScreen screen
|
||||
property real scaling: 1.0
|
||||
|
||||
sizeRatio: 0.8
|
||||
colorBg: Settings.data.nightLight.forced ? Color.mPrimary : Color.mSurfaceVariant
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
baseSize: Style.capsuleHeight
|
||||
colorBg: Settings.data.nightLight.forced ? Color.mPrimary : (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: Settings.data.nightLight.forced ? Color.mOnPrimary : Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.transparent
|
||||
|
|
|
|||
|
|
@ -49,10 +49,11 @@ NIconButton {
|
|||
return count
|
||||
}
|
||||
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.capsuleHeight
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell"
|
||||
tooltipText: Settings.data.notifications.doNotDisturb ? "Notification history.\nRight-click to disable 'Do Not Disturb'." : "Notification history.\nRight-click to enable 'Do Not Disturb'."
|
||||
colorBg: Color.mSurfaceVariant
|
||||
colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.transparent
|
||||
|
|
@ -68,29 +69,20 @@ NIconButton {
|
|||
Loader {
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.rightMargin: -4 * scaling
|
||||
anchors.topMargin: -4 * scaling
|
||||
anchors.rightMargin: 2 * scaling
|
||||
anchors.topMargin: 1 * scaling
|
||||
z: 2
|
||||
active: showUnreadBadge && (!hideWhenZero || computeUnreadCount() > 0)
|
||||
sourceComponent: Rectangle {
|
||||
id: badge
|
||||
readonly property int count: computeUnreadCount()
|
||||
readonly property string label: count <= 99 ? String(count) : "99+"
|
||||
readonly property real pad: 8 * scaling
|
||||
height: 16 * scaling
|
||||
width: Math.max(height, textNode.implicitWidth + pad)
|
||||
height: 8 * scaling
|
||||
width: height
|
||||
radius: height / 2
|
||||
color: Color.mError
|
||||
border.color: Color.mSurface
|
||||
border.width: 1
|
||||
visible: count > 0 || !hideWhenZero
|
||||
NText {
|
||||
id: textNode
|
||||
anchors.centerIn: parent
|
||||
text: badge.label
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mOnError
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ NIconButton {
|
|||
property real scaling: 1.0
|
||||
readonly property bool hasPP: PowerProfileService.available
|
||||
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.capsuleHeight
|
||||
visible: hasPP
|
||||
|
||||
function profileIcon() {
|
||||
|
|
@ -46,7 +46,8 @@ NIconButton {
|
|||
|
||||
icon: root.profileIcon()
|
||||
tooltipText: root.profileName()
|
||||
colorBg: (PowerProfileService.profile === PowerProfile.Balanced) ? Color.mSurfaceVariant : Color.mPrimary
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
colorBg: (PowerProfileService.profile === PowerProfile.Balanced) ? (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) : Color.mPrimary
|
||||
colorFg: (PowerProfileService.profile === PowerProfile.Balanced) ? Color.mOnSurface : Color.mOnPrimary
|
||||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.transparent
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ NIconButton {
|
|||
property ShellScreen screen
|
||||
property real scaling: 1.0
|
||||
|
||||
sizeRatio: 0.8
|
||||
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
baseSize: Style.capsuleHeight
|
||||
icon: "power"
|
||||
tooltipText: "Power Settings"
|
||||
colorBg: Color.mSurfaceVariant
|
||||
colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: Color.mError
|
||||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.transparent
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ NIconButton {
|
|||
|
||||
visible: ScreenRecorderService.isRecording
|
||||
icon: "camera-video"
|
||||
tooltipText: "Screen recording is active\nClick to stop recording"
|
||||
sizeRatio: 0.8
|
||||
tooltipText: "Screen recording is active.\nClick to stop recording."
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
baseSize: Style.capsuleHeight
|
||||
colorBg: Color.mPrimary
|
||||
colorFg: Color.mOnPrimary
|
||||
onClicked: ScreenRecorderService.toggleRecording()
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ NIconButton {
|
|||
|
||||
icon: useDistroLogo ? "" : "noctalia"
|
||||
tooltipText: "Open side panel."
|
||||
sizeRatio: 0.85
|
||||
|
||||
colorBg: Color.mSurfaceVariant
|
||||
baseSize: Style.capsuleHeight
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: Color.mOnSurface
|
||||
colorBgHover: useDistroLogo ? Color.mSurfaceVariant : Color.mTertiary
|
||||
colorBorder: Color.transparent
|
||||
|
|
@ -46,10 +46,11 @@ NIconButton {
|
|||
IconImage {
|
||||
id: logo
|
||||
anchors.centerIn: parent
|
||||
width: root.width * 0.85
|
||||
width: root.width * 0.8
|
||||
height: width
|
||||
source: useDistroLogo ? DistroLogoService.osLogo : ""
|
||||
visible: useDistroLogo && source !== ""
|
||||
smooth: true
|
||||
asynchronous: true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ Rectangle {
|
|||
}
|
||||
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool isVertical: barPosition === "left" || barPosition === "right"
|
||||
readonly property bool compact: (Settings.data.bar.density === "compact")
|
||||
|
||||
readonly property bool showCpuUsage: (widgetSettings.showCpuUsage !== undefined) ? widgetSettings.showCpuUsage : widgetMetadata.showCpuUsage
|
||||
readonly property bool showCpuTemp: (widgetSettings.showCpuTemp !== undefined) ? widgetSettings.showCpuTemp : widgetMetadata.showCpuTemp
|
||||
|
|
@ -37,410 +39,267 @@ Rectangle {
|
|||
readonly property bool showNetworkStats: (widgetSettings.showNetworkStats !== undefined) ? widgetSettings.showNetworkStats : widgetMetadata.showNetworkStats
|
||||
readonly property bool showDiskUsage: (widgetSettings.showDiskUsage !== undefined) ? widgetSettings.showDiskUsage : widgetMetadata.showDiskUsage
|
||||
|
||||
readonly property real textSize: {
|
||||
var base = isVertical ? width * 0.82 : height
|
||||
return Math.max(1, compact ? base * 0.43 : base * 0.33)
|
||||
}
|
||||
|
||||
readonly property real iconSize: textSize * 1.25
|
||||
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * scaling) : Math.round(horizontalLayout.implicitWidth + Style.marginM * 2 * scaling)
|
||||
implicitHeight: (barPosition === "left" || barPosition === "right") ? Math.round(verticalLayout.implicitHeight + Style.marginM * 2 * scaling) : Math.round(Style.capsuleHeight * scaling)
|
||||
implicitWidth: isVertical ? Math.round(Style.capsuleHeight * scaling) : Math.round(mainGrid.implicitWidth + Style.marginM * 2 * scaling)
|
||||
implicitHeight: isVertical ? Math.round(mainGrid.implicitHeight + Style.marginM * 2 * scaling) : Math.round(Style.capsuleHeight * scaling)
|
||||
radius: Math.round(Style.radiusM * scaling)
|
||||
color: Color.mSurfaceVariant
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
// Compact speed formatter for vertical bar display
|
||||
function formatCompactSpeed(bytesPerSecond) {
|
||||
if (!bytesPerSecond || bytesPerSecond <= 0)
|
||||
return "0"
|
||||
const units = ["", "k", "M", "G"]
|
||||
let value = bytesPerSecond
|
||||
let unitIndex = 0
|
||||
while (value >= 1024 && unitIndex < units.length - 1) {
|
||||
value = value / 1024.0
|
||||
unitIndex++
|
||||
}
|
||||
// Promote at ~100 of current unit (e.g., 100k -> ~0.1M shown as 0.1M or 0M if rounded)
|
||||
if (unitIndex < units.length - 1 && value >= 100) {
|
||||
value = value / 1024.0
|
||||
unitIndex++
|
||||
}
|
||||
const display = (value >= 10) ? Math.round(value).toString() : value.toFixed(1)
|
||||
return display + units[unitIndex]
|
||||
}
|
||||
|
||||
// Horizontal layout for top/bottom bars
|
||||
RowLayout {
|
||||
id: horizontalLayout
|
||||
GridLayout {
|
||||
id: mainGrid
|
||||
anchors.centerIn: parent
|
||||
anchors.leftMargin: Style.marginM * scaling
|
||||
anchors.rightMargin: Style.marginM * scaling
|
||||
spacing: Style.marginXS * scaling
|
||||
visible: barPosition === "top" || barPosition === "bottom"
|
||||
|
||||
// Dynamic layout based on bar orientation
|
||||
flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight
|
||||
rows: isVertical ? -1 : 1
|
||||
columns: isVertical ? 1 : -1
|
||||
|
||||
rowSpacing: isVertical ? (Style.marginS * scaling) : (Style.marginXS * scaling)
|
||||
columnSpacing: isVertical ? (Style.marginXS * scaling) : (Style.marginXS * scaling)
|
||||
|
||||
// CPU Usage Component
|
||||
Item {
|
||||
Layout.preferredWidth: cpuUsageRow.implicitWidth
|
||||
Layout.preferredWidth: cpuUsageContent.implicitWidth
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter
|
||||
visible: showCpuUsage
|
||||
|
||||
RowLayout {
|
||||
id: cpuUsageRow
|
||||
GridLayout {
|
||||
id: cpuUsageContent
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * scaling
|
||||
flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight
|
||||
rows: isVertical ? 2 : 1
|
||||
columns: isVertical ? 1 : 2
|
||||
rowSpacing: Style.marginXXS * scaling
|
||||
columnSpacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
text: isVertical ? `${Math.round(SystemStatService.cpuUsage)}%` : `${SystemStatService.cpuUsage}%`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
Layout.row: isVertical ? 0 : 0
|
||||
Layout.column: isVertical ? 0 : 1
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "cpu-usage"
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: `${SystemStatService.cpuUsage}%`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
font.pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CPU Temperature Component
|
||||
Item {
|
||||
Layout.preferredWidth: cpuTempRow.implicitWidth
|
||||
Layout.preferredWidth: cpuTempContent.implicitWidth
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter
|
||||
visible: showCpuTemp
|
||||
|
||||
RowLayout {
|
||||
id: cpuTempRow
|
||||
GridLayout {
|
||||
id: cpuTempContent
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * scaling
|
||||
flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight
|
||||
rows: isVertical ? 2 : 1
|
||||
columns: isVertical ? 1 : 2
|
||||
rowSpacing: Style.marginXXS * scaling
|
||||
columnSpacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
text: isVertical ? `${SystemStatService.cpuTemp}°` : `${SystemStatService.cpuTemp}°C`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
Layout.row: isVertical ? 0 : 0
|
||||
Layout.column: isVertical ? 0 : 1
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "cpu-temperature"
|
||||
// Fire is so tall, we need to make it smaller
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: `${SystemStatService.cpuTemp}°C`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
font.pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Memory Usage Component
|
||||
Item {
|
||||
Layout.preferredWidth: memoryUsageRow.implicitWidth
|
||||
Layout.preferredWidth: memoryContent.implicitWidth
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter
|
||||
visible: showMemoryUsage
|
||||
|
||||
RowLayout {
|
||||
id: memoryUsageRow
|
||||
GridLayout {
|
||||
id: memoryContent
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * scaling
|
||||
flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight
|
||||
rows: isVertical ? 2 : 1
|
||||
columns: isVertical ? 1 : 2
|
||||
rowSpacing: Style.marginXXS * scaling
|
||||
columnSpacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
text: {
|
||||
if (showMemoryAsPercent) {
|
||||
return `${SystemStatService.memPercent}%`
|
||||
} else {
|
||||
return isVertical ? `${Math.round(SystemStatService.memGb)}G` : `${SystemStatService.memGb}G`
|
||||
}
|
||||
}
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
Layout.row: isVertical ? 0 : 0
|
||||
Layout.column: isVertical ? 0 : 1
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "memory"
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: showMemoryAsPercent ? `${SystemStatService.memPercent}%` : `${SystemStatService.memGb}G`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
font.pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Network Download Speed Component
|
||||
Item {
|
||||
Layout.preferredWidth: networkDownloadRow.implicitWidth
|
||||
Layout.preferredWidth: downloadContent.implicitWidth
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter
|
||||
visible: showNetworkStats
|
||||
|
||||
RowLayout {
|
||||
id: networkDownloadRow
|
||||
GridLayout {
|
||||
id: downloadContent
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXS * scaling
|
||||
flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight
|
||||
rows: isVertical ? 2 : 1
|
||||
columns: isVertical ? 1 : 2
|
||||
rowSpacing: Style.marginXXS * scaling
|
||||
columnSpacing: isVertical ? (Style.marginXXS * scaling) : (Style.marginXS * scaling)
|
||||
|
||||
NText {
|
||||
text: isVertical ? SystemStatService.formatCompactSpeed(SystemStatService.rxSpeed) : SystemStatService.formatSpeed(SystemStatService.rxSpeed)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
Layout.row: isVertical ? 0 : 0
|
||||
Layout.column: isVertical ? 0 : 1
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "download-speed"
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: SystemStatService.formatSpeed(SystemStatService.rxSpeed)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
font.pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Network Upload Speed Component
|
||||
Item {
|
||||
Layout.preferredWidth: networkUploadRow.implicitWidth
|
||||
Layout.preferredWidth: uploadContent.implicitWidth
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter
|
||||
visible: showNetworkStats
|
||||
|
||||
RowLayout {
|
||||
id: networkUploadRow
|
||||
GridLayout {
|
||||
id: uploadContent
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXS * scaling
|
||||
flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight
|
||||
rows: isVertical ? 2 : 1
|
||||
columns: isVertical ? 1 : 2
|
||||
rowSpacing: Style.marginXXS * scaling
|
||||
columnSpacing: isVertical ? (Style.marginXXS * scaling) : (Style.marginXS * scaling)
|
||||
|
||||
NText {
|
||||
text: isVertical ? SystemStatService.formatCompactSpeed(SystemStatService.txSpeed) : SystemStatService.formatSpeed(SystemStatService.txSpeed)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
Layout.row: isVertical ? 0 : 0
|
||||
Layout.column: isVertical ? 0 : 1
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "upload-speed"
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: SystemStatService.formatSpeed(SystemStatService.txSpeed)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
font.pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disk Usage Component (primary drive)
|
||||
Item {
|
||||
Layout.preferredWidth: diskUsageRow.implicitWidth
|
||||
Layout.preferredWidth: diskContent.implicitWidth
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter
|
||||
visible: showDiskUsage
|
||||
|
||||
RowLayout {
|
||||
id: diskUsageRow
|
||||
GridLayout {
|
||||
id: diskContent
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXS * scaling
|
||||
|
||||
NIcon {
|
||||
icon: "storage"
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight
|
||||
rows: isVertical ? 2 : 1
|
||||
columns: isVertical ? 1 : 2
|
||||
rowSpacing: Style.marginXXS * scaling
|
||||
columnSpacing: isVertical ? (Style.marginXXS * scaling) : (Style.marginXS * scaling)
|
||||
|
||||
NText {
|
||||
text: `${SystemStatService.diskPercent}%`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
font.pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mPrimary
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical layout for left/right bars
|
||||
ColumnLayout {
|
||||
id: verticalLayout
|
||||
anchors.centerIn: parent
|
||||
anchors.topMargin: Style.marginS * scaling
|
||||
anchors.bottomMargin: Style.marginS * scaling
|
||||
width: Math.round(28 * scaling)
|
||||
spacing: Style.marginS * scaling
|
||||
visible: barPosition === "left" || barPosition === "right"
|
||||
|
||||
// CPU Usage Component
|
||||
Item {
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.preferredWidth: Math.round(28 * scaling)
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: showCpuUsage
|
||||
|
||||
Column {
|
||||
id: cpuUsageRowVertical
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
text: `${Math.round(SystemStatService.cpuUsage)}%`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "cpu-usage"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CPU Temperature Component
|
||||
Item {
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.preferredWidth: Math.round(28 * scaling)
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: showCpuTemp
|
||||
|
||||
Column {
|
||||
id: cpuTempRowVertical
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
text: `${SystemStatService.cpuTemp}°`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "cpu-temperature"
|
||||
// Fire is so tall, we need to make it smaller
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Memory Usage Component
|
||||
Item {
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.preferredWidth: Math.round(28 * scaling)
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: showMemoryUsage
|
||||
|
||||
Column {
|
||||
id: memoryUsageRowVertical
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
text: showMemoryAsPercent ? `${SystemStatService.memPercent}%` : `${Math.round(SystemStatService.memGb)}G`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "memory"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Network Download Speed Component
|
||||
Item {
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.preferredWidth: Math.round(28 * scaling)
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: showNetworkStats
|
||||
|
||||
Column {
|
||||
id: networkDownloadRowVertical
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: formatCompactSpeed(SystemStatService.rxSpeed)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "download-speed"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Network Upload Speed Component
|
||||
Item {
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.preferredWidth: Math.round(28 * scaling)
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: showNetworkStats
|
||||
|
||||
Column {
|
||||
id: networkUploadRowVertical
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: formatCompactSpeed(SystemStatService.txSpeed)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "upload-speed"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disk Usage Component (primary drive)
|
||||
Item {
|
||||
Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
Layout.preferredWidth: Math.round(28 * scaling)
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: showDiskUsage
|
||||
|
||||
ColumnLayout {
|
||||
id: diskUsageRowVertical
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
text: `${SystemStatService.diskPercent}%`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Color.mPrimary
|
||||
Layout.row: isVertical ? 0 : 0
|
||||
Layout.column: isVertical ? 0 : 1
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "storage"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
font.pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
pragma ComponentBehavior
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
|
@ -15,18 +13,32 @@ Rectangle {
|
|||
property ShellScreen screen
|
||||
property real scaling: 1.0
|
||||
|
||||
readonly property real itemSize: Style.baseWidgetSize * 0.8 * scaling
|
||||
readonly property bool isVerticalBar: Settings.data.bar.position === "left" || Settings.data.bar.position === "right"
|
||||
readonly property bool compact: (Settings.data.bar.density === "compact")
|
||||
readonly property real itemSize: compact ? Style.capsuleHeight * 0.9 * scaling : Style.capsuleHeight * 0.8 * scaling
|
||||
|
||||
// Always visible when there are toplevels
|
||||
implicitWidth: taskbarLayout.implicitWidth + Style.marginM * scaling * 2
|
||||
implicitHeight: Math.round(Style.capsuleHeight * scaling)
|
||||
implicitWidth: isVerticalBar ? Math.round(Style.capsuleHeight * scaling) : taskbarLayout.implicitWidth + Style.marginM * scaling * 2
|
||||
implicitHeight: isVerticalBar ? taskbarLayout.implicitHeight + Style.marginM * scaling * 2 : Math.round(Style.capsuleHeight * scaling)
|
||||
radius: Math.round(Style.radiusM * scaling)
|
||||
color: Color.mSurfaceVariant
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
RowLayout {
|
||||
GridLayout {
|
||||
id: taskbarLayout
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.marginXXS * root.scaling
|
||||
anchors.fill: parent
|
||||
anchors {
|
||||
leftMargin: isVerticalBar ? undefined : Style.marginM * scaling
|
||||
rightMargin: isVerticalBar ? undefined : Style.marginM * scaling
|
||||
topMargin: compact ? 0 : isVerticalBar ? Style.marginM * scaling : undefined
|
||||
bottomMargin: compact ? 0 : isVerticalBar ? Style.marginM * scaling : undefined
|
||||
}
|
||||
|
||||
// Configure GridLayout to behave like RowLayout or ColumnLayout
|
||||
rows: isVerticalBar ? -1 : 1 // -1 means unlimited
|
||||
columns: isVerticalBar ? 1 : -1 // -1 means unlimited
|
||||
|
||||
rowSpacing: isVerticalBar ? Style.marginXXS * root.scaling : 0
|
||||
columnSpacing: isVerticalBar ? 0 : Style.marginXXS * root.scaling
|
||||
|
||||
Repeater {
|
||||
model: ToplevelManager && ToplevelManager.toplevels ? ToplevelManager.toplevels : []
|
||||
|
|
@ -43,8 +55,8 @@ Rectangle {
|
|||
Rectangle {
|
||||
id: iconBackground
|
||||
anchors.centerIn: parent
|
||||
width: root.itemSize * 0.75
|
||||
height: root.itemSize * 0.75
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: taskbarItem.isActive ? Color.mPrimary : root.color
|
||||
border.width: 0
|
||||
radius: Math.round(Style.radiusXS * root.scaling)
|
||||
|
|
@ -54,10 +66,11 @@ Rectangle {
|
|||
IconImage {
|
||||
id: appIcon
|
||||
anchors.centerIn: parent
|
||||
width: Style.marginL * root.scaling
|
||||
height: Style.marginL * root.scaling
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
source: AppIcons.iconForAppId(taskbarItem.modelData.appId)
|
||||
smooth: true
|
||||
asynchronous: true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@ Rectangle {
|
|||
property ShellScreen screen
|
||||
property real scaling: 1.0
|
||||
|
||||
readonly property real itemSize: 24 * scaling
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool isVertical: barPosition === "left" || barPosition === "right"
|
||||
readonly property bool compact: (Settings.data.bar.density === "compact")
|
||||
readonly property real itemSize: isVertical ? width * 0.75 : height * 0.85
|
||||
|
||||
function onLoaded() {
|
||||
// When the widget is fully initialized with its props set the screen for the trayMenu
|
||||
|
|
@ -31,7 +32,7 @@ Rectangle {
|
|||
implicitWidth: isVertical ? Math.round(Style.capsuleHeight * scaling) : (trayFlow.implicitWidth + Style.marginS * scaling * 2)
|
||||
implicitHeight: isVertical ? (trayFlow.implicitHeight + Style.marginS * scaling * 2) : Math.round(Style.capsuleHeight * scaling)
|
||||
radius: Math.round(Style.radiusM * scaling)
|
||||
color: Color.mSurfaceVariant
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import qs.Commons
|
|||
import qs.Modules.SettingsPanel
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.Bar.Extras
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -71,10 +72,11 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
NPill {
|
||||
BarPill {
|
||||
id: pill
|
||||
|
||||
rightOpen: BarWidgetRegistry.getNPillDirection(root)
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
rightOpen: BarWidgetRegistry.getPillDirection(root)
|
||||
icon: getIcon()
|
||||
autoHide: false // Important to be false so we can hover as long as we want
|
||||
text: Math.floor(AudioService.volume * 100)
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ NIconButton {
|
|||
property ShellScreen screen
|
||||
property real scaling: 1.0
|
||||
|
||||
sizeRatio: 0.8
|
||||
|
||||
colorBg: Color.mSurfaceVariant
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
baseSize: Style.capsuleHeight
|
||||
colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.transparent
|
||||
|
|
|
|||
|
|
@ -32,6 +32,15 @@ Item {
|
|||
}
|
||||
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool isVertical: barPosition === "left" || barPosition === "right"
|
||||
readonly property bool compact: (Settings.data.bar.density === "compact")
|
||||
readonly property real baseDimensionRatio: {
|
||||
const b = compact ? 0.85 : 0.65
|
||||
if (widgetSettings.labelMode === "none") {
|
||||
return b * 0.75
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
readonly property string labelMode: (widgetSettings.labelMode !== undefined) ? widgetSettings.labelMode : widgetMetadata.labelMode
|
||||
readonly property bool hideUnoccupied: (widgetSettings.hideUnoccupied !== undefined) ? widgetSettings.hideUnoccupied : widgetMetadata.hideUnoccupied
|
||||
|
|
@ -49,47 +58,45 @@ Item {
|
|||
|
||||
signal workspaceChanged(int workspaceId, color accentColor)
|
||||
|
||||
implicitHeight: (barPosition === "left" || barPosition === "right") ? calculatedVerticalHeight() : Math.round(Style.barHeight * scaling)
|
||||
implicitWidth: (barPosition === "left" || barPosition === "right") ? Math.round(Style.barHeight * scaling) : calculatedHorizontalWidth()
|
||||
implicitWidth: isVertical ? Math.round(Style.barHeight * scaling) : computeWidth()
|
||||
implicitHeight: isVertical ? computeHeight() : Math.round(Style.barHeight * scaling)
|
||||
|
||||
function calculatedWsWidth(ws) {
|
||||
function getWorkspaceWidth(ws) {
|
||||
const d = Style.capsuleHeight * root.baseDimensionRatio
|
||||
if (ws.isFocused)
|
||||
return Math.round(44 * scaling)
|
||||
else if (ws.isActive)
|
||||
return Math.round(28 * scaling)
|
||||
return d * 2.5
|
||||
else
|
||||
return Math.round(20 * scaling)
|
||||
return d
|
||||
}
|
||||
|
||||
function calculatedWsHeight(ws) {
|
||||
function getWorkspaceHeight(ws) {
|
||||
const d = Style.capsuleHeight * root.baseDimensionRatio
|
||||
if (ws.isFocused)
|
||||
return Math.round(44 * scaling)
|
||||
else if (ws.isActive)
|
||||
return Math.round(28 * scaling)
|
||||
return d * 3
|
||||
else
|
||||
return Math.round(20 * scaling)
|
||||
return d
|
||||
}
|
||||
|
||||
function calculatedVerticalHeight() {
|
||||
function computeWidth() {
|
||||
let total = 0
|
||||
for (var i = 0; i < localWorkspaces.count; i++) {
|
||||
const ws = localWorkspaces.get(i)
|
||||
total += calculatedWsHeight(ws)
|
||||
total += getWorkspaceWidth(ws)
|
||||
}
|
||||
total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills
|
||||
total += horizontalPadding * 2
|
||||
return total
|
||||
return Math.round(total)
|
||||
}
|
||||
|
||||
function calculatedHorizontalWidth() {
|
||||
function computeHeight() {
|
||||
let total = 0
|
||||
for (var i = 0; i < localWorkspaces.count; i++) {
|
||||
const ws = localWorkspaces.get(i)
|
||||
total += calculatedWsWidth(ws)
|
||||
total += getWorkspaceHeight(ws)
|
||||
}
|
||||
total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills
|
||||
total += horizontalPadding * 2
|
||||
return total
|
||||
return Math.round(total)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
|
|
@ -173,10 +180,10 @@ Item {
|
|||
|
||||
Rectangle {
|
||||
id: workspaceBackground
|
||||
width: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * scaling) : parent.width
|
||||
height: (barPosition === "left" || barPosition === "right") ? parent.height : Math.round(Style.capsuleHeight * scaling)
|
||||
width: isVertical ? Math.round(Style.capsuleHeight * scaling) : parent.width
|
||||
height: isVertical ? parent.height : Math.round(Style.capsuleHeight * scaling)
|
||||
radius: Math.round(Style.radiusM * scaling)
|
||||
color: Color.mSurfaceVariant
|
||||
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
|
@ -187,17 +194,16 @@ Item {
|
|||
id: pillRow
|
||||
spacing: spacingBetweenPills
|
||||
anchors.verticalCenter: workspaceBackground.verticalCenter
|
||||
width: root.width - horizontalPadding * 2
|
||||
x: horizontalPadding
|
||||
visible: barPosition === "top" || barPosition === "bottom"
|
||||
visible: !isVertical
|
||||
|
||||
Repeater {
|
||||
id: workspaceRepeaterHorizontal
|
||||
model: localWorkspaces
|
||||
Item {
|
||||
id: workspacePillContainer
|
||||
height: (labelMode !== "none") ? Math.round(18 * scaling) : Math.round(14 * scaling)
|
||||
width: root.calculatedWsWidth(model)
|
||||
width: root.getWorkspaceWidth(model)
|
||||
height: Style.capsuleHeight * root.baseDimensionRatio
|
||||
|
||||
Rectangle {
|
||||
id: pill
|
||||
|
|
@ -216,7 +222,7 @@ Item {
|
|||
return model.idx.toString()
|
||||
}
|
||||
}
|
||||
font.pointSize: model.isFocused ? Style.fontSizeXS * scaling : Style.fontSizeXXS * scaling
|
||||
font.pointSize: model.isFocused ? workspacePillContainer.height * 0.45 : workspacePillContainer.height * 0.42
|
||||
font.capitalization: Font.AllUppercase
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.weight: Style.fontWeightBold
|
||||
|
|
@ -332,17 +338,16 @@ Item {
|
|||
id: pillColumn
|
||||
spacing: spacingBetweenPills
|
||||
anchors.horizontalCenter: workspaceBackground.horizontalCenter
|
||||
height: root.height - horizontalPadding * 2
|
||||
y: horizontalPadding
|
||||
visible: barPosition === "left" || barPosition === "right"
|
||||
visible: isVertical
|
||||
|
||||
Repeater {
|
||||
id: workspaceRepeaterVertical
|
||||
model: localWorkspaces
|
||||
Item {
|
||||
id: workspacePillContainerVertical
|
||||
width: (labelMode !== "none") ? Math.round(18 * scaling) : Math.round(14 * scaling)
|
||||
height: root.calculatedWsHeight(model)
|
||||
width: Style.capsuleHeight * root.baseDimensionRatio
|
||||
height: root.getWorkspaceHeight(model)
|
||||
|
||||
Rectangle {
|
||||
id: pillVertical
|
||||
|
|
@ -361,7 +366,7 @@ Item {
|
|||
return model.idx.toString()
|
||||
}
|
||||
}
|
||||
font.pointSize: model.isFocused ? Style.fontSizeXS * scaling : Style.fontSizeXXS * scaling
|
||||
font.pointSize: model.isFocused ? workspacePillContainerVertical.width * 0.45 : workspacePillContainerVertical.width * 0.42
|
||||
font.capitalization: Font.AllUppercase
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.weight: Style.fontWeightBold
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ NPanel {
|
|||
enabled: Settings.data.network.bluetoothEnabled
|
||||
icon: BluetoothService.adapter && BluetoothService.adapter.discovering ? "stop" : "refresh"
|
||||
tooltipText: "Refresh Devices"
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: {
|
||||
if (BluetoothService.adapter) {
|
||||
BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering
|
||||
|
|
@ -64,7 +64,7 @@ NPanel {
|
|||
NIconButton {
|
||||
icon: "close"
|
||||
tooltipText: "Close."
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: {
|
||||
root.close()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ NPanel {
|
|||
|
||||
preferredWidth: 340
|
||||
preferredHeight: 320
|
||||
panelAnchorRight: Settings.data.bar.position === "right"
|
||||
|
||||
// Main Column
|
||||
panelContent: ColumnLayout {
|
||||
|
|
|
|||
|
|
@ -79,8 +79,11 @@ Item {
|
|||
"icon": app.icon || "application-x-executable",
|
||||
"isImage": false,
|
||||
"onActivate": function () {
|
||||
Logger.log("ApplicationsPlugin", `Launching: ${app.name}`)
|
||||
// Close the launcher/NPanel immediately without any animations.
|
||||
// Ensures we are not preventing the future focusing of the app
|
||||
launcher.closeCompleted()
|
||||
|
||||
Logger.log("ApplicationsPlugin", `Launching: ${app.name}`)
|
||||
if (Settings.data.appLauncher.useApp2Unit && app.id) {
|
||||
Logger.log("ApplicationsPlugin", `Using app2unit for: ${app.id}`)
|
||||
if (app.runInTerminal)
|
||||
|
|
@ -89,11 +92,9 @@ Item {
|
|||
Quickshell.execDetached(["app2unit", "--"].concat(app.command))
|
||||
} else if (app.execute) {
|
||||
app.execute()
|
||||
} else if (app.exec) {
|
||||
// Fallback to manual execution
|
||||
Process.execute(app.exec)
|
||||
} else {
|
||||
Logger.log("ApplicationsPlugin", `Could not launch: ${app.name}`)
|
||||
}
|
||||
launcher.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ Variants {
|
|||
NIconButton {
|
||||
icon: "close"
|
||||
tooltipText: "Close."
|
||||
sizeRatio: 0.6
|
||||
baseSize: Style.baseWidgetSize * 0.6
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.marginM * scaling
|
||||
anchors.right: parent.right
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ NPanel {
|
|||
|
||||
preferredWidth: 380
|
||||
preferredHeight: 500
|
||||
panelAnchorRight: Settings.data.bar.position === "right"
|
||||
panelKeyboardFocus: true
|
||||
|
||||
panelContent: Rectangle {
|
||||
|
|
@ -48,15 +47,15 @@ NPanel {
|
|||
NIconButton {
|
||||
icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell"
|
||||
tooltipText: Settings.data.notifications.doNotDisturb ? "'Do Not Disturb' is enabled." : "'Do Not Disturb' is disabled."
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb
|
||||
onRightClicked: Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
icon: "trash"
|
||||
tooltipText: "Clear history"
|
||||
sizeRatio: 0.8
|
||||
tooltipText: "Clear history."
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: {
|
||||
NotificationService.clearHistory()
|
||||
root.close()
|
||||
|
|
@ -66,7 +65,7 @@ NPanel {
|
|||
NIconButton {
|
||||
icon: "close"
|
||||
tooltipText: "Close."
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: {
|
||||
root.close()
|
||||
}
|
||||
|
|
@ -136,7 +135,7 @@ NPanel {
|
|||
width: notificationList.width
|
||||
height: notificationLayout.implicitHeight + (Style.marginM * scaling * 2)
|
||||
radius: Style.radiusM * scaling
|
||||
color: notificationMouseArea.containsMouse ? Color.mTertiary : Color.mSurfaceVariant
|
||||
color: Color.mSurfaceVariant
|
||||
border.color: Qt.alpha(Color.mOutline, Style.opacityMedium)
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
|
||||
|
|
@ -169,7 +168,7 @@ NPanel {
|
|||
text: (summary || "No summary").substring(0, 100)
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Font.Medium
|
||||
color: notificationMouseArea.containsMouse ? Color.mOnTertiary : Color.mPrimary
|
||||
color: Color.mPrimary
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true
|
||||
maximumLineCount: 2
|
||||
|
|
@ -179,7 +178,7 @@ NPanel {
|
|||
NText {
|
||||
text: (body || "").substring(0, 150)
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
color: notificationMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface
|
||||
color: Color.mOnSurface
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true
|
||||
maximumLineCount: 3
|
||||
|
|
@ -190,7 +189,7 @@ NPanel {
|
|||
NText {
|
||||
text: NotificationService.formatTimestamp(timestamp)
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
color: notificationMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface
|
||||
color: Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
|
@ -198,8 +197,8 @@ NPanel {
|
|||
// Delete button
|
||||
NIconButton {
|
||||
icon: "trash"
|
||||
tooltipText: "Delete notification"
|
||||
sizeRatio: 0.7
|
||||
tooltipText: "Delete notification."
|
||||
baseSize: Style.baseWidgetSize * 0.7
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
onClicked: {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ NBox {
|
|||
property var widgetModel: []
|
||||
property var availableWidgets: []
|
||||
|
||||
readonly property real miniButtonSize: Style.baseWidgetSize * 0.65
|
||||
|
||||
signal addWidget(string widgetId, string section)
|
||||
signal removeWidget(string section, int index)
|
||||
signal reorderWidget(string section, int fromIndex, int toIndex)
|
||||
|
|
@ -178,7 +180,7 @@ NBox {
|
|||
active: BarWidgetRegistry.widgetHasUserSettings(modelData.id)
|
||||
sourceComponent: NIconButton {
|
||||
icon: "settings"
|
||||
sizeRatio: 0.6
|
||||
baseSize: miniButtonSize
|
||||
colorBorder: Qt.alpha(Color.mOutline, Style.opacityLight)
|
||||
colorBg: Color.mOnSurface
|
||||
colorFg: Color.mOnPrimary
|
||||
|
|
@ -218,7 +220,7 @@ NBox {
|
|||
|
||||
NIconButton {
|
||||
icon: "close"
|
||||
sizeRatio: 0.6
|
||||
baseSize: miniButtonSize
|
||||
colorBorder: Qt.alpha(Color.mOutline, Style.opacityLight)
|
||||
colorBg: Color.mOnSurface
|
||||
colorFg: Color.mOnPrimary
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ ColumnLayout {
|
|||
|
||||
NIconButton {
|
||||
icon: "close"
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.rightMargin: Style.marginXS * scaling
|
||||
onClicked: {
|
||||
|
|
|
|||
|
|
@ -45,32 +45,52 @@ ColumnLayout {
|
|||
description: "Configure bar appearance and positioning."
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: "Bar Position"
|
||||
description: "Choose where to place the bar on the screen."
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
key: "top"
|
||||
name: "Top"
|
||||
}
|
||||
ListElement {
|
||||
key: "bottom"
|
||||
name: "Bottom"
|
||||
}
|
||||
ListElement {
|
||||
key: "left"
|
||||
name: "Left"
|
||||
}
|
||||
ListElement {
|
||||
key: "right"
|
||||
name: "Right"
|
||||
}
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: "Bar Position"
|
||||
description: "Choose where to place the bar on the screen."
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
key: "top"
|
||||
name: "Top"
|
||||
}
|
||||
ListElement {
|
||||
key: "bottom"
|
||||
name: "Bottom"
|
||||
}
|
||||
ListElement {
|
||||
key: "left"
|
||||
name: "Left"
|
||||
}
|
||||
ListElement {
|
||||
key: "right"
|
||||
name: "Right"
|
||||
}
|
||||
currentKey: Settings.data.bar.position
|
||||
onSelected: key => Settings.data.bar.position = key
|
||||
}
|
||||
currentKey: Settings.data.bar.position
|
||||
onSelected: key => Settings.data.bar.position = key
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: "Bar Density"
|
||||
description: "Choose the density of the bar."
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
key: "compact"
|
||||
name: "Compact"
|
||||
}
|
||||
ListElement {
|
||||
key: "default"
|
||||
name: "Default"
|
||||
}
|
||||
ListElement {
|
||||
key: "comfortable"
|
||||
name: "Comfortable"
|
||||
}
|
||||
}
|
||||
currentKey: Settings.data.bar.density
|
||||
onSelected: key => Settings.data.bar.density = key
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
|
|
@ -92,6 +112,15 @@ ColumnLayout {
|
|||
text: Math.floor(Settings.data.bar.backgroundOpacity * 100) + "%"
|
||||
}
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: "Show Capsule"
|
||||
description: "Adds a capsule behind each widget to improve readability on transparent bars."
|
||||
checked: Settings.data.bar.showCapsule
|
||||
onToggled: checked => Settings.data.bar.showCapsule = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: "Floating Bar"
|
||||
|
|
@ -163,40 +192,6 @@ ColumnLayout {
|
|||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
|
||||
// Monitor Configuration
|
||||
ColumnLayout {
|
||||
spacing: Style.marginM * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
NHeader {
|
||||
label: "Monitors Configuration"
|
||||
description: "Choose which monitors should display the bar."
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: Quickshell.screens || []
|
||||
delegate: NCheckbox {
|
||||
Layout.fillWidth: true
|
||||
label: `${modelData.name || "Unknown"}${modelData.model ? `: ${modelData.model}` : ""}`
|
||||
description: `${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})`
|
||||
checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1
|
||||
onToggled: checked => {
|
||||
if (checked) {
|
||||
Settings.data.bar.monitors = addMonitor(Settings.data.bar.monitors, modelData.name)
|
||||
} else {
|
||||
Settings.data.bar.monitors = removeMonitor(Settings.data.bar.monitors, modelData.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
|
||||
// Widgets Management Section
|
||||
ColumnLayout {
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
|
@ -264,6 +259,40 @@ ColumnLayout {
|
|||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
|
||||
// Monitor Configuration
|
||||
ColumnLayout {
|
||||
spacing: Style.marginM * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
NHeader {
|
||||
label: "Monitors Configuration"
|
||||
description: "Show bar on specific monitors. Defaults to all if none are chosen."
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: Quickshell.screens || []
|
||||
delegate: NCheckbox {
|
||||
Layout.fillWidth: true
|
||||
label: modelData.name || "Unknown"
|
||||
description: `${modelData.model} - ${modelData.width}x${modelData.height} [x:${modelData.x} y:${modelData.y}]`
|
||||
checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1
|
||||
onToggled: checked => {
|
||||
if (checked) {
|
||||
Settings.data.bar.monitors = addMonitor(Settings.data.bar.monitors, modelData.name)
|
||||
} else {
|
||||
Settings.data.bar.monitors = removeMonitor(Settings.data.bar.monitors, modelData.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
|
||||
// ---------------------------------
|
||||
// Signal functions
|
||||
// ---------------------------------
|
||||
|
|
|
|||
|
|
@ -87,19 +87,9 @@ ColumnLayout {
|
|||
anchors.margins: Style.marginL * scaling
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
||||
NText {
|
||||
text: (`${modelData.name}: ${modelData.model}` || "Unknown")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NText {
|
||||
text: `Resolution: ${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})`
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
NLabel {
|
||||
label: modelData.name || "Unknown"
|
||||
description: `${modelData.model} - ${modelData.width}x${modelData.height} [x:${modelData.x} y:${modelData.y}]`
|
||||
}
|
||||
|
||||
// Scale
|
||||
|
|
@ -134,8 +124,8 @@ ColumnLayout {
|
|||
|
||||
NIconButton {
|
||||
icon: "refresh"
|
||||
sizeRatio: 0.8
|
||||
tooltipText: "Reset scaling"
|
||||
baseSize: Style.baseWidgetSize * 0.9
|
||||
tooltipText: "Reset scaling."
|
||||
onClicked: ScalingService.setScreenScale(modelData, 1.0)
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
|
|
|||
|
|
@ -93,15 +93,15 @@ ColumnLayout {
|
|||
|
||||
NHeader {
|
||||
label: "Monitors Configuration"
|
||||
description: "Choose which monitors should display the dock."
|
||||
description: "Show dock on specific monitors."
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: Quickshell.screens || []
|
||||
delegate: NCheckbox {
|
||||
Layout.fillWidth: true
|
||||
label: `${modelData.name || "Unknown"}${modelData.model ? `: ${modelData.model}` : ""}`
|
||||
description: `${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})`
|
||||
label: modelData.name || "Unknown"
|
||||
description: `${modelData.model} - ${modelData.width}x${modelData.height} [x:${modelData.x} y:${modelData.y}]`
|
||||
checked: (Settings.data.dock.monitors || []).indexOf(modelData.name) !== -1
|
||||
onToggled: checked => {
|
||||
if (checked) {
|
||||
|
|
|
|||
|
|
@ -46,40 +46,6 @@ ColumnLayout {
|
|||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
|
||||
// Monitor Configuration
|
||||
ColumnLayout {
|
||||
spacing: Style.marginM * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
NHeader {
|
||||
label: "Monitors Configuration"
|
||||
description: "Choose which monitors should display notifications."
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: Quickshell.screens || []
|
||||
delegate: NCheckbox {
|
||||
Layout.fillWidth: true
|
||||
label: `${modelData.name || "Unknown"}${modelData.model ? `: ${modelData.model}` : ""}`
|
||||
description: `${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})`
|
||||
checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1
|
||||
onToggled: checked => {
|
||||
if (checked) {
|
||||
Settings.data.notifications.monitors = addMonitor(Settings.data.notifications.monitors, modelData.name)
|
||||
} else {
|
||||
Settings.data.notifications.monitors = removeMonitor(Settings.data.notifications.monitors, modelData.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
|
||||
// Notification Duration Settings
|
||||
ColumnLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
|
|
@ -159,4 +125,38 @@ ColumnLayout {
|
|||
Layout.topMargin: Style.marginXL * scaling
|
||||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
|
||||
// Monitor Configuration
|
||||
ColumnLayout {
|
||||
spacing: Style.marginM * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
NHeader {
|
||||
label: "Monitors Configuration"
|
||||
description: "Show bar on specific monitors. Defaults to all if none are chosen."
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: Quickshell.screens || []
|
||||
delegate: NCheckbox {
|
||||
Layout.fillWidth: true
|
||||
label: modelData.name || "Unknown"
|
||||
description: `${modelData.model} - ${modelData.width}x${modelData.height} [x:${modelData.x} y:${modelData.y}]`
|
||||
checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1
|
||||
onToggled: checked => {
|
||||
if (checked) {
|
||||
Settings.data.notifications.monitors = addMonitor(Settings.data.notifications.monitors, modelData.name)
|
||||
} else {
|
||||
Settings.data.notifications.monitors = removeMonitor(Settings.data.notifications.monitors, modelData.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ ColumnLayout {
|
|||
// Source
|
||||
NComboBox {
|
||||
label: "Video Source"
|
||||
description: "Portal is recommend, if you get artifacts try Screen."
|
||||
description: "Portal is recommended, if you get artifacts try Screen."
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
key: "portal"
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ Rectangle {
|
|||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.mOutline
|
||||
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
onClicked: root.hide()
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ NPanel {
|
|||
NIconButton {
|
||||
icon: "refresh"
|
||||
tooltipText: "Refresh"
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
enabled: Settings.data.network.wifiEnabled && !NetworkService.scanning
|
||||
onClicked: NetworkService.scan()
|
||||
}
|
||||
|
|
@ -65,7 +65,7 @@ NPanel {
|
|||
NIconButton {
|
||||
icon: "close"
|
||||
tooltipText: "Close."
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: root.close()
|
||||
}
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ NPanel {
|
|||
|
||||
NIconButton {
|
||||
icon: "close"
|
||||
sizeRatio: 0.6
|
||||
baseSize: Style.baseWidgetSize * 0.6
|
||||
onClicked: NetworkService.lastError = ""
|
||||
}
|
||||
}
|
||||
|
|
@ -368,7 +368,7 @@ NPanel {
|
|||
visible: (modelData.existing || modelData.cached) && !modelData.connected && NetworkService.connectingTo !== modelData.ssid && NetworkService.forgettingNetwork !== modelData.ssid && NetworkService.disconnectingFrom !== modelData.ssid
|
||||
icon: "trash"
|
||||
tooltipText: "Forget network"
|
||||
sizeRatio: 0.7
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: expandedSsid = expandedSsid === modelData.ssid ? "" : modelData.ssid
|
||||
}
|
||||
|
||||
|
|
@ -478,7 +478,7 @@ NPanel {
|
|||
|
||||
NIconButton {
|
||||
icon: "close"
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: {
|
||||
passwordSsid = ""
|
||||
passwordInput = ""
|
||||
|
|
@ -532,7 +532,7 @@ NPanel {
|
|||
|
||||
NIconButton {
|
||||
icon: "close"
|
||||
sizeRatio: 0.8
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: expandedSsid = ""
|
||||
}
|
||||
}
|
||||
|
|
|
|||
21
README.md
21
README.md
|
|
@ -230,6 +230,23 @@ Start the Shell with: `qs -c noctalia-shell`
|
|||
Access settings through the side panel (top right button) to configure weather, wallpapers, screen recording, audio, network, and theme options.
|
||||
Configuration is usually stored in ~/.config/noctalia.
|
||||
|
||||
### Some of my app icons are missing!
|
||||
|
||||
The issue is most likely that you did not set up your environment variables properly.
|
||||
Example environment variables that you can use one of the following:
|
||||
|
||||
If you already have an icon theme set for GTK then you can use this one:
|
||||
- `QT_QPA_PLATFORMTHEME=gtk3`
|
||||
|
||||
You can also use Qt6ct to set your icon theme, for that you can use:
|
||||
- `QT_QPA_PLATFORMTHEME=qt6ct`
|
||||
|
||||
If you don't have either of those set then you can just use:
|
||||
- `QS_ICON_THEME="youricontheme"`
|
||||
|
||||
**Any of these environment variables should go into `/etc/environment` (you need to reboot afterwards). For NixOS you can use `environment.variables` or `home.sessionVariables`.**
|
||||
|
||||
|
||||
### Application Launcher
|
||||
|
||||
The launcher supports special commands for enhanced functionality:
|
||||
|
|
@ -278,10 +295,6 @@ window-rule {
|
|||
clip-to-geometry true
|
||||
}
|
||||
|
||||
layer-rule {
|
||||
match namespace="^quickshell-wallpaper$"
|
||||
}
|
||||
|
||||
layer-rule {
|
||||
match namespace="^quickshell-overview$"
|
||||
place-within-backdrop true
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ Singleton {
|
|||
return (widgetMetadata[id] !== undefined) && (widgetMetadata[id].allowUserSettings === true)
|
||||
}
|
||||
|
||||
function getNPillDirection(widget) {
|
||||
function getPillDirection(widget) {
|
||||
try {
|
||||
if (widget.section === "left") {
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ Singleton {
|
|||
|
||||
property var registeredPanels: ({})
|
||||
|
||||
signal willOpen
|
||||
signal willClose
|
||||
|
||||
// Register this panel
|
||||
function registerPanel(panel) {
|
||||
registeredPanels[panel.objectName] = panel
|
||||
|
|
@ -38,6 +41,14 @@ Singleton {
|
|||
openedPanel.close()
|
||||
}
|
||||
openedPanel = panel
|
||||
|
||||
// emit signal
|
||||
willOpen()
|
||||
}
|
||||
|
||||
function willClosePanel(panel) {
|
||||
// emit signal
|
||||
willClose()
|
||||
}
|
||||
|
||||
function closedPanel(panel) {
|
||||
|
|
|
|||
|
|
@ -333,6 +333,26 @@ Singleton {
|
|||
}
|
||||
}
|
||||
|
||||
// Compact speed formatter for vertical bar display
|
||||
function formatCompactSpeed(bytesPerSecond) {
|
||||
if (!bytesPerSecond || bytesPerSecond <= 0)
|
||||
return "0"
|
||||
const units = ["", "K", "M", "G"]
|
||||
let value = bytesPerSecond
|
||||
let unitIndex = 0
|
||||
while (value >= 1024 && unitIndex < units.length - 1) {
|
||||
value = value / 1024.0
|
||||
unitIndex++
|
||||
}
|
||||
// Promote at ~100 of current unit (e.g., 100k -> ~0.1M shown as 0.1M or 0M if rounded)
|
||||
if (unitIndex < units.length - 1 && value >= 100) {
|
||||
value = value / 1024.0
|
||||
unitIndex++
|
||||
}
|
||||
const display = Math.round(value).toString()
|
||||
return display + units[unitIndex]
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Function to start fetching and computing the cpu temperature
|
||||
function updateCpuTemperature() {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Singleton {
|
|||
id: root
|
||||
|
||||
// Public properties
|
||||
property string baseVersion: "2.9.2"
|
||||
property string baseVersion: "2.11.0"
|
||||
property bool isDevelopment: false
|
||||
|
||||
property string currentVersion: `v${!isDevelopment ? baseVersion : baseVersion + "-dev"}`
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Rectangle {
|
|||
signal colorSelected(color color)
|
||||
|
||||
implicitWidth: 150 * scaling
|
||||
implicitHeight: 40 * scaling
|
||||
implicitHeight: Math.round(Style.baseWidgetSize * 1.1 * scaling)
|
||||
|
||||
radius: Style.radiusM * scaling
|
||||
color: Color.mSurface
|
||||
|
|
@ -40,12 +40,16 @@ Rectangle {
|
|||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginS * scaling
|
||||
anchors {
|
||||
leftMargin: Style.marginL * scaling
|
||||
rightMargin: Style.marginL * scaling
|
||||
}
|
||||
spacing: Style.marginS * scaling
|
||||
|
||||
// Color preview circle
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 24 * scaling
|
||||
Layout.preferredHeight: 24 * scaling
|
||||
Layout.preferredWidth: root.height * 0.6 * scaling
|
||||
Layout.preferredHeight: root.height * 0.6 * scaling
|
||||
radius: Layout.preferredWidth * 0.5
|
||||
color: root.selectedColor
|
||||
border.color: Color.mOutline
|
||||
|
|
@ -56,11 +60,14 @@ Rectangle {
|
|||
text: root.selectedColor.toString().toUpperCase()
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "color-picker"
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ import qs.Services
|
|||
Rectangle {
|
||||
id: root
|
||||
|
||||
// Multiplier to control how large the button container is relative to Style.baseWidgetSize
|
||||
property real sizeRatio: 1.0
|
||||
property real baseSize: Style.baseWidgetSize
|
||||
|
||||
property string icon
|
||||
property string tooltipText
|
||||
property bool enabled: true
|
||||
property bool allowClickWhenDisabled: false
|
||||
property bool hovering: false
|
||||
property bool compact: false
|
||||
|
||||
property color colorBg: Color.mSurfaceVariant
|
||||
property color colorFg: Color.mPrimary
|
||||
|
|
@ -29,8 +29,8 @@ Rectangle {
|
|||
signal rightClicked
|
||||
signal middleClicked
|
||||
|
||||
implicitWidth: Math.round(Style.baseWidgetSize * scaling * sizeRatio)
|
||||
implicitHeight: Math.round(Style.baseWidgetSize * scaling * sizeRatio)
|
||||
implicitWidth: Math.round(baseSize * scaling)
|
||||
implicitHeight: Math.round(baseSize * scaling)
|
||||
|
||||
opacity: root.enabled ? Style.opacityFull : Style.opacityMedium
|
||||
color: root.enabled && root.hovering ? colorBgHover : colorBg
|
||||
|
|
@ -47,7 +47,7 @@ Rectangle {
|
|||
|
||||
NIcon {
|
||||
icon: root.icon
|
||||
font.pointSize: Math.max(1, root.width * 0.47)
|
||||
font.pointSize: Math.max(1, root.compact ? root.width * 0.65 : root.width * 0.48)
|
||||
color: root.enabled && root.hovering ? colorFgHover : colorFg
|
||||
// Center horizontally
|
||||
x: (root.width - width) / 2
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ Loader {
|
|||
readonly property real originalOpacity: 0.0
|
||||
property real scaleValue: originalScale
|
||||
property real opacityValue: originalOpacity
|
||||
property real dimmingOpacity: 0
|
||||
|
||||
property alias isClosing: hideTimer.running
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
|
||||
signal opened
|
||||
signal closed
|
||||
|
|
@ -109,9 +109,11 @@ Loader {
|
|||
|
||||
// -----------------------------------------
|
||||
function close() {
|
||||
dimmingOpacity = 0
|
||||
scaleValue = originalScale
|
||||
opacityValue = originalOpacity
|
||||
hideTimer.start()
|
||||
PanelService.willClosePanel(root)
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
|
@ -141,10 +143,16 @@ Loader {
|
|||
|
||||
// PanelWindow has its own screen property inherited of QsWindow
|
||||
property real scaling: ScalingService.getScreenScale(screen)
|
||||
readonly property real barHeight: Math.round(Style.barHeight * scaling)
|
||||
readonly property real barWidth: Math.round(Style.barHeight * scaling)
|
||||
readonly property bool barAtBottom: Settings.data.bar.position === "bottom"
|
||||
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool isVertical: barPosition === "left" || barPosition === "right"
|
||||
readonly property bool barIsVisible: (screen !== null) && (Settings.data.bar.monitors.includes(screen.name) || (Settings.data.bar.monitors.length === 0))
|
||||
readonly property real verticalBarWidth: Math.round(Style.barHeight * scaling)
|
||||
|
||||
Component.onCompleted: {
|
||||
Logger.log("NPanel", "Opened", root.objectName)
|
||||
dimmingOpacity = Style.opacityHeavy
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ScalingService
|
||||
|
|
@ -169,16 +177,14 @@ Loader {
|
|||
|
||||
visible: true
|
||||
|
||||
// Dim desktop if required
|
||||
color: (root.active && !root.isClosing && Settings.data.general.dimDesktop) ? Qt.alpha(Color.mShadow, Style.opacityHeavy) : Color.transparent
|
||||
|
||||
color: Settings.data.general.dimDesktop ? Qt.alpha(Color.mShadow, dimmingOpacity) : Color.transparent
|
||||
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||
WlrLayershell.namespace: "noctalia-panel"
|
||||
WlrLayershell.keyboardFocus: root.panelKeyboardFocus ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationNormal
|
||||
duration: Style.animationSlow
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,29 +192,6 @@ Loader {
|
|||
anchors.left: true
|
||||
anchors.right: true
|
||||
anchors.bottom: true
|
||||
margins.top: {
|
||||
if (!barIsVisible || barAtBottom) {
|
||||
return 0
|
||||
}
|
||||
switch (Settings.data.bar.position) {
|
||||
case "top":
|
||||
return (Style.barHeight + Style.marginM) * scaling + (Settings.data.bar.floating && !panelAnchorVerticalCenter ? Settings.data.bar.marginVertical * Style.marginXL * scaling : 0)
|
||||
default:
|
||||
return Style.marginM * scaling
|
||||
}
|
||||
}
|
||||
|
||||
margins.bottom: {
|
||||
if (!barIsVisible || !barAtBottom) {
|
||||
return 0
|
||||
}
|
||||
switch (Settings.data.bar.position) {
|
||||
case "bottom":
|
||||
return (Style.barHeight + Style.marginM) * scaling + (Settings.data.bar.floating && !panelAnchorVerticalCenter ? Settings.data.bar.marginVertical * Style.marginXL * scaling : 0)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// Close any panel with Esc without requiring focus
|
||||
Shortcut {
|
||||
|
|
@ -225,6 +208,7 @@ Loader {
|
|||
onClicked: root.close()
|
||||
}
|
||||
|
||||
// The actual panel's content
|
||||
Rectangle {
|
||||
id: panelBackground
|
||||
color: panelBackgroundColor
|
||||
|
|
@ -255,130 +239,131 @@ Loader {
|
|||
|
||||
scale: root.scaleValue
|
||||
opacity: root.opacityValue
|
||||
|
||||
x: calculatedX
|
||||
y: calculatedY
|
||||
|
||||
property int calculatedX: {
|
||||
var barPosition = Settings.data.bar.position
|
||||
|
||||
// Check anchor properties first, even when using button positioning
|
||||
if (!panelAnchorHorizontalCenter && panelAnchorLeft) {
|
||||
return Math.round(Style.marginS * scaling)
|
||||
} else if (!panelAnchorHorizontalCenter && panelAnchorRight) {
|
||||
// For right anchor, consider bar position
|
||||
if (barPosition === "right") {
|
||||
// If bar is on right, position panel to the left of the bar
|
||||
var maxX = panelWindow.width - barWidth - panelBackground.width - (Style.marginS * scaling)
|
||||
|
||||
// If we have button position, position close to the button like working panels
|
||||
if (root.useButtonPosition) {
|
||||
// Use the same logic as working panels - position at edge of bar with spacing
|
||||
var maxXWithSpacing = panelWindow.width - barWidth - panelBackground.width
|
||||
// Add spacing - more if screen corners are disabled, less if enabled
|
||||
if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) {
|
||||
maxXWithSpacing -= Style.marginL * scaling
|
||||
} else {
|
||||
maxXWithSpacing -= Style.marginM * scaling
|
||||
}
|
||||
return Math.round(maxXWithSpacing)
|
||||
} else {
|
||||
return Math.round(maxX)
|
||||
}
|
||||
} else {
|
||||
// Default right positioning
|
||||
var rightX = panelWindow.width - panelBackground.width - (Style.marginS * scaling)
|
||||
return Math.round(rightX)
|
||||
}
|
||||
} else if (root.useButtonPosition) {
|
||||
// Position panel relative to button (only if no explicit anchoring)
|
||||
var targetX
|
||||
|
||||
// For vertical bars, position panel close to the button
|
||||
if (barPosition === "left") {
|
||||
// Position panel to the right of the left bar, close to the button
|
||||
var minX = barWidth
|
||||
// Add spacing - more if screen corners are disabled, less if enabled
|
||||
if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) {
|
||||
minX += Style.marginL * scaling
|
||||
} else {
|
||||
minX += Style.marginM * scaling
|
||||
}
|
||||
targetX = minX
|
||||
} else if (barPosition === "right") {
|
||||
// Position panel to the left of the right bar, close to the button
|
||||
var maxX = panelWindow.width - barWidth - panelBackground.width
|
||||
// Add spacing - more if screen corners are disabled, less if enabled
|
||||
if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) {
|
||||
maxX -= Style.marginL * scaling
|
||||
} else {
|
||||
maxX -= Style.marginM * scaling
|
||||
}
|
||||
targetX = maxX
|
||||
} else {
|
||||
// For horizontal bars, center panel on button
|
||||
targetX = root.buttonPosition.x + (root.buttonWidth / 2) - (panelBackground.width / 2)
|
||||
}
|
||||
|
||||
// Keep panel within screen bounds
|
||||
var maxScreenX = panelWindow.width - panelBackground.width - (Style.marginS * scaling)
|
||||
var minScreenX = Style.marginS * scaling
|
||||
|
||||
return Math.round(Math.max(minScreenX, Math.min(targetX, maxScreenX)))
|
||||
} else {
|
||||
// For vertical bars, center but avoid bar overlap
|
||||
var centerX = (panelWindow.width - panelBackground.width) / 2
|
||||
if (barPosition === "left") {
|
||||
var minX = barWidth
|
||||
// Add spacing - more if screen corners are disabled, less if enabled
|
||||
if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) {
|
||||
minX += Style.marginL * scaling
|
||||
} else {
|
||||
minX += Style.marginM * scaling
|
||||
}
|
||||
centerX = Math.max(centerX, minX)
|
||||
} else if (barPosition === "right") {
|
||||
// For right bar, center but ensure it doesn't overlap with the bar
|
||||
var maxX = panelWindow.width - barWidth - panelBackground.width
|
||||
// Add spacing - more if screen corners are disabled, less if enabled
|
||||
if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) {
|
||||
maxX -= Style.marginL * scaling
|
||||
} else {
|
||||
maxX -= Style.marginM * scaling
|
||||
}
|
||||
centerX = Math.min(centerX, maxX)
|
||||
}
|
||||
return Math.round(centerX)
|
||||
// ---------------------------------------------
|
||||
// Does not account for corners are they are negligible and helps keep the code clean.
|
||||
// ---------------------------------------------
|
||||
property real marginTop: {
|
||||
if (!barIsVisible) {
|
||||
return 0
|
||||
}
|
||||
switch (barPosition || panelAnchorVerticalCenter) {
|
||||
case "top":
|
||||
return (Style.barHeight + Style.marginS) * scaling + (Settings.data.bar.floating ? Settings.data.bar.marginVertical * 2 * Style.marginXL * scaling : 0)
|
||||
default:
|
||||
return Style.marginS * scaling
|
||||
}
|
||||
}
|
||||
|
||||
property int calculatedY: {
|
||||
var barPosition = Settings.data.bar.position
|
||||
property real marginBottom: {
|
||||
if (!barIsVisible || panelAnchorVerticalCenter) {
|
||||
return 0
|
||||
}
|
||||
switch (barPosition) {
|
||||
case "bottom":
|
||||
return (Style.barHeight + Style.marginS) * scaling + (Settings.data.bar.floating ? Settings.data.bar.marginVertical * 2 * Style.marginXL * scaling : 0)
|
||||
default:
|
||||
return Style.marginS * scaling
|
||||
}
|
||||
}
|
||||
|
||||
if (root.useButtonPosition) {
|
||||
// Position panel relative to button
|
||||
var targetY = root.buttonPosition.y + (root.buttonHeight / 2) - (panelBackground.height / 2)
|
||||
property real marginLeft: {
|
||||
if (!barIsVisible || panelAnchorHorizontalCenter) {
|
||||
return 0
|
||||
}
|
||||
switch (barPosition) {
|
||||
case "left":
|
||||
return (Style.barHeight + Style.marginS) * scaling + (Settings.data.bar.floating ? Settings.data.bar.marginHorizontal * 2 * Style.marginXL * scaling : 0)
|
||||
default:
|
||||
return Style.marginS * scaling
|
||||
}
|
||||
}
|
||||
|
||||
// Keep panel within screen bounds
|
||||
var maxY = panelWindow.height - panelBackground.height - (Style.marginS * scaling)
|
||||
var minY = Style.marginS * scaling
|
||||
property real marginRight: {
|
||||
if (!barIsVisible || panelAnchorHorizontalCenter) {
|
||||
return 0
|
||||
}
|
||||
switch (barPosition) {
|
||||
case "right":
|
||||
return (Style.barHeight + Style.marginS) * scaling + (Settings.data.bar.floating ? Settings.data.bar.marginHorizontal * 2 * Style.marginXL * scaling : 0)
|
||||
default:
|
||||
return Style.marginS * scaling
|
||||
}
|
||||
}
|
||||
|
||||
return Math.round(Math.max(minY, Math.min(targetY, maxY)))
|
||||
} else if (panelAnchorVerticalCenter) {
|
||||
return Math.round((panelWindow.height - panelBackground.height) / 2)
|
||||
} else if (panelAnchorBottom) {
|
||||
return Math.round(panelWindow.height - panelBackground.height - (Style.marginS * scaling))
|
||||
} else if (panelAnchorTop) {
|
||||
return Math.round(Style.marginS * scaling)
|
||||
} else if (barPosition === "left" || barPosition === "right") {
|
||||
// For vertical bars, center vertically
|
||||
return Math.round((panelWindow.height - panelBackground.height) / 2)
|
||||
} else if (!barAtBottom) {
|
||||
// Below the top bar
|
||||
return Math.round(Style.marginS * scaling)
|
||||
// ---------------------------------------------
|
||||
property int calculatedX: {
|
||||
// Priority to fixed anchoring
|
||||
if (panelAnchorHorizontalCenter) {
|
||||
return Math.round((panelWindow.width - panelBackground.width) / 2)
|
||||
} else if (panelAnchorLeft) {
|
||||
return marginLeft
|
||||
} else if (panelAnchorRight) {
|
||||
return Math.round(panelWindow.width - panelBackground.width - marginRight)
|
||||
}
|
||||
|
||||
// No fixed anchoring
|
||||
if (isVertical) {
|
||||
// Vertical bar
|
||||
if (barPosition === "right") {
|
||||
// To the left of the right bar
|
||||
return Math.round(panelWindow.width - panelBackground.width - marginRight)
|
||||
} else {
|
||||
// To the right of the left bar
|
||||
return marginLeft
|
||||
}
|
||||
} else {
|
||||
// Above the bottom bar
|
||||
return Math.round(panelWindow.height - panelBackground.height - (Style.marginS * scaling))
|
||||
// Horizontal bar
|
||||
if (root.useButtonPosition) {
|
||||
// Position panel relative to button
|
||||
var targetX = buttonPosition.x + (buttonWidth / 2) - (panelBackground.width / 2)
|
||||
// Keep panel within screen bounds
|
||||
var maxX = panelWindow.width - panelBackground.width - marginRight
|
||||
var minX = marginLeft
|
||||
return Math.round(Math.max(minX, Math.min(targetX, maxX)))
|
||||
} else {
|
||||
// Fallback to center horizontally
|
||||
return Math.round((panelWindow.width - panelBackground.width) / 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
property int calculatedY: {
|
||||
// Priority to fixed anchoring
|
||||
if (panelAnchorVerticalCenter) {
|
||||
return Math.round((panelWindow.height - panelBackground.height) / 2)
|
||||
} else if (panelAnchorTop) {
|
||||
return marginTop
|
||||
} else if (panelAnchorBottom) {
|
||||
return Math.round(panelWindow.height - panelBackground.height - marginBottom)
|
||||
}
|
||||
|
||||
// No fixed anchoring
|
||||
if (isVertical) {
|
||||
// Vertical bar
|
||||
if (useButtonPosition) {
|
||||
// Position panel relative to button
|
||||
var targetY = buttonPosition.y + (buttonHeight / 2) - (panelBackground.height / 2)
|
||||
// Keep panel within screen bounds
|
||||
var maxY = panelWindow.height - panelBackground.height - marginBottom
|
||||
var minY = marginTop
|
||||
return Math.round(Math.max(minY, Math.min(targetY, maxY)))
|
||||
} else {
|
||||
// Fallback to center vertically
|
||||
return Math.round((panelWindow.height - panelBackground.height) / 2)
|
||||
}
|
||||
} else {
|
||||
// Horizontal bar
|
||||
if (barPosition === "bottom") {
|
||||
// Above the bottom bar
|
||||
return Math.round(panelWindow.height - panelBackground.height - marginBottom)
|
||||
} else {
|
||||
// Below the top bar
|
||||
return marginTop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ RowLayout {
|
|||
NText {
|
||||
anchors.centerIn: parent
|
||||
text: root.prefix + spinBox.value + root.suffix
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: Color.mOnSurface
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Item {
|
|||
item.onLoaded()
|
||||
}
|
||||
|
||||
//Logger.log("NWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name)
|
||||
Logger.log("NWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue