Add .config/DankMaterialShell/firefox.css

Add .config/DankMaterialShell/plugin_settings.json
Add .config/DankMaterialShell/plugins/dankDesktopWeather.meta
Add .config/DankMaterialShell/plugins/dankHooks.meta
Add .config/DankMaterialShell/plugins/desktopCommand/LICENSE
Add .config/DankMaterialShell/plugins/desktopCommand/README.md
Add .config/DankMaterialShell/plugins/desktopCommand/Settings.qml
Add .config/DankMaterialShell/plugins/desktopCommand/Widget.qml
Add .config/DankMaterialShell/plugins/desktopCommand/assets/screenshot.jpg
Add .config/DankMaterialShell/plugins/desktopCommand/.git/HEAD
Add .config/DankMaterialShell/plugins/desktopCommand/.git/config
Add .config/DankMaterialShell/plugins/desktopCommand/.git/index
Add .config/DankMaterialShell/plugins/desktopCommand/.git/objects/info/.keep
Add .config/DankMaterialShell/plugins/desktopCommand/.git/objects/pack/pack-c2ca48eacecc3ab45931476641d058a89d755775.idx
Add .config/DankMaterialShell/plugins/desktopCommand/.git/objects/pack/pack-c2ca48eacecc3ab45931476641d058a89d755775.rev
Add .config/DankMaterialShell/plugins/desktopCommand/.git/objects/pack/pack-c2ca48eacecc3ab45931476641d058a89d755775.pack
Add .config/DankMaterialShell/plugins/desktopCommand/.git/refs/heads/main
Add .config/DankMaterialShell/plugins/desktopCommand/.git/refs/remotes/origin/main
Add .config/DankMaterialShell/plugins/desktopCommand/.git/refs/tags/.keep
Add .config/DankMaterialShell/plugins/desktopCommand/.gitignore
Add .config/DankMaterialShell/plugins/desktopCommand/wrapCommand
Add .config/DankMaterialShell/plugins/desktopCommand/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankActions/DankActionsSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankActions/DankActionsWidget.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankActions/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankBatteryAlerts/DankBatteryAlerts.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankBatteryAlerts/DankBatteryAlertsSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankBatteryAlerts/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankDesktopWeather/DankDesktopWeather.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankDesktopWeather/DankDesktopWeatherSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankDesktopWeather/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/DankHooks.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/DankHooksSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/README.md
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankPomodoroTimer/DankPomodoroSettings.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankPomodoroTimer/DankPomodoroWidget.qml
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankPomodoroTimer/plugin.json
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/LICENSE
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/README.md
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/HEAD
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/config
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/index
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/info/.keep
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-3221a15c022ef4a7bb6bf2c47e40068b66b3588b.idx
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-3221a15c022ef4a7bb6bf2c47e40068b66b3588b.rev
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-9aca069a8b76b40fcc472eba1ed9b8219a87776b.idx
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-9aca069a8b76b40fcc472eba1ed9b8219a87776b.rev
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-e6f6cdfe9914bfb4a5717ef6036821794d59ab4b.idx
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-e6f6cdfe9914bfb4a5717ef6036821794d59ab4b.rev
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-3221a15c022ef4a7bb6bf2c47e40068b66b3588b.pack
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-9aca069a8b76b40fcc472eba1ed9b8219a87776b.pack
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-e6f6cdfe9914bfb4a5717ef6036821794d59ab4b.pack
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/refs/heads/master
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/refs/remotes/origin/master
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/refs/tags/.keep
Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.gitignore
Add .config/DankMaterialShell/plugins/emojiLauncher/EmojiLauncher.qml
Add .config/DankMaterialShell/plugins/emojiLauncher/EmojiLauncherSettings.qml
Add .config/DankMaterialShell/plugins/emojiLauncher/LICENSE
Add .config/DankMaterialShell/plugins/emojiLauncher/README.md
Add .config/DankMaterialShell/plugins/emojiLauncher/catalog.js
Add .config/DankMaterialShell/plugins/emojiLauncher/data/emojis.txt
Add .config/DankMaterialShell/plugins/emojiLauncher/data/math.txt
Add .config/DankMaterialShell/plugins/emojiLauncher/data/nerdfont.txt
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/HEAD
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/config
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/index
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/info/.keep
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/pack/pack-e04a5b1ea381dc3a792b8bf08cf70e735b195c0d.idx
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/pack/pack-e04a5b1ea381dc3a792b8bf08cf70e735b195c0d.rev
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/pack/pack-e04a5b1ea381dc3a792b8bf08cf70e735b195c0d.pack
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/refs/heads/main
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/refs/remotes/origin/main
Add .config/DankMaterialShell/plugins/emojiLauncher/.git/refs/tags/.keep
Add .config/DankMaterialShell/plugins/emojiLauncher/plugin.json
Add .config/DankMaterialShell/plugins/emojiLauncher/screenshot.png
Add .config/DankMaterialShell/plugins/emojiLauncher/scripts/generate_catalog.py
Add .config/DankMaterialShell/plugins/mediaPlayer/MediaPlayerSettings.qml
Add .config/DankMaterialShell/plugins/mediaPlayer/MediaPlayerTab.qml
Add .config/DankMaterialShell/plugins/mediaPlayer/README.md
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/HEAD
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/config
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/index
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/objects/info/.keep
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/objects/pack/pack-0b9cb33f7da23f6ff361ee3aa5117928714bc3be.idx
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/objects/pack/pack-0b9cb33f7da23f6ff361ee3aa5117928714bc3be.rev
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/objects/pack/pack-0b9cb33f7da23f6ff361ee3aa5117928714bc3be.pack
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/refs/heads/main
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/refs/remotes/origin/main
Add .config/DankMaterialShell/plugins/mediaPlayer/.git/refs/tags/.keep
Add .config/DankMaterialShell/plugins/mediaPlayer/plugin.json
Add .config/DankMaterialShell/plugins/mediaPlayer/screenshot_8.png
Add .config/DankMaterialShell/plugins/dankDesktopWeather
Add .config/DankMaterialShell/plugins/dankHooks
Add .config/DankMaterialShell/settings.json
This commit is contained in:
Lewis Wynne 2026-01-07 15:09:11 +00:00
parent 9d16d6e6b0
commit b18328bbad
96 changed files with 24119 additions and 0 deletions

View file

@ -0,0 +1,767 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Effects
import qs.Common
import qs.Services
import qs.Widgets
import qs.Modules.Plugins
DesktopPluginComponent {
id: root
minWidth: {
switch (viewMode) {
case "compact":
return 80;
case "standard":
return 140;
case "detailed":
return 200;
case "forecast":
return 280;
default:
return 160;
}
}
minHeight: {
switch (viewMode) {
case "compact":
return 80;
case "standard":
return 100;
case "detailed":
return 200;
case "forecast":
return 320;
default:
return 140;
}
}
property string viewMode: pluginData.viewMode ?? "standard"
property real backgroundOpacity: (pluginData.backgroundOpacity ?? 80) / 100
property string colorMode: pluginData.colorMode ?? "primary"
property color customColor: pluginData.customColor ?? "#ffffff"
property bool showLocation: pluginData.showLocation ?? true
property bool showCondition: pluginData.showCondition ?? true
property bool showFeelsLike: pluginData.showFeelsLike ?? true
property bool showHumidity: pluginData.showHumidity ?? true
property bool showWind: pluginData.showWind ?? true
property bool showPressure: pluginData.showPressure ?? false
property bool showPrecipitation: pluginData.showPrecipitation ?? true
property bool showSunTimes: pluginData.showSunTimes ?? true
property bool showForecast: pluginData.showForecast ?? true
property int forecastDays: pluginData.forecastDays ?? 5
property bool showHourlyForecast: pluginData.showHourlyForecast ?? false
property int hourlyCount: pluginData.hourlyCount ?? 6
readonly property color accentColor: {
switch (colorMode) {
case "secondary":
return Theme.secondary;
case "custom":
return customColor;
default:
return Theme.primary;
}
}
readonly property color bgColor: Theme.withAlpha(Theme.surface, backgroundOpacity)
readonly property color tileBg: Theme.withAlpha(Theme.surfaceContainerHigh, backgroundOpacity)
readonly property color textColor: Theme.surfaceText
readonly property color dimColor: Theme.surfaceVariantText
readonly property bool available: WeatherService.weather.available
readonly property var weather: WeatherService.weather
readonly property real scaleFactor: Math.min(width, height) / 200
readonly property int scaledMargin: {
switch (viewMode) {
case "compact":
return 0;
case "standard":
return 2;
default:
return Math.round(Math.max(4, Theme.spacingS * scaleFactor));
}
}
readonly property int scaledSpacing: Math.round(Math.max(1, Theme.spacingXS * scaleFactor))
Ref {
service: WeatherService
}
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadius
color: root.bgColor
border.width: 0
ColumnLayout {
anchors.fill: parent
anchors.margins: root.scaledMargin
spacing: root.scaledSpacing
Loader {
id: headerLoader
Layout.fillWidth: true
Layout.fillHeight: {
switch (root.viewMode) {
case "compact":
case "standard":
return true;
case "detailed":
return !root.showForecast;
case "forecast":
return false;
default:
return true;
}
}
Layout.preferredHeight: {
if (root.viewMode === "forecast")
return 50;
if (root.viewMode === "detailed" && root.showForecast)
return 140;
return -1;
}
sourceComponent: {
switch (root.viewMode) {
case "compact":
return compactView;
case "standard":
return standardView;
case "detailed":
return detailedView;
case "forecast":
return forecastHeaderView;
default:
return standardView;
}
}
}
Loader {
Layout.fillWidth: true
Layout.fillHeight: true
visible: root.viewMode === "forecast" || (root.viewMode === "detailed" && root.showForecast)
active: visible
sourceComponent: forecastSection
}
}
Column {
anchors.centerIn: parent
spacing: Theme.spacingS
visible: !root.available
DankIcon {
name: "cloud_off"
size: Theme.iconSize * 1.5
color: root.dimColor
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: I18n.tr("No Weather Data")
font.pixelSize: Theme.fontSizeSmall
color: root.dimColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
Component {
id: compactView
Item {
id: compactRoot
visible: root.available
readonly property int baseSize: Math.min(width, height)
readonly property int iconSize: Math.round(baseSize * 0.55)
readonly property int tempFontSize: Math.round(baseSize * 0.22)
Column {
anchors.centerIn: parent
spacing: 0
DankIcon {
name: WeatherService.getWeatherIcon(root.weather.wCode)
size: compactRoot.iconSize
color: root.accentColor
anchors.horizontalCenter: parent.horizontalCenter
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
shadowVerticalOffset: 2
shadowBlur: 0.6
shadowColor: Theme.shadowMedium
shadowOpacity: 0.2
}
}
StyledText {
text: WeatherService.formatTemp(root.weather.temp, true, false)
font.pixelSize: compactRoot.tempFontSize
font.weight: Font.Light
color: root.textColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: standardView
Item {
id: standardRoot
visible: root.available
readonly property int baseSize: Math.min(width, height)
readonly property int iconSize: Math.round(baseSize * 0.55)
readonly property int tempFontSize: Math.round(baseSize * 0.28)
readonly property int labelFontSize: Math.max(9, Math.round(baseSize * 0.12))
RowLayout {
anchors.centerIn: parent
width: parent.width
spacing: Math.round(baseSize * 0.04)
DankIcon {
name: WeatherService.getWeatherIcon(root.weather.wCode)
size: standardRoot.iconSize
color: root.accentColor
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
shadowVerticalOffset: 3
shadowBlur: 0.7
shadowColor: Theme.shadowMedium
shadowOpacity: 0.2
}
}
Column {
Layout.fillWidth: true
spacing: 0
StyledText {
text: WeatherService.formatTemp(root.weather.temp, true, false)
font.pixelSize: standardRoot.tempFontSize
font.weight: Font.Light
color: root.textColor
}
StyledText {
visible: root.showCondition
text: WeatherService.getWeatherCondition(root.weather.wCode)
font.pixelSize: standardRoot.labelFontSize
color: root.dimColor
elide: Text.ElideRight
width: parent.width
}
StyledText {
visible: root.showLocation && root.weather.city
text: root.weather.city
font.pixelSize: standardRoot.labelFontSize
color: root.dimColor
elide: Text.ElideRight
width: parent.width
}
}
}
}
}
Component {
id: detailedView
Item {
id: detailedRoot
visible: root.available
readonly property int baseSize: Math.min(width, height)
readonly property int iconSize: Math.round(Math.max(28, Math.min(56, baseSize * 0.28)))
readonly property int tempFontSize: Math.round(Math.max(16, Math.min(32, baseSize * 0.16)))
readonly property int labelFontSize: Math.round(Math.max(10, Math.min(14, baseSize * 0.07)))
readonly property int smallIconSize: Math.round(Math.max(12, Math.min(16, baseSize * 0.07)))
readonly property int itemSpacing: Math.round(Math.max(2, Math.min(8, baseSize * 0.04)))
ColumnLayout {
anchors.fill: parent
spacing: detailedRoot.itemSpacing
RowLayout {
Layout.fillWidth: true
spacing: detailedRoot.itemSpacing * 2
DankIcon {
name: WeatherService.getWeatherIcon(root.weather.wCode)
size: detailedRoot.iconSize
color: root.accentColor
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
shadowVerticalOffset: 3
shadowBlur: 0.7
shadowColor: Theme.shadowMedium
shadowOpacity: 0.2
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 0
StyledText {
text: WeatherService.formatTemp(root.weather.temp, true, false)
font.pixelSize: detailedRoot.tempFontSize
font.weight: Font.Light
color: root.textColor
}
StyledText {
visible: root.showCondition
text: WeatherService.getWeatherCondition(root.weather.wCode)
font.pixelSize: detailedRoot.labelFontSize
color: root.dimColor
}
StyledText {
visible: root.showLocation && root.weather.city
text: root.weather.city
font.pixelSize: detailedRoot.labelFontSize
color: root.dimColor
elide: Text.ElideRight
Layout.fillWidth: true
}
}
Item {
Layout.fillWidth: true
}
ColumnLayout {
visible: root.showSunTimes
spacing: 1
Layout.alignment: Qt.AlignRight
RowLayout {
spacing: 2
DankIcon {
name: "wb_twilight"
size: detailedRoot.smallIconSize
color: root.dimColor
}
StyledText {
text: root.weather.sunrise || "--"
font.pixelSize: detailedRoot.labelFontSize
color: root.dimColor
}
}
RowLayout {
spacing: 2
DankIcon {
name: "bedtime"
size: detailedRoot.smallIconSize
color: root.dimColor
}
StyledText {
text: root.weather.sunset || "--"
font.pixelSize: detailedRoot.labelFontSize
color: root.dimColor
}
}
}
}
Rectangle {
Layout.fillWidth: true
height: 1
color: Theme.withAlpha(Theme.outline, 0.15)
}
Flow {
Layout.fillWidth: true
spacing: detailedRoot.itemSpacing
WeatherMetric {
visible: root.showFeelsLike
icon: "device_thermostat"
label: I18n.tr("Feels")
value: WeatherService.formatTemp(root.weather.feelsLike, true, true)
accentColor: root.accentColor
textColor: root.textColor
dimColor: root.dimColor
iconSize: detailedRoot.smallIconSize
fontSize: detailedRoot.labelFontSize
}
WeatherMetric {
visible: root.showHumidity
icon: "humidity_percentage"
label: I18n.tr("Humidity")
value: WeatherService.formatPercent(root.weather.humidity)
accentColor: root.accentColor
textColor: root.textColor
dimColor: root.dimColor
iconSize: detailedRoot.smallIconSize
fontSize: detailedRoot.labelFontSize
}
WeatherMetric {
visible: root.showWind
icon: "air"
label: I18n.tr("Wind")
value: root.weather.wind || "--"
accentColor: root.accentColor
textColor: root.textColor
dimColor: root.dimColor
iconSize: detailedRoot.smallIconSize
fontSize: detailedRoot.labelFontSize
}
WeatherMetric {
visible: root.showPrecipitation
icon: "rainy"
label: I18n.tr("Precip")
value: WeatherService.formatPercent(root.weather.precipitationProbability)
accentColor: root.accentColor
textColor: root.textColor
dimColor: root.dimColor
iconSize: detailedRoot.smallIconSize
fontSize: detailedRoot.labelFontSize
}
WeatherMetric {
visible: root.showPressure
icon: "speed"
label: I18n.tr("Pressure")
value: WeatherService.formatPressure(root.weather.pressure)
accentColor: root.accentColor
textColor: root.textColor
dimColor: root.dimColor
iconSize: detailedRoot.smallIconSize
fontSize: detailedRoot.labelFontSize
}
}
Item {
Layout.fillHeight: true
visible: !root.showForecast
}
}
}
}
Component {
id: forecastHeaderView
Item {
id: forecastHeaderRoot
visible: root.available
readonly property int baseSize: Math.min(width, height)
readonly property int iconSize: Math.round(Math.max(20, baseSize * 0.7))
readonly property int tempFontSize: Math.round(Math.max(12, baseSize * 0.4))
readonly property int labelFontSize: Math.round(Math.max(9, baseSize * 0.22))
RowLayout {
anchors.fill: parent
spacing: Math.round(baseSize * 0.15)
DankIcon {
name: WeatherService.getWeatherIcon(root.weather.wCode)
size: forecastHeaderRoot.iconSize
color: root.accentColor
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
shadowVerticalOffset: 2
shadowBlur: 0.6
shadowColor: Theme.shadowMedium
shadowOpacity: 0.2
}
}
ColumnLayout {
spacing: 0
StyledText {
text: WeatherService.formatTemp(root.weather.temp, true, false)
font.pixelSize: forecastHeaderRoot.tempFontSize
font.weight: Font.Light
color: root.textColor
}
StyledText {
visible: root.showLocation && root.weather.city
text: root.weather.city
font.pixelSize: forecastHeaderRoot.labelFontSize
color: root.dimColor
}
}
Item {
Layout.fillWidth: true
}
GridLayout {
columns: 2
rowSpacing: 1
columnSpacing: Math.round(forecastHeaderRoot.baseSize * 0.1)
visible: root.width > 300
WeatherMetric {
visible: root.showHumidity
icon: "humidity_percentage"
value: WeatherService.formatPercent(root.weather.humidity)
accentColor: root.accentColor
textColor: root.textColor
dimColor: root.dimColor
compact: true
iconSize: forecastHeaderRoot.labelFontSize
fontSize: forecastHeaderRoot.labelFontSize
}
WeatherMetric {
visible: root.showWind
icon: "air"
value: root.weather.wind || "--"
accentColor: root.accentColor
textColor: root.textColor
dimColor: root.dimColor
compact: true
iconSize: forecastHeaderRoot.labelFontSize
fontSize: forecastHeaderRoot.labelFontSize
}
}
}
}
}
Component {
id: forecastSection
ColumnLayout {
id: forecastRoot
spacing: root.scaledSpacing
visible: root.available && root.showForecast
readonly property int itemFontSize: Math.round(Math.max(10, Math.min(14, root.height * 0.035)))
readonly property int itemIconSize: Math.round(Math.max(12, Math.min(18, root.height * 0.04)))
Rectangle {
Layout.fillWidth: true
height: 1
color: Theme.withAlpha(Theme.outline, 0.15)
visible: root.viewMode === "forecast"
}
DankListView {
id: hourlyList
Layout.fillWidth: true
Layout.preferredHeight: root.showHourlyForecast ? Math.round(Math.max(50, Math.min(80, root.height * 0.18))) : 0
visible: root.showHourlyForecast && root.weather.hourlyForecast?.length > 0
orientation: ListView.Horizontal
flickableDirection: Flickable.HorizontalFlick
spacing: root.scaledSpacing
clip: true
model: Math.min(root.hourlyCount, root.weather.hourlyForecast?.length ?? 0)
delegate: Rectangle {
required property int index
width: Math.round(Math.max(36, hourlyList.height * 0.8))
height: hourlyList.height
radius: Theme.cornerRadius - 2
color: root.tileBg
property var forecast: root.weather.hourlyForecast?.[index] ?? {}
ColumnLayout {
anchors.fill: parent
anchors.margins: 2
spacing: 0
Item {
Layout.fillHeight: true
}
StyledText {
text: forecast.time || "--"
font.pixelSize: forecastRoot.itemFontSize
color: root.dimColor
Layout.alignment: Qt.AlignHCenter
}
DankIcon {
name: WeatherService.getWeatherIcon(forecast.wCode, forecast.isDay)
size: forecastRoot.itemIconSize
color: root.accentColor
Layout.alignment: Qt.AlignHCenter
}
StyledText {
text: WeatherService.formatTemp(forecast.temp, false)
font.pixelSize: forecastRoot.itemFontSize
font.weight: Font.Medium
color: root.textColor
Layout.alignment: Qt.AlignHCenter
}
Item {
Layout.fillHeight: true
}
}
}
}
Rectangle {
Layout.fillWidth: true
height: 1
color: Theme.withAlpha(Theme.outline, 0.1)
visible: root.showHourlyForecast && root.weather.hourlyForecast?.length > 0
}
DankListView {
id: dailyList
Layout.fillWidth: true
Layout.fillHeight: true
spacing: root.scaledSpacing
clip: true
readonly property int itemCount: Math.min(root.forecastDays, root.weather.forecast?.length ?? 0)
readonly property int dynamicItemHeight: itemCount > 0 ? Math.round((height - (itemCount - 1) * spacing) / itemCount) : 24
model: itemCount
delegate: Rectangle {
required property int index
width: dailyList.width
height: dailyList.dynamicItemHeight
radius: Theme.cornerRadius - 2
color: index === 0 ? Theme.withAlpha(root.accentColor, 0.1) : root.tileBg
property var forecast: root.weather.forecast?.[index] ?? {}
RowLayout {
anchors.fill: parent
anchors.leftMargin: root.scaledMargin
anchors.rightMargin: root.scaledMargin
spacing: root.scaledSpacing
StyledText {
text: forecast.day || "--"
font.pixelSize: forecastRoot.itemFontSize
font.weight: index === 0 ? Font.Medium : Font.Normal
color: root.textColor
Layout.preferredWidth: forecastRoot.itemFontSize * 5
}
DankIcon {
name: WeatherService.getWeatherIcon(forecast.wCode, true)
size: forecastRoot.itemIconSize + 2
color: root.accentColor
}
Item {
Layout.fillWidth: true
}
RowLayout {
spacing: 1
visible: forecast.precipitationProbability > 0
DankIcon {
name: "water_drop"
size: forecastRoot.itemIconSize - 2
color: Theme.primary
}
StyledText {
text: forecast.precipitationProbability + "%"
font.pixelSize: forecastRoot.itemFontSize - 1
color: Theme.primary
}
}
StyledText {
text: WeatherService.formatTemp(forecast.tempMax, false)
font.pixelSize: forecastRoot.itemFontSize
font.weight: Font.Medium
color: root.textColor
horizontalAlignment: Text.AlignRight
Layout.preferredWidth: forecastRoot.itemFontSize * 2.5
}
StyledText {
text: WeatherService.formatTemp(forecast.tempMin, false)
font.pixelSize: forecastRoot.itemFontSize
color: root.dimColor
horizontalAlignment: Text.AlignRight
Layout.preferredWidth: forecastRoot.itemFontSize * 2.5
}
}
}
}
}
}
component WeatherMetric: RowLayout {
property string icon: ""
property string label: ""
property string value: ""
property color accentColor: Theme.primary
property color textColor: Theme.surfaceText
property color dimColor: Theme.surfaceVariantText
property bool compact: false
property real iconSize: Theme.iconSizeSmall
property real fontSize: Theme.fontSizeSmall
spacing: 2
DankIcon {
name: parent.icon
size: compact ? parent.iconSize - 2 : parent.iconSize
color: parent.accentColor
}
ColumnLayout {
spacing: 0
visible: !compact
StyledText {
visible: parent.parent.label.length > 0
text: parent.parent.label
font.pixelSize: parent.parent.fontSize - 2
color: parent.parent.dimColor
}
StyledText {
text: parent.parent.value
font.pixelSize: parent.parent.fontSize
color: parent.parent.textColor
}
}
StyledText {
visible: compact
text: parent.value
font.pixelSize: parent.fontSize
color: parent.textColor
}
}
}

View file

@ -0,0 +1,147 @@
import QtQuick
import qs.Common
import qs.Modules.Plugins
PluginSettings {
id: root
pluginId: "dankDesktopWeather"
SelectionSetting {
settingKey: "viewMode"
label: I18n.tr("View Mode")
description: I18n.tr("Choose how the weather widget is displayed")
options: [
{
label: I18n.tr("Compact"),
value: "compact"
},
{
label: I18n.tr("Standard"),
value: "standard"
},
{
label: I18n.tr("Detailed"),
value: "detailed"
},
{
label: I18n.tr("Forecast"),
value: "forecast"
}
]
defaultValue: "standard"
}
SelectionSetting {
settingKey: "colorMode"
label: I18n.tr("Accent Color")
options: [
{
label: I18n.tr("Primary"),
value: "primary"
},
{
label: I18n.tr("Secondary"),
value: "secondary"
},
{
label: I18n.tr("Custom"),
value: "custom"
}
]
defaultValue: "primary"
}
ColorSetting {
settingKey: "customColor"
label: I18n.tr("Custom Color")
description: I18n.tr("Used when accent color is set to Custom")
defaultValue: "#4fc3f7"
}
SliderSetting {
settingKey: "backgroundOpacity"
label: I18n.tr("Background Opacity")
defaultValue: 80
minimum: 0
maximum: 100
unit: "%"
}
ToggleSetting {
settingKey: "showLocation"
label: I18n.tr("Show Location")
defaultValue: true
}
ToggleSetting {
settingKey: "showCondition"
label: I18n.tr("Show Weather Condition")
defaultValue: true
}
ToggleSetting {
settingKey: "showFeelsLike"
label: I18n.tr("Show Feels Like Temperature")
defaultValue: true
}
ToggleSetting {
settingKey: "showHumidity"
label: I18n.tr("Show Humidity")
defaultValue: true
}
ToggleSetting {
settingKey: "showWind"
label: I18n.tr("Show Wind Speed")
defaultValue: true
}
ToggleSetting {
settingKey: "showPressure"
label: I18n.tr("Show Pressure")
defaultValue: false
}
ToggleSetting {
settingKey: "showPrecipitation"
label: I18n.tr("Show Precipitation Probability")
defaultValue: true
}
ToggleSetting {
settingKey: "showSunTimes"
label: I18n.tr("Show Sunrise/Sunset")
defaultValue: true
}
ToggleSetting {
settingKey: "showForecast"
label: I18n.tr("Show Forecast")
description: I18n.tr("Available in Detailed and Forecast view modes")
defaultValue: true
}
SliderSetting {
settingKey: "forecastDays"
label: I18n.tr("Forecast Days")
defaultValue: 5
minimum: 1
maximum: 7
}
ToggleSetting {
settingKey: "showHourlyForecast"
label: I18n.tr("Show Hourly Forecast")
description: I18n.tr("Display hourly weather predictions")
defaultValue: false
}
SliderSetting {
settingKey: "hourlyCount"
label: I18n.tr("Hourly Forecast Count")
defaultValue: 6
minimum: 3
maximum: 12
}
}

View file

@ -0,0 +1,19 @@
{
"id": "dankDesktopWeather",
"name": "Dank Desktop Weather",
"description": "Feature-rich weather widget with current conditions, forecasts, and multiple view modes",
"version": "1.0.1",
"license": "MIT",
"author": "Avenge Media",
"icon": "partly_cloudy_day",
"firstParty": true,
"type": "desktop",
"capabilities": ["desktop-widget", "weather"],
"component": "./DankDesktopWeather.qml",
"settings": "./DankDesktopWeatherSettings.qml",
"requires_dms": ">=1.2.0",
"permissions": [
"settings_read",
"settings_write"
]
}