mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-27 23:12:49 -05:00
plugins/desktop-widgets: create a new "desktop" widget plugin type
- Draggable per-monitor background layer widgets - Add basic dms version checks on plugins - Clock: built-in clock desktop plugin - dgop: built-in system monitor desktop plugin
This commit is contained in:
439
quickshell/Modules/BuiltinDesktopPlugins/DesktopClockWidget.qml
Normal file
439
quickshell/Modules/BuiltinDesktopPlugins/DesktopClockWidget.qml
Normal file
@@ -0,0 +1,439 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property real widgetWidth: 280
|
||||
property real widgetHeight: 200
|
||||
|
||||
property string clockStyle: SettingsData.desktopClockStyle
|
||||
property bool forceSquare: clockStyle === "analog"
|
||||
|
||||
property real defaultWidth: {
|
||||
switch (clockStyle) {
|
||||
case "analog":
|
||||
return 200;
|
||||
case "stacked":
|
||||
return 160;
|
||||
default:
|
||||
return 280;
|
||||
}
|
||||
}
|
||||
property real defaultHeight: {
|
||||
switch (clockStyle) {
|
||||
case "analog":
|
||||
return 200;
|
||||
case "stacked":
|
||||
return 220;
|
||||
default:
|
||||
return 160;
|
||||
}
|
||||
}
|
||||
property real minWidth: {
|
||||
switch (clockStyle) {
|
||||
case "analog":
|
||||
return 120;
|
||||
case "stacked":
|
||||
return 100;
|
||||
default:
|
||||
return 140;
|
||||
}
|
||||
}
|
||||
property real minHeight: {
|
||||
switch (clockStyle) {
|
||||
case "analog":
|
||||
return 120;
|
||||
case "stacked":
|
||||
return 140;
|
||||
default:
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
||||
property bool enabled: SettingsData.desktopClockEnabled
|
||||
property real transparency: SettingsData.desktopClockTransparency
|
||||
property string colorMode: SettingsData.desktopClockColorMode
|
||||
property color customColor: SettingsData.desktopClockCustomColor
|
||||
property bool showDate: SettingsData.desktopClockShowDate
|
||||
property bool showAnalogNumbers: SettingsData.desktopClockShowAnalogNumbers
|
||||
|
||||
readonly property real scaleFactor: Math.min(width, height) / 200
|
||||
|
||||
readonly property color accentColor: {
|
||||
if (colorMode === "primary")
|
||||
return Theme.primary;
|
||||
if (colorMode === "secondary")
|
||||
return Theme.secondary;
|
||||
if (colorMode === "custom")
|
||||
return customColor;
|
||||
return Theme.primary;
|
||||
}
|
||||
|
||||
readonly property color handColor: accentColor
|
||||
readonly property color handColorDim: Theme.withAlpha(accentColor, 0.65)
|
||||
readonly property color textColor: Theme.onSurface
|
||||
readonly property color subtleTextColor: Theme.onSurfaceVariant
|
||||
readonly property color backgroundColor: Theme.withAlpha(Theme.surface, root.transparency)
|
||||
|
||||
SystemClock {
|
||||
id: systemClock
|
||||
precision: SystemClock.Seconds
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Theme.cornerRadius
|
||||
color: root.backgroundColor
|
||||
visible: root.clockStyle !== "analog"
|
||||
}
|
||||
|
||||
OrganicBlobHourBulges {
|
||||
anchors.fill: parent
|
||||
fillColor: root.backgroundColor
|
||||
visible: root.clockStyle === "analog"
|
||||
lobes: 12
|
||||
rotationDeg: -90
|
||||
lobeAmount: 0.075
|
||||
hillPower: 0.92
|
||||
roundness: 0.22
|
||||
paddingFrac: 0.02
|
||||
segments: 144
|
||||
}
|
||||
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
sourceComponent: {
|
||||
if (root.clockStyle === "analog")
|
||||
return analogClock;
|
||||
if (root.clockStyle === "stacked")
|
||||
return stackedClock;
|
||||
return digitalClock;
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: analogClock
|
||||
|
||||
Item {
|
||||
id: analogRoot
|
||||
|
||||
property real clockSize: Math.min(width, height)
|
||||
property real centerX: width / 2
|
||||
property real centerY: height / 2
|
||||
property real faceRadius: clockSize / 2 - 12
|
||||
|
||||
property int hours: systemClock.date?.getHours() % 12 ?? 0
|
||||
property int minutes: systemClock.date?.getMinutes() ?? 0
|
||||
property int seconds: systemClock.date?.getSeconds() ?? 0
|
||||
|
||||
Repeater {
|
||||
model: root.showAnalogNumbers ? 12 : 0
|
||||
|
||||
StyledText {
|
||||
required property int index
|
||||
property real angle: (index + 1) * 30 * Math.PI / 180
|
||||
property real numRadius: analogRoot.faceRadius + 10
|
||||
|
||||
x: analogRoot.centerX + numRadius * Math.sin(angle) - width / 2
|
||||
y: analogRoot.centerY - numRadius * Math.cos(angle) - height / 2
|
||||
text: index + 1
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: root.accentColor
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: hourHand
|
||||
property real angle: (analogRoot.hours + analogRoot.minutes / 60) * 30
|
||||
property real handWidth: Math.max(8, 12 * root.scaleFactor)
|
||||
property real mainLength: analogRoot.faceRadius * 0.55
|
||||
property real tailLength: handWidth * 0.5
|
||||
|
||||
x: analogRoot.centerX - width / 2
|
||||
y: analogRoot.centerY - mainLength
|
||||
width: handWidth
|
||||
height: mainLength + tailLength
|
||||
radius: width / 2
|
||||
color: root.handColor
|
||||
antialiasing: true
|
||||
|
||||
transform: Rotation {
|
||||
origin.x: hourHand.width / 2
|
||||
origin.y: hourHand.mainLength
|
||||
angle: hourHand.angle
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: minuteHand
|
||||
property real angle: (analogRoot.minutes + analogRoot.seconds / 60) * 6
|
||||
property real mainLength: analogRoot.faceRadius * 0.75
|
||||
property real tailLength: hourHand.handWidth * 0.5
|
||||
|
||||
x: analogRoot.centerX - width / 2
|
||||
y: analogRoot.centerY - mainLength
|
||||
width: hourHand.handWidth
|
||||
height: mainLength + tailLength
|
||||
radius: width / 2
|
||||
color: root.handColorDim
|
||||
antialiasing: true
|
||||
|
||||
transform: Rotation {
|
||||
origin.x: minuteHand.width / 2
|
||||
origin.y: minuteHand.mainLength
|
||||
angle: minuteHand.angle
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: secondDot
|
||||
property real angle: analogRoot.seconds * 6 * Math.PI / 180
|
||||
property real orbitRadius: analogRoot.faceRadius * 0.92
|
||||
|
||||
x: analogRoot.centerX + orbitRadius * Math.sin(angle) - width / 2
|
||||
y: analogRoot.centerY - orbitRadius * Math.cos(angle) - height / 2
|
||||
width: Math.max(10, analogRoot.clockSize * 0.07)
|
||||
height: width
|
||||
radius: width / 2
|
||||
color: root.accentColor
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: dateText
|
||||
visible: root.showDate
|
||||
|
||||
property real hourAngle: (analogRoot.hours + analogRoot.minutes / 60) * 30
|
||||
property real minuteAngle: analogRoot.minutes * 6
|
||||
|
||||
property string bestPosition: {
|
||||
const hRad = hourAngle * Math.PI / 180;
|
||||
const mRad = minuteAngle * Math.PI / 180;
|
||||
|
||||
const topWeight = Math.max(0, Math.cos(hRad)) + Math.max(0, Math.cos(mRad));
|
||||
const bottomWeight = Math.max(0, -Math.cos(hRad)) + Math.max(0, -Math.cos(mRad));
|
||||
const rightWeight = Math.max(0, Math.sin(hRad)) + Math.max(0, Math.sin(mRad));
|
||||
const leftWeight = Math.max(0, -Math.sin(hRad)) + Math.max(0, -Math.sin(mRad));
|
||||
|
||||
const minWeight = Math.min(topWeight, bottomWeight, leftWeight, rightWeight);
|
||||
|
||||
if (minWeight === bottomWeight)
|
||||
return "bottom";
|
||||
if (minWeight === topWeight)
|
||||
return "top";
|
||||
if (minWeight === rightWeight)
|
||||
return "right";
|
||||
return "left";
|
||||
}
|
||||
|
||||
x: {
|
||||
if (bestPosition === "left")
|
||||
return analogRoot.centerX - analogRoot.faceRadius * 0.5 - width / 2;
|
||||
if (bestPosition === "right")
|
||||
return analogRoot.centerX + analogRoot.faceRadius * 0.5 - width / 2;
|
||||
return analogRoot.centerX - width / 2;
|
||||
}
|
||||
y: {
|
||||
if (bestPosition === "top")
|
||||
return analogRoot.centerY - analogRoot.faceRadius * 0.5 - height / 2;
|
||||
if (bestPosition === "bottom")
|
||||
return analogRoot.centerY + analogRoot.faceRadius * 0.5 - height / 2;
|
||||
return analogRoot.centerY - height / 2;
|
||||
}
|
||||
|
||||
text: {
|
||||
if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0)
|
||||
return systemClock.date?.toLocaleDateString(Qt.locale(), SettingsData.clockDateFormat) ?? "";
|
||||
return systemClock.date?.toLocaleDateString(Qt.locale(), "ddd, MMM d") ?? "";
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: root.accentColor
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: digitalClock
|
||||
|
||||
Item {
|
||||
id: digitalRoot
|
||||
|
||||
property real baseSize: Math.max(28, height * 0.38)
|
||||
property real smallSize: Math.max(12, baseSize * 0.32)
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 4
|
||||
|
||||
StyledText {
|
||||
visible: root.showDate
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: {
|
||||
if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0)
|
||||
return systemClock.date?.toLocaleDateString(Qt.locale(), SettingsData.clockDateFormat) ?? "";
|
||||
return systemClock.date?.toLocaleDateString(Qt.locale(), "ddd, MMM d") ?? "";
|
||||
}
|
||||
font.pixelSize: digitalRoot.smallSize
|
||||
color: root.accentColor
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: {
|
||||
const hours = SettingsData.use24HourClock ? systemClock.date?.getHours() ?? 0 : ((systemClock.date?.getHours() ?? 0) % 12 || 12);
|
||||
const minutes = String(systemClock.date?.getMinutes() ?? 0).padStart(2, '0');
|
||||
return hours + ":" + minutes;
|
||||
}
|
||||
font.pixelSize: digitalRoot.baseSize
|
||||
font.weight: Font.Normal
|
||||
color: root.accentColor
|
||||
}
|
||||
|
||||
Row {
|
||||
visible: !SettingsData.use24HourClock || SettingsData.showSeconds
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Row {
|
||||
visible: SettingsData.showSeconds
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
DankIcon {
|
||||
name: "timer"
|
||||
size: Math.max(10, digitalRoot.baseSize * 0.25)
|
||||
color: root.subtleTextColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: String(systemClock.date?.getSeconds() ?? 0).padStart(2, '0')
|
||||
font.pixelSize: digitalRoot.smallSize
|
||||
color: root.subtleTextColor
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
visible: !SettingsData.use24HourClock
|
||||
text: (systemClock.date?.getHours() ?? 0) >= 12 ? "PM" : "AM"
|
||||
font.pixelSize: digitalRoot.smallSize
|
||||
font.weight: Font.Medium
|
||||
color: root.accentColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: stackedClock
|
||||
|
||||
Item {
|
||||
id: stackedRoot
|
||||
|
||||
property real baseSize: Math.max(32, height * 0.32)
|
||||
property real smallSize: Math.max(12, baseSize * 0.28)
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: -baseSize * 0.1
|
||||
|
||||
StyledText {
|
||||
visible: root.showDate
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
bottomPadding: Theme.spacingS
|
||||
text: {
|
||||
if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0)
|
||||
return systemClock.date?.toLocaleDateString(Qt.locale(), SettingsData.clockDateFormat) ?? "";
|
||||
return systemClock.date?.toLocaleDateString(Qt.locale(), "ddd, MMM d") ?? "";
|
||||
}
|
||||
font.pixelSize: stackedRoot.smallSize
|
||||
color: root.accentColor
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: {
|
||||
const hours = SettingsData.use24HourClock ? systemClock.date?.getHours() ?? 0 : ((systemClock.date?.getHours() ?? 0) % 12 || 12);
|
||||
return String(hours).padStart(2, '0');
|
||||
}
|
||||
font.pixelSize: stackedRoot.baseSize
|
||||
font.weight: Font.Normal
|
||||
color: root.accentColor
|
||||
lineHeight: 0.85
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: String(systemClock.date?.getMinutes() ?? 0).padStart(2, '0')
|
||||
font.pixelSize: stackedRoot.baseSize
|
||||
font.weight: Font.Normal
|
||||
color: root.accentColor
|
||||
lineHeight: 0.85
|
||||
}
|
||||
|
||||
Row {
|
||||
visible: SettingsData.showSeconds || !SettingsData.use24HourClock
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
topPadding: Theme.spacingXS
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Row {
|
||||
visible: SettingsData.showSeconds
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
DankIcon {
|
||||
name: "timer"
|
||||
size: Math.max(10, stackedRoot.baseSize * 0.28)
|
||||
color: root.subtleTextColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: String(systemClock.date?.getSeconds() ?? 0).padStart(2, '0')
|
||||
font.pixelSize: stackedRoot.smallSize
|
||||
color: root.subtleTextColor
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
visible: !SettingsData.use24HourClock
|
||||
text: (systemClock.date?.getHours() ?? 0) >= 12 ? "PM" : "AM"
|
||||
font.pixelSize: stackedRoot.smallSize
|
||||
font.weight: Font.Medium
|
||||
color: root.accentColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user