mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-29 16:02:51 -05:00
Redesign center command center
This commit is contained in:
@@ -71,10 +71,8 @@ Singleton {
|
|||||||
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
console.log("SystemMonitorService: CPU usage raw data:", text.trim())
|
|
||||||
if (text.trim()) {
|
if (text.trim()) {
|
||||||
root.cpuUsage = parseFloat(text.trim())
|
root.cpuUsage = parseFloat(text.trim())
|
||||||
console.log("SystemMonitorService: CPU usage set to:", root.cpuUsage)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +92,6 @@ Singleton {
|
|||||||
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
console.log("SystemMonitorService: Memory usage raw data:", text.trim())
|
|
||||||
if (text.trim()) {
|
if (text.trim()) {
|
||||||
const parts = text.trim().split(" ")
|
const parts = text.trim().split(" ")
|
||||||
root.memoryUsage = parseFloat(parts[0])
|
root.memoryUsage = parseFloat(parts[0])
|
||||||
@@ -102,7 +99,6 @@ Singleton {
|
|||||||
root.usedMemory = parseFloat(parts[2])
|
root.usedMemory = parseFloat(parts[2])
|
||||||
root.availableMemory = parseFloat(parts[3])
|
root.availableMemory = parseFloat(parts[3])
|
||||||
root.freeMemory = root.totalMemory - root.usedMemory
|
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 var weather: root.weather
|
||||||
property bool useFahrenheit: false
|
property bool useFahrenheit: false
|
||||||
|
|
||||||
// Prevent media player from disappearing during track changes
|
|
||||||
property bool showMediaPlayer: hasActiveMedia || hideMediaTimer.running
|
property bool showMediaPlayer: hasActiveMedia || hideMediaTimer.running
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: hideMediaTimer
|
id: hideMediaTimer
|
||||||
interval: 3000 // 3 second grace period
|
interval: 3000
|
||||||
running: false
|
running: false
|
||||||
repeat: false
|
repeat: false
|
||||||
}
|
}
|
||||||
@@ -36,8 +35,8 @@ PanelWindow {
|
|||||||
|
|
||||||
visible: root.calendarVisible
|
visible: root.calendarVisible
|
||||||
|
|
||||||
implicitWidth: 320
|
implicitWidth: 480
|
||||||
implicitHeight: 400
|
implicitHeight: 600
|
||||||
|
|
||||||
WlrLayershell.layer: WlrLayershell.Overlay
|
WlrLayershell.layer: WlrLayershell.Overlay
|
||||||
WlrLayershell.exclusiveZone: -1
|
WlrLayershell.exclusiveZone: -1
|
||||||
@@ -53,55 +52,135 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 400
|
id: mainContainer
|
||||||
height: showMediaPlayer ? 540 : (weather?.available ? 480 : 400)
|
width: calculateWidth()
|
||||||
|
height: calculateHeight()
|
||||||
x: (parent.width - width) / 2
|
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
|
color: theme.surfaceContainer
|
||||||
radius: theme.cornerRadiusLarge
|
radius: theme.cornerRadiusLarge
|
||||||
border.color: Qt.rgba(theme.outline.r, theme.outline.g, theme.outline.b, 0.12)
|
border.color: Qt.rgba(theme.outline.r, theme.outline.g, theme.outline.b, 0.12)
|
||||||
border.width: 1
|
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
|
opacity: root.calendarVisible ? 1.0 : 0.0
|
||||||
scale: root.calendarVisible ? 1.0 : 0.85
|
scale: root.calendarVisible ? 1.0 : 0.92
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: theme.mediumDuration
|
duration: theme.longDuration
|
||||||
easing.type: theme.emphasizedEasing
|
easing.type: theme.emphasizedEasing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on scale {
|
Behavior on scale {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: theme.mediumDuration
|
duration: theme.longDuration
|
||||||
easing.type: theme.emphasizedEasing
|
easing.type: theme.emphasizedEasing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Behavior on height {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: theme.mediumDuration
|
||||||
|
easing.type: theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: theme.spacingL
|
anchors.margins: theme.spacingM
|
||||||
spacing: theme.spacingM
|
spacing: theme.spacingM
|
||||||
|
|
||||||
// Media Player (when active)
|
// Left section for widgets
|
||||||
MediaPlayerWidget {
|
Column {
|
||||||
visible: showMediaPlayer
|
id: leftWidgets
|
||||||
theme: centerCommandCenter.theme
|
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)
|
// Right section for calendar
|
||||||
WeatherWidget {
|
|
||||||
visible: weather?.available && !showMediaPlayer
|
|
||||||
theme: centerCommandCenter.theme
|
|
||||||
weather: centerCommandCenter.weather
|
|
||||||
useFahrenheit: centerCommandCenter.useFahrenheit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calendar
|
|
||||||
CalendarWidget {
|
CalendarWidget {
|
||||||
width: parent.width
|
width: leftWidgets.hasAnyWidgets ? parent.width * 0.55 - theme.spacingL : parent.width
|
||||||
height: showMediaPlayer ? parent.height - 200 : (weather?.available ? parent.height - 120 : parent.height - 40)
|
height: parent.height
|
||||||
theme: centerCommandCenter.theme
|
theme: centerCommandCenter.theme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,22 @@ Rectangle {
|
|||||||
property var theme: Theme
|
property var theme: Theme
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 160 // Reduced height to prevent overflow
|
height: parent.height
|
||||||
radius: theme.cornerRadius
|
radius: theme.cornerRadiusLarge
|
||||||
color: Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.08)
|
color: Qt.rgba(theme.surfaceContainer.r, theme.surfaceContainer.g, theme.surfaceContainer.b, 0.4)
|
||||||
border.color: Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.2)
|
border.color: Qt.rgba(theme.outline.r, theme.outline.g, theme.outline.b, 0.08)
|
||||||
border.width: 1
|
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
|
property real currentPosition: 0
|
||||||
|
|
||||||
// Simple progress ratio calculation
|
// Simple progress ratio calculation
|
||||||
@@ -68,81 +78,109 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.fill: parent
|
anchors.centerIn: parent
|
||||||
anchors.margins: theme.spacingM
|
width: parent.width - theme.spacingM * 2
|
||||||
spacing: theme.spacingM
|
spacing: theme.spacingM
|
||||||
|
|
||||||
// Album art and track info
|
// Show different content based on whether we have active media
|
||||||
Row {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 70 // Reduced height
|
height: 80
|
||||||
spacing: theme.spacingM
|
|
||||||
|
|
||||||
// Album Art
|
// Placeholder when no media
|
||||||
Rectangle {
|
Column {
|
||||||
width: 70
|
anchors.centerIn: parent
|
||||||
height: 70
|
spacing: theme.spacingS
|
||||||
radius: theme.cornerRadius
|
visible: !activePlayer || !activePlayer.trackTitle || activePlayer.trackTitle === ""
|
||||||
color: Qt.rgba(theme.surfaceVariant.r, theme.surfaceVariant.g, theme.surfaceVariant.b, 0.3)
|
|
||||||
|
|
||||||
Item {
|
Text {
|
||||||
anchors.fill: parent
|
text: "music_note"
|
||||||
clip: true
|
font.family: theme.iconFont
|
||||||
|
font.pixelSize: theme.iconSize + 8
|
||||||
Image {
|
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.5)
|
||||||
id: albumArt
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.fill: parent
|
}
|
||||||
source: activePlayer?.trackArtUrl || ""
|
|
||||||
fillMode: Image.PreserveAspectCrop
|
Text {
|
||||||
smooth: true
|
text: "No Media Playing"
|
||||||
}
|
font.pixelSize: theme.fontSizeMedium
|
||||||
|
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.7)
|
||||||
Rectangle {
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track Info
|
// Normal media info when playing
|
||||||
Column {
|
Row {
|
||||||
width: parent.width - 70 - theme.spacingM
|
anchors.fill: parent
|
||||||
spacing: theme.spacingXS
|
spacing: theme.spacingM
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
visible: activePlayer && activePlayer.trackTitle && activePlayer.trackTitle !== ""
|
||||||
|
|
||||||
Text {
|
// Album Art
|
||||||
text: activePlayer?.trackTitle || "Unknown Track"
|
Rectangle {
|
||||||
font.pixelSize: theme.fontSizeMedium
|
width: 80
|
||||||
font.weight: Font.Bold
|
height: 80
|
||||||
color: theme.surfaceText
|
radius: theme.cornerRadius
|
||||||
width: parent.width
|
color: Qt.rgba(theme.surfaceVariant.r, theme.surfaceVariant.g, theme.surfaceVariant.b, 0.3)
|
||||||
elide: Text.ElideRight
|
|
||||||
|
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 {
|
// Track Info
|
||||||
text: activePlayer?.trackArtist || "Unknown Artist"
|
Column {
|
||||||
font.pixelSize: theme.fontSizeSmall
|
width: parent.width - 80 - theme.spacingM
|
||||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.8)
|
spacing: theme.spacingXS
|
||||||
width: parent.width
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
Text {
|
||||||
|
text: activePlayer?.trackTitle || "Unknown Track"
|
||||||
Text {
|
font.pixelSize: theme.fontSizeMedium
|
||||||
text: activePlayer?.trackAlbum || ""
|
font.weight: Font.Bold
|
||||||
font.pixelSize: theme.fontSizeSmall
|
color: theme.surfaceText
|
||||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.6)
|
width: parent.width
|
||||||
width: parent.width
|
elide: Text.ElideRight
|
||||||
elide: Text.ElideRight
|
}
|
||||||
visible: text.length > 0
|
|
||||||
|
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
|
height: 6
|
||||||
radius: 3
|
radius: 3
|
||||||
color: Qt.rgba(theme.surfaceVariant.r, theme.surfaceVariant.g, theme.surfaceVariant.b, 0.3)
|
color: Qt.rgba(theme.surfaceVariant.r, theme.surfaceVariant.g, theme.surfaceVariant.b, 0.3)
|
||||||
|
visible: activePlayer !== null
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: progressFill
|
id: progressFill
|
||||||
@@ -232,10 +271,11 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control buttons - compact to fit
|
// Control buttons - always visible
|
||||||
Row {
|
Row {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
spacing: theme.spacingL
|
spacing: theme.spacingL
|
||||||
|
visible: activePlayer !== null
|
||||||
|
|
||||||
// Previous button
|
// Previous button
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Effects
|
||||||
import "../../Common"
|
import "../../Common"
|
||||||
import "../../Services"
|
import "../../Services"
|
||||||
|
|
||||||
@@ -11,57 +12,104 @@ Rectangle {
|
|||||||
property bool useFahrenheit: false
|
property bool useFahrenheit: false
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 80
|
height: parent.height
|
||||||
radius: theme.cornerRadius
|
radius: theme.cornerRadiusLarge
|
||||||
color: Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.08)
|
color: Qt.rgba(theme.surfaceContainer.r, theme.surfaceContainer.g, theme.surfaceContainer.b, 0.4)
|
||||||
border.color: Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.2)
|
border.color: Qt.rgba(theme.outline.r, theme.outline.g, theme.outline.b, 0.08)
|
||||||
border.width: 1
|
border.width: 1
|
||||||
|
|
||||||
Row {
|
layer.enabled: true
|
||||||
anchors.centerIn: parent
|
layer.effect: MultiEffect {
|
||||||
spacing: theme.spacingL
|
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
|
// Show different content based on whether we have weather data
|
||||||
Column {
|
Item {
|
||||||
spacing: 2
|
width: parent.width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
height: 60
|
||||||
|
|
||||||
Text {
|
// Placeholder when no weather
|
||||||
text: WeatherService.getWeatherIcon(weather.wCode)
|
Column {
|
||||||
font.family: theme.iconFont
|
anchors.centerIn: parent
|
||||||
font.pixelSize: theme.iconSize + 4
|
spacing: theme.spacingS
|
||||||
color: theme.primary
|
visible: !weather
|
||||||
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
|
|
||||||
|
|
||||||
MouseArea {
|
Text {
|
||||||
anchors.fill: parent
|
text: "cloud_off"
|
||||||
hoverEnabled: true
|
font.family: theme.iconFont
|
||||||
cursorShape: Qt.PointingHandCursor
|
font.pixelSize: theme.iconSize + 8
|
||||||
onClicked: useFahrenheit = !useFahrenheit
|
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 {
|
// Normal weather info when available
|
||||||
text: weather.city
|
Row {
|
||||||
font.pixelSize: theme.fontSizeSmall
|
anchors.fill: parent
|
||||||
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.7)
|
spacing: theme.spacingL
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
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
|
// Weather details grid
|
||||||
Grid {
|
Grid {
|
||||||
columns: 2
|
columns: 2
|
||||||
spacing: theme.spacingS
|
spacing: theme.spacingM
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
visible: weather !== null
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
spacing: theme.spacingXS
|
spacing: theme.spacingXS
|
||||||
@@ -73,7 +121,7 @@ Rectangle {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: weather.humidity + "%"
|
text: weather ? weather.humidity + "%" : "--"
|
||||||
font.pixelSize: theme.fontSizeSmall
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.surfaceText
|
color: theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -90,7 +138,7 @@ Rectangle {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: weather.wind
|
text: weather ? weather.wind : "--"
|
||||||
font.pixelSize: theme.fontSizeSmall
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.surfaceText
|
color: theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -107,7 +155,7 @@ Rectangle {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: weather.sunrise
|
text: weather ? weather.sunrise : "--"
|
||||||
font.pixelSize: theme.fontSizeSmall
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.surfaceText
|
color: theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -124,7 +172,7 @@ Rectangle {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: weather.sunset
|
text: weather ? weather.sunset : "--"
|
||||||
font.pixelSize: theme.fontSizeSmall
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.surfaceText
|
color: theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|||||||
@@ -1,33 +1,14 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell.Services.Mpris
|
|
||||||
import "../../Common"
|
import "../../Common"
|
||||||
import "../../Services"
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
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()
|
property date currentDate: new Date()
|
||||||
|
|
||||||
signal clockClicked()
|
signal clockClicked()
|
||||||
|
|
||||||
width: {
|
width: clockRow.implicitWidth + Theme.spacingM
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
height: 30
|
height: 30
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: clockMouseArea.containsMouse ?
|
color: clockMouseArea.containsMouse ?
|
||||||
@@ -42,94 +23,31 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
id: clockRow
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
// Media info or Weather info
|
Text {
|
||||||
Row {
|
text: Qt.formatTime(root.currentDate, "h:mm AP")
|
||||||
spacing: Theme.spacingXS
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
visible: root.hasActiveMedia || root.weatherAvailable
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
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 {
|
||||||
text: "•"
|
text: "•"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: root.hasActiveMedia || root.weatherAvailable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time and date
|
Text {
|
||||||
Row {
|
text: Qt.formatDate(root.currentDate, "ddd d")
|
||||||
spacing: Theme.spacingS
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
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 {
|
ClockWidget {
|
||||||
id: clockWidget
|
id: clockWidget
|
||||||
anchors.centerIn: parent
|
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: {
|
onClockClicked: {
|
||||||
if (topBar.shellRoot) {
|
if (topBar.shellRoot) {
|
||||||
topBar.shellRoot.calendarVisible = !topBar.shellRoot.calendarVisible
|
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
|
onClicked: {
|
||||||
AudioVisualization {
|
if (topBar.shellRoot) {
|
||||||
parent: clockWidget.children[0].children[0].children[0] // Row -> Row (media info) -> Item (placeholder)
|
topBar.shellRoot.calendarVisible = !topBar.shellRoot.calendarVisible
|
||||||
anchors.fill: parent
|
}
|
||||||
hasActiveMedia: topBar.hasActiveMedia
|
}
|
||||||
activePlayer: topBar.activePlayer
|
}
|
||||||
visible: topBar.hasActiveMedia
|
|
||||||
|
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
|
LauncherButton 1.0 LauncherButton.qml
|
||||||
WorkspaceSwitcher 1.0 WorkspaceSwitcher.qml
|
WorkspaceSwitcher 1.0 WorkspaceSwitcher.qml
|
||||||
ClockWidget 1.0 ClockWidget.qml
|
ClockWidget 1.0 ClockWidget.qml
|
||||||
|
MediaWidget 1.0 MediaWidget.qml
|
||||||
|
WeatherWidget 1.0 WeatherWidget.qml
|
||||||
SystemTrayWidget 1.0 SystemTrayWidget.qml
|
SystemTrayWidget 1.0 SystemTrayWidget.qml
|
||||||
NotificationCenterButton 1.0 NotificationCenterButton.qml
|
NotificationCenterButton 1.0 NotificationCenterButton.qml
|
||||||
ControlCenterButton 1.0 ControlCenterButton.qml
|
ControlCenterButton 1.0 ControlCenterButton.qml
|
||||||
|
|||||||
Reference in New Issue
Block a user