1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-31 00:42:50 -05:00

replace qmlformat with a better tool

still not perfect, but well - what can ya do
This commit is contained in:
bbedward
2025-08-08 15:55:37 -04:00
parent 8dc6e2805d
commit 4d408c65f2
137 changed files with 30315 additions and 29625 deletions

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import Quickshell
@@ -13,16 +14,13 @@ Singleton {
readonly property int slidePx: 80
readonly property var emphasized: [
0.05, 0.00, 0.133333, 0.06, 0.166667, 0.40,
0.208333, 0.82, 0.25, 1.00, 1.00, 1.00
]
readonly property var emphasized: [0.05, 0.00, 0.133333, 0.06, 0.166667, 0.40, 0.208333, 0.82, 0.25, 1.00, 1.00, 1.00]
readonly property var emphasizedDecel: [ 0.05, 0.70, 0.10, 1.00, 1.00, 1.00 ]
readonly property var emphasizedDecel: [0.05, 0.70, 0.10, 1.00, 1.00, 1.00]
readonly property var emphasizedAccel: [ 0.30, 0.00, 0.80, 0.15, 1.00, 1.00 ]
readonly property var emphasizedAccel: [0.30, 0.00, 0.80, 0.15, 1.00, 1.00]
readonly property var standard: [ 0.20, 0.00, 0.00, 1.00, 1.00, 1.00 ]
readonly property var standardDecel: [ 0.00, 0.00, 0.00, 1.00, 1.00, 1.00 ]
readonly property var standardAccel: [ 0.30, 0.00, 1.00, 1.00, 1.00, 1.00 ]
readonly property var standard: [0.20, 0.00, 0.00, 1.00, 1.00, 1.00]
readonly property var standardDecel: [0.00, 0.00, 0.00, 1.00, 1.00, 1.00]
readonly property var standardAccel: [0.30, 0.00, 1.00, 1.00, 1.00, 1.00]
}

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtCore
import QtQuick
@@ -10,47 +11,52 @@ Singleton {
id: root
property var appUsageRanking: {}
property var appUsageRanking: {
}
Component.onCompleted: {
loadSettings();
loadSettings()
}
function loadSettings() {
parseSettings(settingsFile.text());
parseSettings(settingsFile.text())
}
function parseSettings(content) {
try {
if (content && content.trim()) {
var settings = JSON.parse(content);
appUsageRanking = settings.appUsageRanking || {};
var settings = JSON.parse(content)
appUsageRanking = settings.appUsageRanking || {}
}
} catch (e) {
}
}
function saveSettings() {
settingsFile.setText(JSON.stringify({
"appUsageRanking": appUsageRanking
}, null, 2));
}, null, 2))
}
function addAppUsage(app) {
if (!app)
return;
return
var appId = app.id || (app.execString || app.exec || "");
var appId = app.id || (app.execString || app.exec || "")
if (!appId)
return;
return
var currentRanking = Object.assign({}, appUsageRanking);
var currentRanking = Object.assign({}, appUsageRanking)
if (currentRanking[appId]) {
currentRanking[appId].usageCount = (currentRanking[appId].usageCount || 1) + 1;
currentRanking[appId].lastUsed = Date.now();
currentRanking[appId].icon = app.icon || currentRanking[appId].icon || "application-x-executable";
currentRanking[appId].name = app.name || currentRanking[appId].name || "";
currentRanking[appId].usageCount = (currentRanking[appId].usageCount
|| 1) + 1
currentRanking[appId].lastUsed = Date.now()
currentRanking[appId].icon = app.icon || currentRanking[appId].icon
|| "application-x-executable"
currentRanking[appId].name = app.name || currentRanking[appId].name || ""
} else {
currentRanking[appId] = {
"name": app.name || "",
@@ -59,67 +65,67 @@ Singleton {
"comment": app.comment || "",
"usageCount": 1,
"lastUsed": Date.now()
};
}
}
appUsageRanking = currentRanking;
saveSettings();
appUsageRanking = currentRanking
saveSettings()
}
function getAppUsageRanking() {
return appUsageRanking;
return appUsageRanking
}
function getRankedApps() {
var apps = [];
var apps = []
for (var appId in appUsageRanking) {
var appData = appUsageRanking[appId];
var appData = appUsageRanking[appId]
apps.push({
id: appId,
name: appData.name,
exec: appData.exec,
icon: appData.icon,
comment: appData.comment,
usageCount: appData.usageCount,
lastUsed: appData.lastUsed
});
"id": appId,
"name": appData.name,
"exec": appData.exec,
"icon": appData.icon,
"comment": appData.comment,
"usageCount": appData.usageCount,
"lastUsed": appData.lastUsed
})
}
return apps.sort(function(a, b) {
return apps.sort(function (a, b) {
if (a.usageCount !== b.usageCount)
return b.usageCount - a.usageCount;
return a.name.localeCompare(b.name);
});
return b.usageCount - a.usageCount
return a.name.localeCompare(b.name)
})
}
function cleanupAppUsageRanking(availableAppIds) {
var currentRanking = Object.assign({}, appUsageRanking);
var hasChanges = false;
var currentRanking = Object.assign({}, appUsageRanking)
var hasChanges = false
for (var appId in currentRanking) {
if (availableAppIds.indexOf(appId) === -1) {
delete currentRanking[appId];
hasChanges = true;
delete currentRanking[appId]
hasChanges = true
}
}
if (hasChanges) {
appUsageRanking = currentRanking;
saveSettings();
appUsageRanking = currentRanking
saveSettings()
}
}
FileView {
id: settingsFile
path: StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/appusage.json"
path: StandardPaths.writableLocation(
StandardPaths.GenericStateLocation) + "/DankMaterialShell/appusage.json"
blockLoading: true
blockWrites: true
watchChanges: true
onLoaded: {
parseSettings(settingsFile.text());
}
onLoadFailed: (error) => {
parseSettings(settingsFile.text())
}
onLoadFailed: error => {}
}
}

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import Quickshell
@@ -40,7 +41,8 @@ Singleton {
readonly property list<real> standard: [0.2, 0, 0, 1, 1, 1]
readonly property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1]
readonly property list<real> standardDecel: [0, 0, 0, 1, 1, 1]
readonly property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
readonly property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1
/ 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
readonly property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
readonly property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
readonly property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1]

View File

@@ -7,18 +7,22 @@ Singleton {
// Clear all image cache
function clearImageCache() {
Quickshell.execDetached(["rm", "-rf", Paths.stringify(Paths.imagecache)]);
Paths.mkdir(Paths.imagecache);
Quickshell.execDetached(["rm", "-rf", Paths.stringify(Paths.imagecache)])
Paths.mkdir(Paths.imagecache)
}
// Clear cache older than specified minutes
function clearOldCache(ageInMinutes) {
Quickshell.execDetached(["find", Paths.stringify(Paths.imagecache), "-name", "*.png", "-mmin", `+${ageInMinutes}`, "-delete"]);
Quickshell.execDetached(
["find", Paths.stringify(
Paths.imagecache), "-name", "*.png", "-mmin", `+${ageInMinutes}`, "-delete"])
}
// Clear cache for specific size
function clearCacheForSize(size) {
Quickshell.execDetached(["find", Paths.stringify(Paths.imagecache), "-name", `*@${size}x${size}.png`, "-delete"]);
Quickshell.execDetached(
["find", Paths.stringify(
Paths.imagecache), "-name", `*@${size}x${size}.png`, "-delete"])
}
// Get cache size in MB
@@ -26,7 +30,8 @@ Singleton {
var process = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["du", "-sm", "${Paths.stringify(Paths.imagecache)}"]
command: ["du", "-sm", "${Paths.stringify(
Paths.imagecache)}"]
running: true
stdout: StdioCollector {
onStreamFinished: {
@@ -35,7 +40,6 @@ Singleton {
}
}
}
`, root);
`, root)
}
}

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import Qt.labs.platform
import QtQuick
@@ -11,11 +12,18 @@ import qs.Common
Singleton {
id: root
readonly property string _homeUrl: StandardPaths.writableLocation(StandardPaths.HomeLocation)
readonly property string homeDir: _homeUrl.startsWith("file://") ? _homeUrl.substring(7) : _homeUrl
readonly property string _configUrl: StandardPaths.writableLocation(StandardPaths.ConfigLocation)
readonly property string configDir: _configUrl.startsWith("file://") ? _configUrl.substring(7) : _configUrl
readonly property string shellDir: Qt.resolvedUrl(".").toString().replace("file://", "").replace("/Common/", "")
readonly property string _homeUrl: StandardPaths.writableLocation(
StandardPaths.HomeLocation)
readonly property string homeDir: _homeUrl.startsWith(
"file://") ? _homeUrl.substring(
7) : _homeUrl
readonly property string _configUrl: StandardPaths.writableLocation(
StandardPaths.ConfigLocation)
readonly property string configDir: _configUrl.startsWith(
"file://") ? _configUrl.substring(
7) : _configUrl
readonly property string shellDir: Qt.resolvedUrl(".").toString().replace(
"file://", "").replace("/Common/", "")
readonly property string wallpaperPath: SessionData.wallpaperPath
property bool matugenAvailable: false
property bool gtkThemingEnabled: false
@@ -29,18 +37,23 @@ Singleton {
property color primary: getMatugenColor("primary", "#42a5f5")
property color secondary: getMatugenColor("secondary", "#8ab4f8")
property color tertiary: getMatugenColor("tertiary", "#bb86fc")
property color tertiaryContainer: getMatugenColor("tertiary_container", "#3700b3")
property color tertiaryContainer: getMatugenColor("tertiary_container",
"#3700b3")
property color error: getMatugenColor("error", "#cf6679")
property color inversePrimary: getMatugenColor("inverse_primary", "#6200ea")
property color bg: getMatugenColor("background", "#1a1c1e")
property color surface: getMatugenColor("surface", "#1a1c1e")
property color surfaceContainer: getMatugenColor("surface_container", "#1e2023")
property color surfaceContainerHigh: getMatugenColor("surface_container_high", "#292b2f")
property color surfaceContainer: getMatugenColor("surface_container",
"#1e2023")
property color surfaceContainerHigh: getMatugenColor(
"surface_container_high", "#292b2f")
property color surfaceVariant: getMatugenColor("surface_variant", "#44464f")
property color surfaceText: getMatugenColor("on_background", "#e3e8ef")
property color primaryText: getMatugenColor("on_primary", "#ffffff")
property color surfaceVariantText: getMatugenColor("on_surface_variant", "#c4c7c5")
property color primaryContainer: getMatugenColor("primary_container", "#1976d2")
property color surfaceVariantText: getMatugenColor("on_surface_variant",
"#c4c7c5")
property color primaryContainer: getMatugenColor("primary_container",
"#1976d2")
property color surfaceTint: getMatugenColor("surface_tint", "#8ab4f8")
property color outline: getMatugenColor("outline", "#8e918f")
property color accentHi: primary
@@ -50,46 +63,48 @@ Singleton {
function onLightModeChanged() {
if (matugenColors && Object.keys(matugenColors).length > 0) {
colorUpdateTrigger++;
colorsUpdated();
colorUpdateTrigger++
colorsUpdated()
if (typeof Theme !== "undefined" && Theme.isDynamicTheme) {
generateSystemThemes();
generateSystemThemes()
}
}
}
function extractColors() {
extractionRequested = true;
extractionRequested = true
if (matugenAvailable)
fileChecker.running = true;
fileChecker.running = true
else
matugenCheck.running = true;
matugenCheck.running = true
}
function getMatugenColor(path, fallback) {
colorUpdateTrigger;
const colorMode = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "light" : "dark";
let cur = matugenColors && matugenColors.colors && matugenColors.colors[colorMode];
colorUpdateTrigger
const colorMode = (typeof SessionData !== "undefined"
&& SessionData.isLightMode) ? "light" : "dark"
let cur = matugenColors && matugenColors.colors
&& matugenColors.colors[colorMode]
for (const part of path.split(".")) {
if (!cur || typeof cur !== "object" || !(part in cur))
return fallback;
return fallback
cur = cur[part];
cur = cur[part]
}
return cur || fallback;
return cur || fallback
}
function isColorDark(c) {
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5;
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5
}
Component.onCompleted: {
matugenCheck.running = true;
checkGtkThemingAvailability();
checkQtThemingAvailability();
matugenCheck.running = true
checkGtkThemingAvailability()
checkQtThemingAvailability()
if (typeof SessionData !== "undefined")
SessionData.isLightModeChanged.connect(root.onLightModeChanged);
SessionData.isLightModeChanged.connect(root.onLightModeChanged)
}
Process {
@@ -97,14 +112,14 @@ Singleton {
command: ["which", "matugen"]
onExited: code => {
matugenAvailable = (code === 0);
matugenAvailable = (code === 0)
if (!matugenAvailable) {
ToastService.wallpaperErrorStatus = "matugen_missing";
ToastService.showWarning("matugen not found - dynamic theming disabled");
return;
ToastService.wallpaperErrorStatus = "matugen_missing"
ToastService.showWarning("matugen not found - dynamic theming disabled")
return
}
if (extractionRequested) {
fileChecker.running = true;
fileChecker.running = true
}
}
}
@@ -115,10 +130,10 @@ Singleton {
command: ["test", "-r", wallpaperPath]
onExited: code => {
if (code === 0) {
matugenProcess.running = true;
matugenProcess.running = true
} else {
ToastService.wallpaperErrorStatus = "error";
ToastService.showError("Wallpaper processing failed");
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper processing failed")
}
}
}
@@ -132,21 +147,21 @@ Singleton {
id: matugenCollector
onStreamFinished: {
const out = matugenCollector.text;
const out = matugenCollector.text
if (!out.length) {
ToastService.wallpaperErrorStatus = "error";
ToastService.showError("Wallpaper Processing Failed");
return;
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper Processing Failed")
return
}
try {
root.matugenJson = out;
root.matugenColors = JSON.parse(out);
root.colorsUpdated();
generateAppConfigs();
ToastService.clearWallpaperError();
root.matugenJson = out
root.matugenColors = JSON.parse(out)
root.colorsUpdated()
generateAppConfigs()
ToastService.clearWallpaperError()
} catch (e) {
ToastService.wallpaperErrorStatus = "error";
ToastService.showError("Wallpaper Processing Failed");
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper Processing Failed")
}
}
}
@@ -158,28 +173,30 @@ Singleton {
function generateAppConfigs() {
if (!matugenColors || !matugenColors.colors) {
return;
return
}
generateNiriConfig();
generateGhosttyConfig();
generateNiriConfig()
generateGhosttyConfig()
if (gtkThemingEnabled && typeof SettingsData !== "undefined" && SettingsData.gtkThemingEnabled) {
generateSystemThemes();
} else if (qtThemingEnabled && typeof SettingsData !== "undefined" && SettingsData.qtThemingEnabled) {
generateSystemThemes();
if (gtkThemingEnabled && typeof SettingsData !== "undefined"
&& SettingsData.gtkThemingEnabled) {
generateSystemThemes()
} else if (qtThemingEnabled && typeof SettingsData !== "undefined"
&& SettingsData.qtThemingEnabled) {
generateSystemThemes()
}
}
function generateNiriConfig() {
var dark = matugenColors.colors.dark;
var dark = matugenColors.colors.dark
if (!dark)
return;
return
var bg = dark.background || "#1a1c1e";
var primary = dark.primary || "#42a5f5";
var secondary = dark.secondary || "#8ab4f8";
var inverse = dark.inverse_primary || "#6200ea";
var bg = dark.background || "#1a1c1e"
var primary = dark.primary || "#42a5f5"
var secondary = dark.secondary || "#8ab4f8"
var inverse = dark.inverse_primary || "#6200ea"
var content = `layout {
border {
@@ -190,115 +207,126 @@ Singleton {
active-color "${inverse}"
}
background-color "${bg}"
}`;
}`
Quickshell.execDetached(["bash", "-c", `echo '${content}' > niri-colors.generated.kdl`]);
Quickshell.execDetached(
["bash", "-c", `echo '${content}' > niri-colors.generated.kdl`])
}
function generateGhosttyConfig() {
var dark = matugenColors.colors.dark;
var light = matugenColors.colors.light;
var dark = matugenColors.colors.dark
var light = matugenColors.colors.light
if (!dark || !light)
return;
return
var bg = dark.background || "#1a1c1e";
var fg = dark.on_background || "#e3e8ef";
var primary = dark.primary || "#42a5f5";
var secondary = dark.secondary || "#8ab4f8";
var tertiary = dark.tertiary || "#bb86fc";
var tertiary_ctr = dark.tertiary_container || "#3700b3";
var error = dark.error || "#cf6679";
var inverse = dark.inverse_primary || "#6200ea";
var bg = dark.background || "#1a1c1e"
var fg = dark.on_background || "#e3e8ef"
var primary = dark.primary || "#42a5f5"
var secondary = dark.secondary || "#8ab4f8"
var tertiary = dark.tertiary || "#bb86fc"
var tertiary_ctr = dark.tertiary_container || "#3700b3"
var error = dark.error || "#cf6679"
var inverse = dark.inverse_primary || "#6200ea"
var bg_b = light.background || "#fef7ff";
var fg_b = light.on_background || "#1d1b20";
var primary_b = light.primary || "#1976d2";
var secondary_b = light.secondary || "#1565c0";
var tertiary_b = light.tertiary || "#7b1fa2";
var tertiary_ctr_b = light.tertiary_container || "#e1bee7";
var error_b = light.error || "#b00020";
var inverse_b = light.inverse_primary || "#bb86fc";
var bg_b = light.background || "#fef7ff"
var fg_b = light.on_background || "#1d1b20"
var primary_b = light.primary || "#1976d2"
var secondary_b = light.secondary || "#1565c0"
var tertiary_b = light.tertiary || "#7b1fa2"
var tertiary_ctr_b = light.tertiary_container || "#e1bee7"
var error_b = light.error || "#b00020"
var inverse_b = light.inverse_primary || "#bb86fc"
var content = `background = ${bg}
foreground = ${fg}
cursor-color = ${inverse}
selection-background = ${secondary}
selection-foreground = #ffffff
palette = 0=${bg}
palette = 1=${error}
palette = 2=${tertiary}
palette = 3=${secondary}
palette = 4=${primary}
palette = 5=${tertiary_ctr}
palette = 6=${inverse}
palette = 7=${fg}
palette = 8=${bg_b}
palette = 9=${error_b}
palette = 10=${tertiary_b}
palette = 11=${secondary_b}
palette = 12=${primary_b}
palette = 13=${tertiary_ctr_b}
palette = 14=${inverse_b}
palette = 15=${fg_b}`;
foreground = ${fg}
cursor-color = ${inverse}
selection-background = ${secondary}
selection-foreground = #ffffff
palette = 0=${bg}
palette = 1=${error}
palette = 2=${tertiary}
palette = 3=${secondary}
palette = 4=${primary}
palette = 5=${tertiary_ctr}
palette = 6=${inverse}
palette = 7=${fg}
palette = 8=${bg_b}
palette = 9=${error_b}
palette = 10=${tertiary_b}
palette = 11=${secondary_b}
palette = 12=${primary_b}
palette = 13=${tertiary_ctr_b}
palette = 14=${inverse_b}
palette = 15=${fg_b}`
var ghosttyConfigDir = configDir + "/ghostty";
var ghosttyConfigPath = ghosttyConfigDir + "/config-dankcolors";
var ghosttyConfigDir = configDir + "/ghostty"
var ghosttyConfigPath = ghosttyConfigDir + "/config-dankcolors"
Quickshell.execDetached(["bash", "-c", `mkdir -p '${ghosttyConfigDir}' && echo '${content}' > '${ghosttyConfigPath}'`]);
Quickshell.execDetached(
["bash", "-c", `mkdir -p '${ghosttyConfigDir}' && echo '${content}' > '${ghosttyConfigPath}'`])
}
function checkGtkThemingAvailability() {
gtkAvailabilityChecker.running = true;
gtkAvailabilityChecker.running = true
}
function checkQtThemingAvailability() {
qtAvailabilityChecker.running = true;
qtAvailabilityChecker.running = true
}
function generateSystemThemes() {
if (systemThemeGenerationInProgress) {
return;
return
}
if (!matugenAvailable) {
return;
return
}
if (!wallpaperPath || wallpaperPath === "") {
return;
return
}
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "true" : "false";
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default";
const gtkTheming = (typeof SettingsData !== "undefined" && SettingsData.gtkThemingEnabled) ? "true" : "false";
const qtTheming = (typeof SettingsData !== "undefined" && SettingsData.qtThemingEnabled) ? "true" : "false";
const isLight = (typeof SessionData !== "undefined"
&& SessionData.isLightMode) ? "true" : "false"
const iconTheme = (typeof SettingsData !== "undefined"
&& SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
const gtkTheming = (typeof SettingsData !== "undefined"
&& SettingsData.gtkThemingEnabled) ? "true" : "false"
const qtTheming = (typeof SettingsData !== "undefined"
&& SettingsData.qtThemingEnabled) ? "true" : "false"
systemThemeGenerationInProgress = true;
systemThemeGenerator.command = [shellDir + "/generate-themes.sh", wallpaperPath, shellDir, configDir, "generate", isLight, iconTheme, gtkTheming, qtTheming];
systemThemeGenerator.running = true;
systemThemeGenerationInProgress = true
systemThemeGenerator.command = [shellDir + "/generate-themes.sh", wallpaperPath, shellDir, configDir, "generate", isLight, iconTheme, gtkTheming, qtTheming]
systemThemeGenerator.running = true
}
function restoreSystemThemes() {
const shellDir = root.shellDir;
const shellDir = root.shellDir
if (!shellDir) {
return;
return
}
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "true" : "false";
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default";
const gtkTheming = (typeof SettingsData !== "undefined" && SettingsData.gtkThemingEnabled) ? "true" : "false";
const qtTheming = (typeof SettingsData !== "undefined" && SettingsData.qtThemingEnabled) ? "true" : "false";
const isLight = (typeof SessionData !== "undefined"
&& SessionData.isLightMode) ? "true" : "false"
const iconTheme = (typeof SettingsData !== "undefined"
&& SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
const gtkTheming = (typeof SettingsData !== "undefined"
&& SettingsData.gtkThemingEnabled) ? "true" : "false"
const qtTheming = (typeof SettingsData !== "undefined"
&& SettingsData.qtThemingEnabled) ? "true" : "false"
systemThemeRestoreProcess.command = [shellDir + "/generate-themes.sh", "", shellDir, configDir, "restore", isLight, iconTheme, gtkTheming, qtTheming];
systemThemeRestoreProcess.running = true;
systemThemeRestoreProcess.command = [shellDir + "/generate-themes.sh", "", shellDir, configDir, "restore", isLight, iconTheme, gtkTheming, qtTheming]
systemThemeRestoreProcess.running = true
}
Process {
id: gtkAvailabilityChecker
command: ["bash", "-c", "command -v gsettings >/dev/null && [ -d " + configDir + "/gtk-3.0 -o -d " + configDir + "/gtk-4.0 ]"]
command: ["bash", "-c", "command -v gsettings >/dev/null && [ -d "
+ configDir + "/gtk-3.0 -o -d " + configDir + "/gtk-4.0 ]"]
running: false
onExited: exitCode => {
gtkThemingEnabled = (exitCode === 0);
gtkThemingEnabled = (exitCode === 0)
}
}
@@ -307,7 +335,7 @@ palette = 15=${fg_b}`;
command: ["bash", "-c", "command -v qt5ct >/dev/null || command -v qt6ct >/dev/null"]
running: false
onExited: exitCode => {
qtThemingEnabled = (exitCode === 0);
qtThemingEnabled = (exitCode === 0)
}
}
@@ -324,10 +352,11 @@ palette = 15=${fg_b}`;
}
onExited: exitCode => {
systemThemeGenerationInProgress = false;
systemThemeGenerationInProgress = false
if (exitCode !== 0) {
ToastService.showError("Failed to generate system themes: " + systemThemeStderr.text);
ToastService.showError(
"Failed to generate system themes: " + systemThemeStderr.text)
}
}
}
@@ -346,9 +375,10 @@ palette = 15=${fg_b}`;
onExited: exitCode => {
if (exitCode === 0) {
ToastService.showInfo("System themes restored to default");
ToastService.showInfo("System themes restored to default")
} else {
ToastService.showWarning("Failed to restore system themes: " + restoreThemeStderr.text);
ToastService.showWarning(
"Failed to restore system themes: " + restoreThemeStderr.text)
}
}
}

View File

@@ -6,37 +6,43 @@ import QtCore
Singleton {
id: root
readonly property url home: StandardPaths.standardLocations(StandardPaths.HomeLocation)[0]
readonly property url pictures: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
readonly property url home: StandardPaths.standardLocations(
StandardPaths.HomeLocation)[0]
readonly property url pictures: StandardPaths.standardLocations(
StandardPaths.PicturesLocation)[0]
readonly property url data: `${StandardPaths.standardLocations(StandardPaths.GenericDataLocation)[0]}/DankMaterialShell`
readonly property url state: `${StandardPaths.standardLocations(StandardPaths.GenericStateLocation)[0]}/DankMaterialShell`
readonly property url cache: `${StandardPaths.standardLocations(StandardPaths.GenericCacheLocation)[0]}/DankMaterialShell`
readonly property url config: `${StandardPaths.standardLocations(StandardPaths.GenericConfigLocation)[0]}/DankMaterialShell`
readonly property url data: `${StandardPaths.standardLocations(
StandardPaths.GenericDataLocation)[0]}/DankMaterialShell`
readonly property url state: `${StandardPaths.standardLocations(
StandardPaths.GenericStateLocation)[0]}/DankMaterialShell`
readonly property url cache: `${StandardPaths.standardLocations(
StandardPaths.GenericCacheLocation)[0]}/DankMaterialShell`
readonly property url config: `${StandardPaths.standardLocations(
StandardPaths.GenericConfigLocation)[0]}/DankMaterialShell`
readonly property url imagecache: `${cache}/imagecache`
function stringify(path: url): string {
return path.toString().replace(/%20/g, " ");
return path.toString().replace(/%20/g, " ")
}
function expandTilde(path: string): string {
return strip(path.replace("~", stringify(root.home)));
return strip(path.replace("~", stringify(root.home)))
}
function shortenHome(path: string): string {
return path.replace(strip(root.home), "~");
return path.replace(strip(root.home), "~")
}
function strip(path: url): string {
return stringify(path).replace("file://", "");
return stringify(path).replace("file://", "")
}
function mkdir(path: url): void {
Quickshell.execDetached(["mkdir", "-p", strip(path)]);
Quickshell.execDetached(["mkdir", "-p", strip(path)])
}
function copy(from: url, to: url): void {
Quickshell.execDetached(["cp", strip(from), strip(to)]);
Quickshell.execDetached(["cp", strip(from), strip(to)])
}
}

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtCore
import QtQuick
@@ -18,25 +19,27 @@ Singleton {
property var pinnedApps: []
Component.onCompleted: {
loadSettings();
loadSettings()
}
function loadSettings() {
parseSettings(settingsFile.text());
parseSettings(settingsFile.text())
}
function parseSettings(content) {
try {
if (content && content.trim()) {
var settings = JSON.parse(content);
isLightMode = settings.isLightMode !== undefined ? settings.isLightMode : false;
wallpaperPath = settings.wallpaperPath !== undefined ? settings.wallpaperPath : "";
wallpaperLastPath = settings.wallpaperLastPath !== undefined ? settings.wallpaperLastPath : "";
profileLastPath = settings.profileLastPath !== undefined ? settings.profileLastPath : "";
doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false;
pinnedApps = settings.pinnedApps !== undefined ? settings.pinnedApps : [];
var settings = JSON.parse(content)
isLightMode = settings.isLightMode !== undefined ? settings.isLightMode : false
wallpaperPath = settings.wallpaperPath !== undefined ? settings.wallpaperPath : ""
wallpaperLastPath = settings.wallpaperLastPath
!== undefined ? settings.wallpaperLastPath : ""
profileLastPath = settings.profileLastPath !== undefined ? settings.profileLastPath : ""
doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false
pinnedApps = settings.pinnedApps !== undefined ? settings.pinnedApps : []
}
} catch (e) {
}
}
@@ -48,79 +51,82 @@ Singleton {
"profileLastPath": profileLastPath,
"doNotDisturb": doNotDisturb,
"pinnedApps": pinnedApps
}, null, 2));
}, null, 2))
}
function setLightMode(lightMode) {
isLightMode = lightMode;
saveSettings();
isLightMode = lightMode
saveSettings()
}
function setDoNotDisturb(enabled) {
doNotDisturb = enabled;
saveSettings();
doNotDisturb = enabled
saveSettings()
}
function setWallpaperPath(path) {
wallpaperPath = path;
saveSettings();
wallpaperPath = path
saveSettings()
}
function setWallpaper(imagePath) {
wallpaperPath = imagePath;
saveSettings();
wallpaperPath = imagePath
saveSettings()
if (typeof Colors !== "undefined" && typeof SettingsData !== "undefined" && SettingsData.wallpaperDynamicTheming) {
Colors.extractColors();
if (typeof Colors !== "undefined" && typeof SettingsData !== "undefined"
&& SettingsData.wallpaperDynamicTheming) {
Colors.extractColors()
}
}
function setWallpaperLastPath(path) {
wallpaperLastPath = path;
saveSettings();
wallpaperLastPath = path
saveSettings()
}
function setProfileLastPath(path) {
profileLastPath = path;
saveSettings();
profileLastPath = path
saveSettings()
}
function setPinnedApps(apps) {
pinnedApps = apps;
saveSettings();
pinnedApps = apps
saveSettings()
}
function addPinnedApp(appId) {
if (!appId) return;
var currentPinned = [...pinnedApps];
if (!appId)
return
var currentPinned = [...pinnedApps]
if (currentPinned.indexOf(appId) === -1) {
currentPinned.push(appId);
setPinnedApps(currentPinned);
currentPinned.push(appId)
setPinnedApps(currentPinned)
}
}
function removePinnedApp(appId) {
if (!appId) return;
var currentPinned = pinnedApps.filter(id => id !== appId);
setPinnedApps(currentPinned);
if (!appId)
return
var currentPinned = pinnedApps.filter(id => id !== appId)
setPinnedApps(currentPinned)
}
function isPinnedApp(appId) {
return appId && pinnedApps.indexOf(appId) !== -1;
return appId && pinnedApps.indexOf(appId) !== -1
}
FileView {
id: settingsFile
path: StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
path: StandardPaths.writableLocation(
StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
blockLoading: true
blockWrites: true
watchChanges: true
onLoaded: {
parseSettings(settingsFile.text());
}
onLoadFailed: (error) => {
parseSettings(settingsFile.text())
}
onLoadFailed: error => {}
}
IpcHandler {
@@ -135,7 +141,9 @@ Singleton {
return "ERROR: No path provided"
}
var absolutePath = path.startsWith("/") ? path : StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/" + path
var absolutePath = path.startsWith(
"/") ? path : StandardPaths.writableLocation(
StandardPaths.HomeLocation) + "/" + path
try {
root.setWallpaper(absolutePath)

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import Quickshell
@@ -334,20 +335,34 @@ Singleton {
property int currentThemeIndex: 0
property bool isDynamicTheme: false
property bool isLightMode: false
property color primary: isDynamicTheme ? Colors.accentHi : getCurrentTheme().primary
property color primaryText: isDynamicTheme ? Colors.primaryText : getCurrentTheme().primaryText
property color primaryContainer: isDynamicTheme ? Colors.primaryContainer : getCurrentTheme().primaryContainer
property color secondary: isDynamicTheme ? Colors.accentLo : getCurrentTheme().secondary
property color surface: isDynamicTheme ? Colors.surface : getCurrentTheme().surface
property color surfaceText: isDynamicTheme ? Colors.surfaceText : getCurrentTheme().surfaceText
property color surfaceVariant: isDynamicTheme ? Colors.surfaceVariant : getCurrentTheme().surfaceVariant
property color surfaceVariantText: isDynamicTheme ? Colors.surfaceVariantText : getCurrentTheme().surfaceVariantText
property color surfaceTint: isDynamicTheme ? Colors.surfaceTint : getCurrentTheme().surfaceTint
property color background: isDynamicTheme ? Colors.bg : getCurrentTheme().background
property color backgroundText: isDynamicTheme ? Colors.surfaceText : getCurrentTheme().backgroundText
property color outline: isDynamicTheme ? Colors.outline : getCurrentTheme().outline
property color surfaceContainer: isDynamicTheme ? Colors.surfaceContainer : getCurrentTheme().surfaceContainer
property color surfaceContainerHigh: isDynamicTheme ? Colors.surfaceContainerHigh : getCurrentTheme().surfaceContainerHigh
property color primary: isDynamicTheme ? Colors.accentHi : getCurrentTheme(
).primary
property color primaryText: isDynamicTheme ? Colors.primaryText : getCurrentTheme(
).primaryText
property color primaryContainer: isDynamicTheme ? Colors.primaryContainer : getCurrentTheme(
).primaryContainer
property color secondary: isDynamicTheme ? Colors.accentLo : getCurrentTheme(
).secondary
property color surface: isDynamicTheme ? Colors.surface : getCurrentTheme(
).surface
property color surfaceText: isDynamicTheme ? Colors.surfaceText : getCurrentTheme(
).surfaceText
property color surfaceVariant: isDynamicTheme ? Colors.surfaceVariant : getCurrentTheme(
).surfaceVariant
property color surfaceVariantText: isDynamicTheme ? Colors.surfaceVariantText : getCurrentTheme(
).surfaceVariantText
property color surfaceTint: isDynamicTheme ? Colors.surfaceTint : getCurrentTheme(
).surfaceTint
property color background: isDynamicTheme ? Colors.bg : getCurrentTheme(
).background
property color backgroundText: isDynamicTheme ? Colors.surfaceText : getCurrentTheme(
).backgroundText
property color outline: isDynamicTheme ? Colors.outline : getCurrentTheme(
).outline
property color surfaceContainer: isDynamicTheme ? Colors.surfaceContainer : getCurrentTheme(
).surfaceContainer
property color surfaceContainerHigh: isDynamicTheme ? Colors.surfaceContainerHigh : getCurrentTheme(
).surfaceContainerHigh
property color archBlue: "#1793D1"
property color success: "#4CAF50"
property color warning: "#FF9800"
@@ -359,23 +374,37 @@ Singleton {
property color tempDanger: "#ff5555" // Balanced red for dangerous temperatures
property color primaryHover: Qt.rgba(primary.r, primary.g, primary.b, 0.12)
property color primaryHoverLight: Qt.rgba(primary.r, primary.g, primary.b, 0.08)
property color primaryHoverLight: Qt.rgba(primary.r, primary.g,
primary.b, 0.08)
property color primaryPressed: Qt.rgba(primary.r, primary.g, primary.b, 0.16)
property color primarySelected: Qt.rgba(primary.r, primary.g, primary.b, 0.3)
property color primaryBackground: Qt.rgba(primary.r, primary.g, primary.b, 0.04)
property color primaryBackground: Qt.rgba(primary.r, primary.g,
primary.b, 0.04)
property color secondaryHover: Qt.rgba(secondary.r, secondary.g, secondary.b, 0.08)
property color secondaryHover: Qt.rgba(secondary.r, secondary.g,
secondary.b, 0.08)
property color surfaceHover: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.08)
property color surfacePressed: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.12)
property color surfaceSelected: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.15)
property color surfaceLight: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.1)
property color surfaceVariantAlpha: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.2)
property color surfaceTextHover: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.08)
property color surfaceTextPressed: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.12)
property color surfaceTextAlpha: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.3)
property color surfaceTextLight: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.06)
property color surfaceTextMedium: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.7)
property color surfaceHover: Qt.rgba(surfaceVariant.r, surfaceVariant.g,
surfaceVariant.b, 0.08)
property color surfacePressed: Qt.rgba(surfaceVariant.r, surfaceVariant.g,
surfaceVariant.b, 0.12)
property color surfaceSelected: Qt.rgba(surfaceVariant.r, surfaceVariant.g,
surfaceVariant.b, 0.15)
property color surfaceLight: Qt.rgba(surfaceVariant.r, surfaceVariant.g,
surfaceVariant.b, 0.1)
property color surfaceVariantAlpha: Qt.rgba(surfaceVariant.r,
surfaceVariant.g,
surfaceVariant.b, 0.2)
property color surfaceTextHover: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.08)
property color surfaceTextPressed: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.12)
property color surfaceTextAlpha: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.3)
property color surfaceTextLight: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.06)
property color surfaceTextMedium: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.7)
property color outlineLight: Qt.rgba(outline.r, outline.g, outline.b, 0.05)
property color outlineMedium: Qt.rgba(outline.r, outline.g, outline.b, 0.08)
@@ -426,196 +455,200 @@ Singleton {
function onColorsUpdated() {
if (isDynamicTheme) {
currentThemeIndex = 10;
isDynamicTheme = true;
currentThemeIndex = 10
isDynamicTheme = true
if (typeof SettingsData !== "undefined")
SettingsData.setTheme(currentThemeIndex, isDynamicTheme);
SettingsData.setTheme(currentThemeIndex, isDynamicTheme)
}
}
function switchTheme(themeIndex, isDynamic = false, savePrefs = true) {
if (isDynamic && themeIndex === 10) {
isDynamicTheme = true;
isDynamicTheme = true
if (typeof Colors !== "undefined") {
Colors.extractColors();
Colors.extractColors()
}
} else if (themeIndex >= 0 && themeIndex < themes.length) {
if (isDynamicTheme && typeof Colors !== "undefined") {
Colors.restoreSystemThemes();
Colors.restoreSystemThemes()
}
currentThemeIndex = themeIndex;
isDynamicTheme = false;
currentThemeIndex = themeIndex
isDynamicTheme = false
}
if (savePrefs && typeof SettingsData !== "undefined")
SettingsData.setTheme(currentThemeIndex, isDynamicTheme);
SettingsData.setTheme(currentThemeIndex, isDynamicTheme)
}
function toggleLightMode(savePrefs = true) {
isLightMode = !isLightMode;
isLightMode = !isLightMode
if (savePrefs && typeof SessionData !== "undefined")
SessionData.setLightMode(isLightMode);
SessionData.setLightMode(isLightMode)
}
function getCurrentThemeArray() {
return isLightMode ? lightThemes : themes;
return isLightMode ? lightThemes : themes
}
function getCurrentTheme() {
var themeArray = getCurrentThemeArray();
return currentThemeIndex < themeArray.length ? themeArray[currentThemeIndex] : themeArray[0];
var themeArray = getCurrentThemeArray()
return currentThemeIndex < themeArray.length ? themeArray[currentThemeIndex] : themeArray[0]
}
function getPopupBackgroundAlpha() {
return popupTransparency;
return popupTransparency
}
function getContentBackgroundAlpha() {
return popupTransparency;
return popupTransparency
}
function popupBackground() {
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b, popupTransparency);
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b,
popupTransparency)
}
function contentBackground() {
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b, popupTransparency);
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b,
popupTransparency)
}
function panelBackground() {
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b, panelTransparency);
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b,
panelTransparency)
}
function widgetBackground() {
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b, widgetTransparency);
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b,
widgetTransparency)
}
function getBatteryIcon(level, isCharging, batteryAvailable) {
if (!batteryAvailable)
return _getBatteryPowerProfileIcon();
return _getBatteryPowerProfileIcon()
if (isCharging) {
if (level >= 90)
return "battery_charging_full";
return "battery_charging_full"
if (level >= 80)
return "battery_charging_90";
return "battery_charging_90"
if (level >= 60)
return "battery_charging_80";
return "battery_charging_80"
if (level >= 50)
return "battery_charging_60";
return "battery_charging_60"
if (level >= 30)
return "battery_charging_50";
return "battery_charging_50"
if (level >= 20)
return "battery_charging_30";
return "battery_charging_30"
return "battery_charging_20";
return "battery_charging_20"
} else {
if (level >= 95)
return "battery_full";
return "battery_full"
if (level >= 85)
return "battery_6_bar";
return "battery_6_bar"
if (level >= 70)
return "battery_5_bar";
return "battery_5_bar"
if (level >= 55)
return "battery_4_bar";
return "battery_4_bar"
if (level >= 40)
return "battery_3_bar";
return "battery_3_bar"
if (level >= 25)
return "battery_2_bar";
return "battery_2_bar"
if (level >= 10)
return "battery_1_bar";
return "battery_1_bar"
return "battery_alert";
return "battery_alert"
}
}
function _getBatteryPowerProfileIcon() {
if (typeof PowerProfiles === "undefined")
return "balance";
return "balance"
switch (PowerProfiles.profile) {
case PowerProfile.PowerSaver:
return "energy_savings_leaf";
return "energy_savings_leaf"
case PowerProfile.Performance:
return "rocket_launch";
return "rocket_launch"
default:
return "balance";
return "balance"
}
}
function getPowerProfileIcon(profile) {
switch (profile) {
case PowerProfile.PowerSaver:
return "battery_saver";
return "battery_saver"
case PowerProfile.Balanced:
return "battery_std";
return "battery_std"
case PowerProfile.Performance:
return "flash_on";
return "flash_on"
default:
return "settings";
return "settings"
}
}
function getPowerProfileLabel(profile) {
switch (profile) {
case PowerProfile.PowerSaver:
return "Power Saver";
return "Power Saver"
case PowerProfile.Balanced:
return "Balanced";
return "Balanced"
case PowerProfile.Performance:
return "Performance";
return "Performance"
default:
return profile.charAt(0).toUpperCase() + profile.slice(1);
return profile.charAt(0).toUpperCase() + profile.slice(1)
}
}
function getPowerProfileDescription(profile) {
switch (profile) {
case PowerProfile.PowerSaver:
return "Extend battery life";
return "Extend battery life"
case PowerProfile.Balanced:
return "Balance power and performance";
return "Balance power and performance"
case PowerProfile.Performance:
return "Prioritize performance";
return "Prioritize performance"
default:
return "Custom power profile";
return "Custom power profile"
}
}
Component.onCompleted: {
if (typeof Colors !== "undefined")
Colors.colorsUpdated.connect(root.onColorsUpdated);
Colors.colorsUpdated.connect(root.onColorsUpdated)
if (typeof SettingsData !== "undefined") {
if (SettingsData.popupTransparency !== undefined)
root.popupTransparency = SettingsData.popupTransparency;
root.popupTransparency = SettingsData.popupTransparency
if (SettingsData.topBarWidgetTransparency !== undefined)
root.widgetTransparency = SettingsData.topBarWidgetTransparency;
root.widgetTransparency = SettingsData.topBarWidgetTransparency
if (SettingsData.popupTransparencyChanged)
SettingsData.popupTransparencyChanged.connect(function() {
if (typeof SettingsData !== "undefined" && SettingsData.popupTransparency !== undefined)
root.popupTransparency = SettingsData.popupTransparency;
});
SettingsData.popupTransparencyChanged.connect(function () {
if (typeof SettingsData !== "undefined"
&& SettingsData.popupTransparency !== undefined)
root.popupTransparency = SettingsData.popupTransparency
})
if (SettingsData.topBarWidgetTransparencyChanged)
SettingsData.topBarWidgetTransparencyChanged.connect(function() {
if (typeof SettingsData !== "undefined" && SettingsData.topBarWidgetTransparency !== undefined)
root.widgetTransparency = SettingsData.topBarWidgetTransparency;
});
SettingsData.topBarWidgetTransparencyChanged.connect(function () {
if (typeof SettingsData !== "undefined"
&& SettingsData.topBarWidgetTransparency !== undefined)
root.widgetTransparency = SettingsData.topBarWidgetTransparency
})
}
}
}

View File

@@ -18,110 +18,109 @@ DankModal {
property string searchText: ""
function updateFilteredModel() {
filteredClipboardModel.clear();
for (let i = 0; i < clipboardModel.count; i++) {
const entry = clipboardModel.get(i).entry;
filteredClipboardModel.clear()
for (var i = 0; i < clipboardModel.count; i++) {
const entry = clipboardModel.get(i).entry
if (searchText.trim().length === 0) {
filteredClipboardModel.append({
"entry": entry
});
})
} else {
const content = getEntryPreview(entry).toLowerCase();
const content = getEntryPreview(entry).toLowerCase()
if (content.includes(searchText.toLowerCase()))
filteredClipboardModel.append({
"entry": entry
});
})
}
}
clipboardHistoryModal.totalCount = filteredClipboardModel.count;
clipboardHistoryModal.totalCount = filteredClipboardModel.count
}
function toggle() {
if (visible)
hide();
hide()
else
show();
show()
}
function show() {
clipboardHistoryModal.visible = true;
initializeThumbnailSystem();
refreshClipboard();
clipboardHistoryModal.visible = true
initializeThumbnailSystem()
refreshClipboard()
}
function hide() {
clipboardHistoryModal.visible = false;
clipboardHistoryModal.searchText = "";
cleanupTempFiles();
clipboardHistoryModal.visible = false
clipboardHistoryModal.searchText = ""
cleanupTempFiles()
}
function initializeThumbnailSystem() {
// No initialization needed - using direct image display
function initializeThumbnailSystem() {// No initialization needed - using direct image display
}
function cleanupTempFiles() {
Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"]);
Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"])
}
function generateThumbnails() {
// No thumbnail generation needed - using direct image display
function generateThumbnails() {// No thumbnail generation needed - using direct image display
}
function refreshClipboard() {
clipboardProcess.running = true;
clipboardProcess.running = true
}
function copyEntry(entry) {
const entryId = entry.split('\t')[0];
Quickshell.execDetached(["sh", "-c", `cliphist decode ${entryId} | wl-copy`]);
const entryId = entry.split('\t')[0]
Quickshell.execDetached(
["sh", "-c", `cliphist decode ${entryId} | wl-copy`])
ToastService.showInfo("Copied to clipboard");
clipboardHistoryModal.hide();
ToastService.showInfo("Copied to clipboard")
clipboardHistoryModal.hide()
}
function deleteEntry(entry) {
deleteProcess.command = ["sh", "-c", `echo '${entry.replace(/'/g, "'\\''")}' | cliphist delete`];
deleteProcess.running = true;
deleteProcess.command = ["sh", "-c", `echo '${entry.replace(
/'/g, "'\\''")}' | cliphist delete`]
deleteProcess.running = true
}
function clearAll() {
clearProcess.running = true;
clearProcess.running = true
}
function getEntryPreview(entry) {
let content = entry.replace(/^\s*\d+\s+/, "");
if (content.includes("image/") || content.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(content)) {
const dimensionMatch = content.match(/(\d+)x(\d+)/);
let content = entry.replace(/^\s*\d+\s+/, "")
if (content.includes("image/") || content.includes("binary data")
|| /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(content)) {
const dimensionMatch = content.match(/(\d+)x(\d+)/)
if (dimensionMatch)
return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}`;
return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}`
const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i);
const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i)
if (typeMatch)
return `Image (${typeMatch[1].toUpperCase()})`;
return `Image (${typeMatch[1].toUpperCase()})`
return "Image";
return "Image"
}
if (content.length > 100)
return content.substring(0, 100) + "...";
return content.substring(0, 100) + "..."
return content;
return content
}
function getEntryType(entry) {
if (entry.includes("image/") || entry.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(entry) || /\b(png|jpg|jpeg|gif|bmp|webp)\b/i.test(entry))
return "image";
if (entry.includes("image/") || entry.includes("binary data")
|| /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(entry)
|| /\b(png|jpg|jpeg|gif|bmp|webp)\b/i.test(entry))
return "image"
if (entry.length > 200)
return "long_text";
return "long_text"
return "text";
return "text"
}
visible: false
width: 650
height: 550
@@ -132,7 +131,7 @@ DankModal {
borderWidth: 1
enableShadow: true
onBackgroundClicked: {
hide();
hide()
}
DankModal {
@@ -143,7 +142,7 @@ DankModal {
height: 150
keyboardFocus: "ondemand"
onBackgroundClicked: {
showClearConfirmation = false;
showClearConfirmation = false
}
content: Component {
@@ -199,7 +198,6 @@ DankModal {
cursorShape: Qt.PointingHandCursor
onClicked: showClearConfirmation = false
}
}
Rectangle {
@@ -223,22 +221,16 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
clearAll();
showClearConfirmation = false;
hide();
clearAll()
showClearConfirmation = false
hide()
}
}
}
}
}
}
}
}
ListModel {
@@ -257,72 +249,64 @@ DankModal {
stdout: StdioCollector {
onStreamFinished: {
clipboardModel.clear();
const lines = text.trim().split('\n');
clipboardModel.clear()
const lines = text.trim().split('\n')
for (const line of lines) {
if (line.trim().length > 0)
clipboardModel.append({
"entry": line
});
})
}
updateFilteredModel();
updateFilteredModel()
}
}
}
Process {
id: deleteProcess
running: false
onExited: (exitCode) => {
onExited: exitCode => {
if (exitCode === 0)
refreshClipboard();
refreshClipboard()
else
console.warn("Failed to delete clipboard entry");
console.warn("Failed to delete clipboard entry")
}
}
Process {
id: clearProcess
command: ["cliphist", "wipe"]
running: false
onExited: (exitCode) => {
onExited: exitCode => {
if (exitCode === 0) {
clipboardModel.clear();
filteredClipboardModel.clear();
totalCount = 0;
clipboardModel.clear()
filteredClipboardModel.clear()
totalCount = 0
} else {
}
}
}
IpcHandler {
function open() {
clipboardHistoryModal.show();
return "CLIPBOARD_OPEN_SUCCESS";
clipboardHistoryModal.show()
return "CLIPBOARD_OPEN_SUCCESS"
}
function close() {
clipboardHistoryModal.hide();
return "CLIPBOARD_CLOSE_SUCCESS";
clipboardHistoryModal.hide()
return "CLIPBOARD_CLOSE_SUCCESS"
}
function toggle() {
clipboardHistoryModal.toggle();
return "CLIPBOARD_TOGGLE_SUCCESS";
clipboardHistoryModal.toggle()
return "CLIPBOARD_TOGGLE_SUCCESS"
}
target: "clipboard"
@@ -334,10 +318,10 @@ DankModal {
anchors.margins: Theme.spacingL
spacing: Theme.spacingL
focus: true
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
hide();
event.accepted = true;
hide()
event.accepted = true
}
}
@@ -364,7 +348,6 @@ DankModal {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -378,7 +361,7 @@ DankModal {
iconColor: Theme.error
hoverColor: Theme.errorHover
onClicked: {
showClearConfirmation = true;
showClearConfirmation = true
}
}
@@ -389,9 +372,7 @@ DankModal {
hoverColor: Theme.errorHover
onClicked: hide()
}
}
}
DankTextField {
@@ -402,22 +383,21 @@ DankModal {
leftIconName: "search"
showClearButton: true
onTextChanged: {
clipboardHistoryModal.searchText = text;
updateFilteredModel();
clipboardHistoryModal.searchText = text
updateFilteredModel()
}
Connections {
function onOpened() {
searchField.forceActiveFocus();
searchField.forceActiveFocus()
}
function onDialogClosed() {
searchField.clearFocus();
searchField.clearFocus()
}
target: clipboardHistoryModal
}
}
Rectangle {
@@ -471,7 +451,8 @@ DankModal {
property alias thumbnailImageSource: thumbnailImageSource
width: clipboardListView.width
height: Math.max(entryType === "image" ? 72 : 60, contentText.contentHeight + Theme.spacingL)
height: Math.max(entryType === "image" ? 72 : 60,
contentText.contentHeight + Theme.spacingL)
radius: Theme.cornerRadius
color: mouseArea.containsMouse ? Theme.primaryHover : Theme.primaryBackground
border.color: Theme.outlineStrong
@@ -497,7 +478,6 @@ DankModal {
font.weight: Font.Bold
color: Theme.primary
}
}
Row {
@@ -514,7 +494,8 @@ DankModal {
id: thumbnailImageSource
anchors.fill: parent
property string entryId: model.entry.split('\t')[0]
source: entryType === "image" && imageLoader.imageData ? `data:image/png;base64,${imageLoader.imageData}` : ""
source: entryType === "image"
&& imageLoader.imageData ? `data:image/png;base64,${imageLoader.imageData}` : ""
fillMode: Image.PreserveAspectCrop
smooth: true
cache: true
@@ -530,7 +511,7 @@ DankModal {
stdout: StdioCollector {
onStreamFinished: {
imageLoader.imageData = text.trim();
imageLoader.imageData = text.trim()
}
}
}
@@ -542,7 +523,8 @@ DankModal {
source: thumbnailImageSource
maskEnabled: true
maskSource: clipboardCircularMask
visible: entryType === "image" && thumbnailImageSource.status === Image.Ready
visible: entryType === "image"
&& thumbnailImageSource.status === Image.Ready
maskThresholdMin: 0.5
maskSpreadAtMin: 1
}
@@ -562,41 +544,41 @@ DankModal {
color: "black"
antialiasing: true
}
}
DankIcon {
visible: !(entryType === "image" && thumbnailImageSource.status === Image.Ready)
visible: !(entryType === "image"
&& thumbnailImageSource.status === Image.Ready)
name: {
if (entryType === "image")
return "image";
return "image"
if (entryType === "long_text")
return "subject";
return "subject"
return "content_copy";
return "content_copy"
}
size: Theme.iconSize
color: Theme.primary
anchors.centerIn: parent
}
}
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.width - (entryType === "image" ? 48 : Theme.iconSize) - Theme.spacingM
width: parent.width - (entryType === "image" ? 48 : Theme.iconSize)
- Theme.spacingM
spacing: Theme.spacingXS
StyledText {
text: {
switch (entryType) {
case "image":
return "Image • " + entryPreview;
return "Image • " + entryPreview
case "long_text":
return "Long Text";
return "Long Text"
default:
return "Text";
return "Text"
}
}
font.pixelSize: Theme.fontSizeSmall
@@ -617,11 +599,8 @@ DankModal {
maximumLineCount: entryType === "long_text" ? 3 : 1
elide: Text.ElideRight
}
}
}
}
DankActionButton {
@@ -634,7 +613,7 @@ DankModal {
hoverColor: Theme.errorHover
onClicked: {
deleteEntry(model.entry);
deleteEntry(model.entry)
}
}
@@ -652,17 +631,10 @@ DankModal {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}
}
}
}

View File

@@ -28,20 +28,20 @@ PanelWindow {
property real cornerRadius: Theme.cornerRadiusLarge
property bool enableShadow: false
signal opened()
signal dialogClosed()
signal backgroundClicked()
signal opened
signal dialogClosed
signal backgroundClicked
function open() {
visible = true;
visible = true
}
function close() {
visible = false;
visible = false
}
function toggle() {
visible = !visible;
visible = !visible
}
color: "transparent"
@@ -50,22 +50,22 @@ PanelWindow {
WlrLayershell.keyboardFocus: {
switch (root.keyboardFocus) {
case "exclusive":
return WlrKeyboardFocus.Exclusive;
return WlrKeyboardFocus.Exclusive
case "none":
return WlrKeyboardFocus.None;
return WlrKeyboardFocus.None
default:
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.OnDemand
}
}
onVisibleChanged: {
if (root.visible) {
opened();
opened()
} else {
if (Qt.inputMethod) {
Qt.inputMethod.hide();
Qt.inputMethod.reset();
Qt.inputMethod.hide()
Qt.inputMethod.reset()
}
dialogClosed();
dialogClosed()
}
}
@@ -87,11 +87,12 @@ PanelWindow {
MouseArea {
anchors.fill: parent
enabled: root.closeOnBackgroundClick
onClicked: (mouse) => {
var localPos = mapToItem(contentContainer, mouse.x, mouse.y);
if (localPos.x < 0 || localPos.x > contentContainer.width || localPos.y < 0 || localPos.y > contentContainer.height)
root.backgroundClicked();
onClicked: mouse => {
var localPos = mapToItem(contentContainer, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentContainer.width
|| localPos.y < 0
|| localPos.y > contentContainer.height)
root.backgroundClicked()
}
}
@@ -100,9 +101,7 @@ PanelWindow {
duration: root.animationDuration
easing.type: root.animationEasing
}
}
}
Rectangle {
@@ -113,17 +112,18 @@ PanelWindow {
anchors.centerIn: positioning === "center" ? parent : undefined
x: {
if (positioning === "top-right")
return Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL);
return Math.max(Theme.spacingL,
root.screenWidth - width - Theme.spacingL)
else if (positioning === "custom")
return root.customPosition.x;
return 0; // Will be overridden by anchors.centerIn when positioning === "center"
return root.customPosition.x
return 0 // Will be overridden by anchors.centerIn when positioning === "center"
}
y: {
if (positioning === "top-right")
return Theme.barHeight + Theme.spacingXS;
return Theme.barHeight + Theme.spacingXS
else if (positioning === "custom")
return root.customPosition.y;
return 0; // Will be overridden by anchors.centerIn when positioning === "center"
return root.customPosition.y
return 0 // Will be overridden by anchors.centerIn when positioning === "center"
}
color: root.backgroundColor
radius: root.cornerRadius
@@ -133,9 +133,9 @@ PanelWindow {
opacity: root.visible ? 1 : 0
scale: {
if (root.animationType === "scale")
return root.visible ? 1 : 0.9;
return root.visible ? 1 : 0.9
return 1;
return 1
}
transform: root.animationType === "slide" ? slideTransform : null
@@ -159,7 +159,6 @@ PanelWindow {
duration: root.animationDuration
easing.type: root.animationEasing
}
}
Behavior on scale {
@@ -169,7 +168,6 @@ PanelWindow {
duration: root.animationDuration
easing.type: root.animationEasing
}
}
layer.effect: MultiEffect {
@@ -180,7 +178,6 @@ PanelWindow {
shadowColor: Theme.shadowStrong
shadowOpacity: 0.3
}
}
FocusScope {
@@ -190,23 +187,22 @@ PanelWindow {
anchors.fill: parent
visible: root.visible // Only active when the modal is visible
focus: root.visible
Keys.onEscapePressed: (event) => {
Keys.onEscapePressed: event => {
if (root.closeOnEscapeKey) {
root.visible = false;
event.accepted = true;
root.visible = false
event.accepted = true
}
}
onVisibleChanged: {
if (visible) {
Qt.callLater(function() {
focusScope.forceActiveFocus();
});
Qt.callLater(function () {
focusScope.forceActiveFocus()
})
}
}
}
// Expose the focusScope for external access
property alias modalFocusScope: focusScope
}

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import QtQuick.Controls
@@ -7,12 +7,14 @@ import Qt.labs.folderlistmodel
import Quickshell.Io
import qs.Common
import qs.Widgets
DankModal {
id: fileBrowserModal
signal fileSelected(string path)
property string homeDir: StandardPaths.writableLocation(StandardPaths.HomeLocation)
property string homeDir: StandardPaths.writableLocation(
StandardPaths.HomeLocation)
property string currentPath: ""
property var fileExtensions: ["*.*"]
property string browserTitle: "Select File"
@@ -31,35 +33,36 @@ DankModal {
}
function isImageFile(fileName) {
if (!fileName) return false
if (!fileName)
return false
var ext = fileName.toLowerCase().split('.').pop()
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
}
function getLastPath() {
var lastPath = "";
var lastPath = ""
if (browserType === "wallpaper") {
lastPath = SessionData.wallpaperLastPath;
lastPath = SessionData.wallpaperLastPath
} else if (browserType === "profile") {
lastPath = SessionData.profileLastPath;
lastPath = SessionData.profileLastPath
}
if (lastPath && lastPath !== "") {
return lastPath;
return lastPath
}
return homeDir;
return homeDir
}
function saveLastPath(path) {
if (browserType === "wallpaper") {
SessionData.setWallpaperLastPath(path);
SessionData.setWallpaperLastPath(path)
} else if (browserType === "profile") {
SessionData.setProfileLastPath(path);
SessionData.setProfileLastPath(path)
}
}
Component.onCompleted: {
currentPath = getLastPath();
currentPath = getLastPath()
}
width: 800
@@ -72,37 +75,38 @@ DankModal {
onVisibleChanged: {
if (visible) {
var startPath = getLastPath();
currentPath = startPath;
var startPath = getLastPath()
currentPath = startPath
}
}
onCurrentPathChanged: {
}
function navigateUp() {
var path = currentPath;
var path = currentPath
if (path === homeDir) {
return;
return
}
var lastSlash = path.lastIndexOf('/');
var lastSlash = path.lastIndexOf('/')
if (lastSlash > 0) {
var newPath = path.substring(0, lastSlash);
var newPath = path.substring(0, lastSlash)
if (newPath.length < homeDir.length) {
currentPath = homeDir;
saveLastPath(homeDir);
currentPath = homeDir
saveLastPath(homeDir)
} else {
currentPath = newPath;
saveLastPath(newPath);
currentPath = newPath
saveLastPath(newPath)
}
}
}
function navigateTo(path) {
currentPath = path;
saveLastPath(path); // Save the path when navigating
currentPath = path
saveLastPath(path) // Save the path when navigating
}
content: Component {
@@ -155,7 +159,8 @@ DankModal {
width: 32
height: 32
radius: Theme.cornerRadius
color: mouseArea.containsMouse && currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
color: mouseArea.containsMouse
&& currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
opacity: currentPath !== homeDir ? 1.0 : 0.0
DankIcon {
@@ -200,8 +205,12 @@ DankModal {
model: folderModel
ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded }
ScrollBar.horizontal: ScrollBar { policy: ScrollBar.AlwaysOff }
ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded
}
ScrollBar.horizontal: ScrollBar {
policy: ScrollBar.AlwaysOff
}
// Qt 6.9+ scrolling: flickDeceleration/maximumFlickVelocity only affect touch now
interactive: true
@@ -240,7 +249,8 @@ DankModal {
anchors.fill: parent
imagePath: !delegateRoot.fileIsDir ? delegateRoot.filePath : ""
fillMode: Image.PreserveAspectCrop
visible: !delegateRoot.fileIsDir && isImageFile(delegateRoot.fileName)
visible: !delegateRoot.fileIsDir && isImageFile(
delegateRoot.fileName)
maxCacheSize: 80
}
@@ -249,7 +259,8 @@ DankModal {
name: "description"
size: Theme.iconSizeLarge
color: Theme.primary
visible: !delegateRoot.fileIsDir && !isImageFile(delegateRoot.fileName)
visible: !delegateRoot.fileIsDir && !isImageFile(
delegateRoot.fileName)
}
DankIcon {
@@ -282,9 +293,9 @@ DankModal {
onClicked: {
if (delegateRoot.fileIsDir) {
navigateTo(delegateRoot.filePath);
navigateTo(delegateRoot.filePath)
} else {
fileSelected(delegateRoot.filePath);
fileSelected(delegateRoot.filePath)
}
}
}

View File

@@ -16,17 +16,17 @@ DankModal {
property string networkDetails: ""
function showNetworkInfo(ssid, data) {
networkSSID = ssid;
networkData = data;
networkInfoModalVisible = true;
NetworkService.fetchNetworkInfo(ssid);
networkSSID = ssid
networkData = data
networkInfoModalVisible = true
NetworkService.fetchNetworkInfo(ssid)
}
function hideDialog() {
networkInfoModalVisible = false;
networkSSID = "";
networkData = null;
networkDetails = "";
networkInfoModalVisible = false
networkSSID = ""
networkData = null
networkDetails = ""
}
visible: networkInfoModalVisible
@@ -34,13 +34,13 @@ DankModal {
height: 500
enableShadow: true
onBackgroundClicked: {
hideDialog();
hideDialog()
}
onVisibleChanged: {
if (!visible) {
networkSSID = "";
networkData = null;
networkDetails = "";
networkSSID = ""
networkData = null
networkDetails = ""
}
}
@@ -74,7 +74,6 @@ DankModal {
width: parent.width
elide: Text.ElideRight
}
}
DankActionButton {
@@ -83,10 +82,9 @@ DankModal {
iconColor: Theme.surfaceText
hoverColor: Theme.errorHover
onClicked: {
root.hideDialog();
root.hideDialog()
}
}
}
Flickable {
@@ -108,10 +106,13 @@ DankModal {
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: (event) => {
let delta = event.pixelDelta.y !== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
onWheel: event => {
let delta = event.pixelDelta.y
!== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
let newY = parent.contentY - delta
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY))
newY = Math.max(0, Math.min(
parent.contentHeight - parent.height,
newY))
parent.contentY = newY
event.accepted = true
}
@@ -121,7 +122,8 @@ DankModal {
id: detailsRect
width: parent.width
height: Math.max(parent.parent.height, detailsText.contentHeight + Theme.spacingM * 2)
height: Math.max(parent.parent.height,
detailsText.contentHeight + Theme.spacingM * 2)
radius: Theme.cornerRadius
color: Theme.surfaceHover
border.color: Theme.outlineStrong
@@ -132,13 +134,13 @@ DankModal {
anchors.fill: parent
anchors.margins: Theme.spacingM
text: NetworkService.networkInfoDetails.replace(/\\n/g, '\n') || "No information available"
text: NetworkService.networkInfoDetails.replace(/\\n/g, '\n')
|| "No information available"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
wrapMode: Text.WordWrap
lineHeight: 1.5
}
}
ScrollBar.vertical: ScrollBar {
@@ -148,7 +150,6 @@ DankModal {
ScrollBar.horizontal: ScrollBar {
policy: ScrollBar.AlwaysOff
}
}
Item {
@@ -161,7 +162,8 @@ DankModal {
width: Math.max(70, closeText.contentWidth + Theme.spacingM * 2)
height: 36
radius: Theme.cornerRadius
color: closeArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
color: closeArea.containsMouse ? Qt.darker(Theme.primary,
1.1) : Theme.primary
StyledText {
id: closeText
@@ -180,7 +182,7 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.hideDialog();
root.hideDialog()
}
}
@@ -189,17 +191,10 @@ DankModal {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}
}
}
}

View File

@@ -17,17 +17,17 @@ DankModal {
function executePowerAction(action) {
switch (action) {
case "logout":
NiriService.quit();
break;
NiriService.quit()
break
case "suspend":
Quickshell.execDetached(["systemctl", "suspend"]);
break;
Quickshell.execDetached(["systemctl", "suspend"])
break
case "reboot":
Quickshell.execDetached(["systemctl", "reboot"]);
break;
Quickshell.execDetached(["systemctl", "reboot"])
break
case "poweroff":
Quickshell.execDetached(["systemctl", "poweroff"]);
break;
Quickshell.execDetached(["systemctl", "poweroff"])
break
}
}
@@ -37,7 +37,7 @@ DankModal {
keyboardFocus: "ondemand"
enableShadow: false
onBackgroundClicked: {
powerConfirmVisible = false;
powerConfirmVisible = false
}
content: Component {
@@ -55,11 +55,11 @@ DankModal {
color: {
switch (powerConfirmAction) {
case "poweroff":
return Theme.error;
return Theme.error
case "reboot":
return Theme.warning;
return Theme.warning
default:
return Theme.surfaceText;
return Theme.surfaceText
}
}
font.weight: Font.Medium
@@ -105,10 +105,9 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
powerConfirmVisible = false;
powerConfirmVisible = false
}
}
}
Rectangle {
@@ -116,19 +115,22 @@ DankModal {
height: 40
radius: Theme.cornerRadius
color: {
let baseColor;
let baseColor
switch (powerConfirmAction) {
case "poweroff":
baseColor = Theme.error;
break;
baseColor = Theme.error
break
case "reboot":
baseColor = Theme.warning;
break;
baseColor = Theme.warning
break
default:
baseColor = Theme.primary;
break;
baseColor = Theme.primary
break
}
return confirmButton.containsMouse ? Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 0.9) : baseColor;
return confirmButton.containsMouse ? Qt.rgba(baseColor.r,
baseColor.g,
baseColor.b,
0.9) : baseColor
}
StyledText {
@@ -146,19 +148,13 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
powerConfirmVisible = false;
executePowerAction(powerConfirmAction);
powerConfirmVisible = false
executePowerAction(powerConfirmAction)
}
}
}
}
}
}
}
}

View File

@@ -18,22 +18,21 @@ DankModal {
property var tabNames: ["Processes", "Performance", "System"]
function show() {
processListModal.visible = true;
UserInfoService.getUptime();
processListModal.visible = true
UserInfoService.getUptime()
}
function hide() {
processListModal.visible = false;
processListModal.visible = false
if (processContextMenu.visible)
processContextMenu.close();
processContextMenu.close()
}
function toggle() {
if (processListModal.visible)
hide();
hide()
else
show();
show()
}
width: 900
@@ -55,23 +54,18 @@ DankModal {
ProcessesTab {
contextMenu: processContextMenu
}
}
Component {
id: performanceTabComponent
PerformanceTab {
}
PerformanceTab {}
}
Component {
id: systemTabComponent
SystemTab {
}
SystemTab {}
}
ProcessContextMenu {
@@ -82,19 +76,19 @@ DankModal {
Item {
anchors.fill: parent
focus: true
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
processListModal.hide();
event.accepted = true;
processListModal.hide()
event.accepted = true
} else if (event.key === Qt.Key_1) {
currentTab = 0;
event.accepted = true;
currentTab = 0
event.accepted = true
} else if (event.key === Qt.Key_2) {
currentTab = 1;
event.accepted = true;
currentTab = 1
event.accepted = true
} else if (event.key === Qt.Key_3) {
currentTab = 2;
event.accepted = true;
currentTab = 2
event.accepted = true
}
}
@@ -128,7 +122,6 @@ DankModal {
onClicked: processListModal.hide()
Layout.alignment: Qt.AlignVCenter
}
}
Rectangle {
@@ -163,13 +156,13 @@ DankModal {
name: {
switch (index) {
case 0:
return "list_alt";
return "list_alt"
case 1:
return "analytics";
return "analytics"
case 2:
return "settings";
return "settings"
default:
return "tab";
return "tab"
}
}
size: Theme.iconSize - 2
@@ -181,9 +174,7 @@ DankModal {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
StyledText {
@@ -198,11 +189,8 @@ DankModal {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
MouseArea {
@@ -212,7 +200,7 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
currentTab = index;
currentTab = index
}
}
@@ -220,22 +208,16 @@ DankModal {
ColorAnimation {
duration: Theme.shortDuration
}
}
Behavior on border.color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}
}
Rectangle {
@@ -261,9 +243,7 @@ DankModal {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
Loader {
@@ -281,9 +261,7 @@ DankModal {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
Loader {
@@ -301,17 +279,10 @@ DankModal {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
}
}
}

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import Quickshell.Io
import QtQuick
@@ -10,21 +10,21 @@ import qs.Widgets
DankModal {
id: settingsModal
signal closingModal()
signal closingModal
function show() {
settingsModal.visible = true;
settingsModal.visible = true
}
function hide() {
settingsModal.visible = false;
settingsModal.visible = false
}
function toggle() {
if (settingsModal.visible)
hide();
hide()
else
show();
show()
}
width: 750
@@ -37,10 +37,10 @@ DankModal {
Item {
anchors.fill: parent
focus: true
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
settingsModal.hide();
event.accepted = true;
settingsModal.hide()
event.accepted = true
}
}
@@ -81,7 +81,6 @@ DankModal {
hoverColor: Theme.errorHover
onClicked: settingsModal.hide()
}
}
Column {
@@ -94,13 +93,22 @@ DankModal {
width: parent.width
model: [
{ text: "Personalization", icon: "person" },
{ text: "Time & Weather", icon: "schedule" },
{ text: "Widgets", icon: "widgets" },
{ text: "Launcher", icon: "apps" },
{ text: "Appearance", icon: "palette" }
]
model: [{
"text": "Personalization",
"icon": "person"
}, {
"text": "Time & Weather",
"icon": "schedule"
}, {
"text": "Widgets",
"icon": "widgets"
}, {
"text": "Launcher",
"icon": "apps"
}, {
"text": "Appearance",
"icon": "palette"
}]
}
Item {
@@ -166,23 +174,22 @@ DankModal {
}
}
}
}
IpcHandler {
function open() {
settingsModal.show();
return "SETTINGS_OPEN_SUCCESS";
settingsModal.show()
return "SETTINGS_OPEN_SUCCESS"
}
function close() {
settingsModal.hide();
return "SETTINGS_CLOSE_SUCCESS";
settingsModal.hide()
return "SETTINGS_CLOSE_SUCCESS"
}
function toggle() {
settingsModal.toggle();
return "SETTINGS_TOGGLE_SUCCESS";
settingsModal.toggle()
return "SETTINGS_TOGGLE_SUCCESS"
}
target: "settings"

View File

@@ -16,23 +16,23 @@ DankModal {
function show() {
spotlightOpen = true;
spotlightOpen = true
appLauncher.searchQuery = "";
appLauncher.searchQuery = ""
}
function hide() {
spotlightOpen = false;
appLauncher.searchQuery = "";
appLauncher.selectedIndex = 0;
appLauncher.setCategory("All");
spotlightOpen = false
appLauncher.searchQuery = ""
appLauncher.selectedIndex = 0
appLauncher.setCategory("All")
}
function toggle() {
if (spotlightOpen)
hide();
hide()
else
show();
show()
}
visible: spotlightOpen
@@ -47,11 +47,10 @@ DankModal {
onVisibleChanged: {
if (visible && !spotlightOpen)
show();
show()
}
onBackgroundClicked: {
spotlightOpen = false;
spotlightOpen = false
}
Component.onCompleted: {
@@ -63,28 +62,28 @@ DankModal {
viewMode: SettingsData.spotlightModalViewMode
gridColumns: 4
onAppLaunched: hide()
onViewModeSelected: function(mode) {
SettingsData.setSpotlightModalViewMode(mode);
onViewModeSelected: function (mode) {
SettingsData.setSpotlightModalViewMode(mode)
}
}
IpcHandler {
function open() {
spotlightModal.show();
return "SPOTLIGHT_OPEN_SUCCESS";
spotlightModal.show()
return "SPOTLIGHT_OPEN_SUCCESS"
}
function close() {
spotlightModal.hide();
return "SPOTLIGHT_CLOSE_SUCCESS";
spotlightModal.hide()
return "SPOTLIGHT_CLOSE_SUCCESS"
}
function toggle() {
spotlightModal.toggle();
return "SPOTLIGHT_TOGGLE_SUCCESS";
spotlightModal.toggle()
return "SPOTLIGHT_TOGGLE_SUCCESS"
}
target: "spotlight"
@@ -96,29 +95,33 @@ DankModal {
anchors.fill: parent
focus: true
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
hide();
event.accepted = true;
hide()
event.accepted = true
} else if (event.key === Qt.Key_Down) {
appLauncher.selectNext();
event.accepted = true;
appLauncher.selectNext()
event.accepted = true
} else if (event.key === Qt.Key_Up) {
appLauncher.selectPrevious();
event.accepted = true;
} else if (event.key === Qt.Key_Right && appLauncher.viewMode === "grid") {
appLauncher.selectNextInRow();
event.accepted = true;
} else if (event.key === Qt.Key_Left && appLauncher.viewMode === "grid") {
appLauncher.selectPreviousInRow();
event.accepted = true;
appLauncher.selectPrevious()
event.accepted = true
} else if (event.key === Qt.Key_Right
&& appLauncher.viewMode === "grid") {
appLauncher.selectNextInRow()
event.accepted = true
} else if (event.key === Qt.Key_Left
&& appLauncher.viewMode === "grid") {
appLauncher.selectPreviousInRow()
event.accepted = true
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
appLauncher.launchSelected();
event.accepted = true;
} else if (!searchField.activeFocus && event.text && event.text.length > 0 && event.text.match(/[a-zA-Z0-9\\s]/)) {
searchField.forceActiveFocus();
searchField.insertText(event.text);
event.accepted = true;
appLauncher.launchSelected()
event.accepted = true
} else if (!searchField.activeFocus && event.text
&& event.text.length > 0 && event.text.match(
/[a-zA-Z0-9\\s]/)) {
searchField.forceActiveFocus()
searchField.insertText(event.text)
event.accepted = true
}
}
@@ -134,7 +137,8 @@ DankModal {
color: Theme.surfaceVariantAlpha
border.color: Theme.outlineMedium
border.width: 1
visible: appLauncher.categories.length > 1 || appLauncher.model.count > 0
visible: appLauncher.categories.length > 1
|| appLauncher.model.count > 0
CategorySelector {
id: categorySelector
@@ -144,11 +148,10 @@ DankModal {
categories: appLauncher.categories
selectedCategory: appLauncher.selectedCategory
compact: false
onCategorySelected: (category) => {
return appLauncher.setCategory(category);
onCategorySelected: category => {
return appLauncher.setCategory(category)
}
}
}
Row {
@@ -161,7 +164,10 @@ DankModal {
width: parent.width - 80 - Theme.spacingM // Leave space for view toggle buttons
height: 56
cornerRadius: Theme.cornerRadiusLarge
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7)
backgroundColor: Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.7)
normalBorderColor: Theme.outlineMedium
focusedBorderColor: Theme.primary
leftIconName: "search"
@@ -177,35 +183,39 @@ DankModal {
keyForwardTargets: [spotlightKeyHandler]
text: appLauncher.searchQuery
onTextEdited: {
appLauncher.searchQuery = text;
appLauncher.searchQuery = text
}
Keys.onPressed: (event) => {
Keys.onPressed: event => {
if (event.key === Qt.Key_Escape) {
hide();
event.accepted = true;
} else if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length > 0) {
if (appLauncher.keyboardNavigationActive && appLauncher.model.count > 0)
appLauncher.launchSelected();
hide()
event.accepted = true
} else if ((event.key === Qt.Key_Return
|| event.key === Qt.Key_Enter)
&& text.length > 0) {
if (appLauncher.keyboardNavigationActive
&& appLauncher.model.count > 0)
appLauncher.launchSelected()
else if (appLauncher.model.count > 0)
appLauncher.launchApp(appLauncher.model.get(0));
event.accepted = true;
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Up || event.key === Qt.Key_Left || event.key === Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
event.accepted = false;
appLauncher.launchApp(appLauncher.model.get(0))
event.accepted = true
} else if (event.key === Qt.Key_Down || event.key
=== Qt.Key_Up || event.key === Qt.Key_Left || event.key
=== Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
event.accepted = false
}
}
Connections {
function onSpotlightOpenChanged() {
if (spotlightModal.spotlightOpen) {
Qt.callLater(function() {
searchField.forceActiveFocus();
});
Qt.callLater(function () {
searchField.forceActiveFocus()
})
}
}
target: spotlightModal
}
}
Row {
@@ -235,10 +245,9 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
appLauncher.setViewMode("list");
appLauncher.setViewMode("list")
}
}
}
Rectangle {
@@ -263,14 +272,11 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
appLauncher.setViewMode("grid");
appLauncher.setViewMode("grid")
}
}
}
}
}
Rectangle {
@@ -293,21 +299,21 @@ DankModal {
property bool hoverUpdatesSelection: false
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
signal keyboardNavigationReset()
signal keyboardNavigationReset
signal itemClicked(int index, var modelData)
signal itemHovered(int index)
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
function ensureVisible(index) {
if (index < 0 || index >= count)
return;
return
var itemY = index * (itemHeight + itemSpacing);
var itemBottom = itemY + itemHeight;
var itemY = index * (itemHeight + itemSpacing)
var itemBottom = itemY + itemHeight
if (itemY < contentY)
contentY = itemY;
contentY = itemY
else if (itemBottom > contentY + height)
contentY = itemBottom - height;
contentY = itemBottom - height
}
anchors.fill: parent
@@ -324,20 +330,20 @@ DankModal {
onCurrentIndexChanged: {
if (keyboardNavigationActive)
ensureVisible(currentIndex);
ensureVisible(currentIndex)
}
onItemClicked: function(index, modelData) {
appLauncher.launchApp(modelData);
onItemClicked: function (index, modelData) {
appLauncher.launchApp(modelData)
}
onItemHovered: function(index) {
appLauncher.selectedIndex = index;
onItemHovered: function (index) {
appLauncher.selectedIndex = index
}
onItemRightClicked: function(index, modelData, mouseX, mouseY) {
onItemRightClicked: function (index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData)
}
onKeyboardNavigationReset: {
appLauncher.keyboardNavigationActive = false;
appLauncher.keyboardNavigationActive = false
}
ScrollBar.vertical: ScrollBar {
@@ -352,7 +358,7 @@ DankModal {
width: ListView.view.width
height: resultsList.itemHeight
radius: Theme.cornerRadiusLarge
color: ListView.isCurrentItem ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium
border.width: ListView.isCurrentItem ? 2 : 1
@@ -367,10 +373,12 @@ DankModal {
anchors.verticalCenter: parent.verticalCenter
IconImage {
id: iconImg
id: listIconImg
anchors.fill: parent
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
source: (model.icon) ? Quickshell.iconPath(
model.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
smooth: true
asynchronous: true
visible: status === Image.Ready
@@ -378,7 +386,7 @@ DankModal {
Rectangle {
anchors.fill: parent
visible: !iconImg.visible
visible: !listIconImg.visible
color: Theme.surfaceLight
radius: Theme.cornerRadiusLarge
border.width: 1
@@ -386,7 +394,10 @@ DankModal {
StyledText {
anchors.centerIn: parent
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
text: (model.name
&& model.name.length > 0) ? model.name.charAt(
0).toUpperCase(
) : "A"
font.pixelSize: resultsList.iconSize * 0.4
color: Theme.primary
font.weight: Font.Bold
@@ -414,13 +425,14 @@ DankModal {
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
elide: Text.ElideRight
visible: resultsList.showDescription && model.comment && model.comment.length > 0
visible: resultsList.showDescription && model.comment
&& model.comment.length > 0
}
}
}
MouseArea {
id: mouseArea
id: listMouseArea
anchors.fill: parent
hoverEnabled: true
@@ -428,20 +440,23 @@ DankModal {
acceptedButtons: Qt.LeftButton | Qt.RightButton
z: 10
onEntered: {
if (resultsList.hoverUpdatesSelection && !resultsList.keyboardNavigationActive)
resultsList.currentIndex = index;
if (resultsList.hoverUpdatesSelection
&& !resultsList.keyboardNavigationActive)
resultsList.currentIndex = index
resultsList.itemHovered(index);
resultsList.itemHovered(index)
}
onPositionChanged: {
resultsList.keyboardNavigationReset();
resultsList.keyboardNavigationReset()
}
onClicked: (mouse) => {
onClicked: mouse => {
if (mouse.button === Qt.LeftButton) {
resultsList.itemClicked(index, model);
resultsList.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) {
var globalPos = mapToGlobal(mouse.x, mouse.y);
resultsList.itemRightClicked(index, model, globalPos.x, globalPos.y);
var globalPos = mapToGlobal(mouse.x, mouse.y)
resultsList.itemRightClicked(index, model,
globalPos.x,
globalPos.y)
}
}
}
@@ -462,26 +477,31 @@ DankModal {
property int minIconSize: 32
property bool hoverUpdatesSelection: false
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
property int baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns
property int baseCellWidth: adaptiveColumns ? Math.max(
minCellWidth,
Math.min(
maxCellWidth,
width / columns)) : (width - Theme.spacingS * 2) / columns
property int baseCellHeight: baseCellWidth + 20
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns
property int actualColumns: adaptiveColumns ? Math.floor(
width / cellWidth) : columns
property int remainingSpace: width - (actualColumns * cellWidth)
signal keyboardNavigationReset()
signal keyboardNavigationReset
signal itemClicked(int index, var modelData)
signal itemHovered(int index)
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
function ensureVisible(index) {
if (index < 0 || index >= count)
return;
return
var itemY = Math.floor(index / actualColumns) * cellHeight;
var itemBottom = itemY + cellHeight;
var itemY = Math.floor(index / actualColumns) * cellHeight
var itemBottom = itemY + cellHeight
if (itemY < contentY)
contentY = itemY;
contentY = itemY
else if (itemBottom > contentY + height)
contentY = itemBottom - height;
contentY = itemBottom - height
}
anchors.fill: parent
@@ -500,20 +520,20 @@ DankModal {
onCurrentIndexChanged: {
if (keyboardNavigationActive)
ensureVisible(currentIndex);
ensureVisible(currentIndex)
}
onItemClicked: function(index, modelData) {
appLauncher.launchApp(modelData);
onItemClicked: function (index, modelData) {
appLauncher.launchApp(modelData)
}
onItemHovered: function(index) {
appLauncher.selectedIndex = index;
onItemHovered: function (index) {
appLauncher.selectedIndex = index
}
onItemRightClicked: function(index, modelData, mouseX, mouseY) {
onItemRightClicked: function (index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData)
}
onKeyboardNavigationReset: {
appLauncher.keyboardNavigationActive = false;
appLauncher.keyboardNavigationActive = false
}
ScrollBar.vertical: ScrollBar {
@@ -528,8 +548,9 @@ DankModal {
width: resultsGrid.cellWidth - resultsGrid.cellPadding
height: resultsGrid.cellHeight - resultsGrid.cellPadding
radius: Theme.cornerRadiusLarge
color: resultsGrid.currentIndex === index ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: resultsGrid.currentIndex === index ? Theme.primarySelected : Theme.outlineMedium
color: resultsGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: resultsGrid.currentIndex
=== index ? Theme.primarySelected : Theme.outlineMedium
border.width: resultsGrid.currentIndex === index ? 2 : 1
Column {
@@ -537,17 +558,22 @@ DankModal {
spacing: Theme.spacingS
Item {
property int iconSize: Math.min(resultsGrid.maxIconSize, Math.max(resultsGrid.minIconSize, resultsGrid.cellWidth * resultsGrid.iconSizeRatio))
property int iconSize: Math.min(
resultsGrid.maxIconSize, Math.max(
resultsGrid.minIconSize,
resultsGrid.cellWidth * resultsGrid.iconSizeRatio))
width: iconSize
height: iconSize
anchors.horizontalCenter: parent.horizontalCenter
IconImage {
id: iconImg
id: gridIconImg
anchors.fill: parent
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
source: (model.icon) ? Quickshell.iconPath(
model.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
smooth: true
asynchronous: true
visible: status === Image.Ready
@@ -555,7 +581,7 @@ DankModal {
Rectangle {
anchors.fill: parent
visible: !iconImg.visible
visible: !gridIconImg.visible
color: Theme.surfaceLight
radius: Theme.cornerRadiusLarge
border.width: 1
@@ -563,7 +589,10 @@ DankModal {
StyledText {
anchors.centerIn: parent
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
text: (model.name
&& model.name.length > 0) ? model.name.charAt(
0).toUpperCase(
) : "A"
font.pixelSize: Math.min(28, parent.width * 0.5)
color: Theme.primary
font.weight: Font.Bold
@@ -586,7 +615,7 @@ DankModal {
}
MouseArea {
id: mouseArea
id: gridMouseArea
anchors.fill: parent
hoverEnabled: true
@@ -594,32 +623,31 @@ DankModal {
acceptedButtons: Qt.LeftButton | Qt.RightButton
z: 10
onEntered: {
if (resultsGrid.hoverUpdatesSelection && !resultsGrid.keyboardNavigationActive)
resultsGrid.currentIndex = index;
if (resultsGrid.hoverUpdatesSelection
&& !resultsGrid.keyboardNavigationActive)
resultsGrid.currentIndex = index
resultsGrid.itemHovered(index);
resultsGrid.itemHovered(index)
}
onPositionChanged: {
resultsGrid.keyboardNavigationReset();
resultsGrid.keyboardNavigationReset()
}
onClicked: (mouse) => {
onClicked: mouse => {
if (mouse.button === Qt.LeftButton) {
resultsGrid.itemClicked(index, model);
resultsGrid.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) {
var globalPos = mapToGlobal(mouse.x, mouse.y);
resultsGrid.itemRightClicked(index, model, globalPos.x, globalPos.y);
var globalPos = mapToGlobal(mouse.x, mouse.y)
resultsGrid.itemRightClicked(index, model,
globalPos.x,
globalPos.y)
}
}
}
}
}
}
}
}
}
Popup {
@@ -629,24 +657,25 @@ DankModal {
function show(x, y, app) {
currentApp = app
if (!contextMenu.parent && typeof Overlay !== "undefined" && Overlay.overlay)
contextMenu.parent = Overlay.overlay;
if (!contextMenu.parent && typeof Overlay !== "undefined"
&& Overlay.overlay)
contextMenu.parent = Overlay.overlay
const menuWidth = 180;
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2;
const screenWidth = Screen.width;
const screenHeight = Screen.height;
let finalX = x;
let finalY = y;
const menuWidth = 180
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
const screenWidth = Screen.width
const screenHeight = Screen.height
let finalX = x
let finalY = y
if (x + menuWidth > screenWidth - 20)
finalX = x - menuWidth;
finalX = x - menuWidth
if (y + menuHeight > screenHeight - 20)
finalY = y - menuHeight;
finalY = y - menuHeight
contextMenu.x = Math.max(20, finalX);
contextMenu.y = Math.max(20, finalY);
open();
contextMenu.x = Math.max(20, finalX)
contextMenu.y = Math.max(20, finalY)
open()
}
width: 180
@@ -655,17 +684,17 @@ DankModal {
modal: false
closePolicy: Popup.CloseOnEscape
onClosed: {
closePolicy = Popup.CloseOnEscape;
closePolicy = Popup.CloseOnEscape
}
onOpened: {
outsideClickTimer.start();
outsideClickTimer.start()
}
Timer {
id: outsideClickTimer
interval: 100
onTriggered: {
contextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside;
contextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside
}
}
@@ -676,7 +705,8 @@ DankModal {
contentItem: Rectangle {
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
Column {
@@ -689,7 +719,10 @@ DankModal {
width: parent.width
height: 32
radius: Theme.cornerRadiusSmall
color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row {
anchors.left: parent.left
@@ -699,8 +732,11 @@ DankModal {
DankIcon {
name: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) return "push_pin"
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""
if (!contextMenu.currentApp
|| !contextMenu.currentApp.desktopEntry)
return "push_pin"
var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
return SessionData.isPinnedApp(appId) ? "keep_off" : "push_pin"
}
size: Theme.iconSize - 2
@@ -711,9 +747,13 @@ DankModal {
StyledText {
text: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) return "Pin to Dock"
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""
return SessionData.isPinnedApp(appId) ? "Unpin from Dock" : "Pin to Dock"
if (!contextMenu.currentApp
|| !contextMenu.currentApp.desktopEntry)
return "Pin to Dock"
var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
return SessionData.isPinnedApp(
appId) ? "Unpin from Dock" : "Pin to Dock"
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
@@ -728,8 +768,11 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) return
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""
if (!contextMenu.currentApp
|| !contextMenu.currentApp.desktopEntry)
return
var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
if (SessionData.isPinnedApp(appId)) {
SessionData.removePinnedApp(appId)
} else {
@@ -750,7 +793,8 @@ DankModal {
anchors.centerIn: parent
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
}
}
@@ -758,7 +802,10 @@ DankModal {
width: parent.width
height: 32
radius: Theme.cornerRadiusSmall
color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row {
anchors.left: parent.left
@@ -799,5 +846,4 @@ DankModal {
}
}
}
}

View File

@@ -17,21 +17,21 @@ DankModal {
keyboardFocus: "exclusive"
onVisibleChanged: {
if (!visible)
wifiPasswordInput = "";
wifiPasswordInput = ""
}
onBackgroundClicked: {
wifiPasswordModalVisible = false;
wifiPasswordInput = "";
wifiPasswordModalVisible = false
wifiPasswordInput = ""
}
Connections {
function onPasswordDialogShouldReopenChanged() {
if (NetworkService.passwordDialogShouldReopen && NetworkService.connectingSSID !== "") {
wifiPasswordSSID = NetworkService.connectingSSID;
wifiPasswordInput = "";
wifiPasswordModalVisible = true;
NetworkService.passwordDialogShouldReopen = false;
if (NetworkService.passwordDialogShouldReopen
&& NetworkService.connectingSSID !== "") {
wifiPasswordSSID = NetworkService.connectingSSID
wifiPasswordInput = ""
wifiPasswordModalVisible = true
NetworkService.passwordDialogShouldReopen = false
}
}
@@ -69,7 +69,6 @@ DankModal {
width: parent.width
elide: Text.ElideRight
}
}
DankActionButton {
@@ -78,11 +77,10 @@ DankModal {
iconColor: Theme.surfaceText
hoverColor: Theme.errorHover
onClicked: {
wifiPasswordModalVisible = false;
wifiPasswordInput = "";
wifiPasswordModalVisible = false
wifiPasswordInput = ""
}
}
}
Rectangle {
@@ -105,13 +103,14 @@ DankModal {
backgroundColor: "transparent"
focus: true
onTextEdited: {
wifiPasswordInput = text;
wifiPasswordInput = text
}
onAccepted: {
NetworkService.connectToWifiWithPassword(wifiPasswordSSID, passwordInput.text);
wifiPasswordModalVisible = false;
wifiPasswordInput = "";
passwordInput.text = "";
NetworkService.connectToWifiWithPassword(wifiPasswordSSID,
passwordInput.text)
wifiPasswordModalVisible = false
wifiPasswordInput = ""
passwordInput.text = ""
}
Timer {
@@ -121,25 +120,23 @@ DankModal {
}
Component.onCompleted: {
focusTimer.start();
focusTimer.start()
}
Connections {
function onOpened() {
focusTimer.start();
focusTimer.start()
}
function onVisibleChanged() {
if (root.visible) {
focusTimer.start();
focusTimer.start()
}
}
target: root
}
}
}
Row {
@@ -170,10 +167,9 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
showPasswordCheckbox.checked = !showPasswordCheckbox.checked;
showPasswordCheckbox.checked = !showPasswordCheckbox.checked
}
}
}
StyledText {
@@ -182,7 +178,6 @@ DankModal {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Item {
@@ -219,18 +214,18 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
wifiPasswordModalVisible = false;
wifiPasswordInput = "";
wifiPasswordModalVisible = false
wifiPasswordInput = ""
}
}
}
Rectangle {
width: Math.max(80, connectText.contentWidth + Theme.spacingM * 2)
height: 36
radius: Theme.cornerRadius
color: connectArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
color: connectArea.containsMouse ? Qt.darker(Theme.primary,
1.1) : Theme.primary
enabled: passwordInput.text.length > 0
opacity: enabled ? 1 : 0.5
@@ -252,10 +247,11 @@ DankModal {
cursorShape: Qt.PointingHandCursor
enabled: parent.enabled
onClicked: {
NetworkService.connectToWifiWithPassword(wifiPasswordSSID, passwordInput.text);
wifiPasswordModalVisible = false;
wifiPasswordInput = "";
passwordInput.text = "";
NetworkService.connectToWifiWithPassword(wifiPasswordSSID,
passwordInput.text)
wifiPasswordModalVisible = false
wifiPasswordInput = ""
passwordInput.text = ""
}
}
@@ -264,18 +260,11 @@ DankModal {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}
}
}
}
}
}
}
}
}
}

View File

@@ -21,27 +21,27 @@ PanelWindow {
property var triggerScreen: null
function show() {
appDrawerPopout.isVisible = true;
appLauncher.searchQuery = "";
appDrawerPopout.isVisible = true
appLauncher.searchQuery = ""
}
function hide() {
appDrawerPopout.isVisible = false;
appDrawerPopout.isVisible = false
}
function toggle() {
if (appDrawerPopout.isVisible)
hide();
hide()
else
show();
show()
}
function setTriggerPosition(x, y, width, section, screen) {
triggerX = x;
triggerY = y;
triggerWidth = width;
triggerSection = section;
triggerScreen = screen;
triggerX = x
triggerY = y
triggerWidth = width
triggerSection = section
triggerScreen = screen
}
WlrLayershell.layer: WlrLayershell.Overlay
@@ -65,19 +65,19 @@ PanelWindow {
viewMode: SettingsData.appLauncherViewMode
gridColumns: 4
onAppLaunched: appDrawerPopout.hide()
onViewModeSelected: function(mode) {
SettingsData.setAppLauncherViewMode(mode);
onViewModeSelected: function (mode) {
SettingsData.setAppLauncherViewMode(mode)
}
}
MouseArea {
anchors.fill: parent
enabled: appDrawerPopout.isVisible
onClicked: function(mouse) {
var localPos = mapToItem(launcherLoader, mouse.x, mouse.y);
if (localPos.x < 0 || localPos.x > launcherLoader.width || localPos.y < 0 || localPos.y > launcherLoader.height)
appDrawerPopout.hide();
onClicked: function (mouse) {
var localPos = mapToItem(launcherLoader, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > launcherLoader.width || localPos.y < 0
|| localPos.y > launcherLoader.height)
appDrawerPopout.hide()
}
}
@@ -89,18 +89,19 @@ PanelWindow {
readonly property real screenWidth: appDrawerPopout.screen ? appDrawerPopout.screen.width : Screen.width
readonly property real screenHeight: appDrawerPopout.screen ? appDrawerPopout.screen.height : Screen.height
readonly property real calculatedX: {
var centerX = appDrawerPopout.triggerX + (appDrawerPopout.triggerWidth / 2) - (popupWidth / 2);
var centerX = appDrawerPopout.triggerX + (appDrawerPopout.triggerWidth / 2) - (popupWidth / 2)
if (centerX >= Theme.spacingM && centerX + popupWidth <= screenWidth - Theme.spacingM)
return centerX;
if (centerX >= Theme.spacingM
&& centerX + popupWidth <= screenWidth - Theme.spacingM)
return centerX
if (centerX < Theme.spacingM)
return Theme.spacingM;
return Theme.spacingM
if (centerX + popupWidth > screenWidth - Theme.spacingM)
return screenWidth - popupWidth - Theme.spacingM;
return screenWidth - popupWidth - Theme.spacingM
return centerX;
return centerX
}
readonly property real calculatedY: appDrawerPopout.triggerY
@@ -119,7 +120,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
Behavior on scale {
@@ -128,7 +128,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
sourceComponent: Rectangle {
@@ -162,7 +161,8 @@ PanelWindow {
Rectangle {
anchors.fill: parent
color: "transparent"
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
radius: parent.radius
z: -1
@@ -175,32 +175,36 @@ PanelWindow {
focus: true
Component.onCompleted: {
if (appDrawerPopout.isVisible)
forceActiveFocus();
forceActiveFocus()
}
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
appDrawerPopout.hide();
event.accepted = true;
appDrawerPopout.hide()
event.accepted = true
} else if (event.key === Qt.Key_Down) {
appLauncher.selectNext();
event.accepted = true;
appLauncher.selectNext()
event.accepted = true
} else if (event.key === Qt.Key_Up) {
appLauncher.selectPrevious();
event.accepted = true;
} else if (event.key === Qt.Key_Right && appLauncher.viewMode === "grid") {
appLauncher.selectNextInRow();
event.accepted = true;
} else if (event.key === Qt.Key_Left && appLauncher.viewMode === "grid") {
appLauncher.selectPreviousInRow();
event.accepted = true;
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
appLauncher.launchSelected();
event.accepted = true;
} else if (!searchField.activeFocus && event.text && event.text.length > 0 && event.text.match(/[a-zA-Z0-9\\s]/)) {
searchField.forceActiveFocus();
searchField.insertText(event.text);
event.accepted = true;
appLauncher.selectPrevious()
event.accepted = true
} else if (event.key === Qt.Key_Right
&& appLauncher.viewMode === "grid") {
appLauncher.selectNextInRow()
event.accepted = true
} else if (event.key === Qt.Key_Left
&& appLauncher.viewMode === "grid") {
appLauncher.selectPreviousInRow()
event.accepted = true
} else if (event.key === Qt.Key_Return
|| event.key === Qt.Key_Enter) {
appLauncher.launchSelected()
event.accepted = true
} else if (!searchField.activeFocus && event.text
&& event.text.length > 0 && event.text.match(
/[a-zA-Z0-9\\s]/)) {
searchField.forceActiveFocus()
searchField.insertText(event.text)
event.accepted = true
}
}
@@ -234,7 +238,6 @@ PanelWindow {
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
}
}
DankTextField {
@@ -243,8 +246,12 @@ PanelWindow {
width: parent.width
height: 52
cornerRadius: Theme.cornerRadiusLarge
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7)
normalBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
backgroundColor: Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.7)
normalBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.3)
focusedBorderColor: Theme.primary
leftIconName: "search"
leftIconSize: Theme.iconSize
@@ -257,40 +264,43 @@ PanelWindow {
ignoreLeftRightKeys: true
keyForwardTargets: [keyHandler]
onTextEdited: {
appLauncher.searchQuery = text;
appLauncher.searchQuery = text
}
Keys.onPressed: function(event) {
if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length > 0) {
if (appLauncher.keyboardNavigationActive && appLauncher.model.count > 0) {
appLauncher.launchSelected();
Keys.onPressed: function (event) {
if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter)
&& text.length > 0) {
if (appLauncher.keyboardNavigationActive
&& appLauncher.model.count > 0) {
appLauncher.launchSelected()
} else if (appLauncher.model.count > 0) {
var firstApp = appLauncher.model.get(0);
appLauncher.launchApp(firstApp);
var firstApp = appLauncher.model.get(0)
appLauncher.launchApp(firstApp)
}
event.accepted = true;
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Up || event.key === Qt.Key_Left || event.key === Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
event.accepted = false;
event.accepted = true
} else if (event.key === Qt.Key_Down || event.key
=== Qt.Key_Up || event.key === Qt.Key_Left || event.key
=== Qt.Key_Right || ((event.key === Qt.Key_Return || event.key
=== Qt.Key_Enter) && text.length === 0)) {
event.accepted = false
}
}
Component.onCompleted: {
if (appDrawerPopout.isVisible)
searchField.forceActiveFocus();
searchField.forceActiveFocus()
}
Connections {
function onIsVisibleChanged() {
if (appDrawerPopout.isVisible)
Qt.callLater(function() {
searchField.forceActiveFocus();
});
Qt.callLater(function () {
searchField.forceActiveFocus()
})
else
searchField.clearFocus();
searchField.clearFocus()
}
target: appDrawerPopout
}
}
Row {
@@ -309,11 +319,10 @@ PanelWindow {
currentValue: appLauncher.selectedCategory
options: appLauncher.categories
optionIcons: appLauncher.categoryIcons
onValueChanged: function(value) {
appLauncher.setCategory(value);
onValueChanged: function (value) {
appLauncher.setCategory(value)
}
}
}
Item {
@@ -331,10 +340,21 @@ PanelWindow {
iconName: "view_list"
iconSize: 20
iconColor: appLauncher.viewMode === "list" ? Theme.primary : Theme.surfaceText
hoverColor: appLauncher.viewMode === "list" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)
backgroundColor: appLauncher.viewMode === "list" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
hoverColor: appLauncher.viewMode
=== "list" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
backgroundColor: appLauncher.viewMode
=== "list" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
onClicked: {
appLauncher.setViewMode("list");
appLauncher.setViewMode("list")
}
}
@@ -344,28 +364,39 @@ PanelWindow {
iconName: "grid_view"
iconSize: 20
iconColor: appLauncher.viewMode === "grid" ? Theme.primary : Theme.surfaceText
hoverColor: appLauncher.viewMode === "grid" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)
backgroundColor: appLauncher.viewMode === "grid" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
hoverColor: appLauncher.viewMode
=== "grid" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
backgroundColor: appLauncher.viewMode
=== "grid" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
onClicked: {
appLauncher.setViewMode("grid");
appLauncher.setViewMode("grid")
}
}
}
}
Rectangle {
width: parent.width
height: {
let usedHeight = 40 + Theme.spacingL;
usedHeight += 52 + Theme.spacingL;
usedHeight += (searchField.text.length === 0 ? 40 + Theme.spacingL : 0);
return parent.height - usedHeight;
let usedHeight = 40 + Theme.spacingL
usedHeight += 52 + Theme.spacingL
usedHeight += (searchField.text.length === 0 ? 40 + Theme.spacingL : 0)
return parent.height - usedHeight
}
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.05)
border.width: 1
DankListView {
@@ -378,21 +409,21 @@ PanelWindow {
property bool hoverUpdatesSelection: false
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
signal keyboardNavigationReset()
signal keyboardNavigationReset
signal itemClicked(int index, var modelData)
signal itemHovered(int index)
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
function ensureVisible(index) {
if (index < 0 || index >= count)
return;
return
var itemY = index * (itemHeight + itemSpacing);
var itemBottom = itemY + itemHeight;
var itemY = index * (itemHeight + itemSpacing)
var itemBottom = itemY + itemHeight
if (itemY < contentY)
contentY = itemY;
contentY = itemY
else if (itemBottom > contentY + height)
contentY = itemBottom - height;
contentY = itemBottom - height
}
anchors.fill: parent
@@ -409,20 +440,20 @@ PanelWindow {
onCurrentIndexChanged: {
if (keyboardNavigationActive)
ensureVisible(currentIndex);
ensureVisible(currentIndex)
}
onItemClicked: function(index, modelData) {
appLauncher.launchApp(modelData);
onItemClicked: function (index, modelData) {
appLauncher.launchApp(modelData)
}
onItemHovered: function(index) {
appLauncher.selectedIndex = index;
onItemHovered: function (index) {
appLauncher.selectedIndex = index
}
onItemRightClicked: function(index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData);
onItemRightClicked: function (index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData)
}
onKeyboardNavigationReset: {
appLauncher.keyboardNavigationActive = false;
appLauncher.keyboardNavigationActive = false
}
ScrollBar.vertical: ScrollBar {
@@ -437,7 +468,7 @@ PanelWindow {
width: ListView.view.width
height: appList.itemHeight
radius: Theme.cornerRadiusLarge
color: ListView.isCurrentItem ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium
border.width: ListView.isCurrentItem ? 2 : 1
@@ -452,10 +483,12 @@ PanelWindow {
anchors.verticalCenter: parent.verticalCenter
IconImage {
id: iconImg
id: listIconImg
anchors.fill: parent
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
source: (model.icon) ? Quickshell.iconPath(
model.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
smooth: true
asynchronous: true
visible: status === Image.Ready
@@ -463,7 +496,7 @@ PanelWindow {
Rectangle {
anchors.fill: parent
visible: !iconImg.visible
visible: !listIconImg.visible
color: Theme.surfaceLight
radius: Theme.cornerRadiusLarge
border.width: 1
@@ -471,7 +504,10 @@ PanelWindow {
StyledText {
anchors.centerIn: parent
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
text: (model.name
&& model.name.length > 0) ? model.name.charAt(
0).toUpperCase(
) : "A"
font.pixelSize: appList.iconSize * 0.4
color: Theme.primary
font.weight: Font.Bold
@@ -499,13 +535,14 @@ PanelWindow {
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
elide: Text.ElideRight
visible: appList.showDescription && model.comment && model.comment.length > 0
visible: appList.showDescription && model.comment
&& model.comment.length > 0
}
}
}
MouseArea {
id: mouseArea
id: listMouseArea
anchors.fill: parent
hoverEnabled: true
@@ -513,20 +550,23 @@ PanelWindow {
acceptedButtons: Qt.LeftButton | Qt.RightButton
z: 10
onEntered: {
if (appList.hoverUpdatesSelection && !appList.keyboardNavigationActive)
appList.currentIndex = index;
if (appList.hoverUpdatesSelection
&& !appList.keyboardNavigationActive)
appList.currentIndex = index
appList.itemHovered(index);
appList.itemHovered(index)
}
onPositionChanged: {
appList.keyboardNavigationReset();
appList.keyboardNavigationReset()
}
onClicked: (mouse) => {
onClicked: mouse => {
if (mouse.button === Qt.LeftButton) {
appList.itemClicked(index, model);
appList.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) {
var globalPos = mapToGlobal(mouse.x, mouse.y);
appList.itemRightClicked(index, model, globalPos.x, globalPos.y);
var globalPos = mapToGlobal(mouse.x, mouse.y)
appList.itemRightClicked(index, model,
globalPos.x,
globalPos.y)
}
}
}
@@ -547,26 +587,31 @@ PanelWindow {
property int minIconSize: 32
property bool hoverUpdatesSelection: false
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
property int baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns
property int baseCellWidth: adaptiveColumns ? Math.max(
minCellWidth,
Math.min(
maxCellWidth,
width / columns)) : (width - Theme.spacingS * 2) / columns
property int baseCellHeight: baseCellWidth + 20
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns
property int actualColumns: adaptiveColumns ? Math.floor(
width / cellWidth) : columns
property int remainingSpace: width - (actualColumns * cellWidth)
signal keyboardNavigationReset()
signal keyboardNavigationReset
signal itemClicked(int index, var modelData)
signal itemHovered(int index)
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
function ensureVisible(index) {
if (index < 0 || index >= count)
return;
return
var itemY = Math.floor(index / actualColumns) * cellHeight;
var itemBottom = itemY + cellHeight;
var itemY = Math.floor(index / actualColumns) * cellHeight
var itemBottom = itemY + cellHeight
if (itemY < contentY)
contentY = itemY;
contentY = itemY
else if (itemBottom > contentY + height)
contentY = itemBottom - height;
contentY = itemBottom - height
}
anchors.fill: parent
@@ -585,20 +630,20 @@ PanelWindow {
onCurrentIndexChanged: {
if (keyboardNavigationActive)
ensureVisible(currentIndex);
ensureVisible(currentIndex)
}
onItemClicked: function(index, modelData) {
appLauncher.launchApp(modelData);
onItemClicked: function (index, modelData) {
appLauncher.launchApp(modelData)
}
onItemHovered: function(index) {
appLauncher.selectedIndex = index;
onItemHovered: function (index) {
appLauncher.selectedIndex = index
}
onItemRightClicked: function(index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData);
onItemRightClicked: function (index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData)
}
onKeyboardNavigationReset: {
appLauncher.keyboardNavigationActive = false;
appLauncher.keyboardNavigationActive = false
}
ScrollBar.vertical: ScrollBar {
@@ -613,8 +658,9 @@ PanelWindow {
width: appGrid.cellWidth - appGrid.cellPadding
height: appGrid.cellHeight - appGrid.cellPadding
radius: Theme.cornerRadiusLarge
color: appGrid.currentIndex === index ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: appGrid.currentIndex === index ? Theme.primarySelected : Theme.outlineMedium
color: appGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: appGrid.currentIndex
=== index ? Theme.primarySelected : Theme.outlineMedium
border.width: appGrid.currentIndex === index ? 2 : 1
Column {
@@ -622,17 +668,22 @@ PanelWindow {
spacing: Theme.spacingS
Item {
property int iconSize: Math.min(appGrid.maxIconSize, Math.max(appGrid.minIconSize, appGrid.cellWidth * appGrid.iconSizeRatio))
property int iconSize: Math.min(
appGrid.maxIconSize, Math.max(
appGrid.minIconSize,
appGrid.cellWidth * appGrid.iconSizeRatio))
width: iconSize
height: iconSize
anchors.horizontalCenter: parent.horizontalCenter
IconImage {
id: iconImg
id: gridIconImg
anchors.fill: parent
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
source: (model.icon) ? Quickshell.iconPath(
model.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
smooth: true
asynchronous: true
visible: status === Image.Ready
@@ -640,7 +691,7 @@ PanelWindow {
Rectangle {
anchors.fill: parent
visible: !iconImg.visible
visible: !gridIconImg.visible
color: Theme.surfaceLight
radius: Theme.cornerRadiusLarge
border.width: 1
@@ -648,7 +699,10 @@ PanelWindow {
StyledText {
anchors.centerIn: parent
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
text: (model.name
&& model.name.length > 0) ? model.name.charAt(
0).toUpperCase(
) : "A"
font.pixelSize: Math.min(28, parent.width * 0.5)
color: Theme.primary
font.weight: Font.Bold
@@ -671,7 +725,7 @@ PanelWindow {
}
MouseArea {
id: mouseArea
id: gridMouseArea
anchors.fill: parent
hoverEnabled: true
@@ -679,34 +733,32 @@ PanelWindow {
acceptedButtons: Qt.LeftButton | Qt.RightButton
z: 10
onEntered: {
if (appGrid.hoverUpdatesSelection && !appGrid.keyboardNavigationActive)
appGrid.currentIndex = index;
if (appGrid.hoverUpdatesSelection
&& !appGrid.keyboardNavigationActive)
appGrid.currentIndex = index
appGrid.itemHovered(index);
appGrid.itemHovered(index)
}
onPositionChanged: {
appGrid.keyboardNavigationReset();
appGrid.keyboardNavigationReset()
}
onClicked: (mouse) => {
onClicked: mouse => {
if (mouse.button === Qt.LeftButton) {
appGrid.itemClicked(index, model);
appGrid.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) {
var globalPos = mapToGlobal(mouse.x, mouse.y);
appGrid.itemRightClicked(index, model, globalPos.x, globalPos.y);
var globalPos = mapToGlobal(mouse.x, mouse.y)
appGrid.itemRightClicked(index, model,
globalPos.x,
globalPos.y)
}
}
}
}
}
}
}
}
}
}
Popup {
@@ -715,25 +767,26 @@ PanelWindow {
property var currentApp: null
function show(x, y, app) {
currentApp = app;
if (!contextMenu.parent && typeof Overlay !== "undefined" && Overlay.overlay)
contextMenu.parent = Overlay.overlay;
currentApp = app
if (!contextMenu.parent && typeof Overlay !== "undefined"
&& Overlay.overlay)
contextMenu.parent = Overlay.overlay
const menuWidth = 180;
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2;
const screenWidth = Screen.width;
const screenHeight = Screen.height;
let finalX = x;
let finalY = y;
const menuWidth = 180
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
const screenWidth = Screen.width
const screenHeight = Screen.height
let finalX = x
let finalY = y
if (x + menuWidth > screenWidth - 20)
finalX = x - menuWidth;
finalX = x - menuWidth
if (y + menuHeight > screenHeight - 20)
finalY = y - menuHeight;
finalY = y - menuHeight
contextMenu.x = Math.max(20, finalX);
contextMenu.y = Math.max(20, finalY);
open();
contextMenu.x = Math.max(20, finalX)
contextMenu.y = Math.max(20, finalY)
open()
}
width: 180
@@ -742,10 +795,10 @@ PanelWindow {
modal: false
closePolicy: Popup.CloseOnEscape
onClosed: {
closePolicy = Popup.CloseOnEscape;
closePolicy = Popup.CloseOnEscape
}
onOpened: {
outsideClickTimer.start();
outsideClickTimer.start()
}
Timer {
@@ -753,7 +806,7 @@ PanelWindow {
interval: 100
onTriggered: {
contextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside;
contextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside
}
}
@@ -764,7 +817,8 @@ PanelWindow {
contentItem: Rectangle {
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
Column {
@@ -778,7 +832,10 @@ PanelWindow {
width: parent.width
height: 32
radius: Theme.cornerRadiusSmall
color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row {
anchors.left: parent.left
@@ -788,11 +845,13 @@ PanelWindow {
DankIcon {
name: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
return "push_pin";
if (!contextMenu.currentApp
|| !contextMenu.currentApp.desktopEntry)
return "push_pin"
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || "";
return SessionData.isPinnedApp(appId) ? "keep_off" : "push_pin";
var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
return SessionData.isPinnedApp(appId) ? "keep_off" : "push_pin"
}
size: Theme.iconSize - 2
color: Theme.surfaceText
@@ -802,18 +861,20 @@ PanelWindow {
StyledText {
text: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
return "Pin to Dock";
if (!contextMenu.currentApp
|| !contextMenu.currentApp.desktopEntry)
return "Pin to Dock"
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || "";
return SessionData.isPinnedApp(appId) ? "Unpin from Dock" : "Pin to Dock";
var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
return SessionData.isPinnedApp(
appId) ? "Unpin from Dock" : "Pin to Dock"
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -823,18 +884,19 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
return ;
if (!contextMenu.currentApp
|| !contextMenu.currentApp.desktopEntry)
return
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || "";
var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
if (SessionData.isPinnedApp(appId))
SessionData.removePinnedApp(appId);
SessionData.removePinnedApp(appId)
else
SessionData.addPinnedApp(appId);
contextMenu.close();
SessionData.addPinnedApp(appId)
contextMenu.close()
}
}
}
Rectangle {
@@ -847,16 +909,19 @@ PanelWindow {
anchors.centerIn: parent
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
}
}
Rectangle {
width: parent.width
height: 32
radius: Theme.cornerRadiusSmall
color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row {
anchors.left: parent.left
@@ -879,7 +944,6 @@ PanelWindow {
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -890,18 +954,13 @@ PanelWindow {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (contextMenu.currentApp)
appLauncher.launchApp(contextMenu.currentApp);
appLauncher.launchApp(contextMenu.currentApp)
contextMenu.close();
contextMenu.close()
}
}
}
}
}
}
}

View File

@@ -18,16 +18,18 @@ Item {
property int debounceInterval: 50
property bool keyboardNavigationActive: false
property var categories: {
var allCategories = AppSearchService.getAllCategories().filter((cat) => {
return cat !== "Education" && cat !== "Science";
});
var result = ["All"];
return result.concat(allCategories.filter((cat) => {
return cat !== "All";
}));
var allCategories = AppSearchService.getAllCategories().filter(cat => {
return cat !== "Education"
&& cat !== "Science"
})
var result = ["All"]
return result.concat(allCategories.filter(cat => {
return cat !== "All"
}))
}
property var categoryIcons: categories.map((category) => {
return AppSearchService.getCategoryIcon(category);
property var categoryIcons: categories.map(category => {
return AppSearchService.getCategoryIcon(
category)
})
property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {}
property alias model: filteredModel
@@ -38,136 +40,140 @@ Item {
signal viewModeSelected(string mode)
function updateFilteredModel() {
filteredModel.clear();
selectedIndex = 0;
keyboardNavigationActive = false;
var apps = [];
filteredModel.clear()
selectedIndex = 0
keyboardNavigationActive = false
var apps = []
if (searchQuery.length === 0) {
if (selectedCategory === "All") {
apps = AppSearchService.applications || [];
apps = AppSearchService.applications || []
} else {
var categoryApps = AppSearchService.getAppsInCategory(selectedCategory);
apps = categoryApps.slice(0, maxResults);
var categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
apps = categoryApps.slice(0, maxResults)
}
} else {
if (selectedCategory === "All") {
apps = AppSearchService.searchApplications(searchQuery);
apps = AppSearchService.searchApplications(searchQuery)
} else {
var categoryApps = AppSearchService.getAppsInCategory(selectedCategory);
var categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
if (categoryApps.length > 0) {
var allSearchResults = AppSearchService.searchApplications(searchQuery);
var categoryNames = new Set(categoryApps.map((app) => {
return app.name;
}));
apps = allSearchResults.filter((searchApp) => {
return categoryNames.has(searchApp.name);
}).slice(0, maxResults);
var allSearchResults = AppSearchService.searchApplications(
searchQuery)
var categoryNames = new Set(categoryApps.map(app => {
return app.name
}))
apps = allSearchResults.filter(searchApp => {
return categoryNames.has(
searchApp.name)
}).slice(0, maxResults)
} else {
apps = [];
apps = []
}
}
}
if (searchQuery.length === 0)
apps = apps.sort(function(a, b) {
var aId = a.id || (a.execString || a.exec || "");
var bId = b.id || (b.execString || b.exec || "");
var aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0;
var bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0;
apps = apps.sort(function (a, b) {
var aId = a.id || (a.execString || a.exec || "")
var bId = b.id || (b.execString || b.exec || "")
var aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0
var bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0
if (aUsage !== bUsage)
return bUsage - aUsage;
return bUsage - aUsage
return (a.name || "").localeCompare(b.name || "");
});
return (a.name || "").localeCompare(b.name || "")
})
apps.forEach((app) => {
apps.forEach(app => {
if (app)
filteredModel.append({
"name": app.name || "",
"exec": app.execString || "",
"icon": app.icon || "application-x-executable",
"icon": app.icon
|| "application-x-executable",
"comment": app.comment || "",
"categories": app.categories || [],
"desktopEntry": app
});
});
})
})
}
function selectNext() {
if (filteredModel.count > 0) {
keyboardNavigationActive = true;
keyboardNavigationActive = true
if (viewMode === "grid") {
var newIndex = Math.min(selectedIndex + gridColumns, filteredModel.count - 1);
selectedIndex = newIndex;
var newIndex = Math.min(selectedIndex + gridColumns,
filteredModel.count - 1)
selectedIndex = newIndex
} else {
selectedIndex = (selectedIndex + 1) % filteredModel.count;
selectedIndex = (selectedIndex + 1) % filteredModel.count
}
}
}
function selectPrevious() {
if (filteredModel.count > 0) {
keyboardNavigationActive = true;
keyboardNavigationActive = true
if (viewMode === "grid") {
var newIndex = Math.max(selectedIndex - gridColumns, 0);
selectedIndex = newIndex;
var newIndex = Math.max(selectedIndex - gridColumns, 0)
selectedIndex = newIndex
} else {
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : filteredModel.count - 1;
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : filteredModel.count - 1
}
}
}
function selectNextInRow() {
if (filteredModel.count > 0 && viewMode === "grid") {
keyboardNavigationActive = true;
selectedIndex = Math.min(selectedIndex + 1, filteredModel.count - 1);
keyboardNavigationActive = true
selectedIndex = Math.min(selectedIndex + 1, filteredModel.count - 1)
}
}
function selectPreviousInRow() {
if (filteredModel.count > 0 && viewMode === "grid") {
keyboardNavigationActive = true;
selectedIndex = Math.max(selectedIndex - 1, 0);
keyboardNavigationActive = true
selectedIndex = Math.max(selectedIndex - 1, 0)
}
}
function launchSelected() {
if (filteredModel.count > 0 && selectedIndex >= 0 && selectedIndex < filteredModel.count) {
var selectedApp = filteredModel.get(selectedIndex);
launchApp(selectedApp);
if (filteredModel.count > 0 && selectedIndex >= 0
&& selectedIndex < filteredModel.count) {
var selectedApp = filteredModel.get(selectedIndex)
launchApp(selectedApp)
}
}
function launchApp(appData) {
if (!appData)
return ;
return
appData.desktopEntry.execute();
appLaunched(appData);
AppUsageHistoryData.addAppUsage(appData.desktopEntry);
appData.desktopEntry.execute()
appLaunched(appData)
AppUsageHistoryData.addAppUsage(appData.desktopEntry)
}
function setCategory(category) {
selectedCategory = category;
categorySelected(category);
selectedCategory = category
categorySelected(category)
}
function setViewMode(mode) {
viewMode = mode;
viewModeSelected(mode);
viewMode = mode
viewModeSelected(mode)
}
onSearchQueryChanged: {
if (debounceSearch)
searchDebounceTimer.restart();
searchDebounceTimer.restart()
else
updateFilteredModel();
updateFilteredModel()
}
onSelectedCategoryChanged: updateFilteredModel()
onAppUsageRankingChanged: updateFilteredModel()
on_WatchApplicationsChanged: updateFilteredModel()
Component.onCompleted: {
updateFilteredModel();
updateFilteredModel()
}
ListModel {
@@ -181,5 +187,4 @@ Item {
repeat: false
onTriggered: updateFilteredModel()
}
}

View File

@@ -20,14 +20,20 @@ Item {
spacing: Theme.spacingS
Repeater {
model: categories.slice(0, Math.min(categories.length, 8)) // Limit for space
model: categories.slice(0, Math.min(categories.length,
8)) // Limit for space
Rectangle {
height: 36
width: (parent.width - (Math.min(categories.length, 8) - 1) * Theme.spacingS) / Math.min(categories.length, 8)
width: (parent.width - (Math.min(categories.length,
8) - 1) * Theme.spacingS) / Math.min(
categories.length, 8)
radius: Theme.cornerRadiusLarge
color: selectedCategory === modelData ? Theme.primary : "transparent"
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.3)
StyledText {
anchors.centerIn: parent
@@ -43,15 +49,12 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
selectedCategory = modelData;
categorySelected(modelData);
selectedCategory = modelData
categorySelected(modelData)
}
}
}
}
}
Column {
@@ -66,16 +69,20 @@ Item {
spacing: Theme.spacingS
Repeater {
model: parent.topRowCategories.filter((cat) => {
return categories.includes(cat);
model: parent.topRowCategories.filter(cat => {
return categories.includes(cat)
})
Rectangle {
height: 36
width: (parent.width - (parent.topRowCategories.length - 1) * Theme.spacingS) / parent.topRowCategories.length
width: (parent.width - (parent.topRowCategories.length - 1)
* Theme.spacingS) / parent.topRowCategories.length
radius: Theme.cornerRadiusLarge
color: selectedCategory === modelData ? Theme.primary : "transparent"
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.3)
StyledText {
anchors.centerIn: parent
@@ -91,15 +98,12 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
selectedCategory = modelData;
categorySelected(modelData);
selectedCategory = modelData
categorySelected(modelData)
}
}
}
}
}
Row {
@@ -109,16 +113,21 @@ Item {
spacing: Theme.spacingS
Repeater {
model: parent.bottomRowCategories.filter((cat) => {
return categories.includes(cat);
model: parent.bottomRowCategories.filter(cat => {
return categories.includes(
cat)
})
Rectangle {
height: 36
width: (parent.width - (parent.bottomRowCategories.length - 1) * Theme.spacingS) / parent.bottomRowCategories.length
width: (parent.width - (parent.bottomRowCategories.length - 1)
* Theme.spacingS) / parent.bottomRowCategories.length
radius: Theme.cornerRadiusLarge
color: selectedCategory === modelData ? Theme.primary : "transparent"
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.3)
StyledText {
anchors.centerIn: parent
@@ -134,17 +143,12 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
selectedCategory = modelData;
categorySelected(modelData);
selectedCategory = modelData
categorySelected(modelData)
}
}
}
}
}
}
}

View File

@@ -20,18 +20,18 @@ PanelWindow {
interval: BrightnessService.ddcAvailable ? 500 : 50
repeat: false
onTriggered: {
BrightnessService.setBrightnessInternal(pendingValue);
BrightnessService.setBrightnessInternal(pendingValue)
}
}
function show() {
root.brightnessPopupVisible = true;
hideTimer.restart();
root.brightnessPopupVisible = true
hideTimer.restart()
}
function resetHideTimer() {
if (root.brightnessPopupVisible)
hideTimer.restart();
hideTimer.restart()
}
screen: modelData
@@ -55,15 +55,15 @@ PanelWindow {
repeat: false
onTriggered: {
if (!brightnessPopup.containsMouse)
root.brightnessPopupVisible = false;
root.brightnessPopupVisible = false
else
hideTimer.restart();
hideTimer.restart()
}
}
Connections {
function onBrightnessChanged() {
root.show();
root.show()
}
target: BrightnessService
@@ -81,7 +81,8 @@ PanelWindow {
anchors.bottomMargin: Theme.spacingM
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
opacity: root.brightnessPopupVisible ? 1 : 0
scale: root.brightnessPopupVisible ? 1 : 0.9
@@ -110,8 +111,9 @@ PanelWindow {
DankIcon {
anchors.centerIn: parent
name: BrightnessService.brightnessLevel < 30 ? "brightness_low" :
BrightnessService.brightnessLevel < 70 ? "brightness_medium" : "brightness_high"
name: BrightnessService.brightnessLevel
< 30 ? "brightness_low" : BrightnessService.brightnessLevel
< 70 ? "brightness_medium" : "brightness_high"
size: Theme.iconSize
color: Theme.primary
}
@@ -131,25 +133,25 @@ PanelWindow {
unit: "%"
Component.onCompleted: {
if (BrightnessService.brightnessAvailable)
value = BrightnessService.brightnessLevel;
value = BrightnessService.brightnessLevel
}
onSliderValueChanged: function(newValue) {
onSliderValueChanged: function (newValue) {
if (BrightnessService.brightnessAvailable) {
brightnessDebounceTimer.pendingValue = newValue;
brightnessDebounceTimer.restart();
root.resetHideTimer();
brightnessDebounceTimer.pendingValue = newValue
brightnessDebounceTimer.restart()
root.resetHideTimer()
}
}
onSliderDragFinished: function(finalValue) {
onSliderDragFinished: function (finalValue) {
if (BrightnessService.brightnessAvailable) {
brightnessDebounceTimer.stop();
BrightnessService.setBrightnessInternal(finalValue);
brightnessDebounceTimer.stop()
BrightnessService.setBrightnessInternal(finalValue)
}
}
Connections {
function onBrightnessChanged() {
brightnessSlider.value = BrightnessService.brightnessLevel;
brightnessSlider.value = BrightnessService.brightnessLevel
}
target: BrightnessService

View File

@@ -13,31 +13,33 @@ Column {
function loadEventsForMonth() {
if (!CalendarService || !CalendarService.khalAvailable)
return ;
return
let firstDay = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1);
let dayOfWeek = firstDay.getDay();
let startDate = new Date(firstDay);
startDate.setDate(startDate.getDate() - dayOfWeek - 7); // Extra week padding
let lastDay = new Date(displayDate.getFullYear(), displayDate.getMonth() + 1, 0);
let endDate = new Date(lastDay);
endDate.setDate(endDate.getDate() + (6 - lastDay.getDay()) + 7); // Extra week padding
CalendarService.loadEvents(startDate, endDate);
let firstDay = new Date(displayDate.getFullYear(),
displayDate.getMonth(), 1)
let dayOfWeek = firstDay.getDay()
let startDate = new Date(firstDay)
startDate.setDate(startDate.getDate() - dayOfWeek - 7) // Extra week padding
let lastDay = new Date(displayDate.getFullYear(),
displayDate.getMonth() + 1, 0)
let endDate = new Date(lastDay)
endDate.setDate(endDate.getDate() + (6 - lastDay.getDay(
)) + 7) // Extra week padding
CalendarService.loadEvents(startDate, endDate)
}
spacing: Theme.spacingM
onDisplayDateChanged: {
loadEventsForMonth();
loadEventsForMonth()
}
Component.onCompleted: {
loadEventsForMonth();
loadEventsForMonth()
}
Connections {
function onKhalAvailableChanged() {
if (CalendarService && CalendarService.khalAvailable)
loadEventsForMonth();
loadEventsForMonth()
}
target: CalendarService
@@ -52,7 +54,10 @@ Column {
width: 40
height: 40
radius: Theme.cornerRadius
color: prevMonthArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: prevMonthArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
DankIcon {
anchors.centerIn: parent
@@ -68,12 +73,11 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
let newDate = new Date(displayDate);
newDate.setMonth(newDate.getMonth() - 1);
displayDate = newDate;
let newDate = new Date(displayDate)
newDate.setMonth(newDate.getMonth() - 1)
displayDate = newDate
}
}
}
StyledText {
@@ -91,7 +95,10 @@ Column {
width: 40
height: 40
radius: Theme.cornerRadius
color: nextMonthArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: nextMonthArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
DankIcon {
anchors.centerIn: parent
@@ -107,14 +114,12 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
let newDate = new Date(displayDate);
newDate.setMonth(newDate.getMonth() + 1);
displayDate = newDate;
let newDate = new Date(displayDate)
newDate.setMonth(newDate.getMonth() + 1)
displayDate = newDate
}
}
}
}
Row {
@@ -133,22 +138,20 @@ Column {
anchors.centerIn: parent
text: modelData
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
font.weight: Font.Medium
}
}
}
}
Grid {
property date firstDay: {
let date = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1);
let dayOfWeek = date.getDay();
date.setDate(date.getDate() - dayOfWeek);
return date;
let date = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1)
let dayOfWeek = date.getDay()
date.setDate(date.getDate() - dayOfWeek)
return date
}
width: parent.width
@@ -161,13 +164,16 @@ Column {
Rectangle {
property date dayDate: {
let date = new Date(parent.firstDay);
date.setDate(date.getDate() + index);
return date;
let date = new Date(parent.firstDay)
date.setDate(date.getDate() + index)
return date
}
property bool isCurrentMonth: dayDate.getMonth() === displayDate.getMonth()
property bool isToday: dayDate.toDateString() === new Date().toDateString()
property bool isSelected: dayDate.toDateString() === selectedDate.toDateString()
property bool isCurrentMonth: dayDate.getMonth(
) === displayDate.getMonth()
property bool isToday: dayDate.toDateString(
) === new Date().toDateString()
property bool isSelected: dayDate.toDateString(
) === selectedDate.toDateString()
width: parent.width / 7
height: parent.height / 6
@@ -178,7 +184,11 @@ Column {
anchors.centerIn: parent
width: parent.width - 4
height: parent.height - 4
color: isSelected ? Theme.primary : isToday ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : dayArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
color: isSelected ? Theme.primary : isToday ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : dayArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadiusSmall
clip: true
@@ -195,14 +205,15 @@ Column {
anchors.fill: parent
radius: parent.radius
visible: CalendarService && CalendarService.khalAvailable && CalendarService.hasEventsForDate(dayDate)
visible: CalendarService && CalendarService.khalAvailable
&& CalendarService.hasEventsForDate(dayDate)
opacity: {
if (isSelected)
return 0.9;
return 0.9
else if (isToday)
return 0.8;
return 0.8
else
return 0.6;
return 0.6
}
gradient: Gradient {
@@ -215,11 +226,11 @@ Column {
position: 0.9
color: {
if (isSelected)
return Qt.lighter(Theme.primary, 1.3);
return Qt.lighter(Theme.primary, 1.3)
else if (isToday)
return Theme.primary;
return Theme.primary
else
return Theme.primary;
return Theme.primary
}
}
@@ -227,14 +238,13 @@ Column {
position: 1
color: {
if (isSelected)
return Qt.lighter(Theme.primary, 1.3);
return Qt.lighter(Theme.primary, 1.3)
else if (isToday)
return Theme.primary;
return Theme.primary
else
return Theme.primary;
return Theme.primary
}
}
}
Behavior on opacity {
@@ -242,11 +252,8 @@ Column {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
MouseArea {
@@ -256,14 +263,10 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
selectedDate = dayDate;
selectedDate = dayDate
}
}
}
}
}
}

View File

@@ -22,30 +22,29 @@ PanelWindow {
property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) {
triggerX = x;
triggerY = y;
triggerWidth = width;
triggerSection = section;
triggerScreen = screen;
triggerX = x
triggerY = y
triggerWidth = width
triggerSection = section
triggerScreen = screen
}
visible: internalVisible
screen: triggerScreen
onCalendarVisibleChanged: {
if (calendarVisible) {
internalVisible = true;
internalVisible = true
Qt.callLater(() => {
internalVisible = true;
calendarGrid.loadEventsForMonth();
});
internalVisible = true
calendarGrid.loadEventsForMonth()
})
} else {
internalVisible = false;
internalVisible = false
}
}
onVisibleChanged: {
if (visible && calendarGrid)
calendarGrid.loadEventsForMonth();
calendarGrid.loadEventsForMonth()
}
implicitWidth: 480
implicitHeight: 600
@@ -64,61 +63,69 @@ PanelWindow {
Rectangle {
id: mainContainer
readonly property real targetWidth: Math.min((root.screen ? root.screen.width : Screen.width) * 0.9, 600)
readonly property real targetWidth: Math.min(
(root.screen ? root.screen.width : Screen.width) * 0.9,
600)
function calculateWidth() {
let baseWidth = 320;
let baseWidth = 320
if (leftWidgets.hasAnyWidgets)
return Math.min(parent.width * 0.9, 600);
return Math.min(parent.width * 0.9, 600)
return Math.min(parent.width * 0.7, 400);
return Math.min(parent.width * 0.7, 400)
}
function calculateHeight() {
let contentHeight = Theme.spacingM * 2; // margins
let widgetHeight = 160;
widgetHeight += 140 + Theme.spacingM;
let calendarHeight = 300;
let mainRowHeight = Math.max(widgetHeight, calendarHeight);
contentHeight += mainRowHeight + Theme.spacingM;
let contentHeight = Theme.spacingM * 2
// margins
let widgetHeight = 160
widgetHeight += 140 + Theme.spacingM
let calendarHeight = 300
let mainRowHeight = Math.max(widgetHeight, calendarHeight)
contentHeight += mainRowHeight + Theme.spacingM
if (CalendarService && CalendarService.khalAvailable) {
let hasEvents = events.selectedDateEvents && events.selectedDateEvents.length > 0;
let eventsHeight = hasEvents ? Math.min(300, 80 + events.selectedDateEvents.length * 60) : 120;
contentHeight += eventsHeight;
let hasEvents = events.selectedDateEvents
&& events.selectedDateEvents.length > 0
let eventsHeight = hasEvents ? Math.min(
300,
80 + events.selectedDateEvents.length * 60) : 120
contentHeight += eventsHeight
} else {
contentHeight -= Theme.spacingM;
contentHeight -= Theme.spacingM
}
return Math.min(contentHeight, parent.height * 0.9);
return Math.min(contentHeight, parent.height * 0.9)
}
readonly property real calculatedX: {
var screenWidth = root.screen ? root.screen.width : Screen.width;
var screenWidth = root.screen ? root.screen.width : Screen.width
if (root.triggerSection === "center") {
return (screenWidth - targetWidth) / 2;
return (screenWidth - targetWidth) / 2
}
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2);
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2)
if (centerX >= Theme.spacingM && centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX;
if (centerX >= Theme.spacingM
&& centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX
}
if (centerX < Theme.spacingM) {
return Theme.spacingM;
return Theme.spacingM
}
if (centerX + targetWidth > screenWidth - Theme.spacingM) {
return screenWidth - targetWidth - Theme.spacingM;
return screenWidth - targetWidth - Theme.spacingM
}
return centerX;
return centerX
}
width: targetWidth
height: calculateHeight()
color: Theme.surfaceContainer
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
layer.enabled: true
opacity: calendarVisible ? 1 : 0
@@ -128,22 +135,19 @@ PanelWindow {
onOpacityChanged: {
if (opacity === 1)
Qt.callLater(() => {
height = calculateHeight();
});
height = calculateHeight()
})
}
Connections {
function onEventsByDateChanged() {
if (mainContainer.opacity === 1)
mainContainer.height = mainContainer.calculateHeight();
mainContainer.height = mainContainer.calculateHeight()
}
function onKhalAvailableChanged() {
if (mainContainer.opacity === 1)
mainContainer.height = mainContainer.calculateHeight();
mainContainer.height = mainContainer.calculateHeight()
}
target: CalendarService
@@ -153,8 +157,7 @@ PanelWindow {
Connections {
function onSelectedDateEventsChanged() {
if (mainContainer.opacity === 1)
mainContainer.height = mainContainer.calculateHeight();
mainContainer.height = mainContainer.calculateHeight()
}
target: events
@@ -163,7 +166,8 @@ PanelWindow {
Rectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g,
Theme.surfaceTint.b, 0.04)
radius: parent.radius
SequentialAnimation on opacity {
@@ -181,9 +185,7 @@ PanelWindow {
duration: Theme.extraLongDuration
easing.type: Theme.standardEasing
}
}
}
Column {
@@ -191,23 +193,25 @@ PanelWindow {
anchors.margins: Theme.spacingM
spacing: Theme.spacingM
focus: true
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
calendarVisible = false;
event.accepted = true;
calendarVisible = false
event.accepted = true
} else {
// Don't handle other keys - let them bubble up to modals
event.accepted = false;
event.accepted = false
}
}
Row {
width: parent.width
height: {
let widgetHeight = 160; // Media widget
widgetHeight += 140 + Theme.spacingM; // Weather/SystemInfo widget with spacing
let calendarHeight = 300; // Calendar
return Math.max(widgetHeight, calendarHeight);
let widgetHeight = 160
// Media widget
widgetHeight += 140 + Theme.spacingM // Weather/SystemInfo widget with spacing
let calendarHeight = 300
// Calendar
return Math.max(widgetHeight, calendarHeight)
}
spacing: Theme.spacingM
@@ -238,15 +242,17 @@ PanelWindow {
height: 140
visible: !SettingsData.weatherEnabled
}
}
Rectangle {
width: leftWidgets.hasAnyWidgets ? parent.width - leftWidgets.width - Theme.spacingM : parent.width
width: leftWidgets.hasAnyWidgets ? parent.width - leftWidgets.width
- Theme.spacingM : parent.width
height: parent.height
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.2)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
CalendarGrid {
@@ -255,9 +261,7 @@ PanelWindow {
anchors.fill: parent
anchors.margins: Theme.spacingS
}
}
}
Events {
@@ -266,7 +270,6 @@ PanelWindow {
width: parent.width
selectedDate: calendarGrid.selectedDate
}
}
Behavior on opacity {
@@ -275,7 +278,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
Behavior on scale {
@@ -284,7 +286,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
layer.effect: MultiEffect {
@@ -295,19 +296,17 @@ PanelWindow {
shadowColor: Qt.rgba(0, 0, 0, 0.15)
shadowOpacity: 0.15
}
}
MouseArea {
anchors.fill: parent
z: -1
enabled: calendarVisible
onClicked: function(mouse) {
var localPos = mapToItem(mainContainer, mouse.x, mouse.y);
if (localPos.x < 0 || localPos.x > mainContainer.width || localPos.y < 0 || localPos.y > mainContainer.height)
calendarVisible = false;
onClicked: function (mouse) {
var localPos = mapToItem(mainContainer, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > mainContainer.width || localPos.y < 0
|| localPos.y > mainContainer.height)
calendarVisible = false
}
}
}

View File

@@ -15,38 +15,41 @@ Rectangle {
function updateSelectedDateEvents() {
if (CalendarService && CalendarService.khalAvailable) {
let events = CalendarService.getEventsForDate(selectedDate);
selectedDateEvents = events;
let events = CalendarService.getEventsForDate(selectedDate)
selectedDateEvents = events
} else {
selectedDateEvents = [];
selectedDateEvents = []
}
}
onSelectedDateEventsChanged: {
eventsList.model = selectedDateEvents;
eventsList.model = selectedDateEvents
}
width: parent.width
height: shouldShow ? (hasEvents ? Math.min(300, 80 + selectedDateEvents.length * 60) : 120) : 0
height: shouldShow ? (hasEvents ? Math.min(
300,
80 + selectedDateEvents.length * 60) : 120) : 0
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.12)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1
visible: shouldShow
layer.enabled: true
Component.onCompleted: {
updateSelectedDateEvents();
updateSelectedDateEvents()
}
onSelectedDateChanged: {
updateSelectedDateEvents();
updateSelectedDateEvents()
}
Connections {
function onEventsByDateChanged() {
updateSelectedDateEvents();
updateSelectedDateEvents()
}
function onKhalAvailableChanged() {
updateSelectedDateEvents();
updateSelectedDateEvents()
}
target: CalendarService
@@ -70,13 +73,17 @@ Rectangle {
}
StyledText {
text: hasEvents ? (Qt.formatDate(selectedDate, "MMM d") + " • " + (selectedDateEvents.length === 1 ? "1 event" : selectedDateEvents.length + " events")) : Qt.formatDate(selectedDate, "MMM d")
text: hasEvents ? (Qt.formatDate(
selectedDate,
"MMM d") + " • " + (selectedDateEvents.length
=== 1 ? "1 event" : selectedDateEvents.length
+ " events")) : Qt.formatDate(
selectedDate, "MMM d")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
@@ -87,18 +94,19 @@ Rectangle {
DankIcon {
name: "event_busy"
size: Theme.iconSize + 8
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: "No events"
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)
font.weight: Font.Normal
anchors.horizontalCenter: parent.horizontalCenter
}
}
DankListView {
@@ -128,7 +136,7 @@ Rectangle {
WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
property real momentum: 0
onWheel: (event) => {
onWheel: event => {
if (event.pixelDelta.y !== 0) {
// Touchpad with pixel delta
momentum = event.pixelDelta.y * 1.8
@@ -138,7 +146,9 @@ Rectangle {
}
let newY = parent.contentY - momentum
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY))
newY = Math.max(0,
Math.min(parent.contentHeight - parent.height,
newY))
parent.contentY = newY
momentum *= 0.92 // Decay for smooth momentum
event.accepted = true
@@ -146,7 +156,8 @@ Rectangle {
}
ScrollBar.vertical: ScrollBar {
policy: eventsList.contentHeight > eventsList.height ? ScrollBar.AsNeeded : ScrollBar.AlwaysOff
policy: eventsList.contentHeight
> eventsList.height ? ScrollBar.AsNeeded : ScrollBar.AlwaysOff
}
Behavior on opacity {
@@ -154,7 +165,6 @@ Rectangle {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
delegate: Rectangle {
@@ -163,17 +173,21 @@ Rectangle {
radius: Theme.cornerRadius
color: {
if (modelData.url && eventMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
return Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
else if (eventMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06);
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.06);
return Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.06)
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.06)
}
border.color: {
if (modelData.url && eventMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3);
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
else if (eventMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15);
return "transparent";
return Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.15)
return "transparent"
}
border.width: 1
@@ -223,29 +237,33 @@ Rectangle {
DankIcon {
name: "schedule"
size: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (modelData.allDay) {
return "All day";
return "All day"
} else {
let timeFormat = SettingsData.use24HourClock ? "H:mm" : "h:mm AP";
let startTime = Qt.formatTime(modelData.start, timeFormat);
if (modelData.start.toDateString() !== modelData.end.toDateString() || modelData.start.getTime() !== modelData.end.getTime())
return startTime + " " + Qt.formatTime(modelData.end, timeFormat);
let timeFormat = SettingsData.use24HourClock ? "H:mm" : "h:mm AP"
let startTime = Qt.formatTime(modelData.start, timeFormat)
if (modelData.start.toDateString(
) !== modelData.end.toDateString()
|| modelData.start.getTime() !== modelData.end.getTime())
return startTime + " " + Qt.formatTime(modelData.end,
timeFormat)
return startTime;
return startTime
}
}
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -259,24 +277,23 @@ Rectangle {
DankIcon {
name: "location_on"
size: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: modelData.location
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
maximumLineCount: 1
width: Math.min(implicitWidth, 200)
}
}
}
}
MouseArea {
@@ -289,8 +306,7 @@ Rectangle {
onClicked: {
if (modelData.url && modelData.url !== "") {
if (Qt.openUrlExternally(modelData.url) === false)
console.warn("Failed to open URL: " + modelData.url);
console.warn("Failed to open URL: " + modelData.url)
}
}
}
@@ -300,7 +316,6 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on border.color {
@@ -308,11 +323,8 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
layer.effect: MultiEffect {
@@ -329,7 +341,5 @@ Rectangle {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}

View File

@@ -18,19 +18,21 @@ Rectangle {
property real currentPosition: 0
function ratio() {
return activePlayer && activePlayer.length > 0 ? currentPosition / activePlayer.length : 0;
return activePlayer
&& activePlayer.length > 0 ? currentPosition / activePlayer.length : 0
}
onActivePlayerChanged: {
if (!activePlayer)
updateTimer.start();
updateTimer.start()
else
updateTimer.stop();
updateTimer.stop()
}
width: parent.width
height: parent.height
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.4)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1
layer.enabled: true
@@ -40,18 +42,22 @@ Rectangle {
interval: 2000
running: {
return (!activePlayer) || (activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing && activePlayer.length > 0 && !progressMouseArea.isSeeking);
return (!activePlayer)
|| (activePlayer
&& activePlayer.playbackState === MprisPlaybackState.Playing
&& activePlayer.length > 0 && !progressMouseArea.isSeeking)
}
repeat: true
onTriggered: {
if (!activePlayer) {
lastValidTitle = "";
lastValidArtist = "";
lastValidAlbum = "";
lastValidArtUrl = "";
stop(); // Stop after clearing cache
} else if (activePlayer.playbackState === MprisPlaybackState.Playing && !progressMouseArea.isSeeking) {
currentPosition = activePlayer.position;
lastValidTitle = ""
lastValidArtist = ""
lastValidAlbum = ""
lastValidArtUrl = ""
stop() // Stop after clearing cache
} else if (activePlayer.playbackState === MprisPlaybackState.Playing
&& !progressMouseArea.isSeeking) {
currentPosition = activePlayer.position
}
}
}
@@ -59,16 +65,15 @@ Rectangle {
Connections {
function onPositionChanged() {
if (!progressMouseArea.isSeeking)
currentPosition = activePlayer.position;
currentPosition = activePlayer.position
}
function onPostTrackChanged() {
currentPosition = activePlayer && activePlayer.position || 0;
currentPosition = activePlayer && activePlayer.position || 0
}
function onTrackTitleChanged() {
currentPosition = activePlayer && activePlayer.position || 0;
currentPosition = activePlayer && activePlayer.position || 0
}
target: activePlayer
@@ -81,28 +86,32 @@ Rectangle {
Column {
anchors.centerIn: parent
spacing: Theme.spacingS
visible: (!activePlayer && !lastValidTitle) || (activePlayer && activePlayer.trackTitle === "" && lastValidTitle === "")
visible: (!activePlayer && !lastValidTitle)
|| (activePlayer && activePlayer.trackTitle === ""
&& lastValidTitle === "")
DankIcon {
name: "music_note"
size: Theme.iconSize + 8
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.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: "No Media Playing"
font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.horizontalCenter: parent.horizontalCenter
}
}
Column {
anchors.fill: parent
spacing: Theme.spacingS
visible: activePlayer && activePlayer.trackTitle !== "" || lastValidTitle !== ""
visible: activePlayer && activePlayer.trackTitle !== ""
|| lastValidTitle !== ""
Row {
width: parent.width
@@ -113,7 +122,8 @@ Rectangle {
width: 60
height: 60
radius: Theme.cornerRadius
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)
Item {
anchors.fill: parent
@@ -123,11 +133,11 @@ Rectangle {
id: albumArt
anchors.fill: parent
source: activePlayer && activePlayer.trackArtUrl || lastValidArtUrl || ""
source: activePlayer && activePlayer.trackArtUrl
|| lastValidArtUrl || ""
onSourceChanged: {
if (activePlayer && activePlayer.trackArtUrl)
lastValidArtUrl = activePlayer.trackArtUrl;
lastValidArtUrl = activePlayer.trackArtUrl
}
fillMode: Image.PreserveAspectCrop
smooth: true
@@ -145,11 +155,8 @@ Rectangle {
size: 28
color: Theme.surfaceVariantText
}
}
}
}
Column {
@@ -158,11 +165,11 @@ Rectangle {
spacing: Theme.spacingXS
StyledText {
text: activePlayer && activePlayer.trackTitle || lastValidTitle || "Unknown Track"
text: activePlayer && activePlayer.trackTitle || lastValidTitle
|| "Unknown Track"
onTextChanged: {
if (activePlayer && activePlayer.trackTitle)
lastValidTitle = activePlayer.trackTitle;
lastValidTitle = activePlayer.trackTitle
}
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Bold
@@ -174,14 +181,15 @@ Rectangle {
}
StyledText {
text: activePlayer && activePlayer.trackArtist || lastValidArtist || "Unknown Artist"
text: activePlayer && activePlayer.trackArtist || lastValidArtist
|| "Unknown Artist"
onTextChanged: {
if (activePlayer && activePlayer.trackArtist)
lastValidArtist = activePlayer.trackArtist;
lastValidArtist = activePlayer.trackArtist
}
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.8)
width: parent.width
elide: Text.ElideRight
wrapMode: Text.NoWrap
@@ -189,23 +197,22 @@ Rectangle {
}
StyledText {
text: activePlayer && activePlayer.trackAlbum || lastValidAlbum || ""
text: activePlayer && activePlayer.trackAlbum
|| lastValidAlbum || ""
onTextChanged: {
if (activePlayer && activePlayer.trackAlbum)
lastValidAlbum = activePlayer.trackAlbum;
lastValidAlbum = activePlayer.trackAlbum
}
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
width: parent.width
elide: Text.ElideRight
wrapMode: Text.NoWrap
maximumLineCount: 1
visible: text.length > 0
}
}
}
Item {
@@ -220,7 +227,8 @@ Rectangle {
width: parent.width
height: 6
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
anchors.verticalCenter: parent.verticalCenter
@@ -236,9 +244,7 @@ Rectangle {
NumberAnimation {
duration: 100
}
}
}
Rectangle {
@@ -250,20 +256,19 @@ Rectangle {
color: Theme.primary
border.color: Qt.lighter(Theme.primary, 1.3)
border.width: 1
x: Math.max(0, Math.min(parent.width - width, progressFill.width - width / 2))
x: Math.max(0, Math.min(parent.width - width,
progressFill.width - width / 2))
anchors.verticalCenter: parent.verticalCenter
visible: activePlayer && activePlayer.length > 0
scale: progressMouseArea.containsMouse || progressMouseArea.pressed ? 1.2 : 1
scale: progressMouseArea.containsMouse
|| progressMouseArea.pressed ? 1.2 : 1
Behavior on scale {
NumberAnimation {
duration: 150
}
}
}
}
MouseArea {
@@ -274,34 +279,39 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
enabled: activePlayer && activePlayer.length > 0 && activePlayer.canSeek
enabled: activePlayer && activePlayer.length > 0
&& activePlayer.canSeek
preventStealing: true
onPressed: function(mouse) {
isSeeking = true;
onPressed: function (mouse) {
isSeeking = true
if (activePlayer && activePlayer.length > 0) {
let ratio = Math.max(0, Math.min(1, mouse.x / progressBarBackground.width));
let seekPosition = ratio * activePlayer.length;
activePlayer.position = seekPosition;
currentPosition = seekPosition;
let ratio = Math.max(0, Math.min(
1, mouse.x / progressBarBackground.width))
let seekPosition = ratio * activePlayer.length
activePlayer.position = seekPosition
currentPosition = seekPosition
}
}
onReleased: {
isSeeking = false;
isSeeking = false
}
onPositionChanged: function(mouse) {
if (pressed && isSeeking && activePlayer && activePlayer.length > 0) {
let ratio = Math.max(0, Math.min(1, mouse.x / progressBarBackground.width));
let seekPosition = ratio * activePlayer.length;
activePlayer.position = seekPosition;
currentPosition = seekPosition;
onPositionChanged: function (mouse) {
if (pressed && isSeeking && activePlayer
&& activePlayer.length > 0) {
let ratio = Math.max(0, Math.min(
1, mouse.x / progressBarBackground.width))
let seekPosition = ratio * activePlayer.length
activePlayer.position = seekPosition
currentPosition = seekPosition
}
}
onClicked: function(mouse) {
onClicked: function (mouse) {
if (activePlayer && activePlayer.length > 0) {
let ratio = Math.max(0, Math.min(1, mouse.x / progressBarBackground.width));
let seekPosition = ratio * activePlayer.length;
activePlayer.position = seekPosition;
currentPosition = seekPosition;
let ratio = Math.max(0, Math.min(
1, mouse.x / progressBarBackground.width))
let seekPosition = ratio * activePlayer.length
activePlayer.position = seekPosition
currentPosition = seekPosition
}
}
}
@@ -316,20 +326,21 @@ Rectangle {
enabled: progressMouseArea.isSeeking
visible: false
preventStealing: true
onPositionChanged: function(mouse) {
if (progressMouseArea.isSeeking && activePlayer && activePlayer.length > 0) {
let globalPos = mapToItem(progressBarBackground, mouse.x, mouse.y);
let ratio = Math.max(0, Math.min(1, globalPos.x / progressBarBackground.width));
let seekPosition = ratio * activePlayer.length;
activePlayer.position = seekPosition;
currentPosition = seekPosition;
onPositionChanged: function (mouse) {
if (progressMouseArea.isSeeking && activePlayer
&& activePlayer.length > 0) {
let globalPos = mapToItem(progressBarBackground, mouse.x, mouse.y)
let ratio = Math.max(
0, Math.min(1, globalPos.x / progressBarBackground.width))
let seekPosition = ratio * activePlayer.length
activePlayer.position = seekPosition
currentPosition = seekPosition
}
}
onReleased: {
progressMouseArea.isSeeking = false;
progressMouseArea.isSeeking = false
}
}
}
Item {
@@ -346,7 +357,10 @@ Rectangle {
width: 28
height: 28
radius: 14
color: prevBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent"
color: prevBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.12) : "transparent"
DankIcon {
anchors.centerIn: parent
@@ -363,17 +377,16 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!activePlayer)
return ;
return
if (currentPosition > 8 && activePlayer.canSeek) {
activePlayer.position = 0;
currentPosition = 0;
activePlayer.position = 0
currentPosition = 0
} else {
activePlayer.previous();
activePlayer.previous()
}
}
}
}
Rectangle {
@@ -384,7 +397,8 @@ Rectangle {
DankIcon {
anchors.centerIn: parent
name: activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow"
name: activePlayer && activePlayer.playbackState
=== MprisPlaybackState.Playing ? "pause" : "play_arrow"
size: 20
color: Theme.background
}
@@ -395,14 +409,16 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: activePlayer && activePlayer.togglePlaying()
}
}
Rectangle {
width: 28
height: 28
radius: 14
color: nextBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent"
color: nextBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.12) : "transparent"
DankIcon {
anchors.centerIn: parent
@@ -419,15 +435,10 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: activePlayer && activePlayer.next()
}
}
}
}
}
}
layer.effect: MultiEffect {
@@ -438,5 +449,4 @@ Rectangle {
shadowColor: Qt.rgba(0, 0, 0, 0.1)
shadowOpacity: 0.1
}
}

View File

@@ -7,7 +7,8 @@ Rectangle {
id: root
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.4)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1
@@ -46,13 +47,12 @@ Rectangle {
StyledText {
text: SysMonitorService.distribution + " • " + SysMonitorService.architecture
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
width: parent.width
elide: Text.ElideRight
}
}
}
Rectangle {
@@ -82,19 +82,20 @@ Rectangle {
}
StyledText {
text: SysMonitorService.processCount + " proc, " + SysMonitorService.threadCount + " threads"
text: SysMonitorService.processCount + " proc, "
+ SysMonitorService.threadCount + " threads"
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.8)
width: parent.width
elide: Text.ElideRight
}
}
}
function formatUptime(uptime) {
if (!uptime) return "0m"
if (!uptime)
return "0m"
// Parse the uptime string - handle formats like "1 week, 4 days, 3:45" or "4 days, 3:45" or "3:45"
var uptimeStr = uptime.toString().trim()
@@ -130,7 +131,5 @@ Rectangle {
// Fallback - return as is but truncated
return uptimeStr.length > 8 ? uptimeStr.substring(0, 8) + "…" : uptimeStr
}
}

View File

@@ -11,7 +11,8 @@ Rectangle {
width: parent.width
height: parent.height
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.4)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1
layer.enabled: true
@@ -23,29 +24,32 @@ Rectangle {
Column {
anchors.centerIn: parent
spacing: Theme.spacingS
visible: !WeatherService.weather.available || WeatherService.weather.temp === 0
visible: !WeatherService.weather.available
|| WeatherService.weather.temp === 0
DankIcon {
name: "cloud_off"
size: Theme.iconSize + 8
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.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: "No Weather Data"
font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.horizontalCenter: parent.horizontalCenter
}
}
Column {
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingS
visible: WeatherService.weather.available && WeatherService.weather.temp !== 0
visible: WeatherService.weather.available
&& WeatherService.weather.temp !== 0
Item {
width: parent.width
@@ -67,7 +71,8 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp) + "°" + (SettingsData.useFahrenheit ? "F" : "C")
text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp)
+ "°" + (SettingsData.useFahrenheit ? "F" : "C")
font.pixelSize: Theme.fontSizeXLarge
color: Theme.surfaceText
font.weight: Font.Light
@@ -78,25 +83,21 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (WeatherService.weather.available)
SettingsData.setTemperatureUnit(!SettingsData.useFahrenheit);
SettingsData.setTemperatureUnit(!SettingsData.useFahrenheit)
}
enabled: WeatherService.weather.available
}
}
StyledText {
text: WeatherService.weather.city || ""
font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: text.length > 0
}
}
}
}
Grid {
@@ -120,7 +121,6 @@ Rectangle {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -139,7 +139,6 @@ Rectangle {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -158,7 +157,6 @@ Rectangle {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -177,11 +175,8 @@ Rectangle {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
layer.effect: MultiEffect {
@@ -192,5 +187,4 @@ Rectangle {
shadowColor: Qt.rgba(0, 0, 0, 0.1)
shadowOpacity: 0.1
}
}

View File

@@ -11,7 +11,8 @@ import qs.Widgets
Column {
id: root
property string currentSinkDisplayName: AudioService.sink ? AudioService.displayName(AudioService.sink) : ""
property string currentSinkDisplayName: AudioService.sink ? AudioService.displayName(
AudioService.sink) : ""
width: parent.width
spacing: Theme.spacingM
@@ -28,7 +29,8 @@ Column {
height: 35
radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.3)
border.width: 1
visible: AudioService.sink !== null
@@ -50,34 +52,33 @@ Column {
color: Theme.primary
font.weight: Font.Medium
}
}
}
Repeater {
model: {
if (!Pipewire.ready || !Pipewire.nodes || !Pipewire.nodes.values)
return [];
return []
let sinks = [];
for (let i = 0; i < Pipewire.nodes.values.length; i++) {
let node = Pipewire.nodes.values[i];
let sinks = []
for (var i = 0; i < Pipewire.nodes.values.length; i++) {
let node = Pipewire.nodes.values[i]
if (!node || node.isStream)
continue;
continue
if ((node.type & PwNodeType.AudioSink) === PwNodeType.AudioSink)
sinks.push(node);
sinks.push(node)
}
return sinks;
return sinks
}
Rectangle {
width: parent.width
height: 50
radius: Theme.cornerRadius
color: deviceArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (modelData === AudioService.sink ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
color: deviceArea.containsMouse ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.08) : (modelData === AudioService.sink ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: modelData === AudioService.sink ? Theme.primary : "transparent"
border.width: 1
@@ -90,13 +91,13 @@ Column {
DankIcon {
name: {
if (modelData.name.includes("bluez"))
return "headset";
return "headset"
else if (modelData.name.includes("hdmi"))
return "tv";
return "tv"
else if (modelData.name.includes("usb"))
return "headset";
return "headset"
else
return "speaker";
return "speaker"
}
size: Theme.iconSize
color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText
@@ -116,18 +117,19 @@ Column {
StyledText {
text: {
if (AudioService.subtitle(modelData.name) && AudioService.subtitle(modelData.name) !== "")
return AudioService.subtitle(modelData.name) + (modelData === AudioService.sink ? " • Selected" : "");
if (AudioService.subtitle(modelData.name)
&& AudioService.subtitle(modelData.name) !== "")
return AudioService.subtitle(
modelData.name) + (modelData === AudioService.sink ? " • Selected" : "")
else
return modelData === AudioService.sink ? "Selected" : "";
return modelData === AudioService.sink ? "Selected" : ""
}
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: text !== ""
}
}
}
MouseArea {
@@ -138,13 +140,9 @@ Column {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData)
Pipewire.preferredDefaultAudioSink = modelData;
Pipewire.preferredDefaultAudioSink = modelData
}
}
}
}
}

View File

@@ -11,7 +11,8 @@ import qs.Widgets
Column {
id: root
property string currentSourceDisplayName: AudioService.source ? AudioService.displayName(AudioService.source) : ""
property string currentSourceDisplayName: AudioService.source ? AudioService.displayName(
AudioService.source) : ""
width: parent.width
spacing: Theme.spacingM
@@ -28,7 +29,8 @@ Column {
height: 35
radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.3)
border.width: 1
visible: AudioService.source !== null
@@ -50,34 +52,34 @@ Column {
color: Theme.primary
font.weight: Font.Medium
}
}
}
Repeater {
model: {
if (!Pipewire.ready || !Pipewire.nodes || !Pipewire.nodes.values)
return [];
return []
let sources = [];
for (let i = 0; i < Pipewire.nodes.values.length; i++) {
let node = Pipewire.nodes.values[i];
let sources = []
for (var i = 0; i < Pipewire.nodes.values.length; i++) {
let node = Pipewire.nodes.values[i]
if (!node || node.isStream)
continue;
if ((node.type & PwNodeType.AudioSource) === PwNodeType.AudioSource && !node.name.includes(".monitor"))
sources.push(node);
continue
if ((node.type & PwNodeType.AudioSource) === PwNodeType.AudioSource
&& !node.name.includes(".monitor"))
sources.push(node)
}
return sources;
return sources
}
Rectangle {
width: parent.width
height: 50
radius: Theme.cornerRadius
color: sourceArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (modelData === AudioService.source ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
color: sourceArea.containsMouse ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.08) : (modelData === AudioService.source ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: modelData === AudioService.source ? Theme.primary : "transparent"
border.width: 1
@@ -90,11 +92,11 @@ Column {
DankIcon {
name: {
if (modelData.name.includes("bluez"))
return "headset_mic";
return "headset_mic"
else if (modelData.name.includes("usb"))
return "headset_mic";
return "headset_mic"
else
return "mic";
return "mic"
}
size: Theme.iconSize
color: modelData === AudioService.source ? Theme.primary : Theme.surfaceText
@@ -114,18 +116,19 @@ Column {
StyledText {
text: {
if (AudioService.subtitle(modelData.name) && AudioService.subtitle(modelData.name) !== "")
return AudioService.subtitle(modelData.name) + (modelData === AudioService.source ? " • Selected" : "");
if (AudioService.subtitle(modelData.name)
&& AudioService.subtitle(modelData.name) !== "")
return AudioService.subtitle(
modelData.name) + (modelData === AudioService.source ? " • Selected" : "")
else
return modelData === AudioService.source ? "Selected" : "";
return modelData === AudioService.source ? "Selected" : ""
}
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: text !== ""
}
}
}
MouseArea {
@@ -136,13 +139,9 @@ Column {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData)
Pipewire.preferredDefaultAudioSource = modelData;
Pipewire.preferredDefaultAudioSource = modelData
}
}
}
}
}

View File

@@ -10,8 +10,12 @@ import qs.Widgets
Column {
id: root
property real micLevel: Math.min(100, (AudioService.source && AudioService.source.audio && AudioService.source.audio.volume * 100) || 0)
property bool micMuted: (AudioService.source && AudioService.source.audio && AudioService.source.audio.muted) || false
property real micLevel: Math.min(
100,
(AudioService.source && AudioService.source.audio
&& AudioService.source.audio.volume * 100) || 0)
property bool micMuted: (AudioService.source && AudioService.source.audio
&& AudioService.source.audio.muted) || false
width: parent.width
spacing: Theme.spacingM
@@ -39,11 +43,9 @@ Column {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (AudioService.source && AudioService.source.audio)
AudioService.source.audio.muted = !AudioService.source.audio.muted;
AudioService.source.audio.muted = !AudioService.source.audio.muted
}
}
}
Item {
@@ -59,7 +61,8 @@ Column {
width: parent.width
height: 8
radius: 4
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)
anchors.verticalCenter: parent.verticalCenter
Rectangle {
@@ -76,9 +79,7 @@ Column {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standardDecel
}
}
}
Rectangle {
@@ -90,7 +91,8 @@ Column {
color: Theme.primary
border.color: Qt.lighter(Theme.primary, 1.3)
border.width: 2
x: Math.max(0, Math.min(parent.width - width, micSliderFill.width - width / 2))
x: Math.max(0, Math.min(parent.width - width,
micSliderFill.width - width / 2))
anchors.verticalCenter: parent.verticalCenter
scale: micMouseArea.containsMouse || micMouseArea.pressed ? 1.2 : 1
@@ -106,7 +108,8 @@ Column {
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
visible: (micMouseArea.containsMouse && !root.micMuted) || micMouseArea.isDragging
visible: (micMouseArea.containsMouse && !root.micMuted)
|| micMouseArea.isDragging
opacity: visible ? 1 : 0
StyledText {
@@ -124,9 +127,7 @@ Column {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Behavior on scale {
@@ -135,11 +136,8 @@ Column {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standard
}
}
}
}
MouseArea {
@@ -151,34 +149,39 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
preventStealing: true
onPressed: (mouse) => {
isDragging = true;
let ratio = Math.max(0, Math.min(1, mouse.x / micSliderTrack.width));
let newMicLevel = Math.round(ratio * 100);
onPressed: mouse => {
isDragging = true
let ratio = Math.max(0, Math.min(
1, mouse.x / micSliderTrack.width))
let newMicLevel = Math.round(ratio * 100)
if (AudioService.source && AudioService.source.audio) {
AudioService.source.audio.muted = false;
AudioService.source.audio.volume = newMicLevel / 100;
AudioService.source.audio.muted = false
AudioService.source.audio.volume = newMicLevel / 100
}
}
onReleased: {
isDragging = false;
isDragging = false
}
onPositionChanged: (mouse) => {
onPositionChanged: mouse => {
if (pressed && isDragging) {
let ratio = Math.max(0, Math.min(1, mouse.x / micSliderTrack.width));
let newMicLevel = Math.max(0, Math.min(100, Math.round(ratio * 100)));
let ratio = Math.max(
0, Math.min(1, mouse.x / micSliderTrack.width))
let newMicLevel = Math.max(
0, Math.min(100, Math.round(ratio * 100)))
if (AudioService.source
&& AudioService.source.audio) {
AudioService.source.audio.muted = false
AudioService.source.audio.volume = newMicLevel / 100
}
}
}
onClicked: mouse => {
let ratio = Math.max(0, Math.min(
1, mouse.x / micSliderTrack.width))
let newMicLevel = Math.round(ratio * 100)
if (AudioService.source && AudioService.source.audio) {
AudioService.source.audio.muted = false;
AudioService.source.audio.volume = newMicLevel / 100;
}
}
}
onClicked: (mouse) => {
let ratio = Math.max(0, Math.min(1, mouse.x / micSliderTrack.width));
let newMicLevel = Math.round(ratio * 100);
if (AudioService.source && AudioService.source.audio) {
AudioService.source.audio.muted = false;
AudioService.source.audio.volume = newMicLevel / 100;
AudioService.source.audio.muted = false
AudioService.source.audio.volume = newMicLevel / 100
}
}
}
@@ -193,22 +196,27 @@ Column {
enabled: micMouseArea.isDragging
visible: false
preventStealing: true
onPositionChanged: (mouse) => {
onPositionChanged: mouse => {
if (micMouseArea.isDragging) {
let globalPos = mapToItem(micSliderTrack, mouse.x, mouse.y);
let ratio = Math.max(0, Math.min(1, globalPos.x / micSliderTrack.width));
let newMicLevel = Math.max(0, Math.min(100, Math.round(ratio * 100)));
if (AudioService.source && AudioService.source.audio) {
AudioService.source.audio.muted = false;
AudioService.source.audio.volume = newMicLevel / 100;
let globalPos = mapToItem(micSliderTrack,
mouse.x, mouse.y)
let ratio = Math.max(
0,
Math.min(1,
globalPos.x / micSliderTrack.width))
let newMicLevel = Math.max(
0, Math.min(100, Math.round(ratio * 100)))
if (AudioService.source
&& AudioService.source.audio) {
AudioService.source.audio.muted = false
AudioService.source.audio.volume = newMicLevel / 100
}
}
}
onReleased: {
micMouseArea.isDragging = false;
micMouseArea.isDragging = false
}
}
}
DankIcon {
@@ -217,7 +225,5 @@ Column {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}

View File

@@ -6,8 +6,12 @@ import qs.Widgets
Column {
id: root
property real volumeLevel: Math.min(100, (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) || 0)
property bool volumeMuted: (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.muted) || false
property real volumeLevel: Math.min(
100,
(AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.volume * 100) || 0)
property bool volumeMuted: (AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.muted) || false
width: parent.width
spacing: Theme.spacingM
@@ -32,31 +36,30 @@ Column {
unit: "%"
Connections {
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null
target: AudioService.sink
&& AudioService.sink.audio ? AudioService.sink.audio : null
function onVolumeChanged() {
volumeSlider.value = Math.round(AudioService.sink.audio.volume * 100);
volumeSlider.value = Math.round(AudioService.sink.audio.volume * 100)
}
}
Component.onCompleted: {
if (AudioService.sink && AudioService.sink.audio) {
value = Math.round(AudioService.sink.audio.volume * 100);
value = Math.round(AudioService.sink.audio.volume * 100)
}
let leftIconItem = volumeSlider.children[0].children[0];
let leftIconItem = volumeSlider.children[0].children[0]
if (leftIconItem) {
let mouseArea = Qt.createQmlObject(
'import QtQuick; import qs.Services; MouseArea { anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: { if (AudioService.sink && AudioService.sink.audio) AudioService.sink.audio.muted = !AudioService.sink.audio.muted; } }',
leftIconItem,
"dynamicMouseArea"
);
leftIconItem, "dynamicMouseArea")
}
}
onSliderValueChanged: (newValue) => {
onSliderValueChanged: newValue => {
if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = false;
AudioService.sink.audio.volume = newValue / 100;
AudioService.sink.audio.muted = false
AudioService.sink.audio.volume = newValue / 100
}
}
}

View File

@@ -28,8 +28,8 @@ Item {
}, {
"text": "Input"
}]
onTabClicked: function(index) {
audioTab.audioSubTab = index;
onTabClicked: function (index) {
audioTab.audioSubTab = index
}
}

View File

@@ -38,7 +38,12 @@ Column {
width: Math.max(100, scanText.contentWidth + Theme.spacingL * 2)
height: 32
radius: Theme.cornerRadius
color: scanArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
color: scanArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.08)
border.color: Theme.primary
border.width: 1
@@ -47,7 +52,8 @@ Column {
spacing: Theme.spacingXS
DankIcon {
name: BluetoothService.adapter && BluetoothService.adapter.discovering ? "stop" : "bluetooth_searching"
name: BluetoothService.adapter
&& BluetoothService.adapter.discovering ? "stop" : "bluetooth_searching"
size: Theme.iconSize - 6
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
@@ -56,13 +62,13 @@ Column {
StyledText {
id: scanText
text: BluetoothService.adapter && BluetoothService.adapter.discovering ? "Stop Scanning" : "Scan"
text: BluetoothService.adapter
&& BluetoothService.adapter.discovering ? "Stop Scanning" : "Scan"
font.pixelSize: Theme.fontSizeSmall
color: Theme.primary
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -73,13 +79,10 @@ Column {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (BluetoothService.adapter)
BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering;
BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering
}
}
}
}
Rectangle {
@@ -87,7 +90,8 @@ Column {
height: noteColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.08)
border.color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.2)
border.color: Qt.rgba(Theme.warning.r, Theme.warning.g,
Theme.warning.b, 0.2)
border.width: 1
Column {
@@ -115,30 +119,33 @@ Column {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: "Quickshell does not support pairing devices that require pin or confirmation."
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.8)
wrapMode: Text.WordWrap
width: parent.width
}
}
}
Repeater {
model: {
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices)
return [];
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering
|| !Bluetooth.devices)
return []
var filtered = Bluetooth.devices.values.filter((dev) => {
return dev && !dev.paired && !dev.pairing && !dev.blocked && (dev.signalStrength === undefined || dev.signalStrength > 0);
});
return BluetoothService.sortDevices(filtered);
var filtered = Bluetooth.devices.values.filter(dev => {
return dev && !dev.paired
&& !dev.pairing
&& !dev.blocked
&& (dev.signalStrength === undefined
|| dev.signalStrength > 0)
})
return BluetoothService.sortDevices(filtered)
}
Rectangle {
@@ -150,24 +157,28 @@ Column {
radius: Theme.cornerRadius
color: {
if (availableDeviceArea.containsMouse && !isBusy)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08);
return Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.08)
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12);
if (modelData.pairing
|| modelData.state === BluetoothDeviceState.Connecting)
return Qt.rgba(Theme.warning.r, Theme.warning.g,
Theme.warning.b, 0.12)
if (modelData.blocked)
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08);
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08)
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08);
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
}
border.color: {
if (modelData.pairing)
return Theme.warning;
return Theme.warning
if (modelData.blocked)
return Theme.error;
return Theme.error
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2);
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
border.width: 1
@@ -182,12 +193,12 @@ Column {
size: Theme.iconSize
color: {
if (modelData.pairing)
return Theme.warning;
return Theme.warning
if (modelData.blocked)
return Theme.error;
return Theme.error
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -201,12 +212,12 @@ Column {
font.pixelSize: Theme.fontSizeMedium
color: {
if (modelData.pairing)
return Theme.warning;
return Theme.warning
if (modelData.blocked)
return Theme.error;
return Theme.error
return Theme.surfaceText;
return Theme.surfaceText
}
font.weight: modelData.pairing ? Font.Medium : Font.Normal
}
@@ -220,45 +231,49 @@ Column {
StyledText {
text: {
if (modelData.pairing)
return "Pairing...";
return "Pairing..."
if (modelData.blocked)
return "Blocked";
return "Blocked"
return BluetoothService.getSignalStrength(modelData);
return BluetoothService.getSignalStrength(modelData)
}
font.pixelSize: Theme.fontSizeSmall
color: {
if (modelData.pairing)
return Theme.warning;
return Theme.warning
if (modelData.blocked)
return Theme.error;
return Theme.error
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7);
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
}
}
DankIcon {
name: BluetoothService.getSignalIcon(modelData)
size: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
visible: modelData.signalStrength !== undefined && modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: modelData.signalStrength !== undefined
&& modelData.signalStrength > 0 && !modelData.pairing
&& !modelData.blocked
}
StyledText {
text: (modelData.signalStrength !== undefined && modelData.signalStrength > 0) ? modelData.signalStrength + "%" : ""
text: (modelData.signalStrength !== undefined
&& modelData.signalStrength > 0) ? modelData.signalStrength + "%" : ""
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
visible: modelData.signalStrength !== undefined && modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
visible: modelData.signalStrength !== undefined
&& modelData.signalStrength > 0 && !modelData.pairing
&& !modelData.blocked
}
}
}
}
}
Rectangle {
@@ -271,14 +286,19 @@ Column {
visible: modelData.state !== BluetoothDeviceState.Connecting
color: {
if (!canConnect && !isBusy)
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3);
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
if (actionButtonArea.containsMouse && !isBusy)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
return Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
return "transparent";
return "transparent"
}
border.color: canConnect || isBusy ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.color: canConnect || isBusy ? Theme.primary : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
opacity: canConnect || isBusy ? 1 : 0.5
@@ -286,15 +306,18 @@ Column {
anchors.centerIn: parent
text: {
if (modelData.pairing)
return "Pairing...";
return "Pairing..."
if (modelData.blocked)
return "Blocked";
return "Blocked"
return "Connect";
return "Connect"
}
font.pixelSize: Theme.fontSizeSmall
color: canConnect || isBusy ? Theme.primary : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
color: canConnect || isBusy ? Theme.primary : Qt.rgba(
Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
font.weight: Font.Medium
}
@@ -303,15 +326,14 @@ Column {
anchors.fill: parent
hoverEnabled: true
cursorShape: canConnect && !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor)
cursorShape: canConnect
&& !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor)
enabled: canConnect && !isBusy
onClicked: {
if (modelData)
BluetoothService.connectDeviceWithTrust(modelData);
BluetoothService.connectDeviceWithTrust(modelData)
}
}
}
MouseArea {
@@ -320,30 +342,34 @@ Column {
anchors.fill: parent
anchors.rightMargin: 90
hoverEnabled: true
cursorShape: canConnect && !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor)
cursorShape: canConnect
&& !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor)
enabled: canConnect && !isBusy
onClicked: {
if (modelData)
BluetoothService.connectDeviceWithTrust(modelData);
BluetoothService.connectDeviceWithTrust(modelData)
}
}
}
}
Column {
width: parent.width
spacing: Theme.spacingM
visible: {
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices)
return false;
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering
|| !Bluetooth.devices)
return false
var availableCount = Bluetooth.devices.values.filter((dev) => {
return dev && !dev.paired && !dev.pairing && !dev.blocked && (dev.signalStrength === undefined || dev.signalStrength > 0);
}).length;
return availableCount === 0;
var availableCount = Bluetooth.devices.values.filter(dev => {
return dev
&& !dev.paired
&& !dev.pairing
&& !dev.blocked
&& (dev.signalStrength === undefined
|| dev.signalStrength > 0)
}).length
return availableCount === 0
}
Row {
@@ -363,7 +389,6 @@ Column {
to: 360
duration: 2000
}
}
StyledText {
@@ -373,34 +398,38 @@ Column {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: "Make sure your device is in pairing mode"
font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.horizontalCenter: parent.horizontalCenter
}
}
StyledText {
text: "No devices found. Put your device in pairing mode and click Start Scanning."
font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: {
if (!BluetoothService.adapter || !Bluetooth.devices)
return true;
return true
var availableCount = Bluetooth.devices.values.filter((dev) => {
return dev && !dev.paired && !dev.pairing && !dev.blocked && (dev.signalStrength === undefined || dev.signalStrength > 0);
}).length;
return availableCount === 0 && !BluetoothService.adapter.discovering;
var availableCount = Bluetooth.devices.values.filter(dev => {
return dev
&& !dev.paired
&& !dev.pairing
&& !dev.blocked
&& (dev.signalStrength === undefined
|| dev.signalStrength > 0)
}).length
return availableCount === 0 && !BluetoothService.adapter.discovering
}
wrapMode: Text.WordWrap
width: parent.width
horizontalAlignment: Text.AlignHCenter
}
}

View File

@@ -16,23 +16,23 @@ Rectangle {
property var parentItem
function show(x, y) {
const menuWidth = 160;
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2;
let finalX = x - menuWidth / 2;
let finalY = y;
finalX = Math.max(0, Math.min(finalX, parentItem.width - menuWidth));
finalY = Math.max(0, Math.min(finalY, parentItem.height - menuHeight));
root.x = finalX;
root.y = finalY;
root.visible = true;
root.menuVisible = true;
const menuWidth = 160
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
let finalX = x - menuWidth / 2
let finalY = y
finalX = Math.max(0, Math.min(finalX, parentItem.width - menuWidth))
finalY = Math.max(0, Math.min(finalY, parentItem.height - menuHeight))
root.x = finalX
root.y = finalY
root.visible = true
root.menuVisible = true
}
function hide() {
root.menuVisible = false;
root.menuVisible = false
Qt.callLater(() => {
root.visible = false;
});
root.visible = false
})
}
visible: false
@@ -68,7 +68,10 @@ Rectangle {
width: parent.width
height: 32
radius: Theme.cornerRadiusSmall
color: connectArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: connectArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row {
anchors.left: parent.left
@@ -77,7 +80,8 @@ Rectangle {
spacing: Theme.spacingS
DankIcon {
name: root.deviceData && root.deviceData.connected ? "link_off" : "link"
name: root.deviceData
&& root.deviceData.connected ? "link_off" : "link"
size: Theme.iconSize - 2
color: Theme.surfaceText
opacity: 0.7
@@ -85,13 +89,13 @@ Rectangle {
}
StyledText {
text: root.deviceData && root.deviceData.connected ? "Disconnect" : "Connect"
text: root.deviceData
&& root.deviceData.connected ? "Disconnect" : "Connect"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -103,11 +107,11 @@ Rectangle {
onClicked: {
if (root.deviceData) {
if (root.deviceData.connected)
root.deviceData.disconnect();
root.deviceData.disconnect()
else
BluetoothService.connectDeviceWithTrust(root.deviceData);
BluetoothService.connectDeviceWithTrust(root.deviceData)
}
root.hide();
root.hide()
}
}
@@ -116,9 +120,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Rectangle {
@@ -133,14 +135,15 @@ Rectangle {
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
}
Rectangle {
width: parent.width
height: 32
radius: Theme.cornerRadiusSmall
color: forgetArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
color: forgetArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b,
0.12) : "transparent"
Row {
anchors.left: parent.left
@@ -163,7 +166,6 @@ Rectangle {
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -174,9 +176,9 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (root.deviceData)
root.deviceData.forget();
root.deviceData.forget()
root.hide();
root.hide()
}
}
@@ -185,11 +187,8 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
Behavior on opacity {
@@ -197,7 +196,6 @@ Rectangle {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
@@ -205,7 +203,5 @@ Rectangle {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}

View File

@@ -14,8 +14,12 @@ Rectangle {
width: parent.width
height: 60
radius: Theme.cornerRadius
color: bluetoothToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : (BluetoothService.adapter && BluetoothService.adapter.enabled ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12))
border.color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : "transparent"
color: bluetoothToggle.containsMouse ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12) : (BluetoothService.adapter
&& BluetoothService.adapter.enabled ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12))
border.color: BluetoothService.adapter
&& BluetoothService.adapter.enabled ? Theme.primary : "transparent"
border.width: 2
Row {
@@ -27,7 +31,8 @@ Rectangle {
DankIcon {
name: "bluetooth"
size: Theme.iconSizeLarge
color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceText
color: BluetoothService.adapter
&& BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
@@ -38,18 +43,19 @@ Rectangle {
StyledText {
text: "Bluetooth"
font.pixelSize: Theme.fontSizeLarge
color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceText
color: BluetoothService.adapter
&& BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceText
font.weight: Font.Medium
}
StyledText {
text: BluetoothService.adapter && BluetoothService.adapter.enabled ? "Enabled" : "Disabled"
text: BluetoothService.adapter
&& BluetoothService.adapter.enabled ? "Enabled" : "Disabled"
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
}
}
}
MouseArea {
@@ -60,9 +66,7 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (BluetoothService.adapter)
BluetoothService.adapter.enabled = !BluetoothService.adapter.enabled;
BluetoothService.adapter.enabled = !BluetoothService.adapter.enabled
}
}
}

View File

@@ -12,13 +12,13 @@ Column {
id: root
function findBluetoothContextMenu() {
var p = parent;
var p = parent
while (p) {
if (p.bluetoothContextMenuWindow)
return p.bluetoothContextMenuWindow;
p = p.parent;
return p.bluetoothContextMenuWindow
p = p.parent
}
return null;
return null
}
width: parent.width
@@ -33,15 +33,28 @@ Column {
}
Repeater {
model: BluetoothService.adapter && BluetoothService.adapter.devices ? BluetoothService.adapter.devices.values.filter((dev) => {
return dev && (dev.paired || dev.trusted);
model: BluetoothService.adapter
&& BluetoothService.adapter.devices ? BluetoothService.adapter.devices.values.filter(
dev => {
return dev
&& (dev.paired
|| dev.trusted)
}) : []
Rectangle {
width: parent.width
height: 60
radius: Theme.cornerRadius
color: btDeviceArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (modelData.connected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
color: btDeviceArea.containsMouse ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.08) : (modelData.connected ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b,
0.08))
border.color: modelData.connected ? Theme.primary : "transparent"
border.width: 1
@@ -75,28 +88,30 @@ Column {
StyledText {
text: BluetoothDeviceState.toString(modelData.state)
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
}
StyledText {
text: {
if (modelData.batteryAvailable && modelData.battery > 0)
return "• " + Math.round(modelData.battery * 100) + "%";
return "• " + Math.round(modelData.battery * 100) + "%"
var btBattery = BatteryService.bluetoothDevices.find((dev) => {
return dev.name === (modelData.name || modelData.deviceName) || dev.name.toLowerCase().includes((modelData.name || modelData.deviceName).toLowerCase()) || (modelData.name || modelData.deviceName).toLowerCase().includes(dev.name.toLowerCase());
});
return btBattery ? "• " + btBattery.percentage + "%" : "";
var btBattery = BatteryService.bluetoothDevices.find(dev => {
return dev.name === (modelData.name || modelData.deviceName) || dev.name.toLowerCase().includes((modelData.name || modelData.deviceName).toLowerCase()) || (modelData.name || modelData.deviceName).toLowerCase(
).includes(
dev.name.toLowerCase(
))
})
return btBattery ? "• " + btBattery.percentage + "%" : ""
}
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: text.length > 0
}
}
}
}
Rectangle {
@@ -105,7 +120,10 @@ Column {
width: 32
height: 32
radius: Theme.cornerRadius
color: btMenuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
color: btMenuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
anchors.right: parent.right
anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
@@ -125,11 +143,13 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
var contextMenu = root.findBluetoothContextMenu();
var contextMenu = root.findBluetoothContextMenu()
if (contextMenu) {
contextMenu.deviceData = modelData;
let localPos = btMenuButtonArea.mapToItem(contextMenu.parentItem, btMenuButtonArea.width / 2, btMenuButtonArea.height);
contextMenu.show(localPos.x, localPos.y);
contextMenu.deviceData = modelData
let localPos = btMenuButtonArea.mapToItem(
contextMenu.parentItem, btMenuButtonArea.width / 2,
btMenuButtonArea.height)
contextMenu.show(localPos.x, localPos.y)
}
}
}
@@ -138,9 +158,7 @@ Column {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
MouseArea {
@@ -153,14 +171,11 @@ Column {
cursorShape: enabled ? Qt.PointingHandCursor : Qt.BusyCursor
onClicked: {
if (modelData.connected)
modelData.disconnect();
modelData.disconnect()
else
BluetoothService.connectDeviceWithTrust(modelData);
BluetoothService.connectDeviceWithTrust(modelData)
}
}
}
}
}

View File

@@ -51,7 +51,7 @@ Item {
anchors.fill: parent
visible: bluetoothContextMenuWindow.visible
onClicked: {
bluetoothContextMenuWindow.hide();
bluetoothContextMenuWindow.hide()
}
MouseArea {
@@ -60,6 +60,7 @@ Item {
width: bluetoothContextMenuWindow.width
height: bluetoothContextMenuWindow.height
onClicked: {
}
}
}

View File

@@ -24,26 +24,26 @@ PanelWindow {
property string triggerSection: "right"
function setTriggerPosition(x, y, width, section, screen) {
triggerX = x;
triggerY = y;
triggerWidth = width;
triggerSection = section;
triggerScreen = screen;
triggerX = x
triggerY = y
triggerWidth = width
triggerSection = section
triggerScreen = screen
}
signal powerActionRequested(string action, string title, string message)
signal lockRequested()
signal lockRequested
visible: controlCenterVisible
screen: triggerScreen
onVisibleChanged: {
NetworkService.autoRefreshEnabled = visible && NetworkService.wifiEnabled;
if (!visible && BluetoothService.adapter && BluetoothService.adapter.discovering)
BluetoothService.adapter.discovering = false;
NetworkService.autoRefreshEnabled = visible && NetworkService.wifiEnabled
if (!visible && BluetoothService.adapter
&& BluetoothService.adapter.discovering)
BluetoothService.adapter.discovering = false
if (visible && UserInfoService)
UserInfoService.getUptime();
UserInfoService.getUptime()
}
implicitWidth: 600
implicitHeight: 500
@@ -64,7 +64,8 @@ PanelWindow {
readonly property real screenWidth: root.screen ? root.screen.width : Screen.width
readonly property real screenHeight: root.screen ? root.screen.height : Screen.height
readonly property real targetWidth: Math.min(600, screenWidth - Theme.spacingL * 2)
readonly property real targetWidth: Math.min(
600, screenWidth - Theme.spacingL * 2)
asynchronous: true
active: controlCenterVisible
@@ -72,21 +73,22 @@ PanelWindow {
height: root.powerOptionsExpanded ? 570 : 500
y: Theme.barHeight + Theme.spacingXS
x: {
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2);
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2)
if (centerX >= Theme.spacingM && centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX;
if (centerX >= Theme.spacingM
&& centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX
}
if (centerX < Theme.spacingM) {
return Theme.spacingM;
return Theme.spacingM
}
if (centerX + targetWidth > screenWidth - Theme.spacingM) {
return screenWidth - targetWidth - Theme.spacingM;
return screenWidth - targetWidth - Theme.spacingM
}
return centerX;
return centerX
}
opacity: controlCenterVisible ? 1 : 0
scale: controlCenterVisible ? 1 : 0.9
@@ -97,7 +99,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
Behavior on scale {
@@ -106,36 +107,36 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
sourceComponent: Rectangle {
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
antialiasing: true
smooth: true
focus: true
Component.onCompleted: {
if (controlCenterVisible)
forceActiveFocus();
forceActiveFocus()
}
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
controlCenterVisible = false;
event.accepted = true;
controlCenterVisible = false
event.accepted = true
} else {
event.accepted = false;
event.accepted = false
}
}
Connections {
function onControlCenterVisibleChanged() {
if (controlCenterVisible)
Qt.callLater(function() {
parent.forceActiveFocus();
});
Qt.callLater(function () {
parent.forceActiveFocus()
})
}
target: root
}
@@ -153,8 +154,11 @@ PanelWindow {
width: parent.width
height: 90
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
Row {
@@ -186,12 +190,12 @@ PanelWindow {
source: {
if (PortalService.profileImage === "")
return "";
return ""
if (PortalService.profileImage.startsWith("/"))
return "file://" + PortalService.profileImage;
return "file://" + PortalService.profileImage
return PortalService.profileImage;
return PortalService.profileImage
}
smooth: true
asynchronous: true
@@ -226,7 +230,6 @@ PanelWindow {
color: "black"
antialiasing: true
}
}
Rectangle {
@@ -241,7 +244,6 @@ PanelWindow {
size: Theme.iconSize + 8
color: Theme.primaryText
}
}
DankIcon {
@@ -249,9 +251,9 @@ PanelWindow {
name: "warning"
size: Theme.iconSize + 8
color: Theme.primaryText
visible: PortalService.profileImage !== "" && profileImageLoader.status === Image.Error
visible: PortalService.profileImage !== ""
&& profileImageLoader.status === Image.Error
}
}
Column {
@@ -259,7 +261,8 @@ PanelWindow {
spacing: Theme.spacingXS
StyledText {
text: UserInfoService.fullName || UserInfoService.username || "User"
text: UserInfoService.fullName
|| UserInfoService.username || "User"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
@@ -271,9 +274,7 @@ PanelWindow {
color: Theme.surfaceVariantText
font.weight: Font.Normal
}
}
}
Row {
@@ -287,11 +288,14 @@ PanelWindow {
iconName: "lock"
iconSize: Theme.iconSize - 2
iconColor: Theme.surfaceText
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
backgroundColor: Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.5)
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
onClicked: {
controlCenterVisible = false;
root.lockRequested();
controlCenterVisible = false
root.lockRequested()
}
}
@@ -299,7 +303,15 @@ PanelWindow {
width: 40
height: 40
radius: 20
color: powerButton.containsMouse || root.powerOptionsExpanded ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
color: powerButton.containsMouse
|| root.powerOptionsExpanded ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Rectangle {
anchors.centerIn: parent
@@ -315,7 +327,8 @@ PanelWindow {
anchors.centerIn: parent
name: root.powerOptionsExpanded ? "expand_less" : "power_settings_new"
size: Theme.iconSize - 2
color: powerButton.containsMouse || root.powerOptionsExpanded ? Theme.error : Theme.surfaceText
color: powerButton.containsMouse
|| root.powerOptionsExpanded ? Theme.error : Theme.surfaceText
Behavior on name {
SequentialAnimation {
@@ -339,13 +352,9 @@ PanelWindow {
duration: Theme.shortDuration / 2
easing.type: Theme.standardEasing
}
}
}
}
}
MouseArea {
@@ -355,7 +364,7 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.powerOptionsExpanded = !root.powerOptionsExpanded;
root.powerOptionsExpanded = !root.powerOptionsExpanded
}
}
@@ -364,9 +373,7 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
DankActionButton {
@@ -374,24 +381,28 @@ PanelWindow {
iconName: "settings"
iconSize: Theme.iconSize - 2
iconColor: Theme.surfaceText
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
backgroundColor: Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.5)
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
onClicked: {
controlCenterVisible = false;
settingsModal.show();
controlCenterVisible = false
settingsModal.show()
}
}
}
}
Rectangle {
width: parent.width
height: root.powerOptionsExpanded ? 60 : 0
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: root.powerOptionsExpanded ? 1 : 0
opacity: root.powerOptionsExpanded ? 1 : 0
clip: true
@@ -405,7 +416,14 @@ PanelWindow {
width: 100
height: 34
radius: Theme.cornerRadius
color: logoutButton.containsMouse ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
color: logoutButton.containsMouse ? Qt.rgba(Theme.warning.r,
Theme.warning.g,
Theme.warning.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Row {
anchors.centerIn: parent
@@ -425,7 +443,6 @@ PanelWindow {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -435,8 +452,10 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.powerOptionsExpanded = false;
root.powerActionRequested("logout", "Logout", "Are you sure you want to logout?");
root.powerOptionsExpanded = false
root.powerActionRequested(
"logout", "Logout",
"Are you sure you want to logout?")
}
}
@@ -445,16 +464,21 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Rectangle {
width: 100
height: 34
radius: Theme.cornerRadius
color: rebootButton.containsMouse ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
color: rebootButton.containsMouse ? Qt.rgba(Theme.warning.r,
Theme.warning.g,
Theme.warning.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Row {
anchors.centerIn: parent
@@ -474,7 +498,6 @@ PanelWindow {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -484,8 +507,10 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.powerOptionsExpanded = false;
root.powerActionRequested("reboot", "Restart", "Are you sure you want to restart?");
root.powerOptionsExpanded = false
root.powerActionRequested(
"reboot", "Restart",
"Are you sure you want to restart?")
}
}
@@ -494,16 +519,21 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Rectangle {
width: 100
height: 34
radius: Theme.cornerRadius
color: suspendButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
color: suspendButton.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Row {
anchors.centerIn: parent
@@ -523,7 +553,6 @@ PanelWindow {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -533,8 +562,10 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.powerOptionsExpanded = false;
root.powerActionRequested("suspend", "Suspend", "Are you sure you want to suspend?");
root.powerOptionsExpanded = false
root.powerActionRequested(
"suspend", "Suspend",
"Are you sure you want to suspend?")
}
}
@@ -543,16 +574,21 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Rectangle {
width: 100
height: 34
radius: Theme.cornerRadius
color: shutdownButton.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
color: shutdownButton.containsMouse ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Row {
anchors.centerIn: parent
@@ -572,7 +608,6 @@ PanelWindow {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -582,8 +617,10 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.powerOptionsExpanded = false;
root.powerActionRequested("poweroff", "Shutdown", "Are you sure you want to shutdown?");
root.powerOptionsExpanded = false
root.powerActionRequested(
"poweroff", "Shutdown",
"Are you sure you want to shutdown?")
}
}
@@ -592,11 +629,8 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
Behavior on height {
@@ -604,7 +638,6 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on opacity {
@@ -612,17 +645,17 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Rectangle {
width: parent.width
height: tabBar.height + Theme.spacingM * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.15)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.15)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1
DankTabBar {
@@ -632,58 +665,58 @@ PanelWindow {
width: parent.width - Theme.spacingM * 2
tabHeight: 40
currentIndex: {
let tabs = ["network", "audio"];
let tabs = ["network", "audio"]
if (BluetoothService.available)
tabs.push("bluetooth");
tabs.push("bluetooth")
tabs.push("display");
return tabs.indexOf(root.currentTab);
tabs.push("display")
return tabs.indexOf(root.currentTab)
}
model: {
let tabs = [{
"text": "Network",
"icon": "wifi",
"id": "network"
}];
}]
tabs.push({
"text": "Audio",
"icon": "volume_up",
"id": "audio"
});
})
if (BluetoothService.available)
tabs.push({
"text": "Bluetooth",
"icon": "bluetooth",
"id": "bluetooth"
});
})
tabs.push({
"text": "Display",
"icon": "brightness_6",
"id": "display"
});
return tabs;
})
return tabs
}
onTabClicked: function(index) {
let tabs = ["network", "audio"];
onTabClicked: function (index) {
let tabs = ["network", "audio"]
if (BluetoothService.available)
tabs.push("bluetooth");
tabs.push("bluetooth")
tabs.push("display");
root.currentTab = tabs[index];
tabs.push("display")
root.currentTab = tabs[index]
}
}
}
}
Rectangle {
width: parent.width
Layout.fillHeight: true
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.05)
border.width: 1
NetworkTab {
@@ -701,7 +734,8 @@ PanelWindow {
BluetoothTab {
anchors.fill: parent
anchors.margins: Theme.spacingS
visible: BluetoothService.available && root.currentTab === "bluetooth"
visible: BluetoothService.available
&& root.currentTab === "bluetooth"
}
Column {
@@ -713,7 +747,7 @@ PanelWindow {
interval: BrightnessService.ddcAvailable ? 500 : 50
repeat: false
onTriggered: {
BrightnessService.setBrightnessInternal(pendingValue);
BrightnessService.setBrightnessInternal(pendingValue)
}
}
@@ -741,13 +775,13 @@ PanelWindow {
rightIcon: "brightness_high"
enabled: BrightnessService.brightnessAvailable
showValue: true
onSliderValueChanged: function(newValue) {
parent.parent.brightnessDebounceTimer.pendingValue = newValue;
parent.parent.brightnessDebounceTimer.restart();
onSliderValueChanged: function (newValue) {
parent.parent.brightnessDebounceTimer.pendingValue = newValue
parent.parent.brightnessDebounceTimer.restart()
}
onSliderDragFinished: function(finalValue) {
parent.parent.brightnessDebounceTimer.stop();
BrightnessService.setBrightnessInternal(finalValue);
onSliderDragFinished: function (finalValue) {
parent.parent.brightnessDebounceTimer.stop()
BrightnessService.setBrightnessInternal(finalValue)
}
}
@@ -755,10 +789,10 @@ PanelWindow {
text: "ddc changes can be slow to respond"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
visible: BrightnessService.ddcAvailable && !BrightnessService.laptopBacklightAvailable
visible: BrightnessService.ddcAvailable
&& !BrightnessService.laptopBacklightAvailable
anchors.horizontalCenter: parent.horizontalCenter
}
}
DankToggle {
@@ -766,8 +800,8 @@ PanelWindow {
text: "Night Mode"
description: "Apply warm color temperature to reduce eye strain"
checked: SettingsData.nightModeEnabled
onToggled: (checked) => {
SettingsData.setNightModeEnabled(checked);
onToggled: checked => {
SettingsData.setNightModeEnabled(checked)
}
}
@@ -776,13 +810,12 @@ PanelWindow {
text: "Light Mode"
description: "Use light theme instead of dark theme"
checked: SessionData.isLightMode
onToggled: (checked) => {
SessionData.setLightMode(checked);
Theme.isLightMode = checked;
PortalService.setLightMode(checked);
onToggled: checked => {
SessionData.setLightMode(checked)
Theme.isLightMode = checked
PortalService.setLightMode(checked)
}
}
}
Behavior on height {
@@ -790,11 +823,8 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
Behavior on height {
@@ -802,22 +832,18 @@ PanelWindow {
duration: Theme.shortDuration // Faster for height changes
easing.type: Theme.standardEasing
}
}
}
}
MouseArea {
anchors.fill: parent
z: -1
onClicked: function(mouse) {
var localPos = mapToItem(contentLoader, mouse.x, mouse.y);
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height)
controlCenterVisible = false;
onClicked: function (mouse) {
var localPos = mapToItem(contentLoader, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0
|| localPos.y > contentLoader.height)
controlCenterVisible = false
}
}
}

View File

@@ -19,7 +19,7 @@ Item {
interval: BrightnessService.ddcAvailable ? 500 : 50
repeat: false
onTriggered: {
BrightnessService.setBrightnessInternal(pendingValue);
BrightnessService.setBrightnessInternal(pendingValue)
}
}
@@ -50,9 +50,9 @@ Item {
id: nightModeEnableProcess
command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"]
running: false
onExited: (exitCode) => {
onExited: exitCode => {
if (exitCode !== 0) {
SettingsData.setNightModeEnabled(false);
SettingsData.setNightModeEnabled(false)
}
}
}
@@ -61,7 +61,7 @@ Item {
id: nightModeDisableProcess
command: ["bash", "-c", "pkill wlsunset; pkill redshift; if command -v wlsunset > /dev/null; then wlsunset -t 6500 -T 6500 & sleep 1; pkill wlsunset; elif command -v redshift > /dev/null; then redshift -P -O 6500; redshift -x; fi"]
running: false
onExited: (exitCode) => {
onExited: exitCode => {
if (exitCode !== 0) {
}
@@ -88,13 +88,13 @@ Item {
leftIcon: "brightness_low"
rightIcon: "brightness_high"
enabled: BrightnessService.brightnessAvailable
onSliderValueChanged: function(newValue) {
brightnessDebounceTimer.pendingValue = newValue;
brightnessDebounceTimer.restart();
onSliderValueChanged: function (newValue) {
brightnessDebounceTimer.pendingValue = newValue
brightnessDebounceTimer.restart()
}
onSliderDragFinished: function(finalValue) {
brightnessDebounceTimer.stop();
BrightnessService.setBrightnessInternal(finalValue);
onSliderDragFinished: function (finalValue) {
brightnessDebounceTimer.stop()
BrightnessService.setBrightnessInternal(finalValue)
}
}
@@ -102,7 +102,8 @@ Item {
text: "using ddc - changes may take a moment to apply"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
visible: BrightnessService.ddcAvailable && !BrightnessService.laptopBacklightAvailable
visible: BrightnessService.ddcAvailable
&& !BrightnessService.laptopBacklightAvailable
anchors.horizontalCenter: parent.horizontalCenter
}
}
@@ -129,7 +130,11 @@ Item {
width: (parent.width - Theme.spacingM) / 2
height: 80
radius: Theme.cornerRadius
color: SettingsData.nightModeEnabled ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : (nightModeToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
color: SettingsData.nightModeEnabled ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : (nightModeToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: SettingsData.nightModeEnabled ? Theme.primary : "transparent"
border.width: SettingsData.nightModeEnabled ? 1 : 0
@@ -160,11 +165,11 @@ Item {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (SettingsData.nightModeEnabled) {
nightModeDisableProcess.running = true;
SettingsData.setNightModeEnabled(false);
nightModeDisableProcess.running = true
SettingsData.setNightModeEnabled(false)
} else {
nightModeEnableProcess.running = true;
SettingsData.setNightModeEnabled(true);
nightModeEnableProcess.running = true
SettingsData.setNightModeEnabled(true)
}
}
}
@@ -174,7 +179,10 @@ Item {
width: (parent.width - Theme.spacingM) / 2
height: 80
radius: Theme.cornerRadius
color: Theme.isLightMode ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : (lightModeToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
color: Theme.isLightMode ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.12) : (lightModeToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: Theme.isLightMode ? Theme.primary : "transparent"
border.width: Theme.isLightMode ? 1 : 0
@@ -204,7 +212,7 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
Theme.toggleLightMode();
Theme.toggleLightMode()
}
}

View File

@@ -14,12 +14,20 @@ Rectangle {
height: 80
radius: Theme.cornerRadius
color: {
if (ethernetPreferenceArea.containsMouse && NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "ethernet")
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.8);
if (ethernetPreferenceArea.containsMouse && NetworkService.ethernetConnected
&& NetworkService.wifiEnabled
&& NetworkService.networkStatus !== "ethernet")
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.8)
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.5);
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.5)
}
border.color: NetworkService.networkStatus === "ethernet" ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.color: NetworkService.networkStatus === "ethernet" ? Theme.primary : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b,
0.12)
border.width: NetworkService.networkStatus === "ethernet" ? 2 : 1
Column {
@@ -48,17 +56,17 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
}
}
StyledText {
text: NetworkService.ethernetConnected ? (NetworkService.ethernetIP || "Connected") : "Disconnected"
text: NetworkService.ethernetConnected ? (NetworkService.ethernetIP
|| "Connected") : "Disconnected"
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
leftPadding: Theme.iconSize + Theme.spacingM
elide: Text.ElideRight
}
}
DankIcon {
@@ -70,7 +78,8 @@ Rectangle {
anchors.right: ethernetToggle.left
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
visible: NetworkService.changingPreference && NetworkService.targetPreference === "ethernet"
visible: NetworkService.changingPreference
&& NetworkService.targetPreference === "ethernet"
z: 10
RotationAnimation {
@@ -82,7 +91,6 @@ Rectangle {
duration: 1000
loops: Animation.Infinite
}
}
DankToggle {
@@ -94,7 +102,7 @@ Rectangle {
anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
onClicked: {
NetworkService.toggleNetworkConnection("ethernet");
NetworkService.toggleNetworkConnection("ethernet")
}
}
@@ -104,15 +112,19 @@ Rectangle {
anchors.fill: parent
anchors.rightMargin: 60 // Exclude toggle area
hoverEnabled: true
cursorShape: (NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "ethernet") ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "ethernet" && !NetworkService.changingNetworkPreference
cursorShape: (NetworkService.ethernetConnected && NetworkService.wifiEnabled
&& NetworkService.networkStatus
!== "ethernet") ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled
&& NetworkService.networkStatus !== "ethernet"
&& !NetworkService.changingNetworkPreference
onClicked: {
if (NetworkService.ethernetConnected && NetworkService.wifiEnabled) {
if (NetworkService.networkStatus !== "ethernet")
NetworkService.setNetworkPreference("ethernet");
NetworkService.setNetworkPreference("ethernet")
else
NetworkService.setNetworkPreference("auto");
NetworkService.setNetworkPreference("auto")
}
}
}
@@ -122,7 +134,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -15,15 +15,15 @@ Rectangle {
function getWiFiSignalIcon(signalStrength) {
switch (signalStrength) {
case "excellent":
return "wifi";
return "wifi"
case "good":
return "wifi_2_bar";
return "wifi_2_bar"
case "fair":
return "wifi_1_bar";
return "wifi_1_bar"
case "poor":
return "signal_wifi_0_bar";
return "signal_wifi_0_bar"
default:
return "wifi";
return "wifi"
}
}
@@ -31,12 +31,20 @@ Rectangle {
height: 80
radius: Theme.cornerRadius
color: {
if (wifiPreferenceArea.containsMouse && NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "wifi")
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.8);
if (wifiPreferenceArea.containsMouse && NetworkService.ethernetConnected
&& NetworkService.wifiEnabled
&& NetworkService.networkStatus !== "wifi")
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.8)
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.5);
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.5)
}
border.color: NetworkService.networkStatus === "wifi" ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.color: NetworkService.networkStatus === "wifi" ? Theme.primary : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b,
0.12)
border.width: NetworkService.networkStatus === "wifi" ? 2 : 1
visible: NetworkService.wifiAvailable
@@ -54,11 +62,11 @@ Rectangle {
DankIcon {
name: {
if (!NetworkService.wifiEnabled)
return "wifi_off";
return "wifi_off"
else if (NetworkService.currentWifiSSID !== "")
return getWiFiSignalIcon(NetworkService.wifiSignalStrength);
return getWiFiSignalIcon(NetworkService.wifiSignalStrength)
else
return "wifi";
return "wifi"
}
size: Theme.iconSize
color: NetworkService.networkStatus === "wifi" ? Theme.primary : Theme.surfaceText
@@ -68,11 +76,11 @@ Rectangle {
StyledText {
text: {
if (!NetworkService.wifiEnabled)
return "WiFi is off";
return "WiFi is off"
else if (NetworkService.wifiEnabled && NetworkService.currentWifiSSID)
return NetworkService.currentWifiSSID || "Connected";
return NetworkService.currentWifiSSID || "Connected"
else
return "Not Connected";
return "Not Connected"
}
font.pixelSize: Theme.fontSizeMedium
color: NetworkService.networkStatus === "wifi" ? Theme.primary : Theme.surfaceText
@@ -80,24 +88,23 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
}
}
StyledText {
text: {
if (!NetworkService.wifiEnabled)
return "Turn on WiFi to see networks";
return "Turn on WiFi to see networks"
else if (NetworkService.wifiEnabled && NetworkService.currentWifiSSID)
return NetworkService.wifiIP || "Connected";
return NetworkService.wifiIP || "Connected"
else
return "Select a network below";
return "Select a network below"
}
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
leftPadding: Theme.iconSize + Theme.spacingM
elide: Text.ElideRight
}
}
DankIcon {
@@ -109,7 +116,8 @@ Rectangle {
anchors.right: wifiToggle.left
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
visible: NetworkService.changingPreference && NetworkService.targetPreference === "wifi"
visible: NetworkService.changingPreference
&& NetworkService.targetPreference === "wifi"
z: 10
RotationAnimation {
@@ -121,7 +129,6 @@ Rectangle {
duration: 1000
loops: Animation.Infinite
}
}
DankToggle {
@@ -135,19 +142,18 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
onClicked: {
if (NetworkService.wifiEnabled) {
NetworkService.currentWifiSSID = "";
NetworkService.wifiSignalStrength = "excellent";
NetworkService.wifiNetworks = [];
NetworkService.savedWifiNetworks = [];
NetworkService.connectionStatus = "";
NetworkService.connectingSSID = "";
NetworkService.isScanning = false;
NetworkService.refreshNetworkStatus();
NetworkService.currentWifiSSID = ""
NetworkService.wifiSignalStrength = "excellent"
NetworkService.wifiNetworks = []
NetworkService.savedWifiNetworks = []
NetworkService.connectionStatus = ""
NetworkService.connectingSSID = ""
NetworkService.isScanning = false
NetworkService.refreshNetworkStatus()
}
NetworkService.toggleWifiRadio();
NetworkService.toggleWifiRadio()
if (refreshTimer)
refreshTimer.triggered = true;
refreshTimer.triggered = true
}
}
@@ -157,15 +163,19 @@ Rectangle {
anchors.fill: parent
anchors.rightMargin: 60 // Exclude toggle area
hoverEnabled: true
cursorShape: (NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "wifi") ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "wifi" && !NetworkService.changingNetworkPreference
cursorShape: (NetworkService.ethernetConnected && NetworkService.wifiEnabled
&& NetworkService.networkStatus
!== "wifi") ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled
&& NetworkService.networkStatus !== "wifi"
&& !NetworkService.changingNetworkPreference
onClicked: {
if (NetworkService.ethernetConnected && NetworkService.wifiEnabled) {
if (NetworkService.networkStatus !== "wifi")
NetworkService.setNetworkPreference("wifi");
NetworkService.setNetworkPreference("wifi")
else
NetworkService.setNetworkPreference("auto");
NetworkService.setNetworkPreference("auto")
}
}
}
@@ -175,7 +185,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -17,29 +17,35 @@ Rectangle {
property var networkInfoModalRef
function show(x, y) {
const menuWidth = 160;
wifiContextMenuWindow.visible = true;
const menuWidth = 160
wifiContextMenuWindow.visible = true
Qt.callLater(() => {
const menuHeight = wifiMenuColumn.implicitHeight + Theme.spacingS * 2;
let finalX = x - menuWidth / 2;
let finalY = y + 4;
finalX = Math.max(Theme.spacingS, Math.min(finalX, parentItem.width - menuWidth - Theme.spacingS));
finalY = Math.max(Theme.spacingS, Math.min(finalY, parentItem.height - menuHeight - Theme.spacingS));
const menuHeight = wifiMenuColumn.implicitHeight + Theme.spacingS * 2
let finalX = x - menuWidth / 2
let finalY = y + 4
finalX = Math.max(
Theme.spacingS,
Math.min(finalX,
parentItem.width - menuWidth - Theme.spacingS))
finalY = Math.max(
Theme.spacingS,
Math.min(finalY,
parentItem.height - menuHeight - Theme.spacingS))
if (finalY + menuHeight > parentItem.height - Theme.spacingS) {
finalY = y - menuHeight - 4;
finalY = Math.max(Theme.spacingS, finalY);
finalY = y - menuHeight - 4
finalY = Math.max(Theme.spacingS, finalY)
}
wifiContextMenuWindow.x = finalX;
wifiContextMenuWindow.y = finalY;
wifiContextMenuWindow.menuVisible = true;
});
wifiContextMenuWindow.x = finalX
wifiContextMenuWindow.y = finalY
wifiContextMenuWindow.menuVisible = true
})
}
function hide() {
wifiContextMenuWindow.menuVisible = false;
wifiContextMenuWindow.menuVisible = false
Qt.callLater(() => {
wifiContextMenuWindow.visible = false;
});
wifiContextMenuWindow.visible = false
})
}
visible: false
@@ -53,8 +59,8 @@ Rectangle {
opacity: menuVisible ? 1 : 0
scale: menuVisible ? 1 : 0.85
Component.onCompleted: {
menuVisible = false;
visible = false;
menuVisible = false
visible = false
}
Rectangle {
@@ -79,7 +85,10 @@ Rectangle {
width: parent.width
height: 32
radius: Theme.cornerRadiusSmall
color: connectWifiArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: connectWifiArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row {
anchors.left: parent.left
@@ -88,7 +97,8 @@ Rectangle {
spacing: Theme.spacingS
DankIcon {
name: wifiContextMenuWindow.networkData && wifiContextMenuWindow.networkData.connected ? "wifi_off" : "wifi"
name: wifiContextMenuWindow.networkData
&& wifiContextMenuWindow.networkData.connected ? "wifi_off" : "wifi"
size: Theme.iconSize - 2
color: Theme.surfaceText
opacity: 0.7
@@ -96,13 +106,13 @@ Rectangle {
}
StyledText {
text: wifiContextMenuWindow.networkData && wifiContextMenuWindow.networkData.connected ? "Disconnect" : "Connect"
text: wifiContextMenuWindow.networkData
&& wifiContextMenuWindow.networkData.connected ? "Disconnect" : "Connect"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -114,22 +124,24 @@ Rectangle {
onClicked: {
if (wifiContextMenuWindow.networkData) {
if (wifiContextMenuWindow.networkData.connected) {
NetworkService.disconnectWifi();
NetworkService.disconnectWifi()
} else {
if (wifiContextMenuWindow.networkData.saved) {
NetworkService.connectToWifi(wifiContextMenuWindow.networkData.ssid);
NetworkService.connectToWifi(
wifiContextMenuWindow.networkData.ssid)
} else if (wifiContextMenuWindow.networkData.secured) {
if (wifiPasswordModalRef) {
wifiPasswordModalRef.wifiPasswordSSID = wifiContextMenuWindow.networkData.ssid;
wifiPasswordModalRef.wifiPasswordInput = "";
wifiPasswordModalRef.wifiPasswordModalVisible = true;
wifiPasswordModalRef.wifiPasswordSSID = wifiContextMenuWindow.networkData.ssid
wifiPasswordModalRef.wifiPasswordInput = ""
wifiPasswordModalRef.wifiPasswordModalVisible = true
}
} else {
NetworkService.connectToWifi(wifiContextMenuWindow.networkData.ssid);
NetworkService.connectToWifi(
wifiContextMenuWindow.networkData.ssid)
}
}
}
wifiContextMenuWindow.hide();
wifiContextMenuWindow.hide()
}
}
@@ -138,9 +150,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Rectangle {
@@ -155,15 +165,19 @@ Rectangle {
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
}
Rectangle {
width: parent.width
height: 32
radius: Theme.cornerRadiusSmall
color: forgetWifiArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
visible: wifiContextMenuWindow.networkData && (wifiContextMenuWindow.networkData.saved || wifiContextMenuWindow.networkData.connected)
color: forgetWifiArea.containsMouse ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.12) : "transparent"
visible: wifiContextMenuWindow.networkData
&& (wifiContextMenuWindow.networkData.saved
|| wifiContextMenuWindow.networkData.connected)
Row {
anchors.left: parent.left
@@ -186,7 +200,6 @@ Rectangle {
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -197,9 +210,10 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (wifiContextMenuWindow.networkData)
NetworkService.forgetWifiNetwork(wifiContextMenuWindow.networkData.ssid);
NetworkService.forgetWifiNetwork(
wifiContextMenuWindow.networkData.ssid)
wifiContextMenuWindow.hide();
wifiContextMenuWindow.hide()
}
}
@@ -208,16 +222,17 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Rectangle {
width: parent.width
height: 32
radius: Theme.cornerRadiusSmall
color: infoWifiArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: infoWifiArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row {
anchors.left: parent.left
@@ -240,7 +255,6 @@ Rectangle {
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -251,9 +265,11 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (wifiContextMenuWindow.networkData && networkInfoModalRef)
networkInfoModalRef.showNetworkInfo(wifiContextMenuWindow.networkData.ssid, wifiContextMenuWindow.networkData);
networkInfoModalRef.showNetworkInfo(
wifiContextMenuWindow.networkData.ssid,
wifiContextMenuWindow.networkData)
wifiContextMenuWindow.hide();
wifiContextMenuWindow.hide()
}
}
@@ -262,11 +278,8 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
Behavior on opacity {
@@ -274,7 +287,6 @@ Rectangle {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
@@ -282,7 +294,5 @@ Rectangle {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}

View File

@@ -17,15 +17,15 @@ Column {
function getWiFiSignalIcon(signalStrength) {
switch (signalStrength) {
case "excellent":
return "wifi";
return "wifi"
case "good":
return "wifi_2_bar";
return "wifi_2_bar"
case "fair":
return "wifi_1_bar";
return "wifi_1_bar"
case "poor":
return "signal_wifi_0_bar";
return "signal_wifi_0_bar"
default:
return "wifi";
return "wifi"
}
}
@@ -58,7 +58,11 @@ Column {
width: 28
height: 28
radius: 14
color: refreshAreaSpan.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : NetworkService.isScanning ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06) : "transparent"
color: refreshAreaSpan.containsMouse ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : NetworkService.isScanning ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06) : "transparent"
DankIcon {
id: refreshIconSpan
@@ -84,9 +88,7 @@ Column {
duration: 200
easing.type: Easing.OutQuad
}
}
}
MouseArea {
@@ -97,14 +99,12 @@ Column {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!NetworkService.isScanning) {
refreshIconSpan.rotation += 30;
NetworkService.scanWifi();
refreshIconSpan.rotation += 30
NetworkService.scanWifi()
}
}
}
}
}
Flickable {
@@ -121,10 +121,13 @@ Column {
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: (event) => {
let delta = event.pixelDelta.y !== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
onWheel: event => {
let delta = event.pixelDelta.y
!== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
let newY = parent.contentY - delta
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY))
newY = Math.max(0,
Math.min(parent.contentHeight - parent.height,
newY))
parent.contentY = newY
event.accepted = true
}
@@ -137,13 +140,18 @@ Column {
spacing: Theme.spacingXS
Repeater {
model: NetworkService.wifiAvailable && NetworkService.wifiEnabled ? sortedWifiNetworks : []
model: NetworkService.wifiAvailable
&& NetworkService.wifiEnabled ? sortedWifiNetworks : []
Rectangle {
width: spanningNetworksColumn.width
height: 38
radius: Theme.cornerRadiusSmall
color: networkArea2.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : modelData.connected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: networkArea2.containsMouse ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.08) : modelData.connected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
border.color: modelData.connected ? Theme.primary : "transparent"
border.width: modelData.connected ? 1 : 0
@@ -183,32 +191,36 @@ Column {
width: parent.width
text: {
if (modelData.connected)
return "Connected";
return "Connected"
if (NetworkService.connectionStatus === "connecting" && NetworkService.connectingSSID === modelData.ssid)
return "Connecting...";
if (NetworkService.connectionStatus === "connecting"
&& NetworkService.connectingSSID === modelData.ssid)
return "Connecting..."
if (NetworkService.connectionStatus === "invalid_password" && NetworkService.connectingSSID === modelData.ssid)
return "Invalid password";
if (NetworkService.connectionStatus === "invalid_password"
&& NetworkService.connectingSSID === modelData.ssid)
return "Invalid password"
if (modelData.saved)
return "Saved" + (modelData.secured ? " • Secured" : " • Open");
return "Saved" + (modelData.secured ? " • Secured" : " • Open")
return modelData.secured ? "Secured" : "Open";
return modelData.secured ? "Secured" : "Open"
}
font.pixelSize: Theme.fontSizeSmall - 1
color: {
if (NetworkService.connectionStatus === "connecting" && NetworkService.connectingSSID === modelData.ssid)
return Theme.primary;
if (NetworkService.connectionStatus === "connecting"
&& NetworkService.connectingSSID === modelData.ssid)
return Theme.primary
if (NetworkService.connectionStatus === "invalid_password" && NetworkService.connectingSSID === modelData.ssid)
return Theme.error;
if (NetworkService.connectionStatus === "invalid_password"
&& NetworkService.connectingSSID === modelData.ssid)
return Theme.error
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7);
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
}
elide: Text.ElideRight
}
}
Row {
@@ -221,7 +233,8 @@ Column {
DankIcon {
name: "lock"
size: Theme.iconSize - 8
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
visible: modelData.secured
anchors.verticalCenter: parent.verticalCenter
}
@@ -232,7 +245,11 @@ Column {
width: 24
height: 24
radius: 12
color: wifiMenuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
color: wifiMenuButtonArea.containsMouse ? Qt.rgba(
Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
DankIcon {
name: "more_vert"
@@ -249,13 +266,16 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
wifiContextMenuWindow.networkData = modelData;
let buttonCenter = wifiMenuButtonArea.width / 2;
let buttonBottom = wifiMenuButtonArea.height;
let globalPos = wifiMenuButtonArea.mapToItem(wifiContextMenuWindow.parentItem, buttonCenter, buttonBottom);
wifiContextMenuWindow.networkData = modelData
let buttonCenter = wifiMenuButtonArea.width / 2
let buttonBottom = wifiMenuButtonArea.height
let globalPos = wifiMenuButtonArea.mapToItem(
wifiContextMenuWindow.parentItem, buttonCenter,
buttonBottom)
Qt.callLater(() => {
wifiContextMenuWindow.show(globalPos.x, globalPos.y);
});
wifiContextMenuWindow.show(globalPos.x,
globalPos.y)
})
}
}
@@ -263,13 +283,9 @@ Column {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}
MouseArea {
@@ -281,32 +297,27 @@ Column {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData.connected)
return ;
return
if (modelData.saved) {
NetworkService.connectToWifi(modelData.ssid);
NetworkService.connectToWifi(modelData.ssid)
} else if (modelData.secured) {
if (wifiPasswordModalRef) {
wifiPasswordModalRef.wifiPasswordSSID = modelData.ssid;
wifiPasswordModalRef.wifiPasswordInput = "";
wifiPasswordModalRef.wifiPasswordModalVisible = true;
wifiPasswordModalRef.wifiPasswordSSID = modelData.ssid
wifiPasswordModalRef.wifiPasswordInput = ""
wifiPasswordModalRef.wifiPasswordModalVisible = true
}
} else {
NetworkService.connectToWifi(modelData.ssid);
NetworkService.connectToWifi(modelData.ssid)
}
}
}
}
}
}
ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded
}
}
}

View File

@@ -16,34 +16,37 @@ Item {
property var sortedWifiNetworks: {
if (!NetworkService.wifiAvailable || !NetworkService.wifiEnabled) {
return [];
return []
}
var allNetworks = NetworkService.wifiNetworks;
var savedNetworks = NetworkService.savedWifiNetworks;
var currentSSID = NetworkService.currentWifiSSID;
var signalStrength = NetworkService.wifiSignalStrength;
var refreshTrigger = forceRefresh; // Force recalculation
var allNetworks = NetworkService.wifiNetworks
var savedNetworks = NetworkService.savedWifiNetworks
var currentSSID = NetworkService.currentWifiSSID
var signalStrength = NetworkService.wifiSignalStrength
var refreshTrigger = forceRefresh
var networks = [...allNetworks];
// Force recalculation
var networks = [...allNetworks]
networks.forEach(function(network) {
network.connected = (network.ssid === currentSSID);
network.saved = savedNetworks.some(function(saved) {
return saved.ssid === network.ssid;
});
networks.forEach(function (network) {
network.connected = (network.ssid === currentSSID)
network.saved = savedNetworks.some(function (saved) {
return saved.ssid === network.ssid
})
if (network.connected && signalStrength) {
network.signalStrength = signalStrength;
network.signalStrength = signalStrength
}
});
})
networks.sort(function(a, b) {
if (a.connected && !b.connected) return -1;
if (!a.connected && b.connected) return 1;
return b.signal - a.signal;
});
networks.sort(function (a, b) {
if (a.connected && !b.connected)
return -1
if (!a.connected && b.connected)
return 1
return b.signal - a.signal
})
return networks;
return networks
}
property int forceRefresh: 0
@@ -51,21 +54,21 @@ Item {
Connections {
target: NetworkService
function onNetworksUpdated() {
forceRefresh++;
forceRefresh++
}
}
Component.onCompleted: {
NetworkService.addRef();
NetworkService.autoRefreshEnabled = true;
NetworkService.addRef()
NetworkService.autoRefreshEnabled = true
if (NetworkService.wifiEnabled)
NetworkService.scanWifi();
wifiMonitorTimer.start();
NetworkService.scanWifi()
wifiMonitorTimer.start()
}
Component.onDestruction: {
NetworkService.removeRef();
NetworkService.autoRefreshEnabled = false;
NetworkService.removeRef()
NetworkService.autoRefreshEnabled = false
}
Row {
@@ -91,10 +94,12 @@ Item {
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: (event) => {
let delta = event.pixelDelta.y !== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
onWheel: event => {
let delta = event.pixelDelta.y
!== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
let newY = parent.contentY - delta
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY))
newY = Math.max(
0, Math.min(parent.contentHeight - parent.height, newY))
parent.contentY = newY
event.accepted = true
}
@@ -135,10 +140,12 @@ Item {
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: (event) => {
let delta = event.pixelDelta.y !== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
onWheel: event => {
let delta = event.pixelDelta.y
!== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
let newY = parent.contentY - delta
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY))
newY = Math.max(
0, Math.min(parent.contentHeight - parent.height, newY))
parent.contentY = newY
event.accepted = true
}
@@ -149,8 +156,7 @@ Item {
width: parent.width
spacing: Theme.spacingM
EthernetCard {
}
EthernetCard {}
}
ScrollBar.vertical: ScrollBar {
@@ -177,14 +183,16 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
name: "wifi_off"
size: 48
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
}
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
text: "WiFi is turned off"
font.pixelSize: Theme.fontSizeLarge
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
font.weight: Font.Medium
}
@@ -192,7 +200,8 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
text: "Turn on WiFi to see networks"
font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.4)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.4)
}
}
}
@@ -209,11 +218,11 @@ Item {
running: visible && refreshTimer.triggered
property bool triggered: false
onTriggered: {
NetworkService.refreshNetworkStatus();
NetworkService.refreshNetworkStatus()
if (NetworkService.wifiEnabled && !NetworkService.isScanning) {
NetworkService.scanWifi();
NetworkService.scanWifi()
}
triggered = false;
triggered = false
}
}
@@ -221,18 +230,18 @@ Item {
target: NetworkService
function onWifiEnabledChanged() {
if (NetworkService.wifiEnabled && visible) {
wifiScanDelayTimer.start();
wifiMonitorTimer.start();
wifiScanDelayTimer.start()
wifiMonitorTimer.start()
} else {
NetworkService.currentWifiSSID = "";
NetworkService.wifiSignalStrength = "excellent";
NetworkService.wifiNetworks = [];
NetworkService.savedWifiNetworks = [];
NetworkService.connectionStatus = "";
NetworkService.connectingSSID = "";
NetworkService.isScanning = false;
NetworkService.refreshNetworkStatus();
wifiMonitorTimer.stop();
NetworkService.currentWifiSSID = ""
NetworkService.wifiSignalStrength = "excellent"
NetworkService.wifiNetworks = []
NetworkService.savedWifiNetworks = []
NetworkService.connectionStatus = ""
NetworkService.connectingSSID = ""
NetworkService.isScanning = false
NetworkService.refreshNetworkStatus()
wifiMonitorTimer.stop()
}
}
}
@@ -245,9 +254,9 @@ Item {
onTriggered: {
if (NetworkService.wifiEnabled && visible) {
if (!NetworkService.isScanning) {
NetworkService.scanWifi();
NetworkService.scanWifi()
} else {
wifiRetryTimer.start();
wifiRetryTimer.start()
}
}
}
@@ -259,9 +268,10 @@ Item {
running: false
repeat: false
onTriggered: {
if (NetworkService.wifiEnabled && visible && NetworkService.wifiNetworks.length === 0) {
if (NetworkService.wifiEnabled && visible
&& NetworkService.wifiNetworks.length === 0) {
if (!NetworkService.isScanning) {
NetworkService.scanWifi();
NetworkService.scanWifi()
}
}
}
@@ -274,33 +284,32 @@ Item {
repeat: true
onTriggered: {
if (!visible || !NetworkService.wifiEnabled) {
running = false;
return;
running = false
return
}
var shouldScan = false;
var reason = "";
var shouldScan = false
var reason = ""
if (NetworkService.networkStatus !== "wifi") {
shouldScan = true;
reason = "not connected to WiFi";
}
else if (NetworkService.wifiNetworks.length === 0) {
shouldScan = true;
reason = "no networks cached";
shouldScan = true
reason = "not connected to WiFi"
} else if (NetworkService.wifiNetworks.length === 0) {
shouldScan = true
reason = "no networks cached"
}
if (shouldScan && !NetworkService.isScanning) {
NetworkService.scanWifi();
NetworkService.scanWifi()
}
}
}
onVisibleChanged: {
if (visible && NetworkService.wifiEnabled) {
wifiMonitorTimer.start();
wifiMonitorTimer.start()
} else {
wifiMonitorTimer.stop();
wifiMonitorTimer.stop()
}
}
@@ -315,7 +324,7 @@ Item {
anchors.fill: parent
visible: wifiContextMenuWindow.visible
onClicked: {
wifiContextMenuWindow.hide();
wifiContextMenuWindow.hide()
}
MouseArea {
@@ -324,6 +333,7 @@ Item {
width: wifiContextMenuWindow.width
height: wifiContextMenuWindow.height
onClicked: {
}
}
}

View File

@@ -34,7 +34,7 @@ PanelWindow {
MouseArea {
anchors.fill: parent
onClicked: {
powerMenuVisible = false;
powerMenuVisible = false
}
}
@@ -45,7 +45,8 @@ PanelWindow {
y: Theme.barHeight + Theme.spacingXS
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
opacity: powerMenuVisible ? 1 : 0
scale: powerMenuVisible ? 1 : 0.85
@@ -54,6 +55,7 @@ PanelWindow {
anchors.fill: parent
onClicked: {
}
}
@@ -84,10 +86,9 @@ PanelWindow {
iconColor: Theme.surfaceText
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
onClicked: {
powerMenuVisible = false;
powerMenuVisible = false
}
}
}
Column {
@@ -98,7 +99,13 @@ PanelWindow {
width: parent.width
height: 50
radius: Theme.cornerRadius
color: logoutArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)
color: logoutArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.08) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
Row {
anchors.left: parent.left
@@ -120,7 +127,6 @@ PanelWindow {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -130,21 +136,26 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
powerMenuVisible = false;
root.powerConfirmAction = "logout";
root.powerConfirmTitle = "Log Out";
root.powerConfirmMessage = "Are you sure you want to log out?";
root.powerConfirmVisible = true;
powerMenuVisible = false
root.powerConfirmAction = "logout"
root.powerConfirmTitle = "Log Out"
root.powerConfirmMessage = "Are you sure you want to log out?"
root.powerConfirmVisible = true
}
}
}
Rectangle {
width: parent.width
height: 50
radius: Theme.cornerRadius
color: suspendArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)
color: suspendArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.08) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
Row {
anchors.left: parent.left
@@ -166,7 +177,6 @@ PanelWindow {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -176,21 +186,26 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
powerMenuVisible = false;
root.powerConfirmAction = "suspend";
root.powerConfirmTitle = "Suspend";
root.powerConfirmMessage = "Are you sure you want to suspend the system?";
root.powerConfirmVisible = true;
powerMenuVisible = false
root.powerConfirmAction = "suspend"
root.powerConfirmTitle = "Suspend"
root.powerConfirmMessage = "Are you sure you want to suspend the system?"
root.powerConfirmVisible = true
}
}
}
Rectangle {
width: parent.width
height: 50
radius: Theme.cornerRadius
color: rebootArea.containsMouse ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)
color: rebootArea.containsMouse ? Qt.rgba(Theme.warning.r,
Theme.warning.g,
Theme.warning.b,
0.08) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
Row {
anchors.left: parent.left
@@ -212,7 +227,6 @@ PanelWindow {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -222,21 +236,26 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
powerMenuVisible = false;
root.powerConfirmAction = "reboot";
root.powerConfirmTitle = "Reboot";
root.powerConfirmMessage = "Are you sure you want to reboot the system?";
root.powerConfirmVisible = true;
powerMenuVisible = false
root.powerConfirmAction = "reboot"
root.powerConfirmTitle = "Reboot"
root.powerConfirmMessage = "Are you sure you want to reboot the system?"
root.powerConfirmVisible = true
}
}
}
Rectangle {
width: parent.width
height: 50
radius: Theme.cornerRadius
color: powerOffArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)
color: powerOffArea.containsMouse ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.08) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
Row {
anchors.left: parent.left
@@ -258,7 +277,6 @@ PanelWindow {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -268,18 +286,15 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
powerMenuVisible = false;
root.powerConfirmAction = "poweroff";
root.powerConfirmTitle = "Power Off";
root.powerConfirmMessage = "Are you sure you want to power off the system?";
root.powerConfirmVisible = true;
powerMenuVisible = false
root.powerConfirmAction = "poweroff"
root.powerConfirmTitle = "Power Off"
root.powerConfirmMessage = "Are you sure you want to power off the system?"
root.powerConfirmVisible = true
}
}
}
}
}
Behavior on opacity {
@@ -287,7 +302,6 @@ PanelWindow {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
@@ -295,9 +309,6 @@ PanelWindow {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}

View File

@@ -20,21 +20,30 @@ PanelWindow {
property bool autoHide: SettingsData.dockAutoHide
property real backgroundTransparency: SettingsData.dockTransparency
property bool contextMenuOpen: (contextMenu && contextMenu.visible && contextMenu.screen === modelData) || (windowsMenu && windowsMenu.visible && windowsMenu.screen === modelData)
property bool contextMenuOpen: (contextMenu && contextMenu.visible
&& contextMenu.screen === modelData)
|| (windowsMenu && windowsMenu.visible
&& windowsMenu.screen === modelData)
property bool windowIsFullscreen: {
if (!NiriService.focusedWindowId || !NiriService.niriAvailable) return false
var focusedWindow = NiriService.windows.find(w => w.id === NiriService.focusedWindowId)
if (!focusedWindow) return false
if (!NiriService.focusedWindowId || !NiriService.niriAvailable)
return false
var focusedWindow = NiriService.windows.find(
w => w.id === NiriService.focusedWindowId)
if (!focusedWindow)
return false
var fullscreenApps = ["vlc", "mpv", "kodi", "steam", "lutris", "wine", "dosbox"]
return fullscreenApps.some(app => focusedWindow.app_id && focusedWindow.app_id.toLowerCase().includes(app))
return fullscreenApps.some(app => focusedWindow.app_id
&& focusedWindow.app_id.toLowerCase(
).includes(app))
}
property bool reveal: (!autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen) && !windowIsFullscreen
property bool reveal: (!autoHide || dockMouseArea.containsMouse
|| dockApps.requestDockShow || contextMenuOpen)
&& !windowIsFullscreen
Connections {
target: SettingsData
function onDockTransparencyChanged() {
dock.backgroundTransparency = SettingsData.dockTransparency;
dock.backgroundTransparency = SettingsData.dockTransparency
}
}
@@ -77,7 +86,6 @@ PanelWindow {
}
}
Item {
id: dockContainer
anchors.fill: parent
@@ -109,7 +117,8 @@ PanelWindow {
anchors.topMargin: 4
anchors.bottomMargin: 1
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, backgroundTransparency)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, backgroundTransparency)
radius: Theme.cornerRadiusXLarge
border.width: 1
border.color: Theme.outlineMedium
@@ -117,7 +126,8 @@ PanelWindow {
Rectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g,
Theme.surfaceTint.b, 0.04)
radius: parent.radius
}
@@ -133,24 +143,26 @@ PanelWindow {
contextMenu: dock.contextMenu
windowsMenu: dock.windowsMenu
}
}
Rectangle {
id: appTooltip
property var hoveredButton: {
if (!dockApps.children[0]) return null
if (!dockApps.children[0])
return null
var row = dockApps.children[0]
var repeater = null
for (var i = 0; i < row.children.length; i++) {
var child = row.children[i]
if (child && typeof child.count !== "undefined" && typeof child.itemAt === "function") {
if (child && typeof child.count !== "undefined"
&& typeof child.itemAt === "function") {
repeater = child
break
}
}
if (!repeater || !repeater.itemAt) return null
if (!repeater || !repeater.itemAt)
return null
for (var i = 0; i < repeater.count; i++) {
var item = repeater.itemAt(i)
if (item && item.dockButton && item.dockButton.showTooltip) {
@@ -172,7 +184,9 @@ PanelWindow {
border.color: Theme.outlineMedium
y: -height - 8
x: hoveredButton ? hoveredButton.mapToItem(dockContainer, hoveredButton.width/2, 0).x - width/2 : 0
x: hoveredButton ? hoveredButton.mapToItem(dockContainer,
hoveredButton.width / 2,
0).x - width / 2 : 0
StyledText {
id: tooltipLabel
@@ -181,7 +195,6 @@ PanelWindow {
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
}
}
}
}

View File

@@ -106,18 +106,19 @@ Item {
cursorShape: longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onPressed: (mouse) => {
if (mouse.button === Qt.LeftButton && appData && appData.isPinned) {
onPressed: mouse => {
if (mouse.button === Qt.LeftButton && appData
&& appData.isPinned) {
dragStartPos = Qt.point(mouse.x, mouse.y)
longPressTimer.start()
}
}
onReleased: (mouse) => {
onReleased: mouse => {
longPressTimer.stop()
if (longPressing) {
if (dragging && targetIndex >= 0 && targetIndex !== originalIndex && dockApps) {
if (dragging && targetIndex >= 0
&& targetIndex !== originalIndex && dockApps) {
dockApps.movePinnedApp(originalIndex, targetIndex)
}
@@ -129,9 +130,12 @@ Item {
}
}
onPositionChanged: (mouse) => {
onPositionChanged: mouse => {
if (longPressing && !dragging) {
var distance = Math.sqrt(Math.pow(mouse.x - dragStartPos.x, 2) + Math.pow(mouse.y - dragStartPos.y, 2))
var distance = Math.sqrt(
Math.pow(mouse.x - dragStartPos.x,
2) + Math.pow(mouse.y - dragStartPos.y,
2))
if (distance > 5) {
dragging = true
targetIndex = index
@@ -140,15 +144,18 @@ Item {
}
if (dragging) {
dragOffset = Qt.point(mouse.x - dragStartPos.x, mouse.y - dragStartPos.y)
dragOffset = Qt.point(mouse.x - dragStartPos.x,
mouse.y - dragStartPos.y)
if (dockApps) {
var threshold = 40
var newTargetIndex = targetIndex
if (dragOffset.x > threshold && targetIndex < dockApps.pinnedAppCount - 1) {
if (dragOffset.x > threshold
&& targetIndex < dockApps.pinnedAppCount - 1) {
newTargetIndex = targetIndex + 1
} else if (dragOffset.x < -threshold && targetIndex > 0) {
} else if (dragOffset.x < -threshold
&& targetIndex > 0) {
newTargetIndex = targetIndex - 1
}
@@ -160,8 +167,9 @@ Item {
}
}
onClicked: (mouse) => {
if (!appData || longPressing) return
onClicked: mouse => {
if (!appData || longPressing)
return
if (mouse.button === Qt.LeftButton) {
var windowCount = appData.windows ? appData.windows.count : 0
@@ -171,11 +179,15 @@ Item {
var desktopEntry = DesktopEntries.byId(appData.appId)
if (desktopEntry) {
AppUsageHistoryData.addAppUsage({
id: appData.appId,
name: desktopEntry.name || appData.appId,
icon: desktopEntry.icon || "",
exec: desktopEntry.exec || "",
comment: desktopEntry.comment || ""
"id": appData.appId,
"name": desktopEntry.name
|| appData.appId,
"icon": desktopEntry.icon
|| "",
"exec": desktopEntry.exec
|| "",
"comment": desktopEntry.comment
|| ""
})
}
Quickshell.execDetached(["gtk-launch", appData.appId])
@@ -191,11 +203,15 @@ Item {
var desktopEntry = DesktopEntries.byId(appData.appId)
if (desktopEntry) {
AppUsageHistoryData.addAppUsage({
id: appData.appId,
name: desktopEntry.name || appData.appId,
icon: desktopEntry.icon || "",
exec: desktopEntry.exec || "",
comment: desktopEntry.comment || ""
"id": appData.appId,
"name": desktopEntry.name
|| appData.appId,
"icon": desktopEntry.icon
|| "",
"exec": desktopEntry.exec
|| "",
"comment": desktopEntry.comment
|| ""
})
}
Quickshell.execDetached(["gtk-launch", appData.appId])
@@ -210,22 +226,25 @@ Item {
property bool showTooltip: mouseArea.containsMouse && !dragging
property string tooltipText: {
if (!appData || !appData.appId) return ""
if (!appData || !appData.appId)
return ""
var desktopEntry = DesktopEntries.byId(appData.appId)
return desktopEntry && desktopEntry.name ? desktopEntry.name : appData.appId
}
IconImage {
id: iconImg
width: 40
height: 40
anchors.centerIn: parent
source: {
if (!appData || !appData.appId) return ""
if (!appData || !appData.appId)
return ""
var desktopEntry = DesktopEntries.byId(appData.appId)
if (desktopEntry && desktopEntry.icon) {
var iconPath = Quickshell.iconPath(desktopEntry.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme)
var iconPath = Quickshell.iconPath(
desktopEntry.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme)
return iconPath
}
return ""
@@ -250,7 +269,8 @@ Item {
Text {
anchors.centerIn: parent
text: {
if (!appData || !appData.appId) return "?"
if (!appData || !appData.appId)
return "?"
var desktopEntry = DesktopEntries.byId(appData.appId)
if (desktopEntry && desktopEntry.name) {
return desktopEntry.name.charAt(0).toUpperCase()
@@ -263,7 +283,6 @@ Item {
}
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
@@ -278,10 +297,15 @@ Item {
height: 2
radius: 1
color: {
if (!appData || !appData.windows || appData.windows.count === 0) return "transparent"
if (!appData || !appData.windows || appData.windows.count === 0)
return "transparent"
var window = appData.windows.get(index)
return window && window.id == NiriService.focusedWindowId ? Theme.primary :
Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
return window
&& window.id == NiriService.focusedWindowId ? Theme.primary : Qt.rgba(
Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.6)
}
}
}

View File

@@ -17,10 +17,13 @@ Item {
implicitHeight: row.height
function movePinnedApp(fromIndex, toIndex) {
if (fromIndex === toIndex) return
if (fromIndex === toIndex)
return
var currentPinned = [...(SessionData.pinnedApps || [])]
if (fromIndex < 0 || fromIndex >= currentPinned.length || toIndex < 0 || toIndex >= currentPinned.length) return
if (fromIndex < 0 || fromIndex >= currentPinned.length || toIndex < 0
|| toIndex >= currentPinned.length)
return
var movedApp = currentPinned.splice(fromIndex, 1)[0]
currentPinned.splice(toIndex, 0, movedApp)
@@ -49,16 +52,16 @@ Item {
var pinnedApps = [...(SessionData.pinnedApps || [])]
var addedApps = new Set()
pinnedApps.forEach(appId => {
var lowerAppId = appId.toLowerCase()
if (!addedApps.has(lowerAppId)) {
var windows = NiriService.getWindowsByAppId(appId)
var windows = NiriService.getWindowsByAppId(
appId)
items.push({
appId: appId,
windows: windows,
isPinned: true,
isRunning: windows.length > 0
"appId": appId,
"windows": windows,
"isPinned": true,
"isRunning": windows.length > 0
})
addedApps.add(lowerAppId)
}
@@ -85,10 +88,12 @@ Item {
var recentApps = []
for (var appId in appUsageRanking) {
var lowerAppId = appId.toLowerCase()
if (!addedApps.has(lowerAppId) && !unpinnedAppsSet.has(lowerAppId)) {
if (!addedApps.has(lowerAppId) && !unpinnedAppsSet.has(
lowerAppId)) {
recentApps.push({
appId: appId,
lastUsed: appUsageRanking[appId].lastUsed || 0
"appId": appId,
"lastUsed": appUsageRanking[appId].lastUsed
|| 0
})
}
}
@@ -101,19 +106,20 @@ Item {
}
if (pinnedApps.length > 0 && unpinnedApps.length > 0) {
items.push({
appId: "__SEPARATOR__",
windows: [],
isPinned: false,
isRunning: false
"appId": "__SEPARATOR__",
"windows": [],
"isPinned": false,
"isRunning": false
})
}
unpinnedApps.forEach(appId => {
var windows = NiriService.getWindowsByAppId(appId)
var windows = NiriService.getWindowsByAppId(
appId)
items.push({
appId: appId,
windows: windows,
isPinned: false,
isRunning: windows.length > 0
"appId": appId,
"windows": windows,
"isPinned": false,
"isRunning": windows.length > 0
})
})
items.forEach(item => {
@@ -158,12 +164,18 @@ Item {
Connections {
target: NiriService
function onWindowsChanged() { dockModel.updateModel() }
function onWindowOpenedOrChanged() { dockModel.updateModel() }
function onWindowsChanged() {
dockModel.updateModel()
}
function onWindowOpenedOrChanged() {
dockModel.updateModel()
}
}
Connections {
target: SessionData
function onPinnedAppsChanged() { dockModel.updateModel() }
function onPinnedAppsChanged() {
dockModel.updateModel()
}
}
}

View File

@@ -34,7 +34,9 @@ PanelWindow {
showContextMenu = true
}
function close() { showContextMenu = false }
function close() {
showContextMenu = false
}
screen: Quickshell.screens[0]
@@ -43,22 +45,28 @@ PanelWindow {
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent"
anchors { top: true; left: true; right: true; bottom: true }
anchors {
top: true
left: true
right: true
bottom: true
}
property point anchorPos: Qt.point(screen.width/2, screen.height - 100)
property point anchorPos: Qt.point(screen.width / 2, screen.height - 100)
onAnchorItemChanged: updatePosition()
onVisibleChanged: if (visible) updatePosition()
onVisibleChanged: if (visible)
updatePosition()
function updatePosition() {
if (!anchorItem) {
anchorPos = Qt.point(screen.width/2, screen.height - 100)
anchorPos = Qt.point(screen.width / 2, screen.height - 100)
return
}
var dockWindow = anchorItem.Window.window
if (!dockWindow) {
anchorPos = Qt.point(screen.width/2, screen.height - 100)
anchorPos = Qt.point(screen.width / 2, screen.height - 100)
return
}
@@ -72,7 +80,8 @@ PanelWindow {
}
for (var i = 0; i < item.children.length; i++) {
var found = findDockBackground(item.children[i])
if (found) return found
if (found)
return found
}
return null
}
@@ -88,7 +97,7 @@ PanelWindow {
var dockContentWidth = dockWindow.width
var screenWidth = root.screen.width
var dockLeftMargin = Math.round((screenWidth - dockContentWidth) / 2)
var buttonScreenX = dockLeftMargin + buttonPosInDock.x + anchorItem.width/2
var buttonScreenX = dockLeftMargin + buttonPosInDock.x + anchorItem.width / 2
anchorPos = Qt.point(buttonScreenX, buttonScreenY)
}
@@ -96,19 +105,22 @@ PanelWindow {
Rectangle {
id: menuContainer
width: Math.min(400, Math.max(200, menuColumn.implicitWidth + Theme.spacingS * 2))
width: Math.min(400,
Math.max(200,
menuColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
x: {
var left = 10
var right = root.width - width - 10
var want = root.anchorPos.x - width/2
var want = root.anchorPos.x - width / 2
return Math.max(left, Math.min(right, want))
}
y: Math.max(10, root.anchorPos.y - height + 30)
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
opacity: showContextMenu ? 1 : 0
scale: showContextMenu ? 1 : 0.85
@@ -136,7 +148,10 @@ PanelWindow {
width: parent.width
height: 28
radius: Theme.cornerRadiusSmall
color: pinArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: pinArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText {
anchors.left: parent.left
@@ -144,7 +159,8 @@ PanelWindow {
anchors.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
text: root.appData && root.appData.isPinned ? "Unpin from Dock" : "Pin to Dock"
text: root.appData
&& root.appData.isPinned ? "Unpin from Dock" : "Pin to Dock"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
@@ -158,7 +174,8 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!root.appData) return
if (!root.appData)
return
if (root.appData.isPinned) {
SessionData.removePinnedApp(root.appData.appId)
} else {
@@ -170,21 +187,26 @@ PanelWindow {
}
Rectangle {
visible: root.appData && root.appData.windows && root.appData.windows.count > 0
visible: root.appData && root.appData.windows
&& root.appData.windows.count > 0
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
Repeater {
model: root.appData && root.appData.windows ? root.appData.windows : null
model: root.appData
&& root.appData.windows ? root.appData.windows : null
Rectangle {
required property var model
width: menuColumn.width
height: 28
radius: Theme.cornerRadiusSmall
color: windowArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: windowArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText {
anchors.left: parent.left
@@ -214,18 +236,23 @@ PanelWindow {
}
Rectangle {
visible: root.appData && root.appData.windows && root.appData.windows.count > 1
visible: root.appData && root.appData.windows
&& root.appData.windows.count > 1
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
Rectangle {
visible: root.appData && root.appData.windows && root.appData.windows.count > 1
visible: root.appData && root.appData.windows
&& root.appData.windows.count > 1
width: parent.width
height: 28
radius: Theme.cornerRadiusSmall
color: closeAllArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
color: closeAllArea.containsMouse ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.12) : "transparent"
StyledText {
anchors.left: parent.left
@@ -247,7 +274,8 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!root.appData || !root.appData.windows) return
if (!root.appData || !root.appData.windows)
return
for (var i = 0; i < root.appData.windows.count; i++) {
var window = root.appData.windows.get(i)
NiriService.closeWindow(window.id)

View File

@@ -35,7 +35,9 @@ PanelWindow {
showWindowsMenu = true
}
function close() { showWindowsMenu = false }
function close() {
showWindowsMenu = false
}
screen: Quickshell.screens[0]
@@ -44,22 +46,28 @@ PanelWindow {
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent"
anchors { top: true; left: true; right: true; bottom: true }
anchors {
top: true
left: true
right: true
bottom: true
}
property point anchorPos: Qt.point(screen.width/2, screen.height - 100)
property point anchorPos: Qt.point(screen.width / 2, screen.height - 100)
onAnchorItemChanged: updatePosition()
onVisibleChanged: if (visible) updatePosition()
onVisibleChanged: if (visible)
updatePosition()
function updatePosition() {
if (!anchorItem) {
anchorPos = Qt.point(screen.width/2, screen.height - 100)
anchorPos = Qt.point(screen.width / 2, screen.height - 100)
return
}
var dockWindow = anchorItem.Window.window
if (!dockWindow) {
anchorPos = Qt.point(screen.width/2, screen.height - 100)
anchorPos = Qt.point(screen.width / 2, screen.height - 100)
return
}
@@ -73,7 +81,8 @@ PanelWindow {
}
for (var i = 0; i < item.children.length; i++) {
var found = findDockBackground(item.children[i])
if (found) return found
if (found)
return found
}
return null
}
@@ -89,7 +98,7 @@ PanelWindow {
var dockContentWidth = dockWindow.width
var screenWidth = root.screen.width
var dockLeftMargin = Math.round((screenWidth - dockContentWidth) / 2)
var buttonScreenX = dockLeftMargin + buttonPosInDock.x + anchorItem.width/2
var buttonScreenX = dockLeftMargin + buttonPosInDock.x + anchorItem.width / 2
anchorPos = Qt.point(buttonScreenX, buttonScreenY)
}
@@ -97,24 +106,26 @@ PanelWindow {
Rectangle {
id: menuContainer
width: Math.min(600, Math.max(250, windowColumn.implicitWidth + Theme.spacingS * 2))
width: Math.min(600,
Math.max(250,
windowColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(60, windowColumn.implicitHeight + Theme.spacingS * 2)
x: {
var left = 10
var right = root.width - width - 10
var want = root.anchorPos.x - width/2
var want = root.anchorPos.x - width / 2
return Math.max(left, Math.min(right, want))
}
y: Math.max(10, root.anchorPos.y - height + 30)
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
opacity: showWindowsMenu ? 1 : 0
scale: showWindowsMenu ? 1 : 0.85
Rectangle {
anchors.fill: parent
anchors.topMargin: 4
@@ -126,7 +137,6 @@ PanelWindow {
z: parent.z - 1
}
Column {
id: windowColumn
width: parent.width - Theme.spacingS * 2
@@ -136,14 +146,18 @@ PanelWindow {
spacing: 1
Repeater {
model: root.appData && root.appData.windows ? root.appData.windows : null
model: root.appData
&& root.appData.windows ? root.appData.windows : null
Rectangle {
required property var model
width: windowColumn.width
height: 32
radius: Theme.cornerRadiusSmall
color: windowArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: windowArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText {
anchors.left: parent.left

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import Quickshell
@@ -32,7 +32,7 @@ Item {
LockSurface {
lock: lock
sharedPasswordBuffer: lock.sharedPasswordBuffer
onPasswordChanged: (newPassword) => {
onPasswordChanged: newPassword => {
lock.sharedPasswordBuffer = newPassword
}
}

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import QtQuick.Controls
@@ -21,32 +21,11 @@ Item {
property var powerModal: null
property string confirmAction: ""
property var facts: [
"Light takes 100,000 years to escape the Sun's core, then just 8 minutes to reach us.",
"A teaspoon of neutron star matter would weigh a billion tons here on Earth.",
"Right now, 100 trillion solar neutrinos are passing through your body every second.",
"The Sun burns 4 million tons of itself into pure energy every second.",
"The universe still glows with leftover heat from the Big Bang—just 2.7 degrees above absolute zero.",
"There's a nebula out there that's actually colder than empty space itself.",
"We've detected black holes crashing together by measuring spacetime stretch by less than 1/10,000th the width of a proton.",
"Some cosmic radio bursts release more energy in milliseconds than our Sun does in days.",
"Our galaxy might be crawling with billions of rogue planets drifting alone in the dark.",
"Distant galaxies can move away from us faster than light because space itself is stretching.",
"The edge of what we can see is 46.5 billion light-years away, even though the universe is only 13.8 billion years old.",
"The universe is mostly invisible: 5% regular matter, 27% dark matter, 68% dark energy.",
"A day on Venus lasts longer than its entire year around the Sun.",
"On Mercury, the time between sunrises is 176 Earth days long.",
"In about 4.5 billion years, our galaxy will smash into Andromeda.",
"Most of the gold in your jewelry was forged when neutron stars collided somewhere in space.",
"A black hole the mass of our Sun would take longer to evaporate than the current age of the universe... times a trillion trillion trillion trillion trillion.",
"The fastest spinning star we know rotates 716 times per second.",
"Cosmic rays create particles that shouldn't make it to Earth's surface, but time dilation lets them sneak through.",
"Jupiter's magnetic field is so huge that if we could see it, it would look bigger than the Moon in our sky."
]
property var facts: ["Light takes 100,000 years to escape the Sun's core, then just 8 minutes to reach us.", "A teaspoon of neutron star matter would weigh a billion tons here on Earth.", "Right now, 100 trillion solar neutrinos are passing through your body every second.", "The Sun burns 4 million tons of itself into pure energy every second.", "The universe still glows with leftover heat from the Big Bang—just 2.7 degrees above absolute zero.", "There's a nebula out there that's actually colder than empty space itself.", "We've detected black holes crashing together by measuring spacetime stretch by less than 1/10,000th the width of a proton.", "Some cosmic radio bursts release more energy in milliseconds than our Sun does in days.", "Our galaxy might be crawling with billions of rogue planets drifting alone in the dark.", "Distant galaxies can move away from us faster than light because space itself is stretching.", "The edge of what we can see is 46.5 billion light-years away, even though the universe is only 13.8 billion years old.", "The universe is mostly invisible: 5% regular matter, 27% dark matter, 68% dark energy.", "A day on Venus lasts longer than its entire year around the Sun.", "On Mercury, the time between sunrises is 176 Earth days long.", "In about 4.5 billion years, our galaxy will smash into Andromeda.", "Most of the gold in your jewelry was forged when neutron stars collided somewhere in space.", "A black hole the mass of our Sun would take longer to evaporate than the current age of the universe... times a trillion trillion trillion trillion trillion.", "The fastest spinning star we know rotates 716 times per second.", "Cosmic rays create particles that shouldn't make it to Earth's surface, but time dilation lets them sneak through.", "Jupiter's magnetic field is so huge that if we could see it, it would look bigger than the Moon in our sky."]
property string randomFact: ""
signal unlockRequested()
signal unlockRequested
Component.onCompleted: {
pickRandomFact()
@@ -115,7 +94,10 @@ Item {
id: clockText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
text: SettingsData.use24HourClock ? Qt.formatTime(new Date(), "H:mm") : Qt.formatTime(new Date(), "h:mm AP")
text: SettingsData.use24HourClock ? Qt.formatTime(
new Date(),
"H:mm") : Qt.formatTime(
new Date(), "h:mm AP")
font.pixelSize: 120
font.weight: Font.Light
color: "white"
@@ -125,7 +107,11 @@ Item {
interval: 1000
running: true
repeat: true
onTriggered: parent.text = SettingsData.use24HourClock ? Qt.formatTime(new Date(), "H:mm") : Qt.formatTime(new Date(), "h:mm AP")
onTriggered: parent.text = SettingsData.use24HourClock ? Qt.formatTime(
new Date(),
"H:mm") : Qt.formatTime(
new Date(),
"h:mm AP")
}
}
@@ -227,7 +213,8 @@ Item {
name: "warning"
size: Theme.iconSize + 4
color: Theme.primaryText
visible: PortalService.profileImage !== "" && profileImageLoader.status === Image.Error
visible: PortalService.profileImage !== ""
&& profileImageLoader.status === Image.Error
}
}
@@ -235,8 +222,10 @@ Item {
Layout.fillWidth: true
Layout.preferredHeight: 60
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.9)
border.color: passwordField.activeFocus ? Theme.primary : Qt.rgba(1, 1, 1, 0.3)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.9)
border.color: passwordField.activeFocus ? Theme.primary : Qt.rgba(
1, 1, 1, 0.3)
border.width: passwordField.activeFocus ? 2 : 1
property bool showPassword: false
@@ -262,7 +251,10 @@ Item {
id: passwordField
anchors.fill: parent
anchors.leftMargin: lockIcon.width + Theme.spacingM * 2
anchors.rightMargin: (revealButton.visible ? revealButton.width + Theme.spacingM : 0) + (enterButton.visible ? enterButton.width + Theme.spacingM : 0) + (loadingSpinner.visible ? loadingSpinner.width + Theme.spacingM : Theme.spacingM)
anchors.rightMargin: (revealButton.visible ? revealButton.width + Theme.spacingM : 0)
+ (enterButton.visible ? enterButton.width + Theme.spacingM : 0)
+ (loadingSpinner.visible ? loadingSpinner.width
+ Theme.spacingM : Theme.spacingM)
opacity: 0
focus: !demoMode
enabled: !demoMode
@@ -289,7 +281,8 @@ Item {
}
Keys.onPressed: event => {
if (demoMode) return
if (demoMode)
return
if (pam.active) {
console.log("PAM is active, ignoring input")
@@ -310,9 +303,12 @@ Item {
property string pamState: ""
text: {
if (demoMode) return ""
if (root.unlocking) return "Unlocking..."
if (pam.active) return "Authenticating..."
if (demoMode)
return ""
if (root.unlocking)
return "Unlocking..."
if (pam.active)
return "Authenticating..."
return "hunter2"
}
@@ -372,7 +368,8 @@ Item {
anchors.verticalCenter: parent.verticalCenter
iconName: parent.showPassword ? "visibility_off" : "visibility"
buttonSize: 32
visible: !demoMode && root.passwordBuffer.length > 0 && !pam.active && !root.unlocking
visible: !demoMode && root.passwordBuffer.length > 0 && !pam.active
&& !root.unlocking
enabled: visible
onClicked: parent.showPassword = !parent.showPassword
}
@@ -397,8 +394,20 @@ Item {
SequentialAnimation on scale {
running: root.unlocking
NumberAnimation { from: 0; to: 1.2; duration: Anims.durShort; easing.type: Easing.BezierSpline; easing.bezierCurve: Anims.emphasizedDecel }
NumberAnimation { from: 1.2; to: 1; duration: Anims.durShort; easing.type: Easing.BezierSpline; easing.bezierCurve: Anims.emphasizedAccel }
NumberAnimation {
from: 0
to: 1.2
duration: Anims.durShort
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasizedDecel
}
NumberAnimation {
from: 1.2
to: 1
duration: Anims.durShort
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasizedAccel
}
}
}
@@ -412,7 +421,8 @@ Item {
radius: 10
anchors.centerIn: parent
color: "transparent"
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.3)
border.width: 2
}
@@ -430,7 +440,9 @@ Item {
height: parent.height / 2
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.9)
color: Qt.rgba(Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.9)
}
RotationAnimation on rotation {
@@ -451,7 +463,8 @@ Item {
anchors.verticalCenter: parent.verticalCenter
iconName: "keyboard_return"
buttonSize: 36
visible: (demoMode || (root.passwordBuffer.length > 0 && !pam.active && !root.unlocking))
visible: (demoMode || (root.passwordBuffer.length > 0 && !pam.active
&& !root.unlocking))
enabled: !demoMode
onClicked: {
if (!demoMode) {
@@ -468,16 +481,18 @@ Item {
}
}
}
}
StyledText {
Layout.fillWidth: true
Layout.preferredHeight: placeholder.pamState ? 20 : 0
text: {
if (placeholder.pamState === "error") return "Authentication error - try again"
if (placeholder.pamState === "max") return "Too many attempts - locked out"
if (placeholder.pamState === "fail") return "Incorrect password - try again"
if (placeholder.pamState === "error")
return "Authentication error - try again"
if (placeholder.pamState === "max")
return "Too many attempts - locked out"
if (placeholder.pamState === "fail")
return "Incorrect password - try again"
return ""
}
color: Theme.error
@@ -517,9 +532,8 @@ Item {
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: Theme.spacingXL
text: WeatherService.weather.available && WeatherService.weather.city && WeatherService.weather.city !== "Unknown" ?
`${WeatherService.weather.city} ${(SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp)}°${(SettingsData.useFahrenheit ? "F" : "C")}` :
""
text: WeatherService.weather.available && WeatherService.weather.city
&& WeatherService.weather.city !== "Unknown" ? `${WeatherService.weather.city} ${(SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp)}°${(SettingsData.useFahrenheit ? "F" : "C")}` : ""
font.pixelSize: Theme.fontSizeMedium
color: "white"
horizontalAlignment: Text.AlignRight
@@ -606,15 +620,19 @@ Item {
config: pamConfigWatcher.loaded ? "dankshell" : "login"
onResponseRequiredChanged: {
if (demoMode) return
if (demoMode)
return
console.log("PAM response required:", responseRequired)
if (!responseRequired) return
console.log("Responding to PAM with password buffer length:", root.passwordBuffer.length)
if (!responseRequired)
return
console.log("Responding to PAM with password buffer length:",
root.passwordBuffer.length)
respond(root.passwordBuffer)
}
onCompleted: res => {
if (demoMode) return
if (demoMode)
return
console.log("PAM authentication completed with result:", res)
if (res === PamResult.Success) {
console.log("Authentication successful, unlocking")
@@ -656,8 +674,12 @@ Item {
visible: false
z: 1000
function open() { visible = true }
function close() { visible = false }
function open() {
visible = true
}
function close() {
visible = false
}
Rectangle {
anchors.centerIn: parent
@@ -695,8 +717,11 @@ Item {
width: 100
height: 40
radius: Theme.cornerRadius
color: cancelMouse1.pressed ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.7) :
cancelMouse1.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
color: cancelMouse1.pressed ? Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.7) : cancelMouse1.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
StyledText {
anchors.centerIn: parent
@@ -718,8 +743,14 @@ Item {
width: 100
height: 40
radius: Theme.cornerRadius
color: powerMouse.pressed ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.8) :
powerMouse.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 1.0) : Theme.error
color: powerMouse.pressed ? Qt.rgba(
Theme.error.r, Theme.error.g,
Theme.error.b,
0.8) : powerMouse.containsMouse ? Qt.rgba(
Theme.error.r,
Theme.error.g,
Theme.error.b,
1.0) : Theme.error
StyledText {
anchors.centerIn: parent
@@ -752,8 +783,12 @@ Item {
visible: false
z: 1000
function open() { visible = true }
function close() { visible = false }
function open() {
visible = true
}
function close() {
visible = false
}
Rectangle {
anchors.centerIn: parent
@@ -791,8 +826,11 @@ Item {
width: 100
height: 40
radius: Theme.cornerRadius
color: cancelMouse2.pressed ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.7) :
cancelMouse2.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
color: cancelMouse2.pressed ? Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.7) : cancelMouse2.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
StyledText {
anchors.centerIn: parent
@@ -814,8 +852,14 @@ Item {
width: 100
height: 40
radius: Theme.cornerRadius
color: rebootMouse.pressed ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8) :
rebootMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1.0) : Theme.primary
color: rebootMouse.pressed ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.8) : rebootMouse.containsMouse ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
1.0) : Theme.primary
StyledText {
anchors.centerIn: parent
@@ -848,8 +892,12 @@ Item {
visible: false
z: 1000
function open() { visible = true }
function close() { visible = false }
function open() {
visible = true
}
function close() {
visible = false
}
Rectangle {
anchors.centerIn: parent
@@ -887,8 +935,11 @@ Item {
width: 100
height: 40
radius: Theme.cornerRadius
color: cancelMouse3.pressed ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.7) :
cancelMouse3.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
color: cancelMouse3.pressed ? Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.7) : cancelMouse3.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
StyledText {
anchors.centerIn: parent
@@ -910,8 +961,14 @@ Item {
width: 100
height: 40
radius: Theme.cornerRadius
color: logoutMouse.pressed ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8) :
logoutMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1.0) : Theme.primary
color: logoutMouse.pressed ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.8) : logoutMouse.containsMouse ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
1.0) : Theme.primary
StyledText {
anchors.centerIn: parent
@@ -936,5 +993,4 @@ Item {
}
}
}
}

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import Quickshell

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import Quickshell

View File

@@ -14,8 +14,8 @@ PanelWindow {
property bool micPopupVisible: false
function show() {
root.micPopupVisible = true;
hideTimer.restart();
root.micPopupVisible = true
hideTimer.restart()
}
screen: modelData
@@ -38,13 +38,13 @@ PanelWindow {
interval: 2000
repeat: false
onTriggered: {
root.micPopupVisible = false;
root.micPopupVisible = false
}
}
Connections {
function onMicMuteChanged() {
root.show();
root.show()
}
target: AudioService
@@ -60,7 +60,8 @@ PanelWindow {
anchors.bottomMargin: Theme.spacingM
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
opacity: root.micPopupVisible ? 1 : 0
scale: root.micPopupVisible ? 1 : 0.9
@@ -70,9 +71,11 @@ PanelWindow {
id: micContent
anchors.centerIn: parent
name: AudioService.source && AudioService.source.audio && AudioService.source.audio.muted ? "mic_off" : "mic"
name: AudioService.source && AudioService.source.audio
&& AudioService.source.audio.muted ? "mic_off" : "mic"
size: Theme.iconSize
color: AudioService.source && AudioService.source.audio && AudioService.source.audio.muted ? Theme.error : Theme.primary
color: AudioService.source && AudioService.source.audio
&& AudioService.source.audio.muted ? Theme.error : Theme.primary
}
layer.effect: MultiEffect {

View File

@@ -11,25 +11,36 @@ Rectangle {
id: root
property var notificationGroup
property bool expanded: NotificationService.expandedGroups[notificationGroup?.key] || false
property bool descriptionExpanded: NotificationService.expandedMessages[notificationGroup?.latestNotification?.notification?.id + "_desc"] || false
property bool expanded: NotificationService.expandedGroups[notificationGroup?.key]
|| false
property bool descriptionExpanded: NotificationService.expandedMessages[notificationGroup?.latestNotification?.notification?.id + "_desc"]
|| false
property bool userInitiatedExpansion: false
width: parent ? parent.width : 400
height: {
if (expanded) {
return expandedContent.height + 28;
return expandedContent.height + 28
}
const baseHeight = 116;
const baseHeight = 116
if (descriptionExpanded) {
return baseHeight + descriptionText.contentHeight - (descriptionText.font.pixelSize * 1.2 * 2);
return baseHeight + descriptionText.contentHeight - (descriptionText.font.pixelSize * 1.2 * 2)
}
return baseHeight;
return baseHeight
}
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1)
border.color: notificationGroup?.latestNotification?.urgency === NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
border.width: notificationGroup?.latestNotification?.urgency === NotificationUrgency.Critical ? 2 : 1
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.1)
border.color: notificationGroup?.latestNotification?.urgency
=== NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.3) : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.05)
border.width: notificationGroup?.latestNotification?.urgency
=== NotificationUrgency.Critical ? 2 : 1
clip: true
Rectangle {
@@ -67,7 +78,9 @@ Rectangle {
Rectangle {
id: iconContainer
readonly property bool hasNotificationImage: notificationGroup?.latestNotification?.image && notificationGroup.latestNotification.image !== ""
readonly property bool hasNotificationImage: notificationGroup?.latestNotification?.image
&& notificationGroup.latestNotification.image
!== ""
width: 55
height: 55
@@ -84,24 +97,27 @@ Rectangle {
anchors.margins: 2
source: {
if (parent.hasNotificationImage)
return notificationGroup.latestNotification.cleanImage;
return notificationGroup.latestNotification.cleanImage
if (notificationGroup?.latestNotification?.appIcon) {
const appIcon = notificationGroup.latestNotification.appIcon;
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://"))
return appIcon;
return Quickshell.iconPath(appIcon, "");
const appIcon = notificationGroup.latestNotification.appIcon
if (appIcon.startsWith("file://") || appIcon.startsWith("http://")
|| appIcon.startsWith("https://"))
return appIcon
return Quickshell.iconPath(appIcon, "")
}
return "";
return ""
}
visible: status === Image.Ready
}
StyledText {
anchors.centerIn: parent
visible: !parent.hasNotificationImage && (!notificationGroup?.latestNotification?.appIcon || notificationGroup.latestNotification.appIcon === "")
visible: !parent.hasNotificationImage
&& (!notificationGroup?.latestNotification?.appIcon
|| notificationGroup.latestNotification.appIcon === "")
text: {
const appName = notificationGroup?.appName || "?";
return appName.charAt(0).toUpperCase();
const appName = notificationGroup?.appName || "?"
return appName.charAt(0).toUpperCase()
}
font.pixelSize: 20
font.weight: Font.Bold
@@ -121,7 +137,8 @@ Rectangle {
StyledText {
anchors.centerIn: parent
text: (notificationGroup?.count || 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString()
text: (notificationGroup?.count
|| 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString()
color: Theme.primaryText
font.pixelSize: 9
font.weight: Font.Bold
@@ -154,11 +171,12 @@ Rectangle {
StyledText {
width: parent.width
text: {
const timeStr = notificationGroup?.latestNotification?.timeStr || "";
const timeStr = notificationGroup?.latestNotification?.timeStr
|| ""
if (timeStr.length > 0)
return (notificationGroup?.appName || "") + " • " + timeStr;
return (notificationGroup?.appName || "") + " • " + timeStr
else
return notificationGroup?.appName || "";
return notificationGroup?.appName || ""
}
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
@@ -180,7 +198,8 @@ Rectangle {
StyledText {
id: descriptionText
property string fullText: notificationGroup?.latestNotification?.htmlBody || ""
property string fullText: notificationGroup?.latestNotification?.htmlBody
|| ""
property bool hasMoreText: truncated
text: fullText
@@ -192,30 +211,31 @@ Rectangle {
wrapMode: Text.WordWrap
visible: text.length > 0
linkColor: Theme.primary
onLinkActivated: (link) => Qt.openUrlExternally(link)
onLinkActivated: link => Qt.openUrlExternally(link)
MouseArea {
anchors.fill: parent
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor :
(parent.hasMoreText || descriptionExpanded) ? Qt.PointingHandCursor :
Qt.ArrowCursor
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : (parent.hasMoreText
|| descriptionExpanded) ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: mouse => {
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded)) {
const messageId = notificationGroup?.latestNotification?.notification?.id + "_desc";
NotificationService.toggleMessageExpansion(messageId);
if (!parent.hoveredLink
&& (parent.hasMoreText || descriptionExpanded)) {
const messageId = notificationGroup?.latestNotification?.notification?.id + "_desc"
NotificationService.toggleMessageExpansion(
messageId)
}
}
propagateComposedEvents: true
onPressed: mouse => {
if (parent.hoveredLink) {
mouse.accepted = false;
mouse.accepted = false
}
}
onReleased: mouse => {
if (parent.hoveredLink) {
mouse.accepted = false;
mouse.accepted = false
}
}
}
@@ -268,14 +288,15 @@ Rectangle {
StyledText {
anchors.centerIn: parent
text: (notificationGroup?.count || 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString()
text: (notificationGroup?.count
|| 0) > 99 ? "99+" : (notificationGroup?.count
|| 0).toString()
color: Theme.primaryText
font.pixelSize: 9
font.weight: Font.Bold
}
}
}
}
Column {
@@ -287,23 +308,25 @@ Rectangle {
delegate: Rectangle {
required property var modelData
readonly property bool messageExpanded: NotificationService.expandedMessages[modelData?.notification?.id] || false
readonly property bool messageExpanded: NotificationService.expandedMessages[modelData?.notification?.id]
|| false
width: parent.width
height: {
const baseHeight = 120;
const baseHeight = 120
if (messageExpanded) {
const twoLineHeight = bodyText.font.pixelSize * 1.2 * 2;
const twoLineHeight = bodyText.font.pixelSize * 1.2 * 2
if (bodyText.implicitHeight > twoLineHeight + 2) {
const extraHeight = bodyText.implicitHeight - twoLineHeight;
return baseHeight + extraHeight;
const extraHeight = bodyText.implicitHeight - twoLineHeight
return baseHeight + extraHeight
}
}
return baseHeight;
return baseHeight
}
radius: Theme.cornerRadiusLarge
color: "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.05)
border.width: 1
Behavior on height {
@@ -318,7 +341,8 @@ Rectangle {
Rectangle {
id: messageIcon
readonly property bool hasNotificationImage: modelData?.image && modelData.image !== ""
readonly property bool hasNotificationImage: modelData?.image
&& modelData.image !== ""
width: 32
height: 32
@@ -326,8 +350,10 @@ Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 32
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2)
color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.1)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.2)
border.width: 1
IconImage {
@@ -335,26 +361,28 @@ Rectangle {
anchors.margins: 1
source: {
if (parent.hasNotificationImage)
return modelData.cleanImage;
return modelData.cleanImage
if (modelData?.appIcon) {
const appIcon = modelData.appIcon;
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://"))
return appIcon;
const appIcon = modelData.appIcon
if (appIcon.startsWith("file://") || appIcon.startsWith(
"http://") || appIcon.startsWith("https://"))
return appIcon
return Quickshell.iconPath(appIcon, "");
return Quickshell.iconPath(appIcon, "")
}
return "";
return ""
}
visible: status === Image.Ready
}
StyledText {
anchors.centerIn: parent
visible: !parent.hasNotificationImage && (!modelData?.appIcon || modelData.appIcon === "")
visible: !parent.hasNotificationImage
&& (!modelData?.appIcon || modelData.appIcon === "")
text: {
const appName = modelData?.appName || "?";
return appName.charAt(0).toUpperCase();
const appName = modelData?.appName || "?"
return appName.charAt(0).toUpperCase()
}
font.pixelSize: 12
font.weight: Font.Bold
@@ -413,28 +441,29 @@ Rectangle {
wrapMode: Text.WordWrap
visible: text.length > 0
linkColor: Theme.primary
onLinkActivated: (link) => Qt.openUrlExternally(link)
onLinkActivated: link => Qt.openUrlExternally(link)
MouseArea {
anchors.fill: parent
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor :
(bodyText.hasMoreText || messageExpanded) ? Qt.PointingHandCursor :
Qt.ArrowCursor
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : (bodyText.hasMoreText || messageExpanded) ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: mouse => {
if (!parent.hoveredLink && (bodyText.hasMoreText || messageExpanded)) {
NotificationService.toggleMessageExpansion(modelData?.notification?.id || "");
if (!parent.hoveredLink
&& (bodyText.hasMoreText
|| messageExpanded)) {
NotificationService.toggleMessageExpansion(
modelData?.notification?.id || "")
}
}
propagateComposedEvents: true
onPressed: mouse => {
if (parent.hoveredLink) {
mouse.accepted = false;
mouse.accepted = false
}
}
onReleased: mouse => {
if (parent.hoveredLink) {
mouse.accepted = false;
mouse.accepted = false
}
}
}
@@ -462,7 +491,10 @@ Rectangle {
width: Math.max(actionText.implicitWidth + 12, 50)
height: 24
radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
color: isHovered ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.1) : "transparent"
StyledText {
id: actionText
@@ -482,7 +514,7 @@ Rectangle {
onExited: parent.isHovered = false
onClicked: {
if (modelData && modelData.invoke) {
modelData.invoke();
modelData.invoke()
}
}
}
@@ -495,7 +527,10 @@ Rectangle {
width: Math.max(clearText.implicitWidth + 12, 50)
height: 24
radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
color: isHovered ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.1) : "transparent"
StyledText {
id: clearText
@@ -512,7 +547,8 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onEntered: parent.isHovered = true
onExited: parent.isHovered = false
onClicked: NotificationService.dismissNotification(modelData)
onClicked: NotificationService.dismissNotification(
modelData)
}
}
}
@@ -541,7 +577,8 @@ Rectangle {
width: Math.max(actionText.implicitWidth + 12, 50)
height: 24
radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.1) : "transparent"
StyledText {
id: actionText
@@ -561,7 +598,7 @@ Rectangle {
onExited: parent.isHovered = false
onClicked: {
if (modelData && modelData.invoke) {
modelData.invoke();
modelData.invoke()
}
}
}
@@ -582,7 +619,8 @@ Rectangle {
width: clearText.width + 16
height: clearText.height + 8
radius: 6
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.1) : "transparent"
StyledText {
id: clearText
@@ -605,7 +643,8 @@ Rectangle {
MouseArea {
anchors.fill: parent
visible: !expanded && (notificationGroup?.count || 0) > 1 && !descriptionExpanded
visible: !expanded && (notificationGroup?.count || 0) > 1
&& !descriptionExpanded
onClicked: {
root.userInitiatedExpansion = true
NotificationService.toggleGroupExpansion(notificationGroup?.key || "")

View File

@@ -18,15 +18,15 @@ PanelWindow {
property string triggerSection: "right"
function setTriggerPosition(x, y, width, section) {
triggerX = x;
triggerY = y;
triggerWidth = width;
triggerSection = section;
triggerX = x
triggerY = y
triggerWidth = width
triggerSection = section
}
visible: notificationHistoryVisible
onNotificationHistoryVisibleChanged: {
NotificationService.disablePopups(notificationHistoryVisible);
NotificationService.disablePopups(notificationHistoryVisible)
}
implicitWidth: 400
implicitHeight: Math.min(Screen.height * 0.8, 400)
@@ -45,7 +45,7 @@ PanelWindow {
MouseArea {
anchors.fill: parent
onClicked: {
notificationHistoryVisible = false;
notificationHistoryVisible = false
}
}
@@ -53,34 +53,35 @@ PanelWindow {
id: mainRect
function calculateHeight() {
let baseHeight = Theme.spacingL * 2;
baseHeight += notificationHeader.height;
baseHeight += Theme.spacingM;
let listHeight = notificationList.listContentHeight;
let baseHeight = Theme.spacingL * 2
baseHeight += notificationHeader.height
baseHeight += Theme.spacingM
let listHeight = notificationList.listContentHeight
if (NotificationService.groupedNotifications.length === 0)
listHeight = 200;
listHeight = 200
baseHeight += Math.min(listHeight, 600);
return Math.max(300, baseHeight);
baseHeight += Math.min(listHeight, 600)
return Math.max(300, baseHeight)
}
readonly property real popupWidth: 400
readonly property real calculatedX: {
var centerX = root.triggerX + (root.triggerWidth / 2) - (popupWidth / 2);
var centerX = root.triggerX + (root.triggerWidth / 2) - (popupWidth / 2)
if (centerX >= Theme.spacingM && centerX + popupWidth <= Screen.width - Theme.spacingM) {
return centerX;
if (centerX >= Theme.spacingM
&& centerX + popupWidth <= Screen.width - Theme.spacingM) {
return centerX
}
if (centerX < Theme.spacingM) {
return Theme.spacingM;
return Theme.spacingM
}
if (centerX + popupWidth > Screen.width - Theme.spacingM) {
return Screen.width - popupWidth - Theme.spacingM;
return Screen.width - popupWidth - Theme.spacingM
}
return centerX;
return centerX
}
width: popupWidth
@@ -89,7 +90,8 @@ PanelWindow {
y: root.triggerY
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
opacity: notificationHistoryVisible ? 1 : 0
scale: notificationHistoryVisible ? 1 : 0.9
@@ -97,6 +99,7 @@ PanelWindow {
MouseArea {
anchors.fill: parent
onClicked: {
}
}
@@ -109,23 +112,23 @@ PanelWindow {
focus: true
Component.onCompleted: {
if (notificationHistoryVisible)
forceActiveFocus();
forceActiveFocus()
}
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
notificationHistoryVisible = false;
event.accepted = true;
notificationHistoryVisible = false
event.accepted = true
}
}
Connections {
function onNotificationHistoryVisibleChanged() {
if (notificationHistoryVisible)
Qt.callLater(function() {
contentColumn.forceActiveFocus();
});
Qt.callLater(function () {
contentColumn.forceActiveFocus()
})
else
contentColumn.focus = false;
contentColumn.focus = false
}
target: root
}
@@ -140,24 +143,23 @@ PanelWindow {
width: parent.width
height: parent.height - notificationHeader.height - contentColumn.spacing
}
}
Connections {
function onNotificationsChanged() {
mainRect.height = mainRect.calculateHeight();
mainRect.height = mainRect.calculateHeight()
}
function onGroupedNotificationsChanged() {
mainRect.height = mainRect.calculateHeight();
mainRect.height = mainRect.calculateHeight()
}
function onExpandedGroupsChanged() {
mainRect.height = mainRect.calculateHeight();
mainRect.height = mainRect.calculateHeight()
}
function onExpandedMessagesChanged() {
mainRect.height = mainRect.calculateHeight();
mainRect.height = mainRect.calculateHeight()
}
target: NotificationService
@@ -168,7 +170,6 @@ PanelWindow {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on opacity {
@@ -177,7 +178,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
Behavior on scale {
@@ -186,9 +186,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
}
}

View File

@@ -19,18 +19,18 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
name: "notifications_none"
size: Theme.iconSizeLarge + 16
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
}
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
text: "Nothing to see here"
font.pixelSize: Theme.fontSizeLarge
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
font.weight: Font.Medium
horizontalAlignment: Text.AlignHCenter
}
}
}

View File

@@ -63,13 +63,9 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}
Rectangle {
@@ -81,8 +77,14 @@ Item {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
visible: NotificationService.notifications.length > 0
color: clearArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: clearArea.containsMouse ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
color: clearArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: clearArea.containsMouse ? Theme.primary : Qt.rgba(
Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
Row {
@@ -103,7 +105,6 @@ Item {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -120,7 +121,6 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on border.color {
@@ -128,9 +128,6 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}

View File

@@ -21,7 +21,6 @@ DankListView {
anchors.centerIn: parent
}
delegate: NotificationCard {
notificationGroup: modelData
}

View File

@@ -13,52 +13,53 @@ PanelWindow {
required property var notificationData
required property string notificationId
readonly property bool hasValidData: notificationData && notificationData.notification
readonly property bool hasValidData: notificationData
&& notificationData.notification
property int screenY: 0
property bool exiting: false
property bool _isDestroying: false
property bool _finalized: false
signal entered()
signal exitFinished()
signal entered
signal exitFinished
function startExit() {
if (exiting || _isDestroying)
return ;
return
exiting = true;
exitAnim.restart();
exitWatchdog.restart();
exiting = true
exitAnim.restart()
exitWatchdog.restart()
if (NotificationService.removeFromVisibleNotifications)
NotificationService.removeFromVisibleNotifications(win.notificationData);
NotificationService.removeFromVisibleNotifications(win.notificationData)
}
function forceExit() {
if (_isDestroying)
return ;
return
_isDestroying = true;
exiting = true;
visible = false;
exitWatchdog.stop();
finalizeExit("forced");
_isDestroying = true
exiting = true
visible = false
exitWatchdog.stop()
finalizeExit("forced")
}
function finalizeExit(reason) {
if (_finalized)
return ;
return
_finalized = true;
_isDestroying = true;
exitWatchdog.stop();
wrapperConn.enabled = false;
wrapperConn.target = null;
win.exitFinished();
_finalized = true
_isDestroying = true
exitWatchdog.stop()
wrapperConn.enabled = false
wrapperConn.target = null
win.exitFinished()
}
visible: hasValidData
WlrLayershell.layer: notificationData && notificationData.urgency === NotificationUrgency.Critical ? WlrLayershell.Overlay : WlrLayershell.Top
WlrLayershell.layer: notificationData && notificationData.urgency
=== NotificationUrgency.Critical ? WlrLayershell.Overlay : WlrLayershell.Top
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent"
@@ -68,36 +69,37 @@ PanelWindow {
onHasValidDataChanged: {
if (!hasValidData && !exiting && !_isDestroying) {
forceExit();
forceExit()
}
}
Component.onCompleted: {
if (hasValidData) {
Qt.callLater(() => {
return enterX.restart();
});
return enterX.restart()
})
} else {
forceExit();
forceExit()
}
}
onNotificationDataChanged: {
if (!_isDestroying) {
wrapperConn.target = win.notificationData || null;
notificationConn.target = (win.notificationData && win.notificationData.notification && win.notificationData.notification.Retainable) || null;
wrapperConn.target = win.notificationData || null
notificationConn.target = (win.notificationData
&& win.notificationData.notification
&& win.notificationData.notification.Retainable)
|| null
}
}
onEntered: {
if (!_isDestroying)
enterDelay.start();
enterDelay.start()
}
Component.onDestruction: {
_isDestroying = true;
exitWatchdog.stop();
_isDestroying = true
exitWatchdog.stop()
if (notificationData && notificationData.timer)
notificationData.timer.stop();
notificationData.timer.stop()
}
anchors {
@@ -125,8 +127,16 @@ PanelWindow {
anchors.margins: 4
radius: Theme.cornerRadiusLarge
color: Theme.popupBackground()
border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 1
border.color: notificationData && notificationData.urgency
=== NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.3) : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.08)
border.width: notificationData
&& notificationData.urgency === NotificationUrgency.Critical ? 2 : 1
clip: true
Rectangle {
@@ -158,7 +168,8 @@ PanelWindow {
anchors.fill: parent
color: "transparent"
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
radius: parent.radius
z: -1
@@ -167,7 +178,8 @@ PanelWindow {
Rectangle {
anchors.fill: parent
radius: parent.radius
visible: notificationData && notificationData.urgency === NotificationUrgency.Critical
visible: notificationData
&& notificationData.urgency === NotificationUrgency.Critical
opacity: 1
gradient: Gradient {
@@ -187,9 +199,7 @@ PanelWindow {
position: 0.021
color: "transparent"
}
}
}
Item {
@@ -206,7 +216,9 @@ PanelWindow {
Rectangle {
id: iconContainer
readonly property bool hasNotificationImage: notificationData && notificationData.image && notificationData.image !== ""
readonly property bool hasNotificationImage: notificationData
&& notificationData.image
&& notificationData.image !== ""
width: 55
height: 55
@@ -225,35 +237,38 @@ PanelWindow {
asynchronous: true
source: {
if (!notificationData)
return "";
return ""
if (parent.hasNotificationImage)
return notificationData.cleanImage || "";
return notificationData.cleanImage || ""
if (notificationData.appIcon) {
const appIcon = notificationData.appIcon;
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://"))
return appIcon;
const appIcon = notificationData.appIcon
if (appIcon.startsWith("file://") || appIcon.startsWith(
"http://") || appIcon.startsWith("https://"))
return appIcon
return Quickshell.iconPath(appIcon, "");
return Quickshell.iconPath(appIcon, "")
}
return "";
return ""
}
visible: status === Image.Ready
}
StyledText {
anchors.centerIn: parent
visible: !parent.hasNotificationImage && (!notificationData || !notificationData.appIcon || notificationData.appIcon === "")
visible: !parent.hasNotificationImage
&& (!notificationData || !notificationData.appIcon
|| notificationData.appIcon === "")
text: {
const appName = notificationData && notificationData.appName ? notificationData.appName : "?";
return appName.charAt(0).toUpperCase();
const appName = notificationData
&& notificationData.appName ? notificationData.appName : "?"
return appName.charAt(0).toUpperCase()
}
font.pixelSize: 20
font.weight: Font.Bold
color: Theme.primaryText
}
}
Rectangle {
@@ -282,14 +297,14 @@ PanelWindow {
width: parent.width
text: {
if (!notificationData)
return "";
return ""
const appName = notificationData.appName || "";
const timeStr = notificationData.timeStr || "";
const appName = notificationData.appName || ""
const timeStr = notificationData.timeStr || ""
if (timeStr.length > 0)
return appName + " • " + timeStr;
return appName + " • " + timeStr
else
return appName;
return appName
}
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
@@ -319,8 +334,8 @@ PanelWindow {
wrapMode: Text.WordWrap
visible: text.length > 0
linkColor: Theme.primary
onLinkActivated: (link) => {
return Qt.openUrlExternally(link);
onLinkActivated: link => {
return Qt.openUrlExternally(link)
}
MouseArea {
@@ -328,15 +343,10 @@ PanelWindow {
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
}
}
}
}
DankActionButton {
@@ -352,8 +362,7 @@ PanelWindow {
z: 15
onClicked: {
if (notificationData && !win.exiting)
notificationData.popup = false;
notificationData.popup = false
}
}
@@ -374,7 +383,8 @@ PanelWindow {
width: Math.max(actionText.implicitWidth + 12, 50)
height: 24
radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.1) : "transparent"
StyledText {
id: actionText
@@ -396,18 +406,14 @@ PanelWindow {
onExited: parent.isHovered = false
onClicked: {
if (modelData && modelData.invoke)
modelData.invoke();
modelData.invoke()
if (notificationData && !win.exiting)
notificationData.popup = false;
notificationData.popup = false
}
}
}
}
}
Rectangle {
@@ -422,7 +428,8 @@ PanelWindow {
width: Math.max(clearText.implicitWidth + 12, 50)
height: 24
radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.1) : "transparent"
z: 20
StyledText {
@@ -444,11 +451,9 @@ PanelWindow {
onExited: clearButton.isHovered = false
onClicked: {
if (notificationData && !win.exiting)
NotificationService.dismissNotification(notificationData);
NotificationService.dismissNotification(notificationData)
}
}
}
MouseArea {
@@ -461,21 +466,18 @@ PanelWindow {
z: -1
onEntered: {
if (notificationData && notificationData.timer)
notificationData.timer.stop();
notificationData.timer.stop()
}
onExited: {
if (notificationData && notificationData.popup && notificationData.timer)
notificationData.timer.restart();
if (notificationData && notificationData.popup
&& notificationData.timer)
notificationData.timer.restart()
}
onClicked: {
if (notificationData && !win.exiting)
notificationData.popup = false;
notificationData.popup = false
}
}
}
transform: Translate {
@@ -483,7 +485,6 @@ PanelWindow {
x: Anims.slidePx
}
}
NumberAnimation {
@@ -498,7 +499,7 @@ PanelWindow {
easing.bezierCurve: Anims.emphasizedDecel
onStopped: {
if (!win.exiting && !win._isDestroying && Math.abs(tx.x) < 0.5) {
win.entered();
win.entered()
}
}
}
@@ -537,7 +538,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasizedAccel
}
}
Connections {
@@ -545,11 +545,10 @@ PanelWindow {
function onPopupChanged() {
if (!win.notificationData || win._isDestroying)
return ;
return
if (!win.notificationData.popup && !win.exiting)
startExit();
startExit()
}
target: win.notificationData || null
@@ -562,11 +561,11 @@ PanelWindow {
function onDropped() {
if (!win._isDestroying && !win.exiting)
forceExit();
forceExit()
}
target: (win.notificationData && win.notificationData.notification && win.notificationData.notification.Retainable) || null
target: (win.notificationData && win.notificationData.notification
&& win.notificationData.notification.Retainable) || null
ignoreUnknownSignals: true
enabled: !win._isDestroying
}
@@ -577,9 +576,9 @@ PanelWindow {
interval: 160
repeat: false
onTriggered: {
if (notificationData && notificationData.timer && !exiting && !_isDestroying)
notificationData.timer.start();
if (notificationData && notificationData.timer && !exiting
&& !_isDestroying)
notificationData.timer.start()
}
}
@@ -601,7 +600,5 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standardDecel
}
}
}

View File

@@ -19,14 +19,13 @@ QtObject {
onEntered: manager._onPopupEntered(this)
onExitFinished: manager._onPopupExitFinished(this)
}
}
property Connections notificationConnections
notificationConnections: Connections {
function onVisibleNotificationsChanged() {
manager._sync(NotificationService.visibleNotifications);
manager._sync(NotificationService.visibleNotifications)
}
target: NotificationService
@@ -39,21 +38,24 @@ QtObject {
running: false // Not running by default
repeat: true
onTriggered: {
let toRemove = [];
let toRemove = []
for (let p of popupWindows) {
if (!p) {
toRemove.push(p);
continue;
toRemove.push(p)
continue
}
const isZombie = p.status === Component.Null || (!p.visible && !p.exiting) || (!p.notificationData && !p._isDestroying) || (!p.hasValidData && !p._isDestroying);
const isZombie = p.status === Component.Null || (!p.visible
&& !p.exiting)
|| (!p.notificationData && !p._isDestroying)
|| (!p.hasValidData && !p._isDestroying)
if (isZombie) {
toRemove.push(p);
toRemove.push(p)
if (p.forceExit) {
p.forceExit();
p.forceExit()
} else if (p.destroy) {
try {
p.destroy();
p.destroy()
} catch (e) {
}
@@ -62,48 +64,49 @@ QtObject {
}
if (toRemove.length > 0) {
for (let zombie of toRemove) {
const i = popupWindows.indexOf(zombie);
const i = popupWindows.indexOf(zombie)
if (i !== -1)
popupWindows.splice(i, 1);
popupWindows.splice(i, 1)
}
popupWindows = popupWindows.slice();
popupWindows = popupWindows.slice()
const survivors = _active().sort((a, b) => {
return a.screenY - b.screenY;
});
for (let k = 0; k < survivors.length; ++k) {
survivors[k].screenY = topMargin + k * baseNotificationHeight;
return a.screenY - b.screenY
})
for (var k = 0; k < survivors.length; ++k) {
survivors[k].screenY = topMargin + k * baseNotificationHeight
}
}
if (popupWindows.length === 0)
sweeper.stop();
sweeper.stop()
}
}
function _hasWindowFor(w) {
return popupWindows.some((p) => {
return p && p.notificationData === w && !p._isDestroying && p.status !== Component.Null;
});
return popupWindows.some(p => {
return p && p.notificationData === w
&& !p._isDestroying
&& p.status !== Component.Null
})
}
function _isValidWindow(p) {
return p && p.status !== Component.Null && !p._isDestroying && p.hasValidData;
return p && p.status !== Component.Null && !p._isDestroying
&& p.hasValidData
}
function _sync(newWrappers) {
for (let w of newWrappers) {
if (w && !_hasWindowFor(w))
insertNewestAtTop(w);
insertNewestAtTop(w)
}
for (let p of popupWindows.slice()) {
if (!_isValidWindow(p))
continue;
continue
if (p.notificationData && newWrappers.indexOf(p.notificationData) === -1 && !p.exiting) {
p.notificationData.removedByLimit = true;
p.notificationData.popup = false;
if (p.notificationData && newWrappers.indexOf(p.notificationData) === -1
&& !p.exiting) {
p.notificationData.removedByLimit = true
p.notificationData.popup = false
}
}
}
@@ -111,135 +114,136 @@ QtObject {
function insertNewestAtTop(wrapper) {
if (!wrapper) {
return ;
return
}
for (let p of popupWindows) {
if (!_isValidWindow(p))
continue;
continue
if (p.exiting)
continue;
continue
p.screenY = p.screenY + baseNotificationHeight;
p.screenY = p.screenY + baseNotificationHeight
}
const notificationId = wrapper && wrapper.notification ? wrapper.notification.id : "";
const notificationId = wrapper
&& wrapper.notification ? wrapper.notification.id : ""
const win = popupComponent.createObject(null, {
"notificationData": wrapper,
"notificationId": notificationId,
"screenY": topMargin,
"screen": manager.modelData
});
})
if (!win) {
return ;
return
}
if (!win.hasValidData) {
win.destroy();
return ;
win.destroy()
return
}
popupWindows.push(win);
popupWindows.push(win)
if (!sweeper.running)
sweeper.start();
sweeper.start()
_maybeStartOverflow();
_maybeStartOverflow()
}
function _active() {
return popupWindows.filter((p) => {
return _isValidWindow(p) && p.notificationData && p.notificationData.popup && !p.exiting;
});
return popupWindows.filter(p => {
return _isValidWindow(p) && p.notificationData
&& p.notificationData.popup && !p.exiting
})
}
function _bottom() {
let b = null, maxY = -1;
let b = null, maxY = -1
for (let p of _active()) {
if (p.screenY > maxY) {
maxY = p.screenY;
b = p;
maxY = p.screenY
b = p
}
}
return b;
return b
}
function _maybeStartOverflow() {
const activeWindows = _active();
const activeWindows = _active()
if (activeWindows.length <= maxTargetNotifications + 1)
return ;
return
const b = _bottom();
const b = _bottom()
if (b && !b.exiting) {
b.notificationData.removedByLimit = true;
b.notificationData.popup = false;
b.notificationData.removedByLimit = true
b.notificationData.popup = false
}
}
function _onPopupEntered(p) {
if (_isValidWindow(p))
_maybeStartOverflow();
_maybeStartOverflow()
}
function _onPopupExitFinished(p) {
if (!p)
return ;
return
const windowId = p.toString();
const windowId = p.toString()
if (destroyingWindows.has(windowId))
return ;
return
destroyingWindows.add(windowId);
const i = popupWindows.indexOf(p);
destroyingWindows.add(windowId)
const i = popupWindows.indexOf(p)
if (i !== -1) {
popupWindows.splice(i, 1);
popupWindows = popupWindows.slice();
popupWindows.splice(i, 1)
popupWindows = popupWindows.slice()
}
if (NotificationService.releaseWrapper && p.notificationData)
NotificationService.releaseWrapper(p.notificationData);
NotificationService.releaseWrapper(p.notificationData)
Qt.callLater(() => {
if (p && p.destroy) {
try {
p.destroy();
p.destroy()
} catch (e) {
}
}
Qt.callLater(() => {
destroyingWindows.delete(windowId);
});
});
destroyingWindows.delete(windowId)
})
})
const survivors = _active().sort((a, b) => {
return a.screenY - b.screenY;
});
for (let k = 0; k < survivors.length; ++k) {
survivors[k].screenY = topMargin + k * baseNotificationHeight;
return a.screenY - b.screenY
})
for (var k = 0; k < survivors.length; ++k) {
survivors[k].screenY = topMargin + k * baseNotificationHeight
}
_maybeStartOverflow();
_maybeStartOverflow()
}
function cleanupAllWindows() {
sweeper.stop();
sweeper.stop()
for (let p of popupWindows.slice()) {
if (p) {
try {
if (p.forceExit)
p.forceExit();
p.forceExit()
else if (p.destroy)
p.destroy();
p.destroy()
} catch (e) {
}
}
}
popupWindows = [];
destroyingWindows.clear();
popupWindows = []
destroyingWindows.clear()
}
onPopupWindowsChanged: {
if (popupWindows.length > 0 && !sweeper.running)
sweeper.start();
sweeper.start()
else if (popupWindows.length === 0 && sweeper.running)
sweeper.stop();
sweeper.stop()
}
}

View File

@@ -7,39 +7,41 @@ import qs.Widgets
Column {
function formatNetworkSpeed(bytesPerSec) {
if (bytesPerSec < 1024)
return bytesPerSec.toFixed(0) + " B/s";
return bytesPerSec.toFixed(0) + " B/s"
else if (bytesPerSec < 1024 * 1024)
return (bytesPerSec / 1024).toFixed(1) + " KB/s";
return (bytesPerSec / 1024).toFixed(1) + " KB/s"
else if (bytesPerSec < 1024 * 1024 * 1024)
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s";
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s"
else
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s";
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s"
}
function formatDiskSpeed(bytesPerSec) {
if (bytesPerSec < 1024 * 1024)
return (bytesPerSec / 1024).toFixed(1) + " KB/s";
return (bytesPerSec / 1024).toFixed(1) + " KB/s"
else if (bytesPerSec < 1024 * 1024 * 1024)
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s";
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s"
else
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s";
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s"
}
anchors.fill: parent
spacing: Theme.spacingM
Component.onCompleted: {
SysMonitorService.addRef();
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef();
SysMonitorService.removeRef()
}
Rectangle {
width: parent.width
height: 200
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1
Column {
@@ -64,7 +66,8 @@ Column {
width: 80
height: 24
radius: Theme.cornerRadiusSmall
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
anchors.verticalCenter: parent.verticalCenter
StyledText {
@@ -74,7 +77,6 @@ Column {
color: Theme.primary
anchors.centerIn: parent
}
}
Item {
@@ -88,7 +90,6 @@ Column {
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
}
ScrollView {
@@ -122,7 +123,8 @@ Column {
width: parent.width - 80
height: 6
radius: 3
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
anchors.verticalCenter: parent.verticalCenter
Rectangle {
@@ -130,25 +132,22 @@ Column {
height: parent.height
radius: parent.radius
color: {
const usage = modelData;
const usage = modelData
if (usage > 80)
return Theme.error;
return Theme.error
if (usage > 60)
return Theme.warning;
return Theme.warning
return Theme.primary;
return Theme.primary
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
}
}
}
}
StyledText {
@@ -160,25 +159,21 @@ Column {
horizontalAlignment: Text.AlignRight
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
}
}
Rectangle {
width: parent.width
height: 80
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1
Row {
@@ -198,11 +193,12 @@ Column {
}
StyledText {
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB) + " / " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB)
text: SysMonitorService.formatSystemMemory(
SysMonitorService.usedMemoryKB) + " / " + SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB)
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
}
Item {
@@ -222,38 +218,41 @@ Column {
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
Rectangle {
width: SysMonitorService.totalMemoryKB > 0 ? parent.width * (SysMonitorService.usedMemoryKB / SysMonitorService.totalMemoryKB) : 0
width: SysMonitorService.totalMemoryKB
> 0 ? parent.width * (SysMonitorService.usedMemoryKB
/ SysMonitorService.totalMemoryKB) : 0
height: parent.height
radius: parent.radius
color: {
const usage = SysMonitorService.totalMemoryKB > 0 ? (SysMonitorService.usedMemoryKB / SysMonitorService.totalMemoryKB) : 0;
const usage = SysMonitorService.totalMemoryKB
> 0 ? (SysMonitorService.usedMemoryKB
/ SysMonitorService.totalMemoryKB) : 0
if (usage > 0.9)
return Theme.error;
return Theme.error
if (usage > 0.7)
return Theme.warning;
return Theme.warning
return Theme.secondary;
return Theme.secondary
}
Behavior on width {
NumberAnimation {
duration: Theme.mediumDuration
}
}
}
}
StyledText {
text: SysMonitorService.totalMemoryKB > 0 ? ((SysMonitorService.usedMemoryKB / SysMonitorService.totalMemoryKB) * 100).toFixed(1) + "% used" : "No data"
text: SysMonitorService.totalMemoryKB
> 0 ? ((SysMonitorService.usedMemoryKB
/ SysMonitorService.totalMemoryKB) * 100).toFixed(
1) + "% used" : "No data"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
Item {
@@ -273,11 +272,14 @@ Column {
}
StyledText {
text: SysMonitorService.totalSwapKB > 0 ? SysMonitorService.formatSystemMemory(SysMonitorService.usedSwapKB) + " / " + SysMonitorService.formatSystemMemory(SysMonitorService.totalSwapKB) : "No swap configured"
text: SysMonitorService.totalSwapKB
> 0 ? SysMonitorService.formatSystemMemory(
SysMonitorService.usedSwapKB) + " / "
+ SysMonitorService.formatSystemMemory(
SysMonitorService.totalSwapKB) : "No swap configured"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
}
Item {
@@ -297,45 +299,45 @@ Column {
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
Rectangle {
width: SysMonitorService.totalSwapKB > 0 ? parent.width * (SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB) : 0
width: SysMonitorService.totalSwapKB
> 0 ? parent.width * (SysMonitorService.usedSwapKB
/ SysMonitorService.totalSwapKB) : 0
height: parent.height
radius: parent.radius
color: {
if (!SysMonitorService.totalSwapKB)
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3);
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
const usage = SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB;
const usage = SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB
if (usage > 0.9)
return Theme.error;
return Theme.error
if (usage > 0.7)
return Theme.warning;
return Theme.warning
return Theme.info;
return Theme.info
}
Behavior on width {
NumberAnimation {
duration: Theme.mediumDuration
}
}
}
}
StyledText {
text: SysMonitorService.totalSwapKB > 0 ? ((SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB) * 100).toFixed(1) + "% used" : "Not available"
text: SysMonitorService.totalSwapKB
> 0 ? ((SysMonitorService.usedSwapKB
/ SysMonitorService.totalSwapKB) * 100).toFixed(
1) + "% used" : "Not available"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
}
}
Row {
@@ -347,8 +349,10 @@ Column {
width: (parent.width - Theme.spacingM) / 2
height: 80
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1
Column {
@@ -377,12 +381,13 @@ Column {
}
StyledText {
text: SysMonitorService.networkRxRate > 0 ? formatNetworkSpeed(SysMonitorService.networkRxRate) : "0 B/s"
text: SysMonitorService.networkRxRate
> 0 ? formatNetworkSpeed(
SysMonitorService.networkRxRate) : "0 B/s"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
Row {
@@ -395,26 +400,26 @@ Column {
}
StyledText {
text: SysMonitorService.networkTxRate > 0 ? formatNetworkSpeed(SysMonitorService.networkTxRate) : "0 B/s"
text: SysMonitorService.networkTxRate
> 0 ? formatNetworkSpeed(
SysMonitorService.networkTxRate) : "0 B/s"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
}
}
}
Rectangle {
width: (parent.width - Theme.spacingM) / 2
height: 80
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1
Column {
@@ -448,7 +453,6 @@ Column {
font.weight: Font.Bold
color: Theme.surfaceText
}
}
Row {
@@ -466,15 +470,9 @@ Column {
font.weight: Font.Bold
color: Theme.surfaceText
}
}
}
}
}
}
}

View File

@@ -12,24 +12,25 @@ Popup {
property var processData: null
function show(x, y) {
if (!processContextMenu.parent && typeof Overlay !== "undefined" && Overlay.overlay)
processContextMenu.parent = Overlay.overlay;
if (!processContextMenu.parent && typeof Overlay !== "undefined"
&& Overlay.overlay)
processContextMenu.parent = Overlay.overlay
const menuWidth = 180;
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2;
const screenWidth = Screen.width;
const screenHeight = Screen.height;
let finalX = x;
let finalY = y;
const menuWidth = 180
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
const screenWidth = Screen.width
const screenHeight = Screen.height
let finalX = x
let finalY = y
if (x + menuWidth > screenWidth - 20)
finalX = x - menuWidth;
finalX = x - menuWidth
if (y + menuHeight > screenHeight - 20)
finalY = y - menuHeight;
finalY = y - menuHeight
processContextMenu.x = Math.max(20, finalX);
processContextMenu.y = Math.max(20, finalY);
open();
processContextMenu.x = Math.max(20, finalX)
processContextMenu.y = Math.max(20, finalY)
open()
}
width: 180
@@ -38,10 +39,10 @@ Popup {
modal: false
closePolicy: Popup.CloseOnEscape
onClosed: {
closePolicy = Popup.CloseOnEscape;
closePolicy = Popup.CloseOnEscape
}
onOpened: {
outsideClickTimer.start();
outsideClickTimer.start()
}
Timer {
@@ -49,7 +50,7 @@ Popup {
interval: 100
onTriggered: {
processContextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside;
processContextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside
}
}
@@ -62,7 +63,8 @@ Popup {
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
Column {
@@ -76,7 +78,10 @@ Popup {
width: parent.width
height: 28
radius: Theme.cornerRadiusSmall
color: copyPidArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: copyPidArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText {
anchors.left: parent.left
@@ -96,19 +101,22 @@ Popup {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (processContextMenu.processData)
Quickshell.execDetached(["wl-copy", processContextMenu.processData.pid.toString()]);
Quickshell.execDetached(
["wl-copy", processContextMenu.processData.pid.toString()])
processContextMenu.close();
processContextMenu.close()
}
}
}
Rectangle {
width: parent.width
height: 28
radius: Theme.cornerRadiusSmall
color: copyNameArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: copyNameArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText {
anchors.left: parent.left
@@ -128,13 +136,13 @@ Popup {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (processContextMenu.processData) {
let processName = processContextMenu.processData.displayName || processContextMenu.processData.command;
Quickshell.execDetached(["wl-copy", processName]);
let processName = processContextMenu.processData.displayName
|| processContextMenu.processData.command
Quickshell.execDetached(["wl-copy", processName])
}
processContextMenu.close();
processContextMenu.close()
}
}
}
Rectangle {
@@ -149,14 +157,15 @@ Popup {
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
}
Rectangle {
width: parent.width
height: 28
radius: Theme.cornerRadiusSmall
color: killArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
color: killArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b,
0.12) : "transparent"
enabled: processContextMenu.processData
opacity: enabled ? 1 : 0.5
@@ -166,7 +175,9 @@ Popup {
anchors.verticalCenter: parent.verticalCenter
text: "Kill Process"
font.pixelSize: Theme.fontSizeSmall
color: parent.enabled ? (killArea.containsMouse ? Theme.error : Theme.surfaceText) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
color: parent.enabled ? (killArea.containsMouse ? Theme.error : Theme.surfaceText) : Qt.rgba(
Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
font.weight: Font.Normal
}
@@ -179,20 +190,24 @@ Popup {
enabled: parent.enabled
onClicked: {
if (processContextMenu.processData)
Quickshell.execDetached(["kill", processContextMenu.processData.pid.toString()]);
Quickshell.execDetached(
["kill", processContextMenu.processData.pid.toString()])
processContextMenu.close();
processContextMenu.close()
}
}
}
Rectangle {
width: parent.width
height: 28
radius: Theme.cornerRadiusSmall
color: forceKillArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
enabled: processContextMenu.processData && processContextMenu.processData.pid > 1000
color: forceKillArea.containsMouse ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.12) : "transparent"
enabled: processContextMenu.processData
&& processContextMenu.processData.pid > 1000
opacity: enabled ? 1 : 0.5
StyledText {
@@ -201,7 +216,9 @@ Popup {
anchors.verticalCenter: parent.verticalCenter
text: "Force Kill Process"
font.pixelSize: Theme.fontSizeSmall
color: parent.enabled ? (forceKillArea.containsMouse ? Theme.error : Theme.surfaceText) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
color: parent.enabled ? (forceKillArea.containsMouse ? Theme.error : Theme.surfaceText) : Qt.rgba(
Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
font.weight: Font.Normal
}
@@ -214,16 +231,14 @@ Popup {
enabled: parent.enabled
onClicked: {
if (processContextMenu.processData)
Quickshell.execDetached(["kill", "-9", processContextMenu.processData.pid.toString()]);
Quickshell.execDetached(
["kill", "-9", processContextMenu.processData.pid.toString(
)])
processContextMenu.close();
processContextMenu.close()
}
}
}
}
}
}

View File

@@ -12,8 +12,14 @@ Rectangle {
width: parent ? parent.width : 0
height: 40
radius: Theme.cornerRadiusLarge
color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
border.color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.08) : "transparent"
border.color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
border.width: 1
MouseArea {
@@ -23,21 +29,25 @@ Rectangle {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: (mouse) => {
onClicked: mouse => {
if (mouse.button === Qt.RightButton) {
if (process && process.pid > 0 && contextMenu) {
contextMenu.processData = process;
let globalPos = processMouseArea.mapToGlobal(mouse.x, mouse.y);
let localPos = contextMenu.parent ? contextMenu.parent.mapFromGlobal(globalPos.x, globalPos.y) : globalPos;
contextMenu.show(localPos.x, localPos.y);
contextMenu.processData = process
let globalPos = processMouseArea.mapToGlobal(mouse.x,
mouse.y)
let localPos = contextMenu.parent ? contextMenu.parent.mapFromGlobal(
globalPos.x,
globalPos.y) : globalPos
contextMenu.show(localPos.x, localPos.y)
}
}
}
onPressAndHold: {
if (process && process.pid > 0 && contextMenu) {
contextMenu.processData = process;
let globalPos = processMouseArea.mapToGlobal(processMouseArea.width / 2, processMouseArea.height / 2);
contextMenu.show(globalPos.x, globalPos.y);
contextMenu.processData = process
let globalPos = processMouseArea.mapToGlobal(
processMouseArea.width / 2, processMouseArea.height / 2)
contextMenu.show(globalPos.x, globalPos.y)
}
}
}
@@ -53,12 +63,12 @@ Rectangle {
size: Theme.iconSize - 4
color: {
if (process && process.cpu > 80)
return Theme.error;
return Theme.error
if (process && process.cpu > 50)
return Theme.warning;
return Theme.warning
return Theme.surfaceText;
return Theme.surfaceText
}
opacity: 0.8
anchors.left: parent.left
@@ -86,12 +96,14 @@ Rectangle {
radius: Theme.cornerRadius
color: {
if (process && process.cpu > 80)
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12);
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
if (process && process.cpu > 50)
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12);
return Qt.rgba(Theme.warning.r, Theme.warning.g,
Theme.warning.b, 0.12)
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08);
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.08)
}
anchors.right: parent.right
anchors.rightMargin: 194
@@ -104,16 +116,15 @@ Rectangle {
font.weight: Font.Bold
color: {
if (process && process.cpu > 80)
return Theme.error;
return Theme.error
if (process && process.cpu > 50)
return Theme.warning;
return Theme.warning
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.centerIn: parent
}
}
Rectangle {
@@ -124,34 +135,36 @@ Rectangle {
radius: Theme.cornerRadius
color: {
if (process && process.memoryKB > 1024 * 1024)
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12);
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
if (process && process.memoryKB > 512 * 1024)
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12);
return Qt.rgba(Theme.warning.r, Theme.warning.g,
Theme.warning.b, 0.12)
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08);
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.08)
}
anchors.right: parent.right
anchors.rightMargin: 102
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: SysMonitorService.formatMemoryUsage(process ? process.memoryKB : 0)
text: SysMonitorService.formatMemoryUsage(
process ? process.memoryKB : 0)
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: {
if (process && process.memoryKB > 1024 * 1024)
return Theme.error;
return Theme.error
if (process && process.memoryKB > 512 * 1024)
return Theme.warning;
return Theme.warning
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.centerIn: parent
}
}
StyledText {
@@ -173,7 +186,10 @@ Rectangle {
width: 28
height: 28
radius: Theme.cornerRadius
color: menuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
color: menuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
@@ -193,10 +209,13 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (process && process.pid > 0 && contextMenu) {
contextMenu.processData = process;
let globalPos = menuButtonArea.mapToGlobal(menuButtonArea.width / 2, menuButtonArea.height);
let localPos = contextMenu.parent ? contextMenu.parent.mapFromGlobal(globalPos.x, globalPos.y) : globalPos;
contextMenu.show(localPos.x, localPos.y);
contextMenu.processData = process
let globalPos = menuButtonArea.mapToGlobal(
menuButtonArea.width / 2, menuButtonArea.height)
let localPos = contextMenu.parent ? contextMenu.parent.mapFromGlobal(
globalPos.x,
globalPos.y) : globalPos
contextMenu.show(localPos.x, localPos.y)
}
}
}
@@ -205,11 +224,7 @@ Rectangle {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}

View File

@@ -23,29 +23,28 @@ PanelWindow {
property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) {
triggerX = x;
triggerY = y;
triggerWidth = width;
triggerSection = section;
triggerScreen = screen;
triggerX = x
triggerY = y
triggerWidth = width
triggerSection = section
triggerScreen = screen
}
function hide() {
isVisible = false;
isVisible = false
if (processContextMenu.visible)
processContextMenu.close();
processContextMenu.close()
}
function show() {
isVisible = true;
isVisible = true
}
function toggle() {
if (isVisible)
hide();
hide()
else
show();
show()
}
visible: isVisible
@@ -70,11 +69,11 @@ PanelWindow {
MouseArea {
anchors.fill: parent
onClicked: function(mouse) {
var localPos = mapToItem(contentLoader, mouse.x, mouse.y);
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height)
processListPopout.hide();
onClicked: function (mouse) {
var localPos = mapToItem(contentLoader, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0
|| localPos.y > contentLoader.height)
processListPopout.hide()
}
}
@@ -83,24 +82,29 @@ PanelWindow {
readonly property real screenWidth: processListPopout.screen ? processListPopout.screen.width : Screen.width
readonly property real screenHeight: processListPopout.screen ? processListPopout.screen.height : Screen.height
readonly property real targetWidth: Math.min(600, screenWidth - Theme.spacingL * 2)
readonly property real targetHeight: Math.min(600, screenHeight - Theme.barHeight - Theme.spacingS * 2)
readonly property real targetWidth: Math.min(
600, screenWidth - Theme.spacingL * 2)
readonly property real targetHeight: Math.min(
600,
screenHeight - Theme.barHeight - Theme.spacingS * 2)
readonly property real calculatedX: {
var centerX = processListPopout.triggerX + (processListPopout.triggerWidth / 2) - (targetWidth / 2);
var centerX = processListPopout.triggerX + (processListPopout.triggerWidth
/ 2) - (targetWidth / 2)
if (centerX >= Theme.spacingM && centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX;
if (centerX >= Theme.spacingM
&& centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX
}
if (centerX < Theme.spacingM) {
return Theme.spacingM;
return Theme.spacingM
}
if (centerX + targetWidth > screenWidth - Theme.spacingM) {
return screenWidth - targetWidth - Theme.spacingM;
return screenWidth - targetWidth - Theme.spacingM
}
return centerX;
return centerX
}
asynchronous: true
@@ -118,7 +122,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
Behavior on scale {
@@ -127,7 +130,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
sourceComponent: Rectangle {
@@ -135,7 +137,8 @@ PanelWindow {
radius: Theme.cornerRadiusLarge
color: Theme.popupBackground()
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
clip: true
antialiasing: true
@@ -143,21 +146,21 @@ PanelWindow {
focus: true
Component.onCompleted: {
if (processListPopout.isVisible)
forceActiveFocus();
forceActiveFocus()
}
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
processListPopout.hide();
event.accepted = true;
processListPopout.hide()
event.accepted = true
}
}
Connections {
function onIsVisibleChanged() {
if (processListPopout.isVisible)
Qt.callLater(function() {
dropdownContent.forceActiveFocus();
});
Qt.callLater(function () {
dropdownContent.forceActiveFocus()
})
}
target: processListPopout
}
@@ -171,8 +174,10 @@ PanelWindow {
Layout.fillWidth: true
height: systemOverview.height + Theme.spacingM * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.2)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
SystemOverview {
@@ -181,15 +186,16 @@ PanelWindow {
anchors.centerIn: parent
width: parent.width - Theme.spacingM * 2
}
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.05)
border.width: 1
ProcessListView {
@@ -197,17 +203,12 @@ PanelWindow {
anchors.margins: Theme.spacingS
contextMenu: processContextMenu
}
}
}
}
}
ProcessContextMenu {
id: processContextMenu
}
}

View File

@@ -10,10 +10,10 @@ Column {
property var contextMenu: null
Component.onCompleted: {
SysMonitorService.addRef();
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef();
SysMonitorService.removeRef()
}
Item {
@@ -26,7 +26,10 @@ Column {
Rectangle {
width: 60
height: 20
color: processHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
color: processHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
radius: Theme.cornerRadius
anchors.left: parent.left
anchors.leftMargin: 0
@@ -49,7 +52,7 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
SysMonitorService.setSortBy("name");
SysMonitorService.setSortBy("name")
}
}
@@ -57,15 +60,16 @@ Column {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
Rectangle {
width: 80
height: 20
color: cpuHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
color: cpuHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
radius: Theme.cornerRadius
anchors.right: parent.right
anchors.rightMargin: 200
@@ -88,7 +92,7 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
SysMonitorService.setSortBy("cpu");
SysMonitorService.setSortBy("cpu")
}
}
@@ -96,15 +100,16 @@ Column {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
Rectangle {
width: 80
height: 20
color: memoryHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
color: memoryHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
radius: Theme.cornerRadius
anchors.right: parent.right
anchors.rightMargin: 112
@@ -127,7 +132,7 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
SysMonitorService.setSortBy("memory");
SysMonitorService.setSortBy("memory")
}
}
@@ -135,15 +140,16 @@ Column {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
Rectangle {
width: 50
height: 20
color: pidHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
color: pidHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
radius: Theme.cornerRadius
anchors.right: parent.right
anchors.rightMargin: 53
@@ -167,7 +173,7 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
SysMonitorService.setSortBy("pid");
SysMonitorService.setSortBy("pid")
}
}
@@ -175,16 +181,17 @@ Column {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
Rectangle {
width: 28
height: 28
radius: Theme.cornerRadius
color: sortOrderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
color: sortOrderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
anchors.right: parent.right
anchors.rightMargin: 8
anchors.verticalCenter: parent.verticalCenter
@@ -203,7 +210,7 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
SysMonitorService.toggleSortOrder();
SysMonitorService.toggleSortOrder()
}
}
@@ -211,11 +218,8 @@ Column {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
DankListView {
@@ -234,5 +238,4 @@ Column {
contextMenu: root.contextMenu
}
}
}

View File

@@ -25,5 +25,4 @@ ColumnLayout {
ProcessContextMenu {
id: localContextMenu
}
}

View File

@@ -7,10 +7,10 @@ Row {
width: parent.width
spacing: Theme.spacingM
Component.onCompleted: {
SysMonitorService.addRef();
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef();
SysMonitorService.removeRef()
}
Rectangle {
@@ -19,13 +19,19 @@ Row {
radius: Theme.cornerRadiusLarge
color: {
if (SysMonitorService.sortBy === "cpu")
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16);
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16)
else if (cpuCardMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
else
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08);
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
}
border.color: SysMonitorService.sortBy === "cpu" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2)
border.color: SysMonitorService.sortBy === "cpu" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.4) : Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b, 0.2)
border.width: SysMonitorService.sortBy === "cpu" ? 2 : 1
MouseArea {
@@ -66,26 +72,29 @@ Row {
Rectangle {
width: 1
height: 20
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (SysMonitorService.cpuTemperature === undefined || SysMonitorService.cpuTemperature === null || SysMonitorService.cpuTemperature < 0) {
return "--°";
if (SysMonitorService.cpuTemperature === undefined
|| SysMonitorService.cpuTemperature === null
|| SysMonitorService.cpuTemperature < 0) {
return "--°"
}
return Math.round(SysMonitorService.cpuTemperature) + "°";
return Math.round(SysMonitorService.cpuTemperature) + "°"
}
font.pixelSize: Theme.fontSizeMedium
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
color: {
if (SysMonitorService.cpuTemperature > 80)
return Theme.error;
return Theme.error
if (SysMonitorService.cpuTemperature > 60)
return Theme.warning;
return Theme.surfaceText;
return Theme.warning
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -98,23 +107,19 @@ Row {
color: Theme.surfaceText
opacity: 0.7
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
Behavior on border.color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
Rectangle {
@@ -123,13 +128,23 @@ Row {
radius: Theme.cornerRadiusLarge
color: {
if (SysMonitorService.sortBy === "memory")
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16);
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16)
else if (memoryCardMouseArea.containsMouse)
return Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.12);
return Qt.rgba(Theme.secondary.r, Theme.secondary.g,
Theme.secondary.b, 0.12)
else
return Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08);
return Qt.rgba(Theme.secondary.r, Theme.secondary.g,
Theme.secondary.b, 0.08)
}
border.color: SysMonitorService.sortBy === "memory" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.2)
border.color: SysMonitorService.sortBy === "memory" ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.4) : Qt.rgba(
Theme.secondary.r,
Theme.secondary.g,
Theme.secondary.b,
0.2)
border.width: SysMonitorService.sortBy === "memory" ? 2 : 1
MouseArea {
@@ -159,7 +174,8 @@ Row {
spacing: Theme.spacingS
StyledText {
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB)
text: SysMonitorService.formatSystemMemory(
SysMonitorService.usedMemoryKB)
font.pixelSize: Theme.fontSizeLarge
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
@@ -170,13 +186,15 @@ Row {
Rectangle {
width: 1
height: 20
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
anchors.verticalCenter: parent.verticalCenter
visible: SysMonitorService.totalSwapKB > 0
}
StyledText {
text: SysMonitorService.totalSwapKB > 0 ? SysMonitorService.formatSystemMemory(SysMonitorService.usedSwapKB) : ""
text: SysMonitorService.totalSwapKB > 0 ? SysMonitorService.formatSystemMemory(
SysMonitorService.usedSwapKB) : ""
font.pixelSize: Theme.fontSizeMedium
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
@@ -189,40 +207,40 @@ Row {
StyledText {
text: {
if (SysMonitorService.totalSwapKB > 0) {
return "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB) + " + swap";
return "of " + SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB) + " + swap"
}
return "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB);
return "of " + SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB)
}
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
opacity: 0.7
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
Behavior on border.color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
Rectangle {
width: (parent.width - Theme.spacingM * 2) / 3
height: 80
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)
border.color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
border.color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.2)
border.width: 1
Column {
@@ -241,73 +259,79 @@ Row {
StyledText {
text: {
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) {
return "None";
if (!SysMonitorService.availableGpus
|| SysMonitorService.availableGpus.length === 0) {
return "None"
}
if (SysMonitorService.availableGpus.length === 1) {
var gpu = SysMonitorService.availableGpus[0];
var temp = gpu.temperature;
var tempText = (temp === undefined || temp === null || temp === 0) ? "--°" : Math.round(temp) + "°";
return tempText;
var gpu = SysMonitorService.availableGpus[0]
var temp = gpu.temperature
var tempText = (temp === undefined || temp === null
|| temp === 0) ? "--°" : Math.round(temp) + "°"
return tempText
}
// Multiple GPUs - show average temp
var totalTemp = 0;
var validTemps = 0;
var totalTemp = 0
var validTemps = 0
for (var i = 0; i < SysMonitorService.availableGpus.length; i++) {
var temp = SysMonitorService.availableGpus[i].temperature;
var temp = SysMonitorService.availableGpus[i].temperature
if (temp !== undefined && temp !== null && temp > 0) {
totalTemp += temp;
validTemps++;
totalTemp += temp
validTemps++
}
}
if (validTemps > 0) {
return Math.round(totalTemp / validTemps) + "°";
return Math.round(totalTemp / validTemps) + "°"
}
return "--°";
return "--°"
}
font.pixelSize: Theme.fontSizeLarge
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: {
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) {
return Theme.surfaceText;
if (!SysMonitorService.availableGpus
|| SysMonitorService.availableGpus.length === 0) {
return Theme.surfaceText
}
if (SysMonitorService.availableGpus.length === 1) {
var temp = SysMonitorService.availableGpus[0].temperature || 0;
if (temp > 80) return Theme.tempDanger;
if (temp > 60) return Theme.tempWarning;
return Theme.surfaceText;
var temp = SysMonitorService.availableGpus[0].temperature || 0
if (temp > 80)
return Theme.tempDanger
if (temp > 60)
return Theme.tempWarning
return Theme.surfaceText
}
// Multiple GPUs - get max temp for coloring
var maxTemp = 0;
var maxTemp = 0
for (var i = 0; i < SysMonitorService.availableGpus.length; i++) {
var temp = SysMonitorService.availableGpus[i].temperature || 0;
if (temp > maxTemp) maxTemp = temp;
var temp = SysMonitorService.availableGpus[i].temperature || 0
if (temp > maxTemp)
maxTemp = temp
}
if (maxTemp > 80) return Theme.tempDanger;
if (maxTemp > 60) return Theme.tempWarning;
return Theme.surfaceText;
if (maxTemp > 80)
return Theme.tempDanger
if (maxTemp > 60)
return Theme.tempWarning
return Theme.surfaceText
}
}
StyledText {
text: {
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) {
return "No GPUs detected";
if (!SysMonitorService.availableGpus
|| SysMonitorService.availableGpus.length === 0) {
return "No GPUs detected"
}
if (SysMonitorService.availableGpus.length === 1) {
return SysMonitorService.availableGpus[0].driver.toUpperCase();
return SysMonitorService.availableGpus[0].driver.toUpperCase()
}
return SysMonitorService.availableGpus.length + " GPUs detected";
return SysMonitorService.availableGpus.length + " GPUs detected"
}
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
opacity: 0.7
}
}
}
}

View File

@@ -10,10 +10,10 @@ ScrollView {
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Component.onCompleted: {
SysMonitorService.addRef();
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef();
SysMonitorService.removeRef()
}
Column {
@@ -24,7 +24,8 @@ ScrollView {
width: parent.width
height: systemInfoColumn.implicitHeight + 2 * Theme.spacingL
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.6)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.6)
border.width: 0
Column {
@@ -60,10 +61,12 @@ ScrollView {
}
StyledText {
text: SysMonitorService.distribution + " • " + SysMonitorService.architecture + " • " + SysMonitorService.kernelVersion
text: SysMonitorService.distribution + " • " + SysMonitorService.architecture
+ " • " + SysMonitorService.kernelVersion
font.pixelSize: Theme.fontSizeMedium
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
verticalAlignment: Text.AlignVCenter
}
@@ -71,20 +74,22 @@ ScrollView {
text: "Up " + UserInfoService.uptime + " • Boot: " + SysMonitorService.bootTime
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: "Load: " + SysMonitorService.loadAverage + " • " + SysMonitorService.processCount + " processes, " + SysMonitorService.threadCount + " threads"
text: "Load: " + SysMonitorService.loadAverage + " • "
+ SysMonitorService.processCount + " processes, "
+ SysMonitorService.threadCount + " threads"
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle {
@@ -99,11 +104,15 @@ ScrollView {
Rectangle {
width: (parent.width - Theme.spacingXL) / 2
height: Math.max(hardwareColumn.implicitHeight, memoryColumn.implicitHeight) + Theme.spacingM
height: Math.max(hardwareColumn.implicitHeight,
memoryColumn.implicitHeight) + Theme.spacingM
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainerHigh.r, Theme.surfaceContainerHigh.g, Theme.surfaceContainerHigh.b, 0.4)
color: Qt.rgba(Theme.surfaceContainerHigh.r,
Theme.surfaceContainerHigh.g,
Theme.surfaceContainerHigh.b, 0.4)
border.width: 1
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.1)
Column {
id: hardwareColumn
@@ -133,7 +142,6 @@ ScrollView {
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
@@ -153,7 +161,8 @@ ScrollView {
text: SysMonitorService.motherboard
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.8)
width: parent.width
elide: Text.ElideRight
wrapMode: Text.NoWrap
@@ -165,23 +174,26 @@ ScrollView {
text: "BIOS " + SysMonitorService.biosVersion
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
width: parent.width
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle {
width: (parent.width - Theme.spacingXL) / 2
height: Math.max(hardwareColumn.implicitHeight, memoryColumn.implicitHeight) + Theme.spacingM
height: Math.max(hardwareColumn.implicitHeight,
memoryColumn.implicitHeight) + Theme.spacingM
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainerHigh.r, Theme.surfaceContainerHigh.g, Theme.surfaceContainerHigh.b, 0.4)
color: Qt.rgba(Theme.surfaceContainerHigh.r,
Theme.surfaceContainerHigh.g,
Theme.surfaceContainerHigh.b, 0.4)
border.width: 1
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.1)
Column {
id: memoryColumn
@@ -211,11 +223,11 @@ ScrollView {
color: Theme.secondary
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB) + " Total"
text: SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB) + " Total"
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
@@ -226,10 +238,15 @@ ScrollView {
}
StyledText {
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB) + " Used • " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB - SysMonitorService.usedMemoryKB) + " Available"
text: SysMonitorService.formatSystemMemory(
SysMonitorService.usedMemoryKB) + " Used • "
+ SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB
- SysMonitorService.usedMemoryKB) + " Available"
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
width: parent.width
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
@@ -239,22 +256,18 @@ ScrollView {
width: parent.width
height: Theme.fontSizeSmall + Theme.spacingXS
}
}
}
}
}
}
Rectangle {
width: parent.width
height: storageColumn.implicitHeight + 2 * Theme.spacingL
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.6)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.6)
border.width: 0
Column {
@@ -285,7 +298,6 @@ ScrollView {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
@@ -362,7 +374,6 @@ ScrollView {
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
}
Repeater {
@@ -374,7 +385,10 @@ ScrollView {
width: parent.width
height: 24
radius: Theme.cornerRadiusSmall
color: diskMouseArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.04) : "transparent"
color: diskMouseArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.04) : "transparent"
MouseArea {
id: diskMouseArea
@@ -447,33 +461,25 @@ ScrollView {
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: {
const percent = parseInt(modelData.percent);
const percent = parseInt(modelData.percent)
if (percent > 90)
return Theme.error;
return Theme.error
if (percent > 75)
return Theme.warning;
return Theme.warning
return Theme.surfaceText;
return Theme.surfaceText
}
width: parent.width * 0.1
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
}
}
}
}

View File

@@ -51,8 +51,10 @@ Item {
width: parent.width
height: displaySection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -80,7 +82,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
@@ -88,12 +89,12 @@ Item {
text: "Night Mode"
description: "Apply warm color temperature to reduce eye strain"
checked: SettingsData.nightModeEnabled
onToggled: (checked) => {
SettingsData.setNightModeEnabled(checked);
onToggled: checked => {
SettingsData.setNightModeEnabled(checked)
if (checked)
nightModeEnableProcess.running = true;
nightModeEnableProcess.running = true
else
nightModeDisableProcess.running = true;
nightModeDisableProcess.running = true
}
}
@@ -102,10 +103,10 @@ Item {
text: "Light Mode"
description: "Use light theme instead of dark theme"
checked: SessionData.isLightMode
onToggled: (checked) => {
SessionData.setLightMode(checked);
Theme.isLightMode = checked;
PortalService.setLightMode(checked);
onToggled: checked => {
SessionData.setLightMode(checked)
Theme.isLightMode = checked
PortalService.setLightMode(checked)
}
}
@@ -118,14 +119,16 @@ Item {
popupWidthOffset: 100
maxPopupHeight: 400
options: {
SettingsData.detectAvailableIconThemes();
return SettingsData.availableIconThemes;
SettingsData.detectAvailableIconThemes()
return SettingsData.availableIconThemes
}
onValueChanged: (value) => {
SettingsData.setIconTheme(value);
if (value !== "System Default" && !SettingsData.qt5ctAvailable && !SettingsData.qt6ctAvailable)
ToastService.showWarning("qt5ct or qt6ct not found - Qt app themes may not update without these tools");
onValueChanged: value => {
SettingsData.setIconTheme(value)
if (value !== "System Default"
&& !SettingsData.qt5ctAvailable
&& !SettingsData.qt6ctAvailable)
ToastService.showWarning(
"qt5ct or qt6ct not found - Qt app themes may not update without these tools")
}
}
@@ -135,41 +138,48 @@ Item {
description: "Select system font family"
currentValue: {
if (SettingsData.fontFamily === SettingsData.defaultFontFamily)
return "Default (" + SettingsData.defaultFontFamily + ")";
return "Default (" + SettingsData.defaultFontFamily + ")"
else
return SettingsData.fontFamily || "Default (" + SettingsData.defaultFontFamily + ")";
return SettingsData.fontFamily
|| "Default (" + SettingsData.defaultFontFamily + ")"
}
enableFuzzySearch: true
popupWidthOffset: 100
maxPopupHeight: 400
options: {
var fonts = ["Default (" + SettingsData.defaultFontFamily + ")"];
var availableFonts = Qt.fontFamilies();
var rootFamilies = [];
var seenFamilies = new Set();
var fonts = ["Default (" + SettingsData.defaultFontFamily + ")"]
var availableFonts = Qt.fontFamilies()
var rootFamilies = []
var seenFamilies = new Set()
for (var i = 0; i < availableFonts.length; i++) {
var fontName = availableFonts[i];
var fontName = availableFonts[i]
if (fontName.startsWith("."))
continue;
continue
if (fontName === SettingsData.defaultFontFamily)
continue;
continue
var rootName = fontName.replace(/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i, "").replace(/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i, "").replace(/ (UI|Display|Text|Mono|Sans|Serif)$/i, function(match, suffix) {
return match;
}).trim();
var rootName = fontName.replace(
/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i,
"").replace(
/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i,
"").replace(/ (UI|Display|Text|Mono|Sans|Serif)$/i,
function (match, suffix) {
return match
}).trim()
if (!seenFamilies.has(rootName) && rootName !== "") {
seenFamilies.add(rootName);
rootFamilies.push(rootName);
seenFamilies.add(rootName)
rootFamilies.push(rootName)
}
}
return fonts.concat(rootFamilies.sort());
return fonts.concat(rootFamilies.sort())
}
onValueChanged: (value) => {
onValueChanged: value => {
if (value.startsWith("Default ("))
SettingsData.setFontFamily(SettingsData.defaultFontFamily);
SettingsData.setFontFamily(
SettingsData.defaultFontFamily)
else
SettingsData.setFontFamily(value);
SettingsData.setFontFamily(value)
}
}
@@ -180,63 +190,63 @@ Item {
currentValue: {
switch (SettingsData.fontWeight) {
case Font.Thin:
return "Thin";
return "Thin"
case Font.ExtraLight:
return "Extra Light";
return "Extra Light"
case Font.Light:
return "Light";
return "Light"
case Font.Normal:
return "Regular";
return "Regular"
case Font.Medium:
return "Medium";
return "Medium"
case Font.DemiBold:
return "Demi Bold";
return "Demi Bold"
case Font.Bold:
return "Bold";
return "Bold"
case Font.ExtraBold:
return "Extra Bold";
return "Extra Bold"
case Font.Black:
return "Black";
return "Black"
default:
return "Regular";
return "Regular"
}
}
options: ["Thin", "Extra Light", "Light", "Regular", "Medium", "Demi Bold", "Bold", "Extra Bold", "Black"]
onValueChanged: (value) => {
var weight;
onValueChanged: value => {
var weight
switch (value) {
case "Thin":
weight = Font.Thin;
break;
weight = Font.Thin
break
case "Extra Light":
weight = Font.ExtraLight;
break;
weight = Font.ExtraLight
break
case "Light":
weight = Font.Light;
break;
weight = Font.Light
break
case "Regular":
weight = Font.Normal;
break;
weight = Font.Normal
break
case "Medium":
weight = Font.Medium;
break;
weight = Font.Medium
break
case "Demi Bold":
weight = Font.DemiBold;
break;
weight = Font.DemiBold
break
case "Bold":
weight = Font.Bold;
break;
weight = Font.Bold
break
case "Extra Bold":
weight = Font.ExtraBold;
break;
weight = Font.ExtraBold
break
case "Black":
weight = Font.Black;
break;
weight = Font.Black
break
default:
weight = Font.Normal;
break;
weight = Font.Normal
break
}
SettingsData.setFontWeight(weight);
SettingsData.setFontWeight(weight)
}
}
@@ -246,45 +256,58 @@ Item {
description: "Select monospace font for process list and technical displays"
currentValue: {
if (SettingsData.monoFontFamily === SettingsData.defaultMonoFontFamily)
return "Default";
return "Default"
return SettingsData.monoFontFamily || "Default";
return SettingsData.monoFontFamily || "Default"
}
enableFuzzySearch: true
popupWidthOffset: 100
maxPopupHeight: 400
options: {
var fonts = ["Default"];
var availableFonts = Qt.fontFamilies();
var monoFamilies = [];
var seenFamilies = new Set();
var fonts = ["Default"]
var availableFonts = Qt.fontFamilies()
var monoFamilies = []
var seenFamilies = new Set()
for (var i = 0; i < availableFonts.length; i++) {
var fontName = availableFonts[i];
var fontName = availableFonts[i]
if (fontName.startsWith("."))
continue;
continue
if (fontName === SettingsData.defaultMonoFontFamily)
continue;
continue
var lowerName = fontName.toLowerCase();
if (lowerName.includes("mono") || lowerName.includes("code") || lowerName.includes("console") || lowerName.includes("terminal") || lowerName.includes("courier") || lowerName.includes("dejavu sans mono") || lowerName.includes("jetbrains") || lowerName.includes("fira") || lowerName.includes("hack") || lowerName.includes("source code") || lowerName.includes("ubuntu mono") || lowerName.includes("cascadia")) {
var rootName = fontName.replace(/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i, "").replace(/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i, "").trim();
var lowerName = fontName.toLowerCase()
if (lowerName.includes("mono") || lowerName.includes(
"code") || lowerName.includes(
"console") || lowerName.includes(
"terminal") || lowerName.includes(
"courier") || lowerName.includes(
"dejavu sans mono") || lowerName.includes(
"jetbrains") || lowerName.includes(
"fira") || lowerName.includes("hack") || lowerName.includes(
"source code") || lowerName.includes(
"ubuntu mono") || lowerName.includes("cascadia")) {
var rootName = fontName.replace(
/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i,
"").replace(
/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i,
"").trim()
if (!seenFamilies.has(rootName) && rootName !== "") {
seenFamilies.add(rootName);
monoFamilies.push(rootName);
seenFamilies.add(rootName)
monoFamilies.push(rootName)
}
}
}
return fonts.concat(monoFamilies.sort());
return fonts.concat(monoFamilies.sort())
}
onValueChanged: (value) => {
onValueChanged: value => {
if (value === "Default")
SettingsData.setMonoFontFamily(SettingsData.defaultMonoFontFamily);
SettingsData.setMonoFontFamily(
SettingsData.defaultMonoFontFamily)
else
SettingsData.setMonoFontFamily(value);
SettingsData.setMonoFontFamily(value)
}
}
}
}
}
@@ -297,8 +320,10 @@ Item {
width: parent.width
height: transparencySection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -326,7 +351,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
@@ -348,11 +372,11 @@ Item {
maximum: 100
unit: ""
showValue: true
onSliderValueChanged: (newValue) => {
SettingsData.setTopBarTransparency(newValue / 100);
onSliderValueChanged: newValue => {
SettingsData.setTopBarTransparency(
newValue / 100)
}
}
}
Column {
@@ -374,11 +398,11 @@ Item {
maximum: 100
unit: ""
showValue: true
onSliderValueChanged: (newValue) => {
SettingsData.setTopBarWidgetTransparency(newValue / 100);
onSliderValueChanged: newValue => {
SettingsData.setTopBarWidgetTransparency(
newValue / 100)
}
}
}
Column {
@@ -400,13 +424,12 @@ Item {
maximum: 100
unit: ""
showValue: true
onSliderValueChanged: (newValue) => {
SettingsData.setPopupTransparency(newValue / 100);
onSliderValueChanged: newValue => {
SettingsData.setPopupTransparency(
newValue / 100)
}
}
}
}
}
}
@@ -419,8 +442,10 @@ Item {
width: parent.width
height: themeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -448,7 +473,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
@@ -466,10 +490,10 @@ Item {
StyledText {
text: {
if (Theme.isDynamicTheme)
return "Wallpaper-based dynamic colors";
return "Wallpaper-based dynamic colors"
var descriptions = ["Material blue inspired by modern interfaces", "Deep blue inspired by material 3", "Rich purple tones for BB elegance", "Natural green for productivity", "Energetic orange for creativity", "Bold red for impact", "Cool cyan for tranquility", "Vibrant pink for expression", "Warm amber for comfort", "Soft coral for gentle warmth"];
return descriptions[Theme.currentThemeIndex] || "Select a theme";
var descriptions = ["Material blue inspired by modern interfaces", "Deep blue inspired by material 3", "Rich purple tones for BB elegance", "Natural green for productivity", "Energetic orange for creativity", "Bold red for impact", "Cool cyan for tranquility", "Vibrant pink for expression", "Warm amber for comfort", "Soft coral for gentle warmth"]
return descriptions[Theme.currentThemeIndex] || "Select a theme"
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
@@ -478,7 +502,6 @@ Item {
width: Math.min(parent.width, 400)
horizontalAlignment: Text.AlignHCenter
}
}
Column {
@@ -498,8 +521,10 @@ Item {
radius: 16
color: Theme.themes[index].primary
border.color: Theme.outline
border.width: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 2 : 1
scale: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 1.1 : 1
border.width: (Theme.currentThemeIndex === index
&& !Theme.isDynamicTheme) ? 2 : 1
scale: (Theme.currentThemeIndex === index
&& !Theme.isDynamicTheme) ? 1.1 : 1
Rectangle {
width: nameText.contentWidth + Theme.spacingS * 2
@@ -521,7 +546,6 @@ Item {
color: Theme.surfaceText
anchors.centerIn: parent
}
}
MouseArea {
@@ -531,7 +555,7 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
Theme.switchTheme(index, false);
Theme.switchTheme(index, false)
}
}
@@ -540,7 +564,6 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on border.width {
@@ -548,13 +571,9 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
Row {
@@ -570,7 +589,8 @@ Item {
width: 32
height: 32
radius: 16
color: themeIndex < Theme.themes.length ? Theme.themes[themeIndex].primary : "transparent"
color: themeIndex
< Theme.themes.length ? Theme.themes[themeIndex].primary : "transparent"
border.color: Theme.outline
border.width: Theme.currentThemeIndex === themeIndex ? 2 : 1
visible: themeIndex < Theme.themes.length
@@ -586,7 +606,8 @@ Item {
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS
anchors.horizontalCenter: parent.horizontalCenter
visible: mouseArea2.containsMouse && themeIndex < Theme.themes.length
visible: mouseArea2.containsMouse
&& themeIndex < Theme.themes.length
StyledText {
id: nameText2
@@ -596,7 +617,6 @@ Item {
color: Theme.surfaceText
anchors.centerIn: parent
}
}
MouseArea {
@@ -607,8 +627,7 @@ Item {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (themeIndex < Theme.themes.length)
Theme.switchTheme(themeIndex);
Theme.switchTheme(themeIndex)
}
}
@@ -617,7 +636,6 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on border.width {
@@ -625,13 +643,9 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
Item {
@@ -645,18 +659,22 @@ Item {
radius: 20
anchors.horizontalCenter: parent.horizontalCenter
color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12);
if (ToastService.wallpaperErrorStatus === "error"
|| ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b, 0.12)
else
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3);
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
}
border.color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.5);
if (ToastService.wallpaperErrorStatus === "error"
|| ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.5)
else if (Theme.isDynamicTheme)
return Theme.primary;
return Theme.primary
else
return Theme.outline;
return Theme.outline
}
border.width: Theme.isDynamicTheme ? 2 : 1
scale: Theme.isDynamicTheme ? 1.1 : (autoMouseArea.containsMouse ? 1.02 : 1)
@@ -667,17 +685,19 @@ Item {
DankIcon {
name: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return "error";
if (ToastService.wallpaperErrorStatus === "error"
|| ToastService.wallpaperErrorStatus === "matugen_missing")
return "error"
else
return "palette";
return "palette"
}
size: 16
color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error;
if (ToastService.wallpaperErrorStatus === "error"
|| ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error
else
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -685,23 +705,23 @@ Item {
StyledText {
text: {
if (ToastService.wallpaperErrorStatus === "error")
return "Error";
return "Error"
else if (ToastService.wallpaperErrorStatus === "matugen_missing")
return "No matugen";
return "No matugen"
else
return "Auto";
return "Auto"
}
font.pixelSize: Theme.fontSizeMedium
color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error;
if (ToastService.wallpaperErrorStatus === "error"
|| ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error
else
return Theme.surfaceText;
return Theme.surfaceText
}
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -712,11 +732,13 @@ Item {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (ToastService.wallpaperErrorStatus === "matugen_missing")
ToastService.showError("matugen not found - install matugen package for dynamic theming");
ToastService.showError(
"matugen not found - install matugen package for dynamic theming")
else if (ToastService.wallpaperErrorStatus === "error")
ToastService.showError("Wallpaper processing failed - check wallpaper path");
ToastService.showError(
"Wallpaper processing failed - check wallpaper path")
else
Theme.switchTheme(10, true);
Theme.switchTheme(10, true)
}
}
@@ -730,25 +752,29 @@ Item {
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
visible: autoMouseArea.containsMouse && (!Theme.isDynamicTheme || ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
visible: autoMouseArea.containsMouse
&& (!Theme.isDynamicTheme
|| ToastService.wallpaperErrorStatus === "error"
|| ToastService.wallpaperErrorStatus === "matugen_missing")
StyledText {
id: autoTooltipText
text: {
if (ToastService.wallpaperErrorStatus === "matugen_missing")
return "Install matugen package for dynamic themes";
return "Install matugen package for dynamic themes"
else
return "Dynamic wallpaper-based colors";
return "Dynamic wallpaper-based colors"
}
font.pixelSize: Theme.fontSizeSmall
color: (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") ? Theme.error : Theme.surfaceText
color: (ToastService.wallpaperErrorStatus === "error"
|| ToastService.wallpaperErrorStatus
=== "matugen_missing") ? Theme.error : Theme.surfaceText
anchors.centerIn: parent
wrapMode: Text.WordWrap
width: Math.min(implicitWidth, 250)
horizontalAlignment: Text.AlignHCenter
}
}
Behavior on scale {
@@ -756,7 +782,6 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on color {
@@ -764,7 +789,6 @@ Item {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
Behavior on border.color {
@@ -772,13 +796,9 @@ Item {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
}
}
}
}
}
@@ -791,8 +811,10 @@ Item {
width: parent.width
height: systemThemingSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
visible: Theme.isDynamicTheme && Colors.matugenAvailable
@@ -821,7 +843,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
@@ -830,11 +851,10 @@ Item {
description: Colors.gtkThemingEnabled ? "File managers, text editors, and system dialogs will match your theme" : "GTK theming not available (install gsettings)"
enabled: Colors.gtkThemingEnabled
checked: Colors.gtkThemingEnabled && SettingsData.gtkThemingEnabled
onToggled: function(checked) {
SettingsData.setGtkThemingEnabled(checked);
onToggled: function (checked) {
SettingsData.setGtkThemingEnabled(checked)
if (checked && Theme.isDynamicTheme)
Colors.generateGtkThemes();
Colors.generateGtkThemes()
}
}
@@ -844,14 +864,12 @@ Item {
description: Colors.qtThemingEnabled ? "Qt applications will match your theme colors" : "Qt theming not available (install qt5ct or qt6ct)"
enabled: Colors.qtThemingEnabled
checked: Colors.qtThemingEnabled && SettingsData.qtThemingEnabled
onToggled: function(checked) {
SettingsData.setQtThemingEnabled(checked);
onToggled: function (checked) {
SettingsData.setQtThemingEnabled(checked)
if (checked && Theme.isDynamicTheme)
Colors.generateQtThemes();
Colors.generateQtThemes()
}
}
}
}
}
@@ -861,10 +879,9 @@ Item {
command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"]
running: false
onExited: (exitCode) => {
onExited: exitCode => {
if (exitCode !== 0)
SettingsData.setNightModeEnabled(true);
SettingsData.setNightModeEnabled(true)
}
}
@@ -873,11 +890,9 @@ Item {
command: ["bash", "-c", "pkill wlsunset; pkill redshift; if command -v wlsunset > /dev/null; then wlsunset -t 6500 -T 6500 & sleep 1; pkill wlsunset; elif command -v redshift > /dev/null; then redshift -P -O 6500; redshift -x; fi"]
running: false
onExited: (exitCode) => {
onExited: exitCode => {
if (exitCode !== 0)
SettingsData.setNightModeEnabled(false);
SettingsData.setNightModeEnabled(false)
}
}
}

View File

@@ -45,8 +45,10 @@ Item {
width: parent.width
height: appLauncherSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -61,8 +63,8 @@ Item {
text: "Use OS Logo"
description: "Display operating system logo instead of apps icon"
checked: SettingsData.useOSLogo
onToggled: (checked) => {
return SettingsData.setUseOSLogo(checked);
onToggled: checked => {
return SettingsData.setUseOSLogo(checked)
}
}
@@ -95,14 +97,13 @@ Item {
topPadding: Theme.spacingXS
bottomPadding: Theme.spacingXS
onEditingFinished: {
var color = text.trim();
var color = text.trim()
if (color === "" || /^#[0-9A-Fa-f]{6}$/.test(color))
SettingsData.setOSLogoColorOverride(color);
SettingsData.setOSLogoColorOverride(color)
else
text = SettingsData.osLogoColorOverride;
text = SettingsData.osLogoColorOverride
}
}
}
Column {
@@ -124,11 +125,11 @@ Item {
value: Math.round(SettingsData.osLogoBrightness * 100)
unit: "%"
showValue: true
onSliderValueChanged: (newValue) => {
SettingsData.setOSLogoBrightness(newValue / 100);
onSliderValueChanged: newValue => {
SettingsData.setOSLogoBrightness(
newValue / 100)
}
}
}
Column {
@@ -150,11 +151,11 @@ Item {
value: Math.round(SettingsData.osLogoContrast * 100)
unit: "%"
showValue: true
onSliderValueChanged: (newValue) => {
SettingsData.setOSLogoContrast(newValue / 100);
onSliderValueChanged: newValue => {
SettingsData.setOSLogoContrast(
newValue / 100)
}
}
}
Behavior on opacity {
@@ -162,11 +163,8 @@ Item {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
}
@@ -179,8 +177,10 @@ Item {
width: parent.width
height: dockSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -215,7 +215,7 @@ Item {
text: "Show Dock"
description: "Display a dock at the bottom of the screen with pinned and running applications"
checked: SettingsData.showDock
onToggled: (checked) => {
onToggled: checked => {
SettingsData.setShowDock(checked)
}
}
@@ -227,7 +227,7 @@ Item {
checked: SettingsData.dockAutoHide
visible: SettingsData.showDock
opacity: visible ? 1 : 0
onToggled: (checked) => {
onToggled: checked => {
SettingsData.setDockAutoHide(checked)
}
@@ -260,8 +260,9 @@ Item {
maximum: 100
unit: ""
showValue: true
onSliderValueChanged: (newValue) => {
SettingsData.setDockTransparency(newValue / 100);
onSliderValueChanged: newValue => {
SettingsData.setDockTransparency(
newValue / 100)
}
}
@@ -272,7 +273,6 @@ Item {
}
}
}
}
}
}
@@ -285,17 +285,19 @@ Item {
width: parent.width
height: recentlyUsedSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
id: recentlyUsedSection
property var rankedAppsModel: {
var apps = [];
var apps = []
for (var appId in (AppUsageHistoryData.appUsageRanking || {})) {
var appData = (AppUsageHistoryData.appUsageRanking || {})[appId];
var appData = (AppUsageHistoryData.appUsageRanking || {})[appId]
apps.push({
"id": appId,
"name": appData.name,
@@ -304,15 +306,15 @@ Item {
"comment": appData.comment,
"usageCount": appData.usageCount,
"lastUsed": appData.lastUsed
});
})
}
apps.sort(function(a, b) {
apps.sort(function (a, b) {
if (a.usageCount !== b.usageCount)
return b.usageCount - a.usageCount;
return b.usageCount - a.usageCount
return a.name.localeCompare(b.name);
});
return apps.slice(0, 20);
return a.name.localeCompare(b.name)
})
return apps.slice(0, 20)
}
anchors.fill: parent
@@ -339,7 +341,8 @@ Item {
}
Item {
width: parent.width - parent.children[0].width - parent.children[1].width - clearAllButton.width - Theme.spacingM * 3
width: parent.width - parent.children[0].width - parent.children[1].width
- clearAllButton.width - Theme.spacingM * 3
height: 1
}
@@ -349,14 +352,14 @@ Item {
iconName: "delete_sweep"
iconSize: Theme.iconSize - 2
iconColor: Theme.error
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b, 0.12)
anchors.verticalCenter: parent.verticalCenter
onClicked: {
AppUsageHistoryData.appUsageRanking = {};
SettingsData.saveSettings();
AppUsageHistoryData.appUsageRanking = {}
SettingsData.saveSettings()
}
}
}
StyledText {
@@ -380,8 +383,11 @@ Item {
width: rankedAppsList.width
height: 48
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
color: Qt.rgba(Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.1)
border.width: 1
Row {
@@ -409,8 +415,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
onStatusChanged: {
if (status === Image.Error)
source = "image://icon/application-x-executable";
source = "image://icon/application-x-executable"
}
}
@@ -428,34 +433,35 @@ Item {
StyledText {
text: {
if (!modelData.lastUsed)
return "Never used";
return "Never used"
var date = new Date(modelData.lastUsed);
var now = new Date();
var diffMs = now - date;
var diffMins = Math.floor(diffMs / (1000 * 60));
var diffHours = Math.floor(diffMs / (1000 * 60 * 60));
var diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
var date = new Date(modelData.lastUsed)
var now = new Date()
var diffMs = now - date
var diffMins = Math.floor(diffMs / (1000 * 60))
var diffHours = Math.floor(diffMs / (1000 * 60 * 60))
var diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24))
if (diffMins < 1)
return "Last launched just now";
return "Last launched just now"
if (diffMins < 60)
return "Last launched " + diffMins + " minute" + (diffMins === 1 ? "" : "s") + " ago";
return "Last launched " + diffMins + " minute"
+ (diffMins === 1 ? "" : "s") + " ago"
if (diffHours < 24)
return "Last launched " + diffHours + " hour" + (diffHours === 1 ? "" : "s") + " ago";
return "Last launched " + diffHours + " hour"
+ (diffHours === 1 ? "" : "s") + " ago"
if (diffDays < 7)
return "Last launched " + diffDays + " day" + (diffDays === 1 ? "" : "s") + " ago";
return "Last launched " + diffDays + " day"
+ (diffDays === 1 ? "" : "s") + " ago"
return "Last launched " + date.toLocaleDateString();
return "Last launched " + date.toLocaleDateString()
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
}
}
DankActionButton {
@@ -466,31 +472,29 @@ Item {
iconName: "close"
iconSize: 16
iconColor: Theme.error
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b, 0.12)
onClicked: {
var currentRanking = Object.assign({
}, AppUsageHistoryData.appUsageRanking || {});
delete currentRanking[modelData.id];
AppUsageHistoryData.appUsageRanking = currentRanking;
SettingsData.saveSettings();
var currentRanking = Object.assign(
{}, AppUsageHistoryData.appUsageRanking || {})
delete currentRanking[modelData.id]
AppUsageHistoryData.appUsageRanking = currentRanking
SettingsData.saveSettings()
}
}
}
}
StyledText {
width: parent.width
text: recentlyUsedSection.rankedAppsModel.length === 0 ? "No apps have been launched yet." : ""
text: recentlyUsedSection.rankedAppsModel.length
=== 0 ? "No apps have been launched yet." : ""
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
horizontalAlignment: Text.AlignHCenter
visible: recentlyUsedSection.rankedAppsModel.length === 0
}
}
}
}
}

View File

@@ -51,8 +51,10 @@ Item {
width: parent.width
height: profileSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -80,7 +82,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -109,12 +110,12 @@ Item {
source: {
if (PortalService.profileImage === "")
return "";
return ""
if (PortalService.profileImage.startsWith("/"))
return "file://" + PortalService.profileImage;
return "file://" + PortalService.profileImage
return PortalService.profileImage;
return PortalService.profileImage
}
smooth: true
asynchronous: true
@@ -149,7 +150,6 @@ Item {
color: "black"
antialiasing: true
}
}
Rectangle {
@@ -164,7 +164,6 @@ Item {
size: Theme.iconSizeLarge + 8
color: Theme.primaryText
}
}
DankIcon {
@@ -172,9 +171,9 @@ Item {
name: "warning"
size: Theme.iconSizeLarge
color: Theme.error
visible: PortalService.profileImage !== "" && avatarImageSource.status === Image.Error
visible: PortalService.profileImage !== ""
&& avatarImageSource.status === Image.Error
}
}
Column {
@@ -183,7 +182,9 @@ Item {
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: PortalService.profileImage ? PortalService.profileImage.split('/').pop() : "No profile image selected"
text: PortalService.profileImage ? PortalService.profileImage.split(
'/').pop(
) : "No profile image selected"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
elide: Text.ElideMiddle
@@ -216,7 +217,6 @@ Item {
color: Theme.error
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -245,21 +245,18 @@ Item {
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
profileBrowserLoader.active = true;
profileBrowser.visible = true;
profileBrowserLoader.active = true
profileBrowser.visible = true
}
}
}
StyledRect {
width: 80
height: 32
@@ -284,7 +281,6 @@ Item {
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -292,18 +288,13 @@ Item {
enabled: PortalService.profileImage !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
PortalService.setProfileImage("");
PortalService.setProfileImage("")
}
}
}
}
}
}
}
}
}
@@ -316,8 +307,10 @@ Item {
width: parent.width
height: wallpaperSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -345,7 +338,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -375,7 +367,6 @@ Item {
maskThresholdMin: 0.5
maskSpreadAtMin: 1
}
}
Rectangle {
@@ -396,7 +387,6 @@ Item {
color: Theme.surfaceVariantText
visible: SessionData.wallpaperPath === ""
}
}
Column {
@@ -405,7 +395,9 @@ Item {
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: SessionData.wallpaperPath ? SessionData.wallpaperPath.split('/').pop() : "No wallpaper selected"
text: SessionData.wallpaperPath ? SessionData.wallpaperPath.split(
'/').pop(
) : "No wallpaper selected"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
elide: Text.ElideMiddle
@@ -447,18 +439,16 @@ Item {
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
wallpaperBrowserLoader.active = true;
wallpaperBrowser.visible = true;
wallpaperBrowserLoader.active = true
wallpaperBrowser.visible = true
}
}
}
StyledRect {
@@ -485,7 +475,6 @@ Item {
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -493,18 +482,13 @@ Item {
enabled: SessionData.wallpaperPath !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
SessionData.setWallpaper("");
SessionData.setWallpaper("")
}
}
}
}
}
}
}
}
}
@@ -517,8 +501,10 @@ Item {
width: parent.width
height: dynamicThemeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -558,7 +544,6 @@ Item {
wrapMode: Text.WordWrap
width: parent.width
}
}
DankToggle {
@@ -567,14 +552,13 @@ Item {
anchors.verticalCenter: parent.verticalCenter
checked: Theme.isDynamicTheme
enabled: ToastService.wallpaperErrorStatus !== "matugen_missing"
onToggled: (toggled) => {
onToggled: toggled => {
if (toggled)
Theme.switchTheme(10, true);
Theme.switchTheme(10, true)
else
Theme.switchTheme(0);
Theme.switchTheme(0)
}
}
}
StyledText {
@@ -585,7 +569,6 @@ Item {
width: parent.width
leftPadding: Theme.iconSize + Theme.spacingM
}
}
}
}
@@ -602,14 +585,15 @@ Item {
browserIcon: "person"
browserType: "profile"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => {
PortalService.setProfileImage(path);
visible = false;
}
onDialogClosed: {}
onFileSelected: path => {
PortalService.setProfileImage(path)
visible = false
}
onDialogClosed: {
}
}
}
LazyLoader {
id: wallpaperBrowserLoader
@@ -623,13 +607,13 @@ Item {
browserIcon: "wallpaper"
browserType: "wallpaper"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => {
SessionData.setWallpaper(path);
visible = false;
}
onDialogClosed: {}
onFileSelected: path => {
SessionData.setWallpaper(path)
visible = false
}
onDialogClosed: {
}
}
}
}

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import qs.Common
@@ -18,8 +18,7 @@ Column {
spacing: expanded ? Theme.spacingM : 0
Component.onCompleted: {
if (!collapsible)
expanded = true;
expanded = true
}
MouseArea {
@@ -29,13 +28,14 @@ Column {
hoverEnabled: collapsible
onClicked: {
if (collapsible)
expanded = !expanded;
expanded = !expanded
}
Rectangle {
anchors.fill: parent
color: parent.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
color: parent.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.08) : "transparent"
radius: Theme.radiusS
}
@@ -59,9 +59,7 @@ Column {
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
DankIcon {
@@ -79,9 +77,7 @@ Column {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
}
Rectangle {
@@ -106,9 +102,6 @@ Column {
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
}

View File

@@ -39,8 +39,10 @@ Item {
width: parent.width
height: timeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -68,7 +70,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
@@ -76,11 +77,10 @@ Item {
text: "24-Hour Format"
description: "Use 24-hour time format instead of 12-hour AM/PM"
checked: SettingsData.use24HourClock
onToggled: (checked) => {
return SettingsData.setClockFormat(checked);
onToggled: checked => {
return SettingsData.setClockFormat(checked)
}
}
}
}
}
@@ -93,8 +93,10 @@ Item {
width: parent.width
height: weatherSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -122,7 +124,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
@@ -130,8 +131,8 @@ Item {
text: "Enable Weather"
description: "Show weather information in top bar and centcom center"
checked: SettingsData.weatherEnabled
onToggled: (checked) => {
return SettingsData.setWeatherEnabled(checked);
onToggled: checked => {
return SettingsData.setWeatherEnabled(checked)
}
}
@@ -141,8 +142,8 @@ Item {
description: "Use Fahrenheit instead of Celsius for temperature"
checked: SettingsData.useFahrenheit
enabled: SettingsData.weatherEnabled
onToggled: (checked) => {
return SettingsData.setTemperatureUnit(checked);
onToggled: checked => {
return SettingsData.setTemperatureUnit(checked)
}
}
@@ -152,8 +153,8 @@ Item {
description: "Allow wttr.in to determine location based on IP address"
checked: SettingsData.useAutoLocation
enabled: SettingsData.weatherEnabled
onToggled: (checked) => {
return SettingsData.setAutoLocation(checked);
onToggled: checked => {
return SettingsData.setAutoLocation(checked)
}
}
@@ -174,12 +175,11 @@ Item {
currentLocation: SettingsData.weatherLocation
placeholderText: "New York, NY"
onLocationSelected: (displayName, coordinates) => {
SettingsData.setWeatherLocation(displayName, coordinates);
SettingsData.setWeatherLocation(displayName,
coordinates)
}
}
}
}
}
}

View File

@@ -165,62 +165,62 @@ Item {
var widgetObj = {
"id": widgetId,
"enabled": true
};
}
if (widgetId === "spacer")
widgetObj.size = 20;
widgetObj.size = 20
if (widgetId === "gpuTemp")
widgetObj.selectedGpuIndex = 0;
widgetObj.selectedGpuIndex = 0
var widgets = [];
var widgets = []
if (targetSection === "left") {
widgets = SettingsData.topBarLeftWidgets.slice();
widgets.push(widgetObj);
SettingsData.setTopBarLeftWidgets(widgets);
widgets = SettingsData.topBarLeftWidgets.slice()
widgets.push(widgetObj)
SettingsData.setTopBarLeftWidgets(widgets)
} else if (targetSection === "center") {
widgets = SettingsData.topBarCenterWidgets.slice();
widgets.push(widgetObj);
SettingsData.setTopBarCenterWidgets(widgets);
widgets = SettingsData.topBarCenterWidgets.slice()
widgets.push(widgetObj)
SettingsData.setTopBarCenterWidgets(widgets)
} else if (targetSection === "right") {
widgets = SettingsData.topBarRightWidgets.slice();
widgets.push(widgetObj);
SettingsData.setTopBarRightWidgets(widgets);
widgets = SettingsData.topBarRightWidgets.slice()
widgets.push(widgetObj)
SettingsData.setTopBarRightWidgets(widgets)
}
}
function removeWidgetFromSection(sectionId, widgetIndex) {
var widgets = [];
var widgets = []
if (sectionId === "left") {
widgets = SettingsData.topBarLeftWidgets.slice();
widgets = SettingsData.topBarLeftWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets.splice(widgetIndex, 1);
widgets.splice(widgetIndex, 1)
}
SettingsData.setTopBarLeftWidgets(widgets);
SettingsData.setTopBarLeftWidgets(widgets)
} else if (sectionId === "center") {
widgets = SettingsData.topBarCenterWidgets.slice();
widgets = SettingsData.topBarCenterWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets.splice(widgetIndex, 1);
widgets.splice(widgetIndex, 1)
}
SettingsData.setTopBarCenterWidgets(widgets);
SettingsData.setTopBarCenterWidgets(widgets)
} else if (sectionId === "right") {
widgets = SettingsData.topBarRightWidgets.slice();
widgets = SettingsData.topBarRightWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets.splice(widgetIndex, 1);
widgets.splice(widgetIndex, 1)
}
SettingsData.setTopBarRightWidgets(widgets);
SettingsData.setTopBarRightWidgets(widgets)
}
}
function handleItemEnabledChanged(sectionId, itemId, enabled) {
var widgets = [];
var widgets = []
if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice();
widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice();
widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice();
widgets = SettingsData.topBarRightWidgets.slice()
for (var i = 0; i < widgets.length; i++) {
var widget = widgets[i];
var widgetId = typeof widget === "string" ? widget : widget.id;
var widget = widgets[i]
var widgetId = typeof widget === "string" ? widget : widget.id
if (widgetId === itemId) {
widgets[i] = typeof widget === "string" ? {
"id": widget,
@@ -230,38 +230,38 @@ Item {
"enabled": enabled,
"size": widget.size,
"selectedGpuIndex": widget.selectedGpuIndex
};
break;
}
break
}
}
if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets);
SettingsData.setTopBarLeftWidgets(widgets)
else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets);
SettingsData.setTopBarCenterWidgets(widgets)
else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets);
SettingsData.setTopBarRightWidgets(widgets)
}
function handleItemOrderChanged(sectionId, newOrder) {
if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(newOrder);
SettingsData.setTopBarLeftWidgets(newOrder)
else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(newOrder);
SettingsData.setTopBarCenterWidgets(newOrder)
else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(newOrder);
SettingsData.setTopBarRightWidgets(newOrder)
}
function handleSpacerSizeChanged(sectionId, itemId, newSize) {
var widgets = [];
var widgets = []
if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice();
widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice();
widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice();
widgets = SettingsData.topBarRightWidgets.slice()
for (var i = 0; i < widgets.length; i++) {
var widget = widgets[i];
var widgetId = typeof widget === "string" ? widget : widget.id;
var widget = widgets[i]
var widgetId = typeof widget === "string" ? widget : widget.id
if (widgetId === itemId && widgetId === "spacer") {
widgets[i] = typeof widget === "string" ? {
"id": widget,
@@ -272,29 +272,29 @@ Item {
"enabled": widget.enabled,
"size": newSize,
"selectedGpuIndex": widget.selectedGpuIndex
};
break;
}
break
}
}
if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets);
SettingsData.setTopBarLeftWidgets(widgets)
else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets);
SettingsData.setTopBarCenterWidgets(widgets)
else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets);
SettingsData.setTopBarRightWidgets(widgets)
}
function handleGpuSelectionChanged(sectionId, widgetIndex, selectedGpuIndex) {
var widgets = [];
var widgets = []
if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice();
widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice();
widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice();
widgets = SettingsData.topBarRightWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
var widget = widgets[widgetIndex];
var widget = widgets[widgetIndex]
widgets[widgetIndex] = typeof widget === "string" ? {
"id": widget,
"enabled": true,
@@ -304,87 +304,97 @@ Item {
"enabled": widget.enabled,
"size": widget.size,
"selectedGpuIndex": selectedGpuIndex
};
}
}
if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets);
SettingsData.setTopBarLeftWidgets(widgets)
else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets);
SettingsData.setTopBarCenterWidgets(widgets)
else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets);
SettingsData.setTopBarRightWidgets(widgets)
}
function getItemsForSection(sectionId) {
var widgets = [];
var widgetData = [];
var widgets = []
var widgetData = []
if (sectionId === "left")
widgetData = SettingsData.topBarLeftWidgets || [];
widgetData = SettingsData.topBarLeftWidgets || []
else if (sectionId === "center")
widgetData = SettingsData.topBarCenterWidgets || [];
widgetData = SettingsData.topBarCenterWidgets || []
else if (sectionId === "right")
widgetData = SettingsData.topBarRightWidgets || [];
widgetData.forEach((widget) => {
var widgetId = typeof widget === "string" ? widget : widget.id;
var widgetEnabled = typeof widget === "string" ? true : widget.enabled;
var widgetSize = typeof widget === "string" ? undefined : widget.size;
var widgetSelectedGpuIndex = typeof widget === "string" ? undefined : widget.selectedGpuIndex;
var widgetDef = baseWidgetDefinitions.find((w) => {
return w.id === widgetId;
});
widgetData = SettingsData.topBarRightWidgets || []
widgetData.forEach(widget => {
var widgetId = typeof widget === "string" ? widget : widget.id
var widgetEnabled = typeof widget === "string" ? true : widget.enabled
var widgetSize = typeof widget === "string" ? undefined : widget.size
var widgetSelectedGpuIndex = typeof widget
=== "string" ? undefined : widget.selectedGpuIndex
var widgetDef = baseWidgetDefinitions.find(w => {
return w.id === widgetId
})
if (widgetDef) {
var item = Object.assign({
}, widgetDef);
item.enabled = widgetEnabled;
var item = Object.assign({}, widgetDef)
item.enabled = widgetEnabled
if (widgetSize !== undefined)
item.size = widgetSize;
item.size = widgetSize
if (widgetSelectedGpuIndex !== undefined)
item.selectedGpuIndex = widgetSelectedGpuIndex;
item.selectedGpuIndex = widgetSelectedGpuIndex
widgets.push(item);
widgets.push(item)
}
});
return widgets;
})
return widgets
}
Component.onCompleted: {
if (!SettingsData.topBarLeftWidgets || SettingsData.topBarLeftWidgets.length === 0)
SettingsData.setTopBarLeftWidgets(defaultLeftWidgets);
if (!SettingsData.topBarLeftWidgets
|| SettingsData.topBarLeftWidgets.length === 0)
SettingsData.setTopBarLeftWidgets(defaultLeftWidgets)
if (!SettingsData.topBarCenterWidgets || SettingsData.topBarCenterWidgets.length === 0)
SettingsData.setTopBarCenterWidgets(defaultCenterWidgets);
if (!SettingsData.topBarCenterWidgets
|| SettingsData.topBarCenterWidgets.length === 0)
SettingsData.setTopBarCenterWidgets(defaultCenterWidgets)
if (!SettingsData.topBarRightWidgets || SettingsData.topBarRightWidgets.length === 0)
SettingsData.setTopBarRightWidgets(defaultRightWidgets);
["left", "center", "right"].forEach((sectionId) => {
var widgets = [];
if (!SettingsData.topBarRightWidgets
|| SettingsData.topBarRightWidgets.length === 0)
SettingsData.setTopBarRightWidgets(
defaultRightWidgets)["left", "center", "right"].forEach(sectionId => {
var widgets = []
if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice();
widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice();
widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice();
var updated = false;
for (var i = 0; i < widgets.length; i++) {
var widget = widgets[i];
if (typeof widget === "object" && widget.id === "spacer" && !widget.size) {
widgets[i] = Object.assign({
}, widget, {
widgets = SettingsData.topBarRightWidgets.slice()
var updated = false
for (var i = 0; i
< widgets.length; i++) {
var widget = widgets[i]
if (typeof widget === "object"
&& widget.id === "spacer"
&& !widget.size) {
widgets[i] = Object.assign(
{},
widget,
{
"size": 20
});
updated = true;
})
updated = true
}
}
if (updated) {
if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets);
SettingsData.setTopBarLeftWidgets(
widgets)
else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets);
SettingsData.setTopBarCenterWidgets(
widgets)
else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets);
SettingsData.setTopBarRightWidgets(
widgets)
}
});
})
}
DankFlickable {
@@ -457,7 +467,10 @@ Item {
color: resetArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariant
anchors.verticalCenter: parent.verticalCenter
border.width: 1
border.color: resetArea.containsMouse ? Theme.outline : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.5)
border.color: resetArea.containsMouse ? Theme.outline : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.5)
Row {
anchors.centerIn: parent
@@ -486,9 +499,9 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
SettingsData.setTopBarLeftWidgets(defaultLeftWidgets);
SettingsData.setTopBarCenterWidgets(defaultCenterWidgets);
SettingsData.setTopBarRightWidgets(defaultRightWidgets);
SettingsData.setTopBarLeftWidgets(defaultLeftWidgets)
SettingsData.setTopBarCenterWidgets(defaultCenterWidgets)
SettingsData.setTopBarRightWidgets(defaultRightWidgets)
}
}
@@ -517,8 +530,10 @@ Item {
width: parent.width
height: messageText.contentHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
StyledText {
@@ -550,31 +565,38 @@ Item {
allWidgets: widgetsTab.baseWidgetDefinitions
items: widgetsTab.getItemsForSection("left")
onItemEnabledChanged: (sectionId, itemId, enabled) => {
widgetsTab.handleItemEnabledChanged(sectionId, itemId, enabled);
widgetsTab.handleItemEnabledChanged(sectionId,
itemId,
enabled)
}
onItemOrderChanged: (newOrder) => {
widgetsTab.handleItemOrderChanged("left", newOrder);
onItemOrderChanged: newOrder => {
widgetsTab.handleItemOrderChanged("left",
newOrder)
}
onAddWidget: (sectionId) => {
widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions;
widgetSelectionPopup.targetSection = sectionId;
widgetSelectionPopup.safeOpen();
onAddWidget: sectionId => {
widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions
widgetSelectionPopup.targetSection = sectionId
widgetSelectionPopup.safeOpen()
}
onRemoveWidget: (sectionId, widgetIndex) => {
widgetsTab.removeWidgetFromSection(sectionId, widgetIndex);
widgetsTab.removeWidgetFromSection(sectionId,
widgetIndex)
}
onSpacerSizeChanged: (sectionId, itemId, newSize) => {
widgetsTab.handleSpacerSizeChanged(sectionId, itemId, newSize);
widgetsTab.handleSpacerSizeChanged(sectionId,
itemId,
newSize)
}
onCompactModeChanged: (widgetId, enabled) => {
if (widgetId === "clock") {
SettingsData.setClockCompactMode(enabled);
SettingsData.setClockCompactMode(enabled)
} else if (widgetId === "music") {
SettingsData.setMediaCompactMode(enabled);
SettingsData.setMediaCompactMode(enabled)
}
}
onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => {
widgetsTab.handleGpuSelectionChanged(sectionId, widgetIndex, selectedIndex);
widgetsTab.handleGpuSelectionChanged(
sectionId, widgetIndex, selectedIndex)
}
}
@@ -586,31 +608,38 @@ Item {
allWidgets: widgetsTab.baseWidgetDefinitions
items: widgetsTab.getItemsForSection("center")
onItemEnabledChanged: (sectionId, itemId, enabled) => {
widgetsTab.handleItemEnabledChanged(sectionId, itemId, enabled);
widgetsTab.handleItemEnabledChanged(sectionId,
itemId,
enabled)
}
onItemOrderChanged: (newOrder) => {
widgetsTab.handleItemOrderChanged("center", newOrder);
onItemOrderChanged: newOrder => {
widgetsTab.handleItemOrderChanged("center",
newOrder)
}
onAddWidget: (sectionId) => {
widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions;
widgetSelectionPopup.targetSection = sectionId;
widgetSelectionPopup.safeOpen();
onAddWidget: sectionId => {
widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions
widgetSelectionPopup.targetSection = sectionId
widgetSelectionPopup.safeOpen()
}
onRemoveWidget: (sectionId, widgetIndex) => {
widgetsTab.removeWidgetFromSection(sectionId, widgetIndex);
widgetsTab.removeWidgetFromSection(sectionId,
widgetIndex)
}
onSpacerSizeChanged: (sectionId, itemId, newSize) => {
widgetsTab.handleSpacerSizeChanged(sectionId, itemId, newSize);
widgetsTab.handleSpacerSizeChanged(sectionId,
itemId,
newSize)
}
onCompactModeChanged: (widgetId, enabled) => {
if (widgetId === "clock") {
SettingsData.setClockCompactMode(enabled);
SettingsData.setClockCompactMode(enabled)
} else if (widgetId === "music") {
SettingsData.setMediaCompactMode(enabled);
SettingsData.setMediaCompactMode(enabled)
}
}
onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => {
widgetsTab.handleGpuSelectionChanged(sectionId, widgetIndex, selectedIndex);
widgetsTab.handleGpuSelectionChanged(
sectionId, widgetIndex, selectedIndex)
}
}
@@ -622,31 +651,38 @@ Item {
allWidgets: widgetsTab.baseWidgetDefinitions
items: widgetsTab.getItemsForSection("right")
onItemEnabledChanged: (sectionId, itemId, enabled) => {
widgetsTab.handleItemEnabledChanged(sectionId, itemId, enabled);
widgetsTab.handleItemEnabledChanged(sectionId,
itemId,
enabled)
}
onItemOrderChanged: (newOrder) => {
widgetsTab.handleItemOrderChanged("right", newOrder);
onItemOrderChanged: newOrder => {
widgetsTab.handleItemOrderChanged("right",
newOrder)
}
onAddWidget: (sectionId) => {
widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions;
widgetSelectionPopup.targetSection = sectionId;
widgetSelectionPopup.safeOpen();
onAddWidget: sectionId => {
widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions
widgetSelectionPopup.targetSection = sectionId
widgetSelectionPopup.safeOpen()
}
onRemoveWidget: (sectionId, widgetIndex) => {
widgetsTab.removeWidgetFromSection(sectionId, widgetIndex);
widgetsTab.removeWidgetFromSection(sectionId,
widgetIndex)
}
onSpacerSizeChanged: (sectionId, itemId, newSize) => {
widgetsTab.handleSpacerSizeChanged(sectionId, itemId, newSize);
widgetsTab.handleSpacerSizeChanged(sectionId,
itemId,
newSize)
}
onCompactModeChanged: (widgetId, enabled) => {
if (widgetId === "clock") {
SettingsData.setClockCompactMode(enabled);
SettingsData.setClockCompactMode(enabled)
} else if (widgetId === "music") {
SettingsData.setMediaCompactMode(enabled);
SettingsData.setMediaCompactMode(enabled)
}
}
onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => {
widgetsTab.handleGpuSelectionChanged(sectionId, widgetIndex, selectedIndex);
widgetsTab.handleGpuSelectionChanged(
sectionId, widgetIndex, selectedIndex)
}
}
}
@@ -660,8 +696,10 @@ Item {
width: parent.width
height: workspaceSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
Column {
@@ -696,8 +734,8 @@ Item {
text: "Workspace Index Numbers"
description: "Show workspace index numbers in the top bar workspace switcher"
checked: SettingsData.showWorkspaceIndex
onToggled: (checked) => {
return SettingsData.setShowWorkspaceIndex(checked);
onToggled: checked => {
return SettingsData.setShowWorkspaceIndex(checked)
}
}
@@ -706,22 +744,20 @@ Item {
text: "Workspace Padding"
description: "Always show a minimum of 3 workspaces, even if fewer are available"
checked: SettingsData.showWorkspacePadding
onToggled: (checked) => {
return SettingsData.setShowWorkspacePadding(checked);
onToggled: checked => {
return SettingsData.setShowWorkspacePadding(checked)
}
}
}
}
}
DankWidgetSelectionPopup {
id: widgetSelectionPopup
anchors.centerIn: parent
onWidgetSelected: (widgetId, targetSection) => {
widgetsTab.addWidgetToSection(widgetId, targetSection);
widgetsTab.addWidgetToSection(widgetId, targetSection)
}
}
}

View File

@@ -48,7 +48,6 @@ Column {
width: parent.width - 60
height: 1
}
}
Column {
@@ -76,8 +75,10 @@ Column {
anchors.fill: parent
anchors.margins: 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.8)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.8)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
DankIcon {
@@ -119,12 +120,13 @@ Column {
StyledText {
text: modelData.description
font.pixelSize: Theme.fontSizeSmall
color: modelData.enabled ? Theme.outline : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.6)
color: modelData.enabled ? Theme.outline : Qt.rgba(
Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.6)
elide: Text.ElideRight
width: parent.width
wrapMode: Text.WordWrap
}
}
Row {
@@ -144,27 +146,40 @@ Column {
id: gpuDropdown
anchors.fill: parent
currentValue: {
var selectedIndex = modelData.selectedGpuIndex !== undefined ? modelData.selectedGpuIndex : 0;
if (SysMonitorService.availableGpus && SysMonitorService.availableGpus.length > selectedIndex && selectedIndex >= 0) {
var gpu = SysMonitorService.availableGpus[selectedIndex];
return gpu.driver.toUpperCase() + " (" + Math.round(gpu.temperature || 0) + "°C)";
var selectedIndex = modelData.selectedGpuIndex
!== undefined ? modelData.selectedGpuIndex : 0
if (SysMonitorService.availableGpus
&& SysMonitorService.availableGpus.length > selectedIndex
&& selectedIndex >= 0) {
var gpu = SysMonitorService.availableGpus[selectedIndex]
return gpu.driver.toUpperCase() + " (" + Math.round(
gpu.temperature || 0) + "°C)"
}
return SysMonitorService.availableGpus && SysMonitorService.availableGpus.length > 0 ? SysMonitorService.availableGpus[0].driver.toUpperCase() + " (" + Math.round(SysMonitorService.availableGpus[0].temperature || 0) + "°C)" : "";
return SysMonitorService.availableGpus
&& SysMonitorService.availableGpus.length
> 0 ? SysMonitorService.availableGpus[0].driver.toUpperCase(
) + " (" + Math.round(
SysMonitorService.availableGpus[0].temperature
|| 0) + "°C)" : ""
}
options: {
var gpuOptions = [];
if (SysMonitorService.availableGpus && SysMonitorService.availableGpus.length > 0) {
var gpuOptions = []
if (SysMonitorService.availableGpus
&& SysMonitorService.availableGpus.length > 0) {
for (var i = 0; i < SysMonitorService.availableGpus.length; i++) {
var gpu = SysMonitorService.availableGpus[i];
gpuOptions.push(gpu.driver.toUpperCase() + " (" + Math.round(gpu.temperature || 0) + "°C)");
var gpu = SysMonitorService.availableGpus[i]
gpuOptions.push(gpu.driver.toUpperCase(
) + " (" + Math.round(gpu.temperature
|| 0) + "°C)")
}
}
return gpuOptions;
return gpuOptions
}
onValueChanged: (value) => {
var gpuIndex = options.indexOf(value);
onValueChanged: value => {
var gpuIndex = options.indexOf(value)
if (gpuIndex >= 0) {
root.gpuSelectionChanged(root.sectionId, index, gpuIndex);
root.gpuSelectionChanged(root.sectionId,
index, gpuIndex)
}
}
}
@@ -179,14 +194,22 @@ Column {
id: compactModeButton
anchors.fill: parent
buttonSize: 32
iconName: (modelData.id === "clock" && SettingsData.clockCompactMode) || (modelData.id === "music" && SettingsData.mediaCompactMode) ? "zoom_out" : "zoom_in"
iconName: (modelData.id === "clock"
&& SettingsData.clockCompactMode)
|| (modelData.id === "music"
&& SettingsData.mediaCompactMode) ? "zoom_out" : "zoom_in"
iconSize: 18
iconColor: ((modelData.id === "clock" && SettingsData.clockCompactMode) || (modelData.id === "music" && SettingsData.mediaCompactMode)) ? Theme.primary : Theme.outline
iconColor: ((modelData.id === "clock"
&& SettingsData.clockCompactMode)
|| (modelData.id === "music"
&& SettingsData.mediaCompactMode)) ? Theme.primary : Theme.outline
onClicked: {
if (modelData.id === "clock") {
root.compactModeChanged("clock", !SettingsData.clockCompactMode);
root.compactModeChanged("clock",
!SettingsData.clockCompactMode)
} else if (modelData.id === "music") {
root.compactModeChanged("music", !SettingsData.mediaCompactMode);
root.compactModeChanged("music",
!SettingsData.mediaCompactMode)
}
}
}
@@ -199,7 +222,8 @@ Column {
color: Theme.surfaceContainer
border.color: Theme.outline
border.width: 1
visible: compactModeButton.children[1] && compactModeButton.children[1].containsMouse
visible: compactModeButton.children[1]
&& compactModeButton.children[1].containsMouse
opacity: visible ? 1 : 0
x: -width - Theme.spacingS
y: (parent.height - height) / 2
@@ -229,7 +253,8 @@ Column {
iconSize: 18
iconColor: modelData.enabled ? Theme.primary : Theme.outline
onClicked: {
root.itemEnabledChanged(root.sectionId, modelData.id, !modelData.enabled);
root.itemEnabledChanged(root.sectionId, modelData.id,
!modelData.enabled)
}
}
@@ -244,9 +269,9 @@ Column {
iconSize: 14
iconColor: Theme.outline
onClicked: {
var currentSize = modelData.size || 20;
var newSize = Math.max(5, currentSize - 5);
root.spacerSizeChanged(root.sectionId, modelData.id, newSize);
var currentSize = modelData.size || 20
var newSize = Math.max(5, currentSize - 5)
root.spacerSizeChanged(root.sectionId, modelData.id, newSize)
}
}
@@ -263,12 +288,11 @@ Column {
iconSize: 14
iconColor: Theme.outline
onClicked: {
var currentSize = modelData.size || 20;
var newSize = Math.min(5000, currentSize + 5);
root.spacerSizeChanged(root.sectionId, modelData.id, newSize);
var currentSize = modelData.size || 20
var newSize = Math.min(5000, currentSize + 5)
root.spacerSizeChanged(root.sectionId, modelData.id, newSize)
}
}
}
DankActionButton {
@@ -277,10 +301,9 @@ Column {
iconSize: 18
iconColor: Theme.error
onClicked: {
root.removeWidget(root.sectionId, index);
root.removeWidget(root.sectionId, index)
}
}
}
MouseArea {
@@ -298,29 +321,31 @@ Column {
drag.maximumY: itemsList.height
preventStealing: true
onPressed: {
delegateItem.z = 2;
delegateItem.originalY = delegateItem.y;
delegateItem.z = 2
delegateItem.originalY = delegateItem.y
}
onReleased: {
delegateItem.z = 1;
delegateItem.z = 1
if (drag.active) {
var newIndex = Math.round(delegateItem.y / (delegateItem.height + itemsList.spacing));
newIndex = Math.max(0, Math.min(newIndex, root.items.length - 1));
var newIndex = Math.round(
delegateItem.y / (delegateItem.height + itemsList.spacing))
newIndex = Math.max(0, Math.min(newIndex,
root.items.length - 1))
if (newIndex !== index) {
var newItems = root.items.slice();
var draggedItem = newItems.splice(index, 1)[0];
newItems.splice(newIndex, 0, draggedItem);
root.itemOrderChanged(newItems.map((item) => {
var newItems = root.items.slice()
var draggedItem = newItems.splice(index, 1)[0]
newItems.splice(newIndex, 0, draggedItem)
root.itemOrderChanged(newItems.map(item => {
return ({
"id": item.id,
"enabled": item.enabled,
"size": item.size
});
}));
})
}))
}
}
delegateItem.x = 0;
delegateItem.y = delegateItem.originalY;
delegateItem.x = 0
delegateItem.y = delegateItem.originalY
}
}
@@ -331,23 +356,22 @@ Column {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}
}
Rectangle {
width: 200
height: 40
radius: Theme.cornerRadius
color: addButtonArea.containsMouse ? Theme.primaryContainer : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
color: addButtonArea.containsMouse ? Theme.primaryContainer : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1
anchors.horizontalCenter: parent.horizontalCenter
@@ -367,7 +391,7 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.addWidget(root.sectionId);
root.addWidget(root.sectionId)
}
}
@@ -376,9 +400,6 @@ Column {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}

View File

@@ -36,13 +36,13 @@ PanelWindow {
color: {
switch (ToastService.currentLevel) {
case ToastService.levelError:
return Theme.error;
return Theme.error
case ToastService.levelWarn:
return Theme.warning;
return Theme.warning
case ToastService.levelInfo:
return Theme.primary;
return Theme.primary
default:
return Theme.primary;
return Theme.primary
}
}
radius: Theme.cornerRadiusLarge
@@ -60,13 +60,13 @@ PanelWindow {
name: {
switch (ToastService.currentLevel) {
case ToastService.levelError:
return "error";
return "error"
case ToastService.levelWarn:
return "warning";
return "warning"
case ToastService.levelInfo:
return "info";
return "info"
default:
return "info";
return "info"
}
}
size: Theme.iconSize
@@ -83,7 +83,6 @@ PanelWindow {
width: 300
wrapMode: Text.WordWrap
}
}
MouseArea {
@@ -109,7 +108,6 @@ PanelWindow {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
@@ -117,7 +115,6 @@ PanelWindow {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on color {
@@ -125,13 +122,10 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
mask: Region {
item: toast
}
}

View File

@@ -8,7 +8,8 @@ Item {
readonly property MprisPlayer activePlayer: MprisController.activePlayer
readonly property bool hasActiveMedia: activePlayer !== null
readonly property bool isPlaying: hasActiveMedia && activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing
readonly property bool isPlaying: hasActiveMedia && activePlayer
&& activePlayer.playbackState === MprisPlaybackState.Playing
width: 20
height: Theme.iconSize
@@ -24,7 +25,10 @@ Item {
interval: 256
repeat: true
onTriggered: {
CavaService.values = [Math.random() * 40 + 10, Math.random() * 60 + 20, Math.random() * 50 + 15, Math.random() * 35 + 20, Math.random() * 45 + 15, Math.random() * 55 + 25];
CavaService.values = [Math.random() * 40 + 10, Math.random(
) * 60 + 20, Math.random() * 50 + 15, Math.random(
) * 35 + 20, Math.random() * 45 + 15, Math.random(
) * 55 + 25]
}
}
@@ -39,13 +43,14 @@ Item {
width: 2
height: {
if (root.isPlaying && CavaService.values.length > index) {
const rawLevel = CavaService.values[index] || 0;
const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0), 100) / 100) * 100;
const maxHeight = Theme.iconSize - 2;
const minHeight = 3;
return minHeight + (scaledLevel / 100) * (maxHeight - minHeight);
const rawLevel = CavaService.values[index] || 0
const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0),
100) / 100) * 100
const maxHeight = Theme.iconSize - 2
const minHeight = 3
return minHeight + (scaledLevel / 100) * (maxHeight - minHeight)
}
return 3;
return 3
}
radius: 1.5
color: Theme.primary
@@ -57,13 +62,8 @@ Item {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standardDecel
}
}
}
}
}
}

View File

@@ -12,14 +12,16 @@ Rectangle {
property var popupTarget: null
property var parentScreen: null
signal toggleBatteryPopup()
signal toggleBatteryPopup
width: BatteryService.batteryAvailable ? 70 : 40
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = batteryArea.containsMouse || batteryPopupVisible ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = batteryArea.containsMouse
|| batteryPopupVisible ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
visible: true
@@ -28,19 +30,21 @@ Rectangle {
spacing: 4
DankIcon {
name: Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable)
name: Theme.getBatteryIcon(BatteryService.batteryLevel,
BatteryService.isCharging,
BatteryService.batteryAvailable)
size: Theme.iconSize - 6
color: {
if (!BatteryService.batteryAvailable)
return Theme.surfaceText;
return Theme.surfaceText
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error;
return Theme.error
if (BatteryService.isCharging)
return Theme.primary;
return Theme.primary
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
@@ -61,9 +65,7 @@ Rectangle {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standard
}
}
}
StyledText {
@@ -72,20 +74,19 @@ Rectangle {
font.weight: Font.Medium
color: {
if (!BatteryService.batteryAvailable)
return Theme.surfaceText;
return Theme.surfaceText
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error;
return Theme.error
if (BatteryService.isCharging)
return Theme.primary;
return Theme.primary
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
visible: BatteryService.batteryAvailable
}
}
MouseArea {
@@ -96,13 +97,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
toggleBatteryPopup();
toggleBatteryPopup()
}
}
@@ -131,30 +134,29 @@ Rectangle {
text: {
if (!BatteryService.batteryAvailable) {
if (typeof PowerProfiles === "undefined")
return "Power Management";
return "Power Management"
switch (PowerProfiles.profile) {
case PowerProfile.PowerSaver:
return "Power Profile: Power Saver";
return "Power Profile: Power Saver"
case PowerProfile.Performance:
return "Power Profile: Performance";
return "Power Profile: Performance"
default:
return "Power Profile: Balanced";
return "Power Profile: Balanced"
}
}
let status = BatteryService.batteryStatus;
let level = BatteryService.batteryLevel + "%";
let time = BatteryService.formatTimeRemaining();
let status = BatteryService.batteryStatus
let level = BatteryService.batteryLevel + "%"
let time = BatteryService.formatTimeRemaining()
if (time !== "Unknown")
return status + " • " + level + " • " + time;
return status + " • " + level + " • " + time
else
return status + " • " + level;
return status + " • " + level
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
horizontalAlignment: Text.AlignHCenter
}
}
Behavior on opacity {
@@ -162,9 +164,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Behavior on color {
@@ -172,7 +172,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -19,29 +19,28 @@ PanelWindow {
property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) {
triggerX = x;
triggerY = y;
triggerWidth = width;
triggerSection = section;
triggerScreen = screen;
triggerX = x
triggerY = y
triggerWidth = width
triggerSection = section
triggerScreen = screen
}
function isActiveProfile(profile) {
if (typeof PowerProfiles === "undefined")
return false;
return false
return PowerProfiles.profile === profile;
return PowerProfiles.profile === profile
}
function setProfile(profile) {
if (typeof PowerProfiles === "undefined") {
ToastService.showError("power-profiles-daemon not available");
return ;
ToastService.showError("power-profiles-daemon not available")
return
}
PowerProfiles.profile = profile;
PowerProfiles.profile = profile
if (PowerProfiles.profile !== profile)
ToastService.showError("Failed to set power profile");
ToastService.showError("Failed to set power profile")
}
visible: batteryPopupVisible
@@ -62,11 +61,11 @@ PanelWindow {
MouseArea {
anchors.fill: parent
onClicked: function(mouse) {
var localPos = mapToItem(contentLoader, mouse.x, mouse.y);
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height)
batteryPopupVisible = false;
onClicked: function (mouse) {
var localPos = mapToItem(contentLoader, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0
|| localPos.y > contentLoader.height)
batteryPopupVisible = false
}
}
@@ -75,24 +74,28 @@ PanelWindow {
readonly property real screenWidth: root.screen ? root.screen.width : Screen.width
readonly property real screenHeight: root.screen ? root.screen.height : Screen.height
readonly property real targetWidth: Math.min(380, screenWidth - Theme.spacingL * 2)
readonly property real targetHeight: Math.min(450, screenHeight - Theme.barHeight - Theme.spacingS * 2)
readonly property real targetWidth: Math.min(
380, screenWidth - Theme.spacingL * 2)
readonly property real targetHeight: Math.min(
450,
screenHeight - Theme.barHeight - Theme.spacingS * 2)
readonly property real calculatedX: {
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2);
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2)
if (centerX >= Theme.spacingM && centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX;
if (centerX >= Theme.spacingM
&& centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX
}
if (centerX < Theme.spacingM) {
return Theme.spacingM;
return Theme.spacingM
}
if (centerX + targetWidth > screenWidth - Theme.spacingM) {
return screenWidth - targetWidth - Theme.spacingM;
return screenWidth - targetWidth - Theme.spacingM
}
return centerX;
return centerX
}
asynchronous: true
@@ -110,7 +113,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
Behavior on scale {
@@ -119,7 +121,6 @@ PanelWindow {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized
}
}
sourceComponent: Rectangle {
@@ -132,21 +133,21 @@ PanelWindow {
focus: true
Component.onCompleted: {
if (batteryPopupVisible)
forceActiveFocus();
forceActiveFocus()
}
Keys.onPressed: function(event) {
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
batteryPopupVisible = false;
event.accepted = true;
batteryPopupVisible = false
event.accepted = true
}
}
Connections {
function onBatteryPopupVisibleChanged() {
if (batteryPopupVisible)
Qt.callLater(function() {
parent.forceActiveFocus();
});
Qt.callLater(function () {
parent.forceActiveFocus()
})
}
target: root
}
@@ -225,21 +226,22 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
batteryPopupVisible = false;
batteryPopupVisible = false
}
}
}
}
Rectangle {
width: parent.width
height: 80
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: BatteryService.isCharging ? Theme.primary : (BatteryService.isLowBattery ? Theme.error : Theme.outlineMedium)
border.width: BatteryService.isCharging || BatteryService.isLowBattery ? 2 : 1
border.width: BatteryService.isCharging
|| BatteryService.isLowBattery ? 2 : 1
visible: BatteryService.batteryAvailable
Row {
@@ -249,16 +251,18 @@ PanelWindow {
spacing: Theme.spacingL
DankIcon {
name: Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable)
name: Theme.getBatteryIcon(BatteryService.batteryLevel,
BatteryService.isCharging,
BatteryService.batteryAvailable)
size: Theme.iconSizeLarge
color: {
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error;
return Theme.error
if (BatteryService.isCharging)
return Theme.primary;
return Theme.primary
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -274,13 +278,14 @@ PanelWindow {
text: BatteryService.batteryLevel + "%"
font.pixelSize: Theme.fontSizeLarge
color: {
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error;
if (BatteryService.isLowBattery
&& !BatteryService.isCharging)
return Theme.error
if (BatteryService.isCharging)
return Theme.primary;
return Theme.primary
return Theme.surfaceText;
return Theme.surfaceText
}
font.weight: Font.Bold
}
@@ -289,44 +294,44 @@ PanelWindow {
text: BatteryService.batteryStatus
font.pixelSize: Theme.fontSizeMedium
color: {
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error;
if (BatteryService.isLowBattery
&& !BatteryService.isCharging)
return Theme.error
if (BatteryService.isCharging)
return Theme.primary;
return Theme.primary
return Theme.surfaceText;
return Theme.surfaceText
}
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: {
let time = BatteryService.formatTimeRemaining();
let time = BatteryService.formatTimeRemaining()
if (time !== "Unknown")
return BatteryService.isCharging ? "Time until full: " + time : "Time remaining: " + time;
return BatteryService.isCharging ? "Time until full: "
+ time : "Time remaining: " + time
return "";
return ""
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceTextMedium
visible: text.length > 0
}
}
}
}
Rectangle {
width: parent.width
height: 80
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: Theme.outlineMedium
border.width: 1
visible: !BatteryService.batteryAvailable
@@ -358,11 +363,8 @@ PanelWindow {
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceTextMedium
}
}
}
}
Column {
@@ -397,13 +399,12 @@ PanelWindow {
font.pixelSize: Theme.fontSizeMedium
color: {
if (BatteryService.batteryHealth === "N/A")
return Theme.surfaceText;
return Theme.surfaceText
var healthNum = parseInt(BatteryService.batteryHealth);
return healthNum < 80 ? Theme.error : Theme.surfaceText;
var healthNum = parseInt(BatteryService.batteryHealth)
return healthNum < 80 ? Theme.error : Theme.surfaceText
}
}
}
Column {
@@ -418,15 +419,13 @@ PanelWindow {
}
StyledText {
text: BatteryService.batteryCapacity > 0 ? BatteryService.batteryCapacity.toFixed(1) + " Wh" : "Unknown"
text: BatteryService.batteryCapacity > 0 ? BatteryService.batteryCapacity.toFixed(
1) + " Wh" : "Unknown"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
}
}
}
}
Column {
@@ -446,14 +445,17 @@ PanelWindow {
spacing: Theme.spacingS
Repeater {
model: (typeof PowerProfiles !== "undefined") ? [PowerProfile.PowerSaver, PowerProfile.Balanced].concat(PowerProfiles.hasPerformanceProfile ? [PowerProfile.Performance] : []) : [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance]
model: (typeof PowerProfiles
!== "undefined") ? [PowerProfile.PowerSaver, PowerProfile.Balanced].concat(
PowerProfiles.hasPerformanceProfile ? [PowerProfile.Performance] : []) : [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance]
Rectangle {
width: parent.width
height: 50
radius: Theme.cornerRadiusLarge
color: profileArea.containsMouse ? Theme.primaryHoverLight : (root.isActiveProfile(modelData) ? Theme.primaryPressed : Theme.surfaceLight)
border.color: root.isActiveProfile(modelData) ? Theme.primary : Theme.outlineLight
border.color: root.isActiveProfile(
modelData) ? Theme.primary : Theme.outlineLight
border.width: root.isActiveProfile(modelData) ? 2 : 1
Row {
@@ -465,7 +467,8 @@ PanelWindow {
DankIcon {
name: Theme.getPowerProfileIcon(modelData)
size: Theme.iconSize
color: root.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
color: root.isActiveProfile(
modelData) ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
@@ -476,8 +479,10 @@ PanelWindow {
StyledText {
text: Theme.getPowerProfileLabel(modelData)
font.pixelSize: Theme.fontSizeMedium
color: root.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
font.weight: root.isActiveProfile(modelData) ? Font.Medium : Font.Normal
color: root.isActiveProfile(
modelData) ? Theme.primary : Theme.surfaceText
font.weight: root.isActiveProfile(
modelData) ? Font.Medium : Font.Normal
}
StyledText {
@@ -485,9 +490,7 @@ PanelWindow {
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceTextMedium
}
}
}
MouseArea {
@@ -497,16 +500,12 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.setProfile(modelData);
root.setProfile(modelData)
}
}
}
}
}
}
Rectangle {
@@ -516,7 +515,8 @@ PanelWindow {
color: Theme.errorHover
border.color: Theme.primarySelected
border.width: 1
visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None
visible: (typeof PowerProfiles !== "undefined")
&& PowerProfiles.degradationReason !== PerformanceDegradationReason.None
Row {
anchors.left: parent.left
@@ -543,23 +543,18 @@ PanelWindow {
}
StyledText {
text: (typeof PowerProfiles !== "undefined") ? PerformanceDegradationReason.toString(PowerProfiles.degradationReason) : ""
text: (typeof PowerProfiles
!== "undefined") ? PerformanceDegradationReason.toString(
PowerProfiles.degradationReason) : ""
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.8)
color: Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b, 0.8)
}
}
}
}
}
}
}
}
}

View File

@@ -12,17 +12,18 @@ Rectangle {
property var popupTarget: null
property var parentScreen: null
signal clockClicked()
signal clockClicked
width: clockRow.implicitWidth + Theme.spacingS * 2
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = clockMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = clockMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
root.currentDate = systemClock.date;
root.currentDate = systemClock.date
}
Row {
@@ -32,7 +33,9 @@ Rectangle {
spacing: Theme.spacingS
StyledText {
text: SettingsData.use24HourClock ? Qt.formatTime(root.currentDate, "H:mm") : Qt.formatTime(root.currentDate, "h:mm AP")
text: SettingsData.use24HourClock ? Qt.formatTime(root.currentDate,
"H:mm") : Qt.formatTime(
root.currentDate, "h:mm AP")
font.pixelSize: Theme.fontSizeMedium - 1
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
@@ -53,7 +56,6 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
visible: !SettingsData.clockCompactMode
}
}
SystemClock {
@@ -71,13 +73,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clockClicked();
root.clockClicked()
}
}
@@ -86,7 +90,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -11,20 +11,20 @@ Rectangle {
property var popupTarget: null
property var parentScreen: null
signal clicked()
signal clicked
function getWiFiSignalIcon(signalStrength) {
switch (signalStrength) {
case "excellent":
return "wifi";
return "wifi"
case "good":
return "wifi_2_bar";
return "wifi_2_bar"
case "fair":
return "wifi_1_bar";
return "wifi_1_bar"
case "poor":
return "signal_wifi_0_bar";
return "signal_wifi_0_bar"
default:
return "wifi";
return "wifi"
}
}
@@ -32,8 +32,10 @@ Rectangle {
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = controlCenterArea.containsMouse || root.isActive ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = controlCenterArea.containsMouse
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Row {
@@ -45,11 +47,11 @@ Rectangle {
DankIcon {
name: {
if (NetworkService.networkStatus === "ethernet")
return "lan";
return "lan"
else if (NetworkService.networkStatus === "wifi")
return getWiFiSignalIcon(NetworkService.wifiSignalStrength);
return getWiFiSignalIcon(NetworkService.wifiSignalStrength)
else
return "wifi_off";
return "wifi_off"
}
size: Theme.iconSize - 8
color: NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton
@@ -74,9 +76,13 @@ Rectangle {
DankIcon {
id: audioIcon
name: (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.muted) ? "volume_off" : (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) < 33 ? "volume_down" : "volume_up"
name: (AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.muted) ? "volume_off" : (AudioService.sink
&& AudioService.sink.audio
&& AudioService.sink.audio.volume * 100) < 33 ? "volume_down" : "volume_up"
size: Theme.iconSize - 8
color: audioWheelArea.containsMouse || controlCenterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
color: audioWheelArea.containsMouse || controlCenterArea.containsMouse
|| root.isActive ? Theme.primary : Theme.surfaceText
anchors.centerIn: parent
}
@@ -86,22 +92,22 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
onWheel: function(wheelEvent) {
let delta = wheelEvent.angleDelta.y;
let currentVolume = (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) || 0;
let newVolume;
onWheel: function (wheelEvent) {
let delta = wheelEvent.angleDelta.y
let currentVolume = (AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.volume * 100) || 0
let newVolume
if (delta > 0)
newVolume = Math.min(100, currentVolume + 5);
newVolume = Math.min(100, currentVolume + 5)
else
newVolume = Math.max(0, currentVolume - 5);
newVolume = Math.max(0, currentVolume - 5)
if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = false;
AudioService.sink.audio.volume = newVolume / 100;
AudioService.sink.audio.muted = false
AudioService.sink.audio.volume = newVolume / 100
}
wheelEvent.accepted = true;
wheelEvent.accepted = true
}
}
}
DankIcon {
@@ -111,7 +117,6 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
visible: false // TODO: Add mic detection
}
}
MouseArea {
@@ -122,13 +127,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clicked();
root.clicked()
}
}
@@ -137,7 +144,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -18,14 +18,15 @@ Rectangle {
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
SysMonitorService.addRef();
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef();
SysMonitorService.removeRef()
}
MouseArea {
@@ -36,15 +37,17 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
SysMonitorService.setSortBy("cpu");
SysMonitorService.setSortBy("cpu")
if (root.toggleProcessList)
root.toggleProcessList();
root.toggleProcessList()
}
}
@@ -57,29 +60,29 @@ Rectangle {
size: Theme.iconSize - 8
color: {
if (SysMonitorService.cpuUsage > 80)
return Theme.tempDanger;
return Theme.tempDanger
if (SysMonitorService.cpuUsage > 60)
return Theme.tempWarning;
return Theme.tempWarning
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (SysMonitorService.cpuUsage === undefined || SysMonitorService.cpuUsage === null || SysMonitorService.cpuUsage === 0) {
return "--%";
if (SysMonitorService.cpuUsage === undefined
|| SysMonitorService.cpuUsage === null
|| SysMonitorService.cpuUsage === 0) {
return "--%"
}
return SysMonitorService.cpuUsage.toFixed(0) + "%";
return SysMonitorService.cpuUsage.toFixed(0) + "%"
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}

View File

@@ -18,14 +18,15 @@ Rectangle {
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
SysMonitorService.addRef();
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef();
SysMonitorService.removeRef()
}
MouseArea {
@@ -36,15 +37,17 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
SysMonitorService.setSortBy("cpu");
SysMonitorService.setSortBy("cpu")
if (root.toggleProcessList)
root.toggleProcessList();
root.toggleProcessList()
}
}
@@ -57,29 +60,30 @@ Rectangle {
size: Theme.iconSize - 8
color: {
if (SysMonitorService.cpuTemperature > 85)
return Theme.tempDanger;
return Theme.tempDanger
if (SysMonitorService.cpuTemperature > 69)
return Theme.tempWarning;
return Theme.tempWarning
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (SysMonitorService.cpuTemperature === undefined || SysMonitorService.cpuTemperature === null || SysMonitorService.cpuTemperature < 0) {
return "--°";
if (SysMonitorService.cpuTemperature === undefined
|| SysMonitorService.cpuTemperature === null
|| SysMonitorService.cpuTemperature < 0) {
return "--°"
}
return Math.round(SysMonitorService.cpuTemperature) + "°";
return Math.round(SysMonitorService.cpuTemperature) + "°"
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Behavior on color {

View File

@@ -12,18 +12,24 @@ Rectangle {
readonly property int maxNormalWidth: 456
readonly property int maxCompactWidth: 288
width: compactMode ? Math.min(baseWidth, maxCompactWidth) : Math.min(baseWidth, maxNormalWidth)
width: compactMode ? Math.min(baseWidth,
maxCompactWidth) : Math.min(baseWidth,
maxNormalWidth)
height: 30
radius: Theme.cornerRadius
color: {
if (!FocusedWindowService.focusedAppName && !FocusedWindowService.focusedWindowTitle)
return "transparent";
if (!FocusedWindowService.focusedAppName
&& !FocusedWindowService.focusedWindowTitle)
return "transparent"
const baseColor = mouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = mouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
clip: true
visible: FocusedWindowService.niriAvailable && (FocusedWindowService.focusedAppName || FocusedWindowService.focusedWindowTitle)
visible: FocusedWindowService.niriAvailable
&& (FocusedWindowService.focusedAppName
|| FocusedWindowService.focusedWindowTitle)
Row {
id: contentRow
@@ -65,7 +71,6 @@ Rectangle {
width: Math.min(implicitWidth, compactMode ? 180 : 250)
visible: text.length > 0
}
}
MouseArea {
@@ -80,7 +85,6 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on width {
@@ -88,7 +92,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -14,15 +14,17 @@ Rectangle {
property var popupTarget: null
property var parentScreen: null
property var widgetData: null
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex !== undefined) ? widgetData.selectedGpuIndex : 0
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex
!== undefined) ? widgetData.selectedGpuIndex : 0
Connections {
target: SettingsData
function onWidgetDataChanged() {
// Force property re-evaluation by triggering change detection
root.selectedGpuIndex = Qt.binding(() => {
return (root.widgetData && root.widgetData.selectedGpuIndex !== undefined) ? root.widgetData.selectedGpuIndex : 0;
});
return (root.widgetData
&& root.widgetData.selectedGpuIndex !== undefined) ? root.widgetData.selectedGpuIndex : 0
})
}
}
@@ -30,22 +32,26 @@ Rectangle {
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
SysMonitorService.addRef();
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef();
SysMonitorService.removeRef()
}
property real displayTemp: {
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) return 0;
if (selectedGpuIndex >= 0 && selectedGpuIndex < SysMonitorService.availableGpus.length) {
return SysMonitorService.availableGpus[selectedGpuIndex].temperature || 0;
if (!SysMonitorService.availableGpus
|| SysMonitorService.availableGpus.length === 0)
return 0
if (selectedGpuIndex >= 0
&& selectedGpuIndex < SysMonitorService.availableGpus.length) {
return SysMonitorService.availableGpus[selectedGpuIndex].temperature || 0
}
return 0;
return 0
}
MouseArea {
@@ -56,15 +62,17 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
SysMonitorService.setSortBy("cpu");
SysMonitorService.setSortBy("cpu")
if (root.toggleProcessList)
root.toggleProcessList();
root.toggleProcessList()
}
}
@@ -77,29 +85,29 @@ Rectangle {
size: Theme.iconSize - 8
color: {
if (root.displayTemp > 80)
return Theme.tempDanger;
return Theme.tempDanger
if (root.displayTemp > 65)
return Theme.tempWarning;
return Theme.tempWarning
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (root.displayTemp === undefined || root.displayTemp === null || root.displayTemp === 0) {
return "--°";
if (root.displayTemp === undefined || root.displayTemp === null
|| root.displayTemp === 0) {
return "--°"
}
return Math.round(root.displayTemp) + "°";
return Math.round(root.displayTemp) + "°"
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Behavior on color {

View File

@@ -11,14 +11,16 @@ Rectangle {
property var popupTarget: null // Reference to the popup to position
property var parentScreen: null // The screen this button is on
signal clicked()
signal clicked
width: 40
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = launcherArea.containsMouse || isActive ? Theme.surfaceTextPressed : Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = launcherArea.containsMouse
|| isActive ? Theme.surfaceTextPressed : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
SystemLogo {
@@ -47,13 +49,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clicked();
root.clicked()
}
}
@@ -62,7 +66,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -17,13 +17,14 @@ Rectangle {
property var popupTarget: null
property var parentScreen: null
signal clicked()
signal clicked
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
states: [
State {
@@ -35,7 +36,6 @@ Rectangle {
opacity: 1
width: SettingsData.mediaCompactMode ? compactContentWidth : normalContentWidth
}
},
State {
name: "hidden"
@@ -46,7 +46,6 @@ Rectangle {
opacity: 0
width: 0
}
}
]
transitions: [
@@ -64,9 +63,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
},
Transition {
from: "hidden"
@@ -77,7 +74,6 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
]
@@ -104,20 +100,24 @@ Rectangle {
visible: !SettingsData.mediaCompactMode
text: {
if (!activePlayer || !activePlayer.trackTitle)
return "";
return ""
let identity = activePlayer.identity || "";
let isWebMedia = identity.toLowerCase().includes("firefox") || identity.toLowerCase().includes("chrome") || identity.toLowerCase().includes("chromium") || identity.toLowerCase().includes("edge") || identity.toLowerCase().includes("safari");
let title = "";
let subtitle = "";
let identity = activePlayer.identity || ""
let isWebMedia = identity.toLowerCase().includes("firefox")
|| identity.toLowerCase().includes(
"chrome") || identity.toLowerCase().includes("chromium")
|| identity.toLowerCase().includes(
"edge") || identity.toLowerCase().includes("safari")
let title = ""
let subtitle = ""
if (isWebMedia && activePlayer.trackTitle) {
title = activePlayer.trackTitle;
subtitle = activePlayer.trackArtist || identity;
title = activePlayer.trackTitle
subtitle = activePlayer.trackArtist || identity
} else {
title = activePlayer.trackTitle || "Unknown Track";
subtitle = activePlayer.trackArtist || "";
title = activePlayer.trackTitle || "Unknown Track"
subtitle = activePlayer.trackArtist || ""
}
return subtitle.length > 0 ? title + " • " + subtitle : title;
return subtitle.length > 0 ? title + " • " + subtitle : title
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
@@ -132,18 +132,18 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (root.popupTarget && root.popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = root.parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
root.popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, root.width, root.section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = root.parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
root.popupTarget.setTriggerPosition(
relativeX, Theme.barHeight + Theme.spacingXS, root.width,
root.section, currentScreen)
}
root.clicked();
root.clicked()
}
}
}
}
Row {
@@ -174,11 +174,9 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (activePlayer)
activePlayer.previous();
activePlayer.previous()
}
}
}
Rectangle {
@@ -186,15 +184,18 @@ Rectangle {
height: 24
radius: 12
anchors.verticalCenter: parent.verticalCenter
color: activePlayer && activePlayer.playbackState === 1 ? Theme.primary : Theme.primaryHover
color: activePlayer
&& activePlayer.playbackState === 1 ? Theme.primary : Theme.primaryHover
visible: root.playerAvailable
opacity: activePlayer ? 1 : 0.3
DankIcon {
anchors.centerIn: parent
name: activePlayer && activePlayer.playbackState === 1 ? "pause" : "play_arrow"
name: activePlayer
&& activePlayer.playbackState === 1 ? "pause" : "play_arrow"
size: 14
color: activePlayer && activePlayer.playbackState === 1 ? Theme.background : Theme.primary
color: activePlayer
&& activePlayer.playbackState === 1 ? Theme.background : Theme.primary
}
MouseArea {
@@ -203,11 +204,9 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (activePlayer)
activePlayer.togglePlaying();
activePlayer.togglePlaying()
}
}
}
Rectangle {
@@ -234,15 +233,11 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (activePlayer)
activePlayer.next();
activePlayer.next()
}
}
}
}
}
Behavior on color {
@@ -250,7 +245,6 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on width {
@@ -258,7 +252,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -11,21 +11,24 @@ Rectangle {
property var popupTarget: null
property var parentScreen: null
signal clicked()
signal clicked
width: 40
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = notificationArea.containsMouse || root.isActive ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = notificationArea.containsMouse
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
DankIcon {
anchors.centerIn: parent
name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
size: Theme.iconSize - 6
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText)
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse
|| root.isActive ? Theme.primary : Theme.surfaceText)
}
Rectangle {
@@ -48,13 +51,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clicked();
root.clicked()
}
}
@@ -63,7 +68,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -12,7 +12,8 @@ Rectangle {
property var parentScreen: null
readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive
readonly property int activeCount: (PrivacyService.microphoneActive ? 1 : 0) + (PrivacyService.cameraActive ? 1 : 0) + (PrivacyService.screensharingActive ? 1 : 0)
readonly property int activeCount: PrivacyService.microphoneActive + PrivacyService.cameraActive
+ PrivacyService.screensharingActive
width: hasActivePrivacy ? (activeCount > 1 ? 80 : 60) : 0
height: hasActivePrivacy ? 30 : 0
@@ -20,10 +21,12 @@ Rectangle {
visible: hasActivePrivacy
opacity: hasActivePrivacy ? 1 : 0
color: {
const baseColor = privacyArea.containsMouse ? Theme.errorPressed : Theme.errorHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
color: Qt.rgba(
privacyArea.containsMouse ? Theme.errorPressed.r : Theme.errorHover.r,
privacyArea.containsMouse ? Theme.errorPressed.g : Theme.errorHover.g,
privacyArea.containsMouse ? Theme.errorPressed.b : Theme.errorHover.b,
(privacyArea.containsMouse ? Theme.errorPressed.a : Theme.errorHover.a)
* Theme.widgetTransparency)
MouseArea {
id: privacyArea
@@ -32,6 +35,7 @@ Rectangle {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
}
}
@@ -53,7 +57,6 @@ Rectangle {
filled: true
anchors.centerIn: parent
}
}
Item {
@@ -81,7 +84,7 @@ Rectangle {
anchors.topMargin: -1
SequentialAnimation on opacity {
running: parent.visible
running: parent.visible && hasActivePrivacy
loops: Animation.Infinite
NumberAnimation {
@@ -113,20 +116,13 @@ Rectangle {
}
Behavior on width {
enabled: hasActivePrivacy
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on opacity {
enabled: !hasActivePrivacy
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
Rectangle {
id: tooltip
@@ -136,8 +132,8 @@ Rectangle {
color: Theme.popupBackground()
border.color: Theme.outlineMedium
border.width: 1
visible: privacyArea.containsMouse && hasActivePrivacy
opacity: visible ? 1 : 0
visible: false
opacity: privacyArea.containsMouse && hasActivePrivacy ? 1 : 0
z: 100
x: (parent.width - width) / 2
@@ -152,6 +148,7 @@ Rectangle {
}
Behavior on opacity {
enabled: hasActivePrivacy
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing

View File

@@ -18,14 +18,15 @@ Rectangle {
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
SysMonitorService.addRef();
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef();
SysMonitorService.removeRef()
}
MouseArea {
@@ -36,15 +37,17 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
SysMonitorService.setSortBy("memory");
SysMonitorService.setSortBy("memory")
if (root.toggleProcessList)
root.toggleProcessList();
root.toggleProcessList()
}
}
@@ -57,29 +60,29 @@ Rectangle {
size: Theme.iconSize - 8
color: {
if (SysMonitorService.memoryUsage > 90)
return Theme.tempDanger;
return Theme.tempDanger
if (SysMonitorService.memoryUsage > 75)
return Theme.tempWarning;
return Theme.tempWarning
return Theme.surfaceText;
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (SysMonitorService.memoryUsage === undefined || SysMonitorService.memoryUsage === null || SysMonitorService.memoryUsage === 0) {
return "--%";
if (SysMonitorService.memoryUsage === undefined
|| SysMonitorService.memoryUsage === null
|| SysMonitorService.memoryUsage === 0) {
return "--%"
}
return SysMonitorService.memoryUsage.toFixed(0) + "%";
return SysMonitorService.memoryUsage.toFixed(0) + "%"
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}

View File

@@ -9,18 +9,21 @@ Rectangle {
property var parentWindow: null
property var parentScreen: null
readonly property int calculatedWidth: SystemTray.items.values.length > 0 ? SystemTray.items.values.length * 24 + (SystemTray.items.values.length - 1) * Theme.spacingXS + Theme.spacingS * 2 : 0
readonly property int calculatedWidth: SystemTray.items.values.length
> 0 ? SystemTray.items.values.length * 24
+ (SystemTray.items.values.length - 1)
* Theme.spacingXS + Theme.spacingS * 2 : 0
width: calculatedWidth
height: 30
radius: Theme.cornerRadius
color: {
if (SystemTray.items.values.length === 0)
return "transparent";
return "transparent"
const baseColor = Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
visible: SystemTray.items.values.length > 0
@@ -36,16 +39,20 @@ Rectangle {
delegate: Item {
property var trayItem: modelData
property string iconSource: {
let icon = trayItem && trayItem.icon;
let icon = trayItem && trayItem.icon
if (typeof icon === 'string' || icon instanceof String) {
if (icon.includes("?path=")) {
const [name, path] = icon.split("?path=");
const fileName = name.substring(name.lastIndexOf("/") + 1);
return `file://${path}/${fileName}`;
const split = icon.split("?path=")
if (split.length !== 2)
return icon
const name = split[0]
const path = split[1]
const fileName = name.substring(name.lastIndexOf("/") + 1)
return `file://${path}/${fileName}`
}
return icon;
return icon
}
return "";
return ""
}
width: 24
@@ -63,9 +70,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Image {
@@ -85,7 +90,7 @@ Rectangle {
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => {
onClicked: mouse => {
if (!trayItem)
return
@@ -96,22 +101,20 @@ Rectangle {
var relativeX = globalPos.x - screenX
menuAnchor.menu = trayItem.menu
menuAnchor.anchor.window = parentWindow
menuAnchor.anchor.rect = Qt.rect(relativeX, Theme.barHeight + Theme.spacingS, parent.width, 1)
menuAnchor.anchor.rect = Qt.rect(
relativeX, Theme.barHeight + Theme.spacingS,
parent.width, 1)
menuAnchor.open()
} else if (mouse.button === Qt.LeftButton) {
trayItem.activate()
}
}
}
}
}
}
QsMenuAnchor {
id: menuAnchor
}
}

View File

@@ -25,27 +25,28 @@ PanelWindow {
implicitHeight: Theme.barHeight - 4
color: "transparent"
Component.onCompleted: {
let fonts = Qt.fontFamilies();
let fonts = Qt.fontFamilies()
if (fonts.indexOf("Material Symbols Rounded") === -1)
ToastService.showError("Please install Material Symbols Rounded and Restart your Shell. See README.md for instructions");
ToastService.showError(
"Please install Material Symbols Rounded and Restart your Shell. See README.md for instructions")
SettingsData.forceTopBarLayoutRefresh.connect(function() {
SettingsData.forceTopBarLayoutRefresh.connect(function () {
Qt.callLater(() => {
leftSection.visible = false;
centerSection.visible = false;
rightSection.visible = false;
leftSection.visible = false
centerSection.visible = false
rightSection.visible = false
Qt.callLater(() => {
leftSection.visible = true;
centerSection.visible = true;
rightSection.visible = true;
});
});
});
leftSection.visible = true
centerSection.visible = true
rightSection.visible = true
})
})
})
}
Connections {
function onTopBarTransparencyChanged() {
root.backgroundTransparency = SettingsData.topBarTransparency;
root.backgroundTransparency = SettingsData.topBarTransparency
}
target: SettingsData
@@ -56,7 +57,7 @@ PanelWindow {
function onGeometryChanged() {
// Re-layout center widgets when screen geometry changes
if (centerSection && centerSection.width > 0) {
Qt.callLater(centerSection.updateLayout);
Qt.callLater(centerSection.updateLayout)
}
}
}
@@ -84,7 +85,8 @@ PanelWindow {
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadiusXLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, root.backgroundTransparency)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, root.backgroundTransparency)
layer.enabled: true
Rectangle {
@@ -97,7 +99,8 @@ PanelWindow {
Rectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g,
Theme.surfaceTint.b, 0.04)
radius: parent.radius
SequentialAnimation on opacity {
@@ -115,9 +118,7 @@ PanelWindow {
duration: Theme.extraLongDuration
easing.type: Theme.standardEasing
}
}
}
layer.effect: MultiEffect {
@@ -128,7 +129,6 @@ PanelWindow {
shadowColor: Qt.rgba(0, 0, 0, 0.15)
shadowOpacity: 0.15
}
}
Item {
@@ -138,111 +138,125 @@ PanelWindow {
readonly property int launcherButtonWidth: 40
readonly property int workspaceSwitcherWidth: 120 // Approximate
readonly property int focusedAppMaxWidth: 456 // Fixed width since we don't have focusedApp reference
readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth + focusedAppMaxWidth + (Theme.spacingXS * 2)
readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth
+ focusedAppMaxWidth + (Theme.spacingXS * 2)
readonly property int rightSectionWidth: rightSection.width
readonly property int clockWidth: 120 // Approximate clock width
readonly property int mediaMaxWidth: 280 // Normal max width
readonly property int weatherWidth: 80 // Approximate weather width
readonly property bool validLayout: availableWidth > 100 && estimatedLeftSectionWidth > 0 && rightSectionWidth > 0
readonly property bool validLayout: availableWidth > 100
&& estimatedLeftSectionWidth > 0
&& rightSectionWidth > 0
readonly property int clockLeftEdge: (availableWidth - clockWidth) / 2
readonly property int clockRightEdge: clockLeftEdge + clockWidth
readonly property int leftSectionRightEdge: estimatedLeftSectionWidth
readonly property int mediaLeftEdge: clockLeftEdge - mediaMaxWidth - Theme.spacingS
readonly property int rightSectionLeftEdge: availableWidth - rightSectionWidth
readonly property int leftToClockGap: Math.max(0, clockLeftEdge - leftSectionRightEdge)
readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(0, mediaLeftEdge - leftSectionRightEdge) : leftToClockGap
readonly property int leftToClockGap: Math.max(
0,
clockLeftEdge - leftSectionRightEdge)
readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(
0,
mediaLeftEdge - leftSectionRightEdge) : leftToClockGap
readonly property int mediaToClockGap: mediaMaxWidth > 0 ? Theme.spacingS : 0
readonly property int clockToRightGap: validLayout ? Math.max(0, rightSectionLeftEdge - clockRightEdge) : 1000
readonly property bool spacingTight: validLayout && (leftToMediaGap < 150 || clockToRightGap < 100)
readonly property bool overlapping: validLayout && (leftToMediaGap < 100 || clockToRightGap < 50)
readonly property int clockToRightGap: validLayout ? Math.max(
0,
rightSectionLeftEdge
- clockRightEdge) : 1000
readonly property bool spacingTight: validLayout
&& (leftToMediaGap < 150
|| clockToRightGap < 100)
readonly property bool overlapping: validLayout
&& (leftToMediaGap < 100
|| clockToRightGap < 50)
function getWidgetEnabled(enabled) {
return enabled !== undefined ? enabled : true;
return enabled !== undefined ? enabled : true
}
function getWidgetVisible(widgetId) {
switch (widgetId) {
case "launcherButton":
return true;
return true
case "workspaceSwitcher":
return true;
return true
case "focusedWindow":
return true;
return true
case "clock":
return true;
return true
case "music":
return true;
return true
case "weather":
return true;
return true
case "systemTray":
return true;
return true
case "privacyIndicator":
return true;
return true
case "clipboard":
return true;
return true
case "cpuUsage":
return true;
return true
case "memUsage":
return true;
return true
case "cpuTemp":
return true;
return true
case "gpuTemp":
return true;
return true
case "notificationButton":
return true;
return true
case "battery":
return true;
return true
case "controlCenterButton":
return true;
return true
case "spacer":
return true;
return true
case "separator":
return true;
return true
default:
return false;
return false
}
}
function getWidgetComponent(widgetId) {
switch (widgetId) {
case "launcherButton":
return launcherButtonComponent;
return launcherButtonComponent
case "workspaceSwitcher":
return workspaceSwitcherComponent;
return workspaceSwitcherComponent
case "focusedWindow":
return focusedWindowComponent;
return focusedWindowComponent
case "clock":
return clockComponent;
return clockComponent
case "music":
return mediaComponent;
return mediaComponent
case "weather":
return weatherComponent;
return weatherComponent
case "systemTray":
return systemTrayComponent;
return systemTrayComponent
case "privacyIndicator":
return privacyIndicatorComponent;
return privacyIndicatorComponent
case "clipboard":
return clipboardComponent;
return clipboardComponent
case "cpuUsage":
return cpuUsageComponent;
return cpuUsageComponent
case "memUsage":
return memUsageComponent;
return memUsageComponent
case "cpuTemp":
return cpuTempComponent;
return cpuTempComponent
case "gpuTemp":
return gpuTempComponent;
return gpuTempComponent
case "notificationButton":
return notificationButtonComponent;
return notificationButtonComponent
case "battery":
return batteryComponent;
return batteryComponent
case "controlCenterButton":
return controlCenterButtonComponent;
return controlCenterButtonComponent
case "spacer":
return spacerComponent;
return spacerComponent
case "separator":
return separatorComponent;
return separatorComponent
default:
return null;
return null
}
}
@@ -274,9 +288,7 @@ PanelWindow {
sourceComponent: topBarContent.getWidgetComponent(model.widgetId)
opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0
}
}
}
Item {
@@ -290,71 +302,72 @@ PanelWindow {
function updateLayout() {
// Defer layout if dimensions are invalid
if (width <= 0 || height <= 0 || !visible) {
Qt.callLater(updateLayout);
return;
Qt.callLater(updateLayout)
return
}
centerWidgets = [];
totalWidgets = 0;
totalWidth = 0;
for (let i = 0; i < centerRepeater.count; i++) {
let item = centerRepeater.itemAt(i);
centerWidgets = []
totalWidgets = 0
totalWidth = 0
for (var i = 0; i < centerRepeater.count; i++) {
let item = centerRepeater.itemAt(i)
if (item && item.active && item.item) {
centerWidgets.push(item.item);
totalWidgets++;
totalWidth += item.item.width;
centerWidgets.push(item.item)
totalWidgets++
totalWidth += item.item.width
}
}
if (totalWidgets > 1)
totalWidth += spacing * (totalWidgets - 1);
totalWidth += spacing * (totalWidgets - 1)
positionWidgets();
positionWidgets()
}
function positionWidgets() {
if (totalWidgets === 0 || width <= 0)
return ;
return
let parentCenterX = width / 2;
let parentCenterX = width / 2
if (totalWidgets % 2 === 1) {
let middleIndex = Math.floor(totalWidgets / 2);
let currentX = parentCenterX - (centerWidgets[middleIndex].width / 2);
centerWidgets[middleIndex].x = currentX;
centerWidgets[middleIndex].anchors.horizontalCenter = undefined;
currentX = centerWidgets[middleIndex].x;
for (let i = middleIndex - 1; i >= 0; i--) {
currentX -= (spacing + centerWidgets[i].width);
centerWidgets[i].x = currentX;
centerWidgets[i].anchors.horizontalCenter = undefined;
let middleIndex = Math.floor(totalWidgets / 2)
let currentX = parentCenterX - (centerWidgets[middleIndex].width / 2)
centerWidgets[middleIndex].x = currentX
centerWidgets[middleIndex].anchors.horizontalCenter = undefined
currentX = centerWidgets[middleIndex].x
for (var i = middleIndex - 1; i >= 0; i--) {
currentX -= (spacing + centerWidgets[i].width)
centerWidgets[i].x = currentX
centerWidgets[i].anchors.horizontalCenter = undefined
}
currentX = centerWidgets[middleIndex].x + centerWidgets[middleIndex].width;
for (let i = middleIndex + 1; i < totalWidgets; i++) {
currentX += spacing;
centerWidgets[i].x = currentX;
centerWidgets[i].anchors.horizontalCenter = undefined;
currentX += centerWidgets[i].width;
currentX = centerWidgets[middleIndex].x + centerWidgets[middleIndex].width
for (var i = middleIndex + 1; i < totalWidgets; i++) {
currentX += spacing
centerWidgets[i].x = currentX
centerWidgets[i].anchors.horizontalCenter = undefined
currentX += centerWidgets[i].width
}
} else {
let leftMiddleIndex = (totalWidgets / 2) - 1;
let rightMiddleIndex = totalWidgets / 2;
let gapCenter = parentCenterX;
let halfSpacing = spacing / 2;
centerWidgets[leftMiddleIndex].x = gapCenter - halfSpacing - centerWidgets[leftMiddleIndex].width;
centerWidgets[leftMiddleIndex].anchors.horizontalCenter = undefined;
centerWidgets[rightMiddleIndex].x = gapCenter + halfSpacing;
centerWidgets[rightMiddleIndex].anchors.horizontalCenter = undefined;
let currentX = centerWidgets[leftMiddleIndex].x;
for (let i = leftMiddleIndex - 1; i >= 0; i--) {
currentX -= (spacing + centerWidgets[i].width);
centerWidgets[i].x = currentX;
centerWidgets[i].anchors.horizontalCenter = undefined;
let leftMiddleIndex = (totalWidgets / 2) - 1
let rightMiddleIndex = totalWidgets / 2
let gapCenter = parentCenterX
let halfSpacing = spacing / 2
centerWidgets[leftMiddleIndex].x = gapCenter - halfSpacing
- centerWidgets[leftMiddleIndex].width
centerWidgets[leftMiddleIndex].anchors.horizontalCenter = undefined
centerWidgets[rightMiddleIndex].x = gapCenter + halfSpacing
centerWidgets[rightMiddleIndex].anchors.horizontalCenter = undefined
let currentX = centerWidgets[leftMiddleIndex].x
for (var i = leftMiddleIndex - 1; i >= 0; i--) {
currentX -= (spacing + centerWidgets[i].width)
centerWidgets[i].x = currentX
centerWidgets[i].anchors.horizontalCenter = undefined
}
currentX = centerWidgets[rightMiddleIndex].x + centerWidgets[rightMiddleIndex].width;
for (let i = rightMiddleIndex + 1; i < totalWidgets; i++) {
currentX += spacing;
centerWidgets[i].x = currentX;
centerWidgets[i].anchors.horizontalCenter = undefined;
currentX += centerWidgets[i].width;
currentX = centerWidgets[rightMiddleIndex].x + centerWidgets[rightMiddleIndex].width
for (var i = rightMiddleIndex + 1; i < totalWidgets; i++) {
currentX += spacing
centerWidgets[i].x = currentX
centerWidgets[i].anchors.horizontalCenter = undefined
currentX += centerWidgets[i].width
}
}
}
@@ -364,19 +377,19 @@ PanelWindow {
anchors.centerIn: parent
Component.onCompleted: {
Qt.callLater(() => {
Qt.callLater(updateLayout);
});
Qt.callLater(updateLayout)
})
}
onWidthChanged: {
if (width > 0) {
Qt.callLater(updateLayout);
Qt.callLater(updateLayout)
}
}
onVisibleChanged: {
if (visible && width > 0) {
Qt.callLater(updateLayout);
Qt.callLater(updateLayout)
}
}
@@ -396,30 +409,28 @@ PanelWindow {
opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0
onLoaded: {
if (item) {
item.onWidthChanged.connect(centerSection.updateLayout);
item.onWidthChanged.connect(centerSection.updateLayout)
if (model.widgetId === "spacer")
item.spacerSize = Qt.binding(() => {
return model.size || 20;
});
return model.size || 20
})
Qt.callLater(centerSection.updateLayout);
Qt.callLater(centerSection.updateLayout)
}
}
onActiveChanged: {
Qt.callLater(centerSection.updateLayout);
Qt.callLater(centerSection.updateLayout)
}
}
}
Connections {
function onCountChanged() {
Qt.callLater(centerSection.updateLayout);
Qt.callLater(centerSection.updateLayout)
}
target: SettingsData.topBarCenterWidgetsModel
}
}
Row {
@@ -443,9 +454,7 @@ PanelWindow {
sourceComponent: topBarContent.getWidgetComponent(model.widgetId)
opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0
}
}
}
Component {
@@ -456,20 +465,22 @@ PanelWindow {
section: {
// Determine which section this loader is in by checking parent
if (parent && parent.parent) {
if (parent.parent === leftSection) return "left";
if (parent.parent === rightSection) return "right";
if (parent.parent === centerSection) return "center";
if (parent.parent === leftSection)
return "left"
if (parent.parent === rightSection)
return "right"
if (parent.parent === centerSection)
return "center"
}
return "left"; // default fallback
return "left" // default fallback
}
popupTarget: appDrawerPopout
parentScreen: root.screen
onClicked: {
if (appDrawerPopout)
appDrawerPopout.toggle();
appDrawerPopout.toggle()
}
}
}
Component {
@@ -478,7 +489,6 @@ PanelWindow {
WorkspaceSwitcher {
screenName: root.screenName
}
}
Component {
@@ -488,7 +498,6 @@ PanelWindow {
compactMode: topBarContent.spacingTight
availableWidth: topBarContent.leftToMediaGap
}
}
Component {
@@ -497,18 +506,20 @@ PanelWindow {
Clock {
compactMode: topBarContent.overlapping
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "center";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "center"
}
popupTarget: centcomPopout
parentScreen: root.screen
onClockClicked: {
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
centcomPopout.calendarVisible = !centcomPopout.calendarVisible
}
}
}
Component {
@@ -517,18 +528,20 @@ PanelWindow {
Media {
compactMode: topBarContent.spacingTight || topBarContent.overlapping
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "center";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "center"
}
popupTarget: centcomPopout
parentScreen: root.screen
onClicked: {
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
centcomPopout.calendarVisible = !centcomPopout.calendarVisible
}
}
}
Component {
@@ -536,18 +549,20 @@ PanelWindow {
Weather {
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "center";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "center"
}
popupTarget: centcomPopout
parentScreen: root.screen
onClicked: {
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
centcomPopout.calendarVisible = !centcomPopout.calendarVisible
}
}
}
Component {
@@ -557,7 +572,6 @@ PanelWindow {
parentWindow: root
parentScreen: root.screen
}
}
Component {
@@ -565,14 +579,16 @@ PanelWindow {
PrivacyIndicator {
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "right";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
}
parentScreen: root.screen
}
}
Component {
@@ -583,8 +599,9 @@ PanelWindow {
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = clipboardArea.containsMouse ? Theme.primaryHover : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = clipboardArea.containsMouse ? Theme.primaryHover : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
DankIcon {
@@ -601,7 +618,7 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
clipboardHistoryModalPopup.toggle();
clipboardHistoryModalPopup.toggle()
}
}
@@ -610,11 +627,8 @@ PanelWindow {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
Component {
@@ -622,18 +636,20 @@ PanelWindow {
CpuMonitor {
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "right";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
}
popupTarget: processListPopout
parentScreen: root.screen
toggleProcessList: () => {
return processListPopout.toggle();
return processListPopout.toggle()
}
}
}
Component {
@@ -641,18 +657,20 @@ PanelWindow {
RamMonitor {
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "right";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
}
popupTarget: processListPopout
parentScreen: root.screen
toggleProcessList: () => {
return processListPopout.toggle();
return processListPopout.toggle()
}
}
}
Component {
@@ -660,18 +678,20 @@ PanelWindow {
CpuTemperature {
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "right";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
}
popupTarget: processListPopout
parentScreen: root.screen
toggleProcessList: () => {
return processListPopout.toggle();
return processListPopout.toggle()
}
}
}
Component {
@@ -679,19 +699,21 @@ PanelWindow {
GpuTemperature {
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "right";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
}
popupTarget: processListPopout
parentScreen: root.screen
widgetData: parent.widgetData
toggleProcessList: () => {
return processListPopout.toggle();
return processListPopout.toggle()
}
}
}
Component {
@@ -701,18 +723,21 @@ PanelWindow {
hasUnread: root.notificationCount > 0
isActive: notificationCenter.notificationHistoryVisible
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "right";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
}
popupTarget: notificationCenter
parentScreen: root.screen
onClicked: {
notificationCenter.notificationHistoryVisible = !notificationCenter.notificationHistoryVisible;
notificationCenter.notificationHistoryVisible
= !notificationCenter.notificationHistoryVisible
}
}
}
Component {
@@ -721,18 +746,20 @@ PanelWindow {
Battery {
batteryPopupVisible: batteryPopout.batteryPopupVisible
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "right";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
}
popupTarget: batteryPopout
parentScreen: root.screen
onToggleBatteryPopup: {
batteryPopout.batteryPopupVisible = !batteryPopout.batteryPopupVisible;
batteryPopout.batteryPopupVisible = !batteryPopout.batteryPopupVisible
}
}
}
Component {
@@ -741,24 +768,25 @@ PanelWindow {
ControlCenterButton {
isActive: controlCenterPopout.controlCenterVisible
section: {
if (parent && parent.parent === leftSection) return "left";
if (parent && parent.parent === rightSection) return "right";
if (parent && parent.parent === centerSection) return "center";
return "right";
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
}
popupTarget: controlCenterPopout
parentScreen: root.screen
onClicked: {
controlCenterPopout.triggerScreen = root.screen;
controlCenterPopout.controlCenterVisible = !controlCenterPopout.controlCenterVisible;
controlCenterPopout.triggerScreen = root.screen
controlCenterPopout.controlCenterVisible = !controlCenterPopout.controlCenterVisible
if (controlCenterPopout.controlCenterVisible) {
if (NetworkService.wifiEnabled)
NetworkService.scanWifi();
NetworkService.scanWifi()
}
}
}
}
Component {
@@ -771,7 +799,8 @@ PanelWindow {
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.1)
border.width: 1
radius: 2
visible: false
@@ -782,11 +811,8 @@ PanelWindow {
onEntered: parent.visible = true
onExited: parent.visible = false
}
}
}
}
Component {
@@ -798,11 +824,7 @@ PanelWindow {
color: Theme.outline
opacity: 0.3
}
}
}
}
}

View File

@@ -10,15 +10,17 @@ Rectangle {
property var popupTarget: null
property var parentScreen: null
signal clicked()
signal clicked
visible: SettingsData.weatherEnabled
width: visible ? Math.min(100, weatherRow.implicitWidth + Theme.spacingS * 2) : 0
width: visible ? Math.min(100,
weatherRow.implicitWidth + Theme.spacingS * 2) : 0
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Ref {
@@ -40,17 +42,16 @@ Rectangle {
StyledText {
text: {
var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp
if (temp === undefined || temp === null || temp === 0) {
return "--°" + (SettingsData.useFahrenheit ? "F" : "C");
return "--°" + (SettingsData.useFahrenheit ? "F" : "C")
}
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C")
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -61,13 +62,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clicked();
root.clicked()
}
}
@@ -76,7 +79,6 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on width {
@@ -84,7 +86,5 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -11,72 +11,83 @@ Rectangle {
property string screenName: ""
property int currentWorkspace: getDisplayActiveWorkspace()
property var workspaceList: {
var baseList = getDisplayWorkspaces();
return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList;
var baseList = getDisplayWorkspaces()
return SettingsData.showWorkspacePadding ? padWorkspaces(
baseList) : baseList
}
function padWorkspaces(list) {
var padded = list.slice();
while (padded.length < 3)padded.push(-1) // Use -1 as a placeholder
return padded;
var padded = list.slice()
while (padded.length < 3)
padded.push(-1) // Use -1 as a placeholder
return padded
}
function getDisplayWorkspaces() {
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
return [1, 2];
return [1, 2]
if (!root.screenName)
return NiriService.getCurrentOutputWorkspaceNumbers();
return NiriService.getCurrentOutputWorkspaceNumbers()
var displayWorkspaces = [];
var displayWorkspaces = []
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i];
var ws = NiriService.allWorkspaces[i]
if (ws.output === root.screenName)
displayWorkspaces.push(ws.idx + 1);
displayWorkspaces.push(ws.idx + 1)
}
return displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2];
return displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2]
}
function getDisplayActiveWorkspace() {
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
return 1;
return 1
if (!root.screenName)
return NiriService.getCurrentWorkspaceNumber();
return NiriService.getCurrentWorkspaceNumber()
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i];
var ws = NiriService.allWorkspaces[i]
if (ws.output === root.screenName && ws.is_active)
return ws.idx + 1;
return ws.idx + 1
}
return 1;
return 1
}
width: SettingsData.showWorkspacePadding ? Math.max(120, workspaceRow.implicitWidth + Theme.spacingL * 2) : workspaceRow.implicitWidth + Theme.spacingL * 2
width: SettingsData.showWorkspacePadding ? Math.max(
120,
workspaceRow.implicitWidth + Theme.spacingL
* 2) : workspaceRow.implicitWidth
+ Theme.spacingL * 2
height: 30
radius: Theme.cornerRadiusLarge
color: {
const baseColor = Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
const baseColor = Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
visible: NiriService.niriAvailable
Connections {
function onAllWorkspacesChanged() {
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(root.getDisplayWorkspaces()) : root.getDisplayWorkspaces();
root.currentWorkspace = root.getDisplayActiveWorkspace();
root.workspaceList
= SettingsData.showWorkspacePadding ? root.padWorkspaces(
root.getDisplayWorkspaces(
)) : root.getDisplayWorkspaces()
root.currentWorkspace = root.getDisplayActiveWorkspace()
}
function onFocusedWorkspaceIndexChanged() {
root.currentWorkspace = root.getDisplayActiveWorkspace();
root.currentWorkspace = root.getDisplayActiveWorkspace()
}
function onNiriAvailableChanged() {
if (NiriService.niriAvailable) {
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(root.getDisplayWorkspaces()) : root.getDisplayWorkspaces();
root.currentWorkspace = root.getDisplayActiveWorkspace();
root.workspaceList
= SettingsData.showWorkspacePadding ? root.padWorkspaces(
root.getDisplayWorkspaces(
)) : root.getDisplayWorkspaces()
root.currentWorkspace = root.getDisplayActiveWorkspace()
}
}
@@ -85,8 +96,9 @@ Rectangle {
Connections {
function onShowWorkspacePaddingChanged() {
var baseList = root.getDisplayWorkspaces();
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(baseList) : baseList;
var baseList = root.getDisplayWorkspaces()
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(
baseList) : baseList
}
target: SettingsData
@@ -121,8 +133,7 @@ Rectangle {
enabled: !isPlaceholder
onClicked: {
if (!isPlaceholder)
NiriService.switchToWorkspace(modelData - 1);
NiriService.switchToWorkspace(modelData - 1)
}
}
@@ -130,7 +141,11 @@ Rectangle {
visible: SettingsData.showWorkspaceIndex
anchors.centerIn: parent
text: isPlaceholder ? sequentialNumber : sequentialNumber
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
color: isActive ? Qt.rgba(
Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b,
0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall
font.weight: isActive && !isPlaceholder ? Font.DemiBold : Font.Normal
}
@@ -140,7 +155,6 @@ Rectangle {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on color {
@@ -148,13 +162,8 @@ Rectangle {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
}

View File

@@ -14,14 +14,13 @@ PanelWindow {
property bool volumePopupVisible: false
function show() {
root.volumePopupVisible = true;
hideTimer.restart();
root.volumePopupVisible = true
hideTimer.restart()
}
function resetHideTimer() {
if (root.volumePopupVisible)
hideTimer.restart();
hideTimer.restart()
}
screen: modelData
@@ -45,21 +44,20 @@ PanelWindow {
repeat: false
onTriggered: {
if (!volumePopup.containsMouse)
root.volumePopupVisible = false;
root.volumePopupVisible = false
else
hideTimer.restart();
hideTimer.restart()
}
}
Connections {
function onVolumeChanged() {
root.show();
root.show()
}
function onSinkChanged() {
if (root.volumePopupVisible)
root.show();
root.show()
}
target: AudioService
@@ -77,7 +75,8 @@ PanelWindow {
anchors.bottomMargin: Theme.spacingM
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1
opacity: root.volumePopupVisible ? 1 : 0
scale: root.volumePopupVisible ? 1 : 0.9
@@ -106,7 +105,8 @@ PanelWindow {
DankIcon {
anchors.centerIn: parent
name: AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.muted ? "volume_off" : "volume_up"
name: AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.muted ? "volume_off" : "volume_up"
size: Theme.iconSize
color: muteButton.containsMouse ? Theme.primary : Theme.surfaceText
}
@@ -118,11 +118,10 @@ PanelWindow {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
AudioService.toggleMute();
root.resetHideTimer();
AudioService.toggleMute()
root.resetHideTimer()
}
}
}
DankSlider {
@@ -139,28 +138,26 @@ PanelWindow {
unit: "%"
Component.onCompleted: {
if (AudioService.sink && AudioService.sink.audio)
value = Math.round(AudioService.sink.audio.volume * 100);
value = Math.round(AudioService.sink.audio.volume * 100)
}
onSliderValueChanged: function(newValue) {
onSliderValueChanged: function (newValue) {
if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.volume = newValue / 100;
root.resetHideTimer();
AudioService.sink.audio.volume = newValue / 100
root.resetHideTimer()
}
}
Connections {
function onVolumeChanged() {
volumeSlider.value = Math.round(AudioService.sink.audio.volume * 100);
volumeSlider.value = Math.round(
AudioService.sink.audio.volume * 100)
}
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null
target: AudioService.sink
&& AudioService.sink.audio ? AudioService.sink.audio : null
}
}
}
}
MouseArea {
@@ -191,7 +188,6 @@ PanelWindow {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
@@ -199,7 +195,6 @@ PanelWindow {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on transform {
@@ -207,13 +202,10 @@ PanelWindow {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
mask: Region {
item: volumePopup
}
}

View File

@@ -37,11 +37,11 @@ LazyLoader {
onSourceChanged: {
if (!source)
current = null;
current = null
else if (current === one)
two.update();
two.update()
else
one.update();
one.update()
}
Loader {
@@ -96,8 +96,8 @@ LazyLoader {
id: img
function update(): void {
source = "";
source = root.source;
source = ""
source = root.source
}
anchors.fill: parent
@@ -110,7 +110,7 @@ LazyLoader {
onStatusChanged: {
if (status === Image.Ready)
root.current = this;
root.current = this
}
states: State {

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import Quickshell
@@ -13,9 +14,13 @@ Singleton {
property var applications: DesktopEntries.applications.values
property var preppedApps: applications.map(app => ({
name: Fuzzy.prepare(app.name || ""),
comment: Fuzzy.prepare(app.comment || ""),
entry: app
"name": Fuzzy.prepare(
app.name
|| ""),
"comment": Fuzzy.prepare(
app.comment
|| ""),
"entry": app
}))
function searchApplications(query) {
@@ -28,9 +33,9 @@ Singleton {
}
var results = Fuzzy.go(query, preppedApps, {
all: false,
keys: ["name", "comment"],
scoreFn: r => {
"all": false,
"keys": ["name", "comment"],
"scoreFn": r => {
var nameScore = r[0] ? r[0].score : 0
var commentScore = r[1] ? r[1].score : 0
var appName = r.obj.entry.name || ""
@@ -42,17 +47,17 @@ Singleton {
if (nameLower === queryLower) {
finalScore = nameScore * 100
}
else if (nameLower.startsWith(queryLower)) {
} else if (nameLower.startsWith(queryLower)) {
finalScore = nameScore * 50
}
else if (nameLower.includes(" " + queryLower) || nameLower.includes(queryLower + " ") || nameLower.endsWith(" " + queryLower)) {
} else if (nameLower.includes(" " + queryLower)
|| nameLower.includes(
queryLower + " ")
|| nameLower.endsWith(
" " + queryLower)) {
finalScore = nameScore * 25
}
else if (nameLower.includes(queryLower)) {
} else if (nameLower.includes(queryLower)) {
finalScore = nameScore * 10
}
else {
} else {
finalScore = nameScore * 2 + commentScore * 0.1
}
} else {
@@ -61,16 +66,15 @@ Singleton {
return finalScore
},
limit: 50
"limit": 50
})
return results.map(r => r.obj.entry)
}
function getCategoriesForApp(app) {
if (!app || !app.categories) return []
if (!app || !app.categories)
return []
var categoryMap = {
"AudioVideo": "Media",
@@ -150,5 +154,4 @@ Singleton {
return appCategories.includes(category)
})
}
}

Some files were not shown because too many files have changed in this diff Show More