mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
Redesign center command center
This commit is contained in:
@@ -71,10 +71,8 @@ Singleton {
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
console.log("SystemMonitorService: CPU usage raw data:", text.trim())
|
||||
if (text.trim()) {
|
||||
root.cpuUsage = parseFloat(text.trim())
|
||||
console.log("SystemMonitorService: CPU usage set to:", root.cpuUsage)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +92,6 @@ Singleton {
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
console.log("SystemMonitorService: Memory usage raw data:", text.trim())
|
||||
if (text.trim()) {
|
||||
const parts = text.trim().split(" ")
|
||||
root.memoryUsage = parseFloat(parts[0])
|
||||
@@ -102,7 +99,6 @@ Singleton {
|
||||
root.usedMemory = parseFloat(parts[2])
|
||||
root.availableMemory = parseFloat(parts[3])
|
||||
root.freeMemory = root.totalMemory - root.usedMemory
|
||||
console.log("SystemMonitorService: Memory usage set to:", root.memoryUsage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,11 @@ PanelWindow {
|
||||
property var weather: root.weather
|
||||
property bool useFahrenheit: false
|
||||
|
||||
// Prevent media player from disappearing during track changes
|
||||
property bool showMediaPlayer: hasActiveMedia || hideMediaTimer.running
|
||||
|
||||
Timer {
|
||||
id: hideMediaTimer
|
||||
interval: 3000 // 3 second grace period
|
||||
interval: 3000
|
||||
running: false
|
||||
repeat: false
|
||||
}
|
||||
@@ -36,8 +35,8 @@ PanelWindow {
|
||||
|
||||
visible: root.calendarVisible
|
||||
|
||||
implicitWidth: 320
|
||||
implicitHeight: 400
|
||||
implicitWidth: 480
|
||||
implicitHeight: 600
|
||||
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
@@ -53,55 +52,135 @@ PanelWindow {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 400
|
||||
height: showMediaPlayer ? 540 : (weather?.available ? 480 : 400)
|
||||
id: mainContainer
|
||||
width: calculateWidth()
|
||||
height: calculateHeight()
|
||||
x: (parent.width - width) / 2
|
||||
y: theme.barHeight + theme.spacingS
|
||||
y: Theme.barHeight + 4
|
||||
|
||||
function calculateWidth() {
|
||||
let baseWidth = 320
|
||||
if (leftWidgets.hasAnyWidgets) {
|
||||
return Math.min(parent.width * 0.9, 600)
|
||||
}
|
||||
return Math.min(parent.width * 0.7, 400)
|
||||
}
|
||||
|
||||
function calculateHeight() {
|
||||
let contentHeight = theme.spacingM * 2 // margins
|
||||
|
||||
// Calculate widget heights - media widget is always present
|
||||
let widgetHeight = 160 // Media widget always present
|
||||
if (weather?.available) {
|
||||
widgetHeight += (weather ? 140 : 80) + theme.spacingM
|
||||
}
|
||||
|
||||
// Calendar height is always 300
|
||||
let calendarHeight = 300
|
||||
|
||||
// Take the max of widgets and calendar
|
||||
contentHeight += Math.max(widgetHeight, calendarHeight)
|
||||
|
||||
return Math.min(contentHeight, parent.height * 0.85)
|
||||
}
|
||||
|
||||
color: theme.surfaceContainer
|
||||
radius: theme.cornerRadiusLarge
|
||||
border.color: Qt.rgba(theme.outline.r, theme.outline.g, theme.outline.b, 0.12)
|
||||
border.width: 1
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
shadowEnabled: true
|
||||
shadowHorizontalOffset: 0
|
||||
shadowVerticalOffset: 4
|
||||
shadowBlur: 0.5
|
||||
shadowColor: Qt.rgba(0, 0, 0, 0.15)
|
||||
shadowOpacity: 0.15
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(theme.surfaceTint.r, theme.surfaceTint.g, theme.surfaceTint.b, 0.04)
|
||||
radius: parent.radius
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
running: true
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation {
|
||||
to: 0.08
|
||||
duration: theme.extraLongDuration
|
||||
easing.type: theme.standardEasing
|
||||
}
|
||||
NumberAnimation {
|
||||
to: 0.02
|
||||
duration: theme.extraLongDuration
|
||||
easing.type: theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opacity: root.calendarVisible ? 1.0 : 0.0
|
||||
scale: root.calendarVisible ? 1.0 : 0.85
|
||||
scale: root.calendarVisible ? 1.0 : 0.92
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: theme.mediumDuration
|
||||
duration: theme.longDuration
|
||||
easing.type: theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: theme.mediumDuration
|
||||
duration: theme.longDuration
|
||||
easing.type: theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: theme.mediumDuration
|
||||
easing.type: theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
anchors.margins: theme.spacingL
|
||||
anchors.margins: theme.spacingM
|
||||
spacing: theme.spacingM
|
||||
|
||||
// Media Player (when active)
|
||||
MediaPlayerWidget {
|
||||
visible: showMediaPlayer
|
||||
theme: centerCommandCenter.theme
|
||||
// Left section for widgets
|
||||
Column {
|
||||
id: leftWidgets
|
||||
width: hasAnyWidgets ? parent.width * 0.45 : 0
|
||||
height: childrenRect.height
|
||||
spacing: theme.spacingM
|
||||
visible: hasAnyWidgets
|
||||
anchors.top: parent.top
|
||||
|
||||
property bool hasAnyWidgets: true || weather?.available // Always show media widget
|
||||
|
||||
MediaPlayerWidget {
|
||||
visible: true // Always visible - shows placeholder when no media
|
||||
width: parent.width
|
||||
height: 160
|
||||
theme: centerCommandCenter.theme
|
||||
}
|
||||
|
||||
WeatherWidget {
|
||||
visible: weather?.available
|
||||
width: parent.width
|
||||
height: weather ? 140 : 80
|
||||
theme: centerCommandCenter.theme
|
||||
weather: centerCommandCenter.weather
|
||||
useFahrenheit: centerCommandCenter.useFahrenheit
|
||||
}
|
||||
}
|
||||
|
||||
// Weather header (when available and no media)
|
||||
WeatherWidget {
|
||||
visible: weather?.available && !showMediaPlayer
|
||||
theme: centerCommandCenter.theme
|
||||
weather: centerCommandCenter.weather
|
||||
useFahrenheit: centerCommandCenter.useFahrenheit
|
||||
}
|
||||
|
||||
// Calendar
|
||||
// Right section for calendar
|
||||
CalendarWidget {
|
||||
width: parent.width
|
||||
height: showMediaPlayer ? parent.height - 200 : (weather?.available ? parent.height - 120 : parent.height - 40)
|
||||
width: leftWidgets.hasAnyWidgets ? parent.width * 0.55 - theme.spacingL : parent.width
|
||||
height: parent.height
|
||||
theme: centerCommandCenter.theme
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,22 @@ Rectangle {
|
||||
property var theme: Theme
|
||||
|
||||
width: parent.width
|
||||
height: 160 // Reduced height to prevent overflow
|
||||
radius: theme.cornerRadius
|
||||
color: Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.08)
|
||||
border.color: Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.2)
|
||||
height: parent.height
|
||||
radius: theme.cornerRadiusLarge
|
||||
color: Qt.rgba(theme.surfaceContainer.r, theme.surfaceContainer.g, theme.surfaceContainer.b, 0.4)
|
||||
border.color: Qt.rgba(theme.outline.r, theme.outline.g, theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
shadowEnabled: true
|
||||
shadowHorizontalOffset: 0
|
||||
shadowVerticalOffset: 2
|
||||
shadowBlur: 0.5
|
||||
shadowColor: Qt.rgba(0, 0, 0, 0.1)
|
||||
shadowOpacity: 0.1
|
||||
}
|
||||
|
||||
property real currentPosition: 0
|
||||
|
||||
// Simple progress ratio calculation
|
||||
@@ -68,81 +78,109 @@ Rectangle {
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: theme.spacingM
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - theme.spacingM * 2
|
||||
spacing: theme.spacingM
|
||||
|
||||
// Album art and track info
|
||||
Row {
|
||||
// Show different content based on whether we have active media
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 70 // Reduced height
|
||||
spacing: theme.spacingM
|
||||
height: 80
|
||||
|
||||
// Album Art
|
||||
Rectangle {
|
||||
width: 70
|
||||
height: 70
|
||||
radius: theme.cornerRadius
|
||||
color: Qt.rgba(theme.surfaceVariant.r, theme.surfaceVariant.g, theme.surfaceVariant.b, 0.3)
|
||||
// Placeholder when no media
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: theme.spacingS
|
||||
visible: !activePlayer || !activePlayer.trackTitle || activePlayer.trackTitle === ""
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
|
||||
Image {
|
||||
id: albumArt
|
||||
anchors.fill: parent
|
||||
source: activePlayer?.trackArtUrl || ""
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
smooth: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: albumArt.status !== Image.Ready
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "album"
|
||||
font.family: theme.iconFont
|
||||
font.pixelSize: 28
|
||||
color: theme.surfaceVariantText
|
||||
}
|
||||
}
|
||||
Text {
|
||||
text: "music_note"
|
||||
font.family: theme.iconFont
|
||||
font.pixelSize: theme.iconSize + 8
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.5)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "No Media Playing"
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.7)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
// Track Info
|
||||
Column {
|
||||
width: parent.width - 70 - theme.spacingM
|
||||
spacing: theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
// Normal media info when playing
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
spacing: theme.spacingM
|
||||
visible: activePlayer && activePlayer.trackTitle && activePlayer.trackTitle !== ""
|
||||
|
||||
Text {
|
||||
text: activePlayer?.trackTitle || "Unknown Track"
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
font.weight: Font.Bold
|
||||
color: theme.surfaceText
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
// Album Art
|
||||
Rectangle {
|
||||
width: 80
|
||||
height: 80
|
||||
radius: theme.cornerRadius
|
||||
color: Qt.rgba(theme.surfaceVariant.r, theme.surfaceVariant.g, theme.surfaceVariant.b, 0.3)
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
|
||||
Image {
|
||||
id: albumArt
|
||||
anchors.fill: parent
|
||||
source: activePlayer?.trackArtUrl || ""
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
smooth: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: albumArt.status !== Image.Ready
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "album"
|
||||
font.family: theme.iconFont
|
||||
font.pixelSize: 28
|
||||
color: theme.surfaceVariantText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: activePlayer?.trackArtist || "Unknown Artist"
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.8)
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
text: activePlayer?.trackAlbum || ""
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.6)
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
visible: text.length > 0
|
||||
// Track Info
|
||||
Column {
|
||||
width: parent.width - 80 - theme.spacingM
|
||||
spacing: theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Text {
|
||||
text: activePlayer?.trackTitle || "Unknown Track"
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
font.weight: Font.Bold
|
||||
color: theme.surfaceText
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
text: activePlayer?.trackArtist || "Unknown Artist"
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.8)
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
text: activePlayer?.trackAlbum || ""
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.6)
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
visible: text.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,6 +192,7 @@ Rectangle {
|
||||
height: 6
|
||||
radius: 3
|
||||
color: Qt.rgba(theme.surfaceVariant.r, theme.surfaceVariant.g, theme.surfaceVariant.b, 0.3)
|
||||
visible: activePlayer !== null
|
||||
|
||||
Rectangle {
|
||||
id: progressFill
|
||||
@@ -232,10 +271,11 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// Control buttons - compact to fit
|
||||
// Control buttons - always visible
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: theme.spacingL
|
||||
visible: activePlayer !== null
|
||||
|
||||
// Previous button
|
||||
Rectangle {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Effects
|
||||
import "../../Common"
|
||||
import "../../Services"
|
||||
|
||||
@@ -11,57 +12,104 @@ Rectangle {
|
||||
property bool useFahrenheit: false
|
||||
|
||||
width: parent.width
|
||||
height: 80
|
||||
radius: theme.cornerRadius
|
||||
color: Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.08)
|
||||
border.color: Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.2)
|
||||
height: parent.height
|
||||
radius: theme.cornerRadiusLarge
|
||||
color: Qt.rgba(theme.surfaceContainer.r, theme.surfaceContainer.g, theme.surfaceContainer.b, 0.4)
|
||||
border.color: Qt.rgba(theme.outline.r, theme.outline.g, theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: theme.spacingL
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
shadowEnabled: true
|
||||
shadowHorizontalOffset: 0
|
||||
shadowVerticalOffset: 2
|
||||
shadowBlur: 0.5
|
||||
shadowColor: Qt.rgba(0, 0, 0, 0.1)
|
||||
shadowOpacity: 0.1
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: theme.spacingL
|
||||
spacing: theme.spacingM
|
||||
|
||||
// Weather icon and temp
|
||||
Column {
|
||||
spacing: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
// Show different content based on whether we have weather data
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 60
|
||||
|
||||
Text {
|
||||
text: WeatherService.getWeatherIcon(weather.wCode)
|
||||
font.family: theme.iconFont
|
||||
font.pixelSize: theme.iconSize + 4
|
||||
color: theme.primary
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: (useFahrenheit ? weather.tempF : weather.temp) + "°" + (useFahrenheit ? "F" : "C")
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
color: theme.surfaceText
|
||||
font.weight: Font.Bold
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
// Placeholder when no weather
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: theme.spacingS
|
||||
visible: !weather
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: useFahrenheit = !useFahrenheit
|
||||
Text {
|
||||
text: "cloud_off"
|
||||
font.family: theme.iconFont
|
||||
font.pixelSize: theme.iconSize + 8
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.5)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "No Weather Data"
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.7)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: weather.city
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.7)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
// Normal weather info when available
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
spacing: theme.spacingL
|
||||
visible: weather
|
||||
|
||||
// Weather icon
|
||||
Text {
|
||||
text: weather ? WeatherService.getWeatherIcon(weather.wCode) : ""
|
||||
font.family: theme.iconFont
|
||||
font.pixelSize: theme.iconSize + 8
|
||||
color: theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Text {
|
||||
text: weather ? ((useFahrenheit ? weather.tempF : weather.temp) + "°" + (useFahrenheit ? "F" : "C")) : ""
|
||||
font.pixelSize: theme.fontSizeXLarge
|
||||
color: theme.surfaceText
|
||||
font.weight: Font.Light
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: if (weather) useFahrenheit = !useFahrenheit
|
||||
enabled: weather !== null
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: weather ? weather.city : ""
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.7)
|
||||
visible: text.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Weather details grid
|
||||
Grid {
|
||||
columns: 2
|
||||
spacing: theme.spacingS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: theme.spacingM
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: weather !== null
|
||||
|
||||
Row {
|
||||
spacing: theme.spacingXS
|
||||
@@ -73,7 +121,7 @@ Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Text {
|
||||
text: weather.humidity + "%"
|
||||
text: weather ? weather.humidity + "%" : "--"
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -90,7 +138,7 @@ Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Text {
|
||||
text: weather.wind
|
||||
text: weather ? weather.wind : "--"
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -107,7 +155,7 @@ Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Text {
|
||||
text: weather.sunrise
|
||||
text: weather ? weather.sunrise : "--"
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -124,7 +172,7 @@ Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Text {
|
||||
text: weather.sunset
|
||||
text: weather ? weather.sunset : "--"
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
@@ -1,33 +1,14 @@
|
||||
import QtQuick
|
||||
import Quickshell.Services.Mpris
|
||||
import "../../Common"
|
||||
import "../../Services"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property bool hasActiveMedia: false
|
||||
property var activePlayer: null
|
||||
property bool weatherAvailable: false
|
||||
property string weatherCode: ""
|
||||
property int weatherTemp: 0
|
||||
property int weatherTempF: 0
|
||||
property bool useFahrenheit: false
|
||||
property date currentDate: new Date()
|
||||
|
||||
signal clockClicked()
|
||||
|
||||
width: {
|
||||
let baseWidth = 200
|
||||
if (root.hasActiveMedia) {
|
||||
let mediaWidth = 24 + Theme.spacingXS + mediaTitleText.implicitWidth + Theme.spacingM + 180
|
||||
return Math.min(Math.max(mediaWidth, 300), parent.width - Theme.spacingL * 2)
|
||||
} else if (root.weatherAvailable) {
|
||||
return Math.min(280, parent.width - Theme.spacingL * 2)
|
||||
} else {
|
||||
return Math.min(baseWidth, parent.width - Theme.spacingL * 2)
|
||||
}
|
||||
}
|
||||
width: clockRow.implicitWidth + Theme.spacingM
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: clockMouseArea.containsMouse ?
|
||||
@@ -42,94 +23,31 @@ Rectangle {
|
||||
}
|
||||
|
||||
Row {
|
||||
id: clockRow
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// Media info or Weather info
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
visible: root.hasActiveMedia || root.weatherAvailable
|
||||
Text {
|
||||
text: Qt.formatTime(root.currentDate, "h:mm AP")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
// Audio visualization placeholder - will be replaced by parent
|
||||
Item {
|
||||
id: audioVisualizationPlaceholder
|
||||
width: 20
|
||||
height: Theme.iconSize
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: root.hasActiveMedia
|
||||
}
|
||||
|
||||
// Song title when media is playing
|
||||
Text {
|
||||
id: mediaTitleText
|
||||
text: root.activePlayer?.trackTitle || "Unknown Track"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: root.hasActiveMedia
|
||||
width: Math.min(implicitWidth, root.width - 100)
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
// Weather icon when no media but weather available
|
||||
Text {
|
||||
text: WeatherService.getWeatherIcon(root.weatherCode)
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: Theme.iconSize - 2
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: !root.hasActiveMedia && root.weatherAvailable
|
||||
}
|
||||
|
||||
// Weather temp when no media but weather available
|
||||
Text {
|
||||
text: (root.useFahrenheit ? root.weatherTempF : root.weatherTemp) + "°" + (root.useFahrenheit ? "F" : "C")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: !root.hasActiveMedia && root.weatherAvailable
|
||||
}
|
||||
}
|
||||
|
||||
// Separator
|
||||
Text {
|
||||
text: "•"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: root.hasActiveMedia || root.weatherAvailable
|
||||
}
|
||||
|
||||
// Time and date
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
Text {
|
||||
text: Qt.formatDate(root.currentDate, "ddd d")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Text {
|
||||
text: Qt.formatTime(root.currentDate, "h:mm AP")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "•"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: Qt.formatDate(root.currentDate, "ddd d")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
67
Widgets/TopBar/MediaWidget.qml
Normal file
67
Widgets/TopBar/MediaWidget.qml
Normal file
@@ -0,0 +1,67 @@
|
||||
import QtQuick
|
||||
import Quickshell.Services.Mpris
|
||||
import "../../Common"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property var activePlayer: null
|
||||
property bool hasActiveMedia: activePlayer && (activePlayer.trackTitle || activePlayer.trackArtist)
|
||||
|
||||
signal clicked()
|
||||
|
||||
visible: hasActiveMedia
|
||||
width: hasActiveMedia ? Math.min(200, mediaText.implicitWidth + Theme.spacingS + 48) : 0
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: mediaArea.containsMouse ?
|
||||
Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) :
|
||||
Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08)
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
AudioVisualization {
|
||||
width: 20
|
||||
height: Theme.iconSize
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
hasActiveMedia: root.hasActiveMedia
|
||||
activePlayer: root.activePlayer
|
||||
}
|
||||
|
||||
Text {
|
||||
id: mediaText
|
||||
text: activePlayer?.trackTitle || "Unknown Track"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Math.min(implicitWidth, 150)
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mediaArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: root.clicked()
|
||||
}
|
||||
}
|
||||
@@ -172,27 +172,44 @@ PanelWindow {
|
||||
ClockWidget {
|
||||
id: clockWidget
|
||||
anchors.centerIn: parent
|
||||
hasActiveMedia: topBar.hasActiveMedia
|
||||
activePlayer: topBar.activePlayer
|
||||
weatherAvailable: topBar.weatherAvailable
|
||||
weatherCode: topBar.weatherCode
|
||||
weatherTemp: topBar.weatherTemp
|
||||
weatherTempF: topBar.weatherTempF
|
||||
useFahrenheit: topBar.useFahrenheit
|
||||
|
||||
onClockClicked: {
|
||||
if (topBar.shellRoot) {
|
||||
topBar.shellRoot.calendarVisible = !topBar.shellRoot.calendarVisible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MediaWidget {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: clockWidget.left
|
||||
anchors.rightMargin: Theme.spacingS
|
||||
activePlayer: topBar.activePlayer
|
||||
hasActiveMedia: topBar.hasActiveMedia
|
||||
|
||||
// Insert audio visualization into the clock widget placeholder
|
||||
AudioVisualization {
|
||||
parent: clockWidget.children[0].children[0].children[0] // Row -> Row (media info) -> Item (placeholder)
|
||||
anchors.fill: parent
|
||||
hasActiveMedia: topBar.hasActiveMedia
|
||||
activePlayer: topBar.activePlayer
|
||||
visible: topBar.hasActiveMedia
|
||||
onClicked: {
|
||||
if (topBar.shellRoot) {
|
||||
topBar.shellRoot.calendarVisible = !topBar.shellRoot.calendarVisible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WeatherWidget {
|
||||
id: weatherWidget
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: clockWidget.right
|
||||
anchors.leftMargin: Theme.spacingS
|
||||
|
||||
weatherAvailable: topBar.weatherAvailable
|
||||
weatherCode: topBar.weatherCode
|
||||
weatherTemp: topBar.weatherTemp
|
||||
weatherTempF: topBar.weatherTempF
|
||||
useFahrenheit: topBar.useFahrenheit
|
||||
|
||||
onClicked: {
|
||||
if (topBar.shellRoot) {
|
||||
topBar.shellRoot.calendarVisible = !topBar.shellRoot.calendarVisible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
68
Widgets/TopBar/WeatherWidget.qml
Normal file
68
Widgets/TopBar/WeatherWidget.qml
Normal file
@@ -0,0 +1,68 @@
|
||||
import QtQuick
|
||||
import "../../Common"
|
||||
import "../../Services"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property bool weatherAvailable: false
|
||||
property string weatherCode: ""
|
||||
property int weatherTemp: 0
|
||||
property int weatherTempF: 0
|
||||
property bool useFahrenheit: false
|
||||
|
||||
signal clicked()
|
||||
|
||||
visible: weatherAvailable
|
||||
width: weatherAvailable ? Math.min(100, weatherRow.implicitWidth + Theme.spacingS) : 0
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: weatherArea.containsMouse ?
|
||||
Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) :
|
||||
Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08)
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: weatherRow
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Text {
|
||||
text: WeatherService.getWeatherIcon(weatherCode)
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: Theme.iconSize - 4
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: (useFahrenheit ? weatherTempF : weatherTemp) + "°"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: weatherArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: root.clicked()
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ TopBar 1.0 TopBar.qml
|
||||
LauncherButton 1.0 LauncherButton.qml
|
||||
WorkspaceSwitcher 1.0 WorkspaceSwitcher.qml
|
||||
ClockWidget 1.0 ClockWidget.qml
|
||||
MediaWidget 1.0 MediaWidget.qml
|
||||
WeatherWidget 1.0 WeatherWidget.qml
|
||||
SystemTrayWidget 1.0 SystemTrayWidget.qml
|
||||
NotificationCenterButton 1.0 NotificationCenterButton.qml
|
||||
ControlCenterButton 1.0 ControlCenterButton.qml
|
||||
|
||||
Reference in New Issue
Block a user