mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-02 10:32:07 -04:00
Compare commits
5 Commits
4eb896629d
...
bcfa508da5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcfa508da5 | ||
|
|
c0ae3ef58b | ||
|
|
1e70d7b4c3 | ||
|
|
f8dc6ad2bc | ||
|
|
e22482988f |
@@ -2,28 +2,42 @@
|
||||
|
||||
Contributions are welcome and encouraged.
|
||||
|
||||
## Formatting
|
||||
To contribute fork this repository, make your changes, and open a pull request.
|
||||
|
||||
The preferred tool for formatting files is [qmlfmt](https://github.com/jesperhh/qmlfmt) (also available on aur as qmlfmt-git). It actually kinda sucks, but `qmlformat` doesn't work with null safe operators and ternarys and pragma statements and a bunch of other things that are supported.
|
||||
## VSCode Setup
|
||||
|
||||
We need some consistent style, so this at least gives the same formatter that Qt Creator uses.
|
||||
This is a monorepo, the easiest thing to do is to open an editor in either `quickshell`, `core`, or both depending on which part of the project you are working on.
|
||||
|
||||
You can configure it to format on save in vscode by configuring the "custom local formatters" extension then adding this to settings json.
|
||||
### QML (`quickshell` directory)
|
||||
|
||||
1. Install the [QML Extension](https://doc.qt.io/vscodeext/)
|
||||
2. Configure `ctrl+shift+p` -> user preferences (json) with qmlls path
|
||||
|
||||
```json
|
||||
"customLocalFormatters.formatters": [
|
||||
{
|
||||
"command": "sh -c \"qmlfmt -t 4 -i 4 -b 250 | sed 's/pragma ComponentBehavior$/pragma ComponentBehavior: Bound/g'\"",
|
||||
"languages": ["qml"]
|
||||
}
|
||||
],
|
||||
"[qml]": {
|
||||
"editor.defaultFormatter": "jkillian.custom-local-formatters",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
{
|
||||
"qt-qml.doNotAskForQmllsDownload": true,
|
||||
"qt-qml.qmlls.customExePath": "/usr/lib/qt6/bin/qmlls"
|
||||
}
|
||||
```
|
||||
|
||||
Sometimes it just breaks code though. Like turning `"_\""` into `"_""`, so you may not want to do formatOnSave.
|
||||
3. Create empty `.qmlls.ini` file in `quickshell/` directory
|
||||
|
||||
```bash
|
||||
cd quickshell
|
||||
touch .qmlls.ini
|
||||
```
|
||||
|
||||
4. Restart dms to generate the `.qmlls.ini` file
|
||||
|
||||
5. Make your changes, test, and open a pull request.
|
||||
|
||||
### GO (`core` directory)
|
||||
|
||||
1. Install the [Go Extension](https://code.visualstudio.com/docs/languages/go)
|
||||
2. Ensure code is formatted with `make fmt`
|
||||
3. Add appropriate test coverage and ensure tests pass with `make test`
|
||||
4. Run `go mod tidy`
|
||||
5. Open pull request
|
||||
|
||||
## Pull request
|
||||
|
||||
|
||||
@@ -2,19 +2,16 @@ import QtQuick
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
import qs.Modules
|
||||
import qs.Services
|
||||
|
||||
Variants {
|
||||
model: {
|
||||
if (SessionData.isGreeterMode) {
|
||||
return Quickshell.screens
|
||||
return Quickshell.screens;
|
||||
}
|
||||
return SettingsData.getFilteredScreens("wallpaper")
|
||||
return SettingsData.getFilteredScreens("wallpaper");
|
||||
}
|
||||
|
||||
PanelWindow {
|
||||
@@ -50,9 +47,9 @@ Variants {
|
||||
target: SessionData
|
||||
function onIsLightModeChanged() {
|
||||
if (SessionData.perModeWallpaper) {
|
||||
var newSource = SessionData.getMonitorWallpaper(modelData.name) || ""
|
||||
var newSource = SessionData.getMonitorWallpaper(modelData.name) || "";
|
||||
if (newSource !== root.source) {
|
||||
root.source = newSource
|
||||
root.source = newSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,32 +58,32 @@ Variants {
|
||||
function getFillMode(modeName) {
|
||||
switch (modeName) {
|
||||
case "Stretch":
|
||||
return Image.Stretch
|
||||
return Image.Stretch;
|
||||
case "Fit":
|
||||
case "PreserveAspectFit":
|
||||
return Image.PreserveAspectFit
|
||||
return Image.PreserveAspectFit;
|
||||
case "Fill":
|
||||
case "PreserveAspectCrop":
|
||||
return Image.PreserveAspectCrop
|
||||
return Image.PreserveAspectCrop;
|
||||
case "Tile":
|
||||
return Image.Tile
|
||||
return Image.Tile;
|
||||
case "TileVertically":
|
||||
return Image.TileVertically
|
||||
return Image.TileVertically;
|
||||
case "TileHorizontally":
|
||||
return Image.TileHorizontally
|
||||
return Image.TileHorizontally;
|
||||
case "Pad":
|
||||
return Image.Pad
|
||||
return Image.Pad;
|
||||
default:
|
||||
return Image.PreserveAspectCrop
|
||||
return Image.PreserveAspectCrop;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (source) {
|
||||
const formattedSource = source.startsWith("file://") ? source : "file://" + source
|
||||
setWallpaperImmediate(formattedSource)
|
||||
const formattedSource = source.startsWith("file://") ? source : "file://" + source;
|
||||
setWallpaperImmediate(formattedSource);
|
||||
}
|
||||
isInitialized = true
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
property bool isInitialized: false
|
||||
@@ -94,55 +91,54 @@ Variants {
|
||||
readonly property bool transitioning: transitionAnimation.running
|
||||
|
||||
onSourceChanged: {
|
||||
const isColor = source.startsWith("#")
|
||||
const isColor = source.startsWith("#");
|
||||
|
||||
if (!source) {
|
||||
setWallpaperImmediate("")
|
||||
setWallpaperImmediate("");
|
||||
} else if (isColor) {
|
||||
setWallpaperImmediate("")
|
||||
setWallpaperImmediate("");
|
||||
} else {
|
||||
if (!isInitialized || !currentWallpaper.source) {
|
||||
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source)
|
||||
isInitialized = true
|
||||
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source);
|
||||
isInitialized = true;
|
||||
} else if (CompositorService.isNiri && SessionData.isSwitchingMode) {
|
||||
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source)
|
||||
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source);
|
||||
} else {
|
||||
changeWallpaper(source.startsWith("file://") ? source : "file://" + source)
|
||||
changeWallpaper(source.startsWith("file://") ? source : "file://" + source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setWallpaperImmediate(newSource) {
|
||||
transitionAnimation.stop()
|
||||
root.transitionProgress = 0.0
|
||||
currentWallpaper.source = newSource
|
||||
nextWallpaper.source = ""
|
||||
currentWallpaper.opacity = 1
|
||||
nextWallpaper.opacity = 0
|
||||
transitionAnimation.stop();
|
||||
root.transitionProgress = 0.0;
|
||||
currentWallpaper.source = newSource;
|
||||
nextWallpaper.source = "";
|
||||
currentWallpaper.opacity = 1;
|
||||
nextWallpaper.opacity = 0;
|
||||
}
|
||||
|
||||
function changeWallpaper(newPath) {
|
||||
if (newPath === currentWallpaper.source)
|
||||
return
|
||||
return;
|
||||
if (!newPath || newPath.startsWith("#"))
|
||||
return
|
||||
|
||||
return;
|
||||
if (root.transitioning) {
|
||||
transitionAnimation.stop()
|
||||
root.transitionProgress = 0
|
||||
currentWallpaper.source = nextWallpaper.source
|
||||
nextWallpaper.source = ""
|
||||
transitionAnimation.stop();
|
||||
root.transitionProgress = 0;
|
||||
currentWallpaper.source = nextWallpaper.source;
|
||||
nextWallpaper.source = "";
|
||||
}
|
||||
|
||||
if (!currentWallpaper.source) {
|
||||
setWallpaperImmediate(newPath)
|
||||
return
|
||||
setWallpaperImmediate(newPath);
|
||||
return;
|
||||
}
|
||||
|
||||
nextWallpaper.source = newPath
|
||||
nextWallpaper.source = newPath;
|
||||
|
||||
if (nextWallpaper.status === Image.Ready) {
|
||||
transitionAnimation.start()
|
||||
transitionAnimation.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,10 +175,9 @@ Variants {
|
||||
|
||||
onStatusChanged: {
|
||||
if (status !== Image.Ready)
|
||||
return
|
||||
|
||||
return;
|
||||
if (!root.transitioning) {
|
||||
transitionAnimation.start()
|
||||
transitionAnimation.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,14 +217,14 @@ Variants {
|
||||
easing.type: Easing.InOutCubic
|
||||
onFinished: {
|
||||
Qt.callLater(() => {
|
||||
if (nextWallpaper.source && nextWallpaper.status === Image.Ready && !nextWallpaper.source.toString().startsWith("#")) {
|
||||
currentWallpaper.source = nextWallpaper.source
|
||||
}
|
||||
nextWallpaper.source = ""
|
||||
currentWallpaper.opacity = 1
|
||||
nextWallpaper.opacity = 0
|
||||
root.transitionProgress = 0.0
|
||||
})
|
||||
if (nextWallpaper.source && nextWallpaper.status === Image.Ready && !nextWallpaper.source.toString().startsWith("#")) {
|
||||
currentWallpaper.source = nextWallpaper.source;
|
||||
}
|
||||
nextWallpaper.source = "";
|
||||
currentWallpaper.opacity = 1;
|
||||
nextWallpaper.opacity = 0;
|
||||
root.transitionProgress = 0.0;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,9 +430,9 @@ PanelWindow {
|
||||
bottom: barWindow.isVertical ? parent.bottom : undefined
|
||||
}
|
||||
readonly property bool inOverview: CompositorService.isNiri && NiriService.inOverview && SettingsData.dankBarOpenOnOverview
|
||||
hoverEnabled: SettingsData.dankBarAutoHide && !topBarCore.reveal && !inOverview
|
||||
hoverEnabled: SettingsData.dankBarAutoHide && !inOverview
|
||||
acceptedButtons: Qt.NoButton
|
||||
enabled: SettingsData.dankBarAutoHide && !topBarCore.reveal && !inOverview
|
||||
enabled: SettingsData.dankBarAutoHide && !inOverview
|
||||
|
||||
Item {
|
||||
id: topBarContainer
|
||||
|
||||
@@ -37,10 +37,10 @@ BasePill {
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
|
||||
if (temp === undefined || temp === null || temp === 0) {
|
||||
if (!WeatherService.weather.available) {
|
||||
return "--";
|
||||
}
|
||||
const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
|
||||
return temp;
|
||||
}
|
||||
font.pixelSize: Theme.barTextSize(root.barThickness)
|
||||
@@ -64,11 +64,10 @@ BasePill {
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
|
||||
if (temp === undefined || temp === null || temp === 0) {
|
||||
if (!WeatherService.weather.available) {
|
||||
return "--°" + (SettingsData.useFahrenheit ? "F" : "C");
|
||||
}
|
||||
|
||||
const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
|
||||
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
|
||||
}
|
||||
font.pixelSize: Theme.barTextSize(root.barThickness)
|
||||
|
||||
@@ -139,7 +139,7 @@ Item {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (WeatherService.weather.available) {
|
||||
SettingsData.set("temperatureUnit", !SettingsData.useFahrenheit)
|
||||
SettingsData.set("useFahrenheit", !SettingsData.useFahrenheit)
|
||||
}
|
||||
}
|
||||
enabled: WeatherService.weather.available
|
||||
@@ -656,4 +656,4 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +257,8 @@ Variants {
|
||||
|
||||
height: {
|
||||
if (dock.isVertical) {
|
||||
return dock.reveal ? Math.min(dockBackground.implicitHeight + 4, maxDockHeight) : Math.min(Math.max(dockBackground.implicitHeight + 64, 200), screenHeight * 0.5)
|
||||
const hiddenHeight = Math.min(Math.max(dockBackground.implicitHeight + 64, 200), screenHeight * 0.5)
|
||||
return dock.reveal ? Math.max(Math.min(dockBackground.implicitHeight + 4, maxDockHeight), hiddenHeight) : hiddenHeight
|
||||
} else {
|
||||
return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1
|
||||
}
|
||||
@@ -266,7 +267,8 @@ Variants {
|
||||
if (dock.isVertical) {
|
||||
return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1
|
||||
} else {
|
||||
return dock.reveal ? Math.min(dockBackground.implicitWidth + 4, maxDockWidth) : Math.min(Math.max(dockBackground.implicitWidth + 64, 200), screenWidth * 0.5)
|
||||
const hiddenWidth = Math.min(Math.max(dockBackground.implicitWidth + 64, 200), screenWidth * 0.5)
|
||||
return dock.reveal ? Math.max(Math.min(dockBackground.implicitWidth + 4, maxDockWidth), hiddenWidth) : hiddenWidth
|
||||
}
|
||||
}
|
||||
anchors {
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
@@ -42,7 +37,7 @@ DankPopout {
|
||||
onShouldBeVisibleChanged: {
|
||||
if (shouldBeVisible) {
|
||||
if (SystemUpdateService.updateCount === 0 && !SystemUpdateService.isChecking) {
|
||||
SystemUpdateService.checkForUpdates()
|
||||
SystemUpdateService.checkForUpdates();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,19 +52,23 @@ DankPopout {
|
||||
smooth: true
|
||||
|
||||
Repeater {
|
||||
model: [{
|
||||
model: [
|
||||
{
|
||||
"margin": -3,
|
||||
"color": Qt.rgba(0, 0, 0, 0.05),
|
||||
"z": -3
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"margin": -2,
|
||||
"color": Qt.rgba(0, 0, 0, 0.08),
|
||||
"z": -2
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"margin": 0,
|
||||
"color": Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12),
|
||||
"z": -1
|
||||
}]
|
||||
}
|
||||
]
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: modelData.margin
|
||||
@@ -109,14 +108,18 @@ DankPopout {
|
||||
StyledText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: {
|
||||
if (SystemUpdateService.isChecking) return "Checking...";
|
||||
if (SystemUpdateService.hasError) return "Error";
|
||||
if (SystemUpdateService.updateCount === 0) return "Up to date";
|
||||
if (SystemUpdateService.isChecking)
|
||||
return "Checking...";
|
||||
if (SystemUpdateService.hasError)
|
||||
return "Error";
|
||||
if (SystemUpdateService.updateCount === 0)
|
||||
return "Up to date";
|
||||
return SystemUpdateService.updateCount + " updates";
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: {
|
||||
if (SystemUpdateService.hasError) return Theme.error;
|
||||
if (SystemUpdateService.hasError)
|
||||
return Theme.error;
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
@@ -131,7 +134,7 @@ DankPopout {
|
||||
enabled: !SystemUpdateService.isChecking
|
||||
opacity: enabled ? 1.0 : 0.5
|
||||
onClicked: {
|
||||
SystemUpdateService.checkForUpdates()
|
||||
SystemUpdateService.checkForUpdates();
|
||||
}
|
||||
|
||||
RotationAnimation {
|
||||
@@ -145,7 +148,7 @@ DankPopout {
|
||||
|
||||
onRunningChanged: {
|
||||
if (!running) {
|
||||
checkForUpdatesButton.rotation = 0
|
||||
checkForUpdatesButton.rotation = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,9 +159,9 @@ DankPopout {
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: {
|
||||
let usedHeight = 40 + Theme.spacingL
|
||||
usedHeight += 48 + Theme.spacingL
|
||||
return parent.height - usedHeight
|
||||
let usedHeight = 40 + Theme.spacingL;
|
||||
usedHeight += 48 + Theme.spacingL;
|
||||
return parent.height - usedHeight;
|
||||
}
|
||||
radius: Theme.cornerRadius
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1)
|
||||
@@ -190,7 +193,8 @@ DankPopout {
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: {
|
||||
if (SystemUpdateService.hasError) return Theme.errorText;
|
||||
if (SystemUpdateService.hasError)
|
||||
return Theme.errorText;
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
wrapMode: Text.WordWrap
|
||||
@@ -246,7 +250,9 @@ DankPopout {
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: Theme.shortDuration }
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -274,7 +280,9 @@ DankPopout {
|
||||
opacity: SystemUpdateService.updateCount > 0 ? 1.0 : 0.5
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: Theme.shortDuration }
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
@@ -304,13 +312,12 @@ DankPopout {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: SystemUpdateService.updateCount > 0
|
||||
onClicked: {
|
||||
SystemUpdateService.runUpdates()
|
||||
systemUpdatePopout.close()
|
||||
SystemUpdateService.runUpdates();
|
||||
systemUpdatePopout.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
height: parent.height
|
||||
@@ -318,7 +325,9 @@ DankPopout {
|
||||
color: closeMouseArea.containsMouse ? Theme.errorPressed : Theme.secondaryHover
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: Theme.shortDuration }
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
@@ -347,13 +356,12 @@ DankPopout {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
systemUpdatePopout.close()
|
||||
systemUpdatePopout.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,10 +190,6 @@ Singleton {
|
||||
"forecast_days=7"
|
||||
]
|
||||
|
||||
if (SettingsData.useFahrenheit) {
|
||||
params.push("temperature_unit=fahrenheit")
|
||||
}
|
||||
|
||||
return "https://api.open-meteo.com/v1/forecast?" + params.join('&')
|
||||
}
|
||||
|
||||
@@ -471,17 +467,17 @@ Singleton {
|
||||
const currentUnits = data.current_units || {}
|
||||
|
||||
const tempC = current.temperature_2m || 0
|
||||
const tempF = SettingsData.useFahrenheit ? tempC : (tempC * 9/5 + 32)
|
||||
const tempF = (tempC * 9/5 + 32)
|
||||
const feelsLikeC = current.apparent_temperature || tempC
|
||||
const feelsLikeF = SettingsData.useFahrenheit ? feelsLikeC : (feelsLikeC * 9/5 + 32)
|
||||
const feelsLikeF = (feelsLikeC * 9/5 + 32)
|
||||
|
||||
const forecast = []
|
||||
if (daily.time && daily.time.length > 0) {
|
||||
for (let i = 0; i < Math.min(daily.time.length, 7); i++) {
|
||||
const tempMinC = daily.temperature_2m_min?.[i] || 0
|
||||
const tempMaxC = daily.temperature_2m_max?.[i] || 0
|
||||
const tempMinF = SettingsData.useFahrenheit ? tempMinC : (tempMinC * 9/5 + 32)
|
||||
const tempMaxF = SettingsData.useFahrenheit ? tempMaxC : (tempMaxC * 9/5 + 32)
|
||||
const tempMinF = (tempMinC * 9/5 + 32)
|
||||
const tempMaxF = (tempMaxC * 9/5 + 32)
|
||||
|
||||
forecast.push({
|
||||
"day": formatForecastDay(daily.time[i], i),
|
||||
@@ -630,11 +626,6 @@ Singleton {
|
||||
root.forceRefresh()
|
||||
})
|
||||
|
||||
SettingsData.useFahrenheitChanged.connect(() => {
|
||||
root.lastFetchTime = 0
|
||||
root.forceRefresh()
|
||||
})
|
||||
|
||||
SettingsData.weatherEnabledChanged.connect(() => {
|
||||
if (SettingsData.weatherEnabled && root.refCount > 0 && !root.weather.available) {
|
||||
root.forceRefresh()
|
||||
|
||||
Reference in New Issue
Block a user