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

Compare commits

..

33 Commits

Author SHA1 Message Date
Flux
a7cdb39b0b labwc patch (#1391) 2026-01-16 09:52:13 -05:00
bbedward
0ceba92a23 i18n: more RTL fixes across settings 2026-01-16 09:52:13 -05:00
bbedward
4daa7a4c88 popout: fix cross-monitor handling of widgets fixes #1364 2026-01-16 09:52:13 -05:00
bbedward
cc4a6a5899 doctor: add mango and labwc to compositors fixes #1394 2026-01-16 09:52:13 -05:00
bbedward
994947477c greeter: remove WLR_DRM_DEVICES setting fixes #1393 2026-01-16 09:52:13 -05:00
bbedward
311817ee97 dankbar: fix property preservation in widgets fixes #1392 2026-01-16 09:52:13 -05:00
bbedward
b80c73f9b9 weather: fix precipitationw weekly propability fixes #1395 2026-01-16 09:52:13 -05:00
bbedward
a85101c099 plugins: ensure daemon plugins not instantiated twice 2026-01-16 09:52:13 -05:00
bbedward
3513d57e06 cc: fixed width column, remove anchoring from individual icons on vbar maybe #1376 2026-01-16 09:52:13 -05:00
Lucas
1234847abb nix: fix home module (#1387) 2026-01-16 09:52:13 -05:00
Bailey
0ed595b43d nix: Support specifying systemd target (#1385) 2026-01-16 09:52:13 -05:00
Ivan Molodetskikh
060cbefc79 Add screencast indicator for niri (#1361)
* niri: Handle new Cast events

* bar: Add screen sharing indicator

Configurable like other icons; on by default.

* lockscreen: Add screen sharing indicator
2026-01-16 09:52:10 -05:00
bbedward
e022c04519 bump version 2026-01-15 23:45:21 -05:00
bbedward
f534384e5e cc: wrap icons in fixed size containers
maybe #1376
2026-01-15 23:45:09 -05:00
bbedward
a25cdb43d5 controlcenter: fix visibility condition of no icons fixes #1377 2026-01-15 23:45:09 -05:00
purian23
4e9b4ca400 Fix fedora version format 2026-01-15 23:44:19 -05:00
bbedward
5bab1c98b1 plugins: fix plugin confirm third part repo window 2026-01-15 23:44:19 -05:00
purian23
2284bb002f distro: Update Fedora dynamic versioning 2026-01-15 23:44:19 -05:00
purian23
b0611d6104 feat: Allow more pinned services in Control Center/Settings 2026-01-15 23:44:19 -05:00
purian23
27965862d6 core: Update ghostty on dankinstall 2026-01-15 23:44:19 -05:00
Abhinav Chalise
e74a901e05 fix volume osd sliding ui update for vertical layout (#1382) 2026-01-15 23:44:19 -05:00
bbedward
77794deb2c widgets: add fallback for steam apps 2026-01-15 23:44:19 -05:00
Lucas
1c10746e50 doctor: use dbus for checking on services (#1384)
* doctor: use dbus for checking on services

* doctor: show docs URL for failed checks

* core: remove unused function
2026-01-15 23:44:19 -05:00
bbedward
8ecb7282b9 dankdash: fix weather open IPC fixes #1367 2026-01-15 23:44:19 -05:00
bbedward
9b3fa804ab matugen: fix nvim ID in skipTemplates 2026-01-15 23:44:19 -05:00
purian23
b2ad31a27e dankdash: Center Media Art & Controls 2026-01-15 23:44:19 -05:00
bbedward
db17e4cb14 i18n: update terms 2026-01-15 23:44:02 -05:00
bbedward
1b7dcf56a8 bump VERSION 2026-01-14 08:00:15 -05:00
bbedward
502bb88e92 modals: fix wifi passowrd, polkit, and VPN import 2026-01-14 08:00:05 -05:00
bbedward
b76d0ce97d settings: fix child windows on newer quickshell-git 2026-01-13 16:58:08 -05:00
bbedward
fa66d330cf bump VERSION 2026-01-13 16:42:49 -05:00
Lucas
157eab2d07 settings: fix modal not opening on latest quickshell (#1357) 2026-01-13 16:42:38 -05:00
Lucas
f50ad2dc22 nix: escape version string (#1353) 2026-01-13 16:42:38 -05:00
93 changed files with 3594 additions and 15621 deletions

View File

@@ -4,14 +4,13 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
package: package:
description: "Package to update" description: "Package to update (dms, dms-git, or all)"
required: true required: false
type: choice default: "all"
options: tag_version:
- dms description: "Specific tag version for dms stable (e.g., v1.0.2). Leave empty to auto-detect latest release."
- dms-git required: false
- all default: ""
default: "dms"
rebuild_release: rebuild_release:
description: "Release number for rebuilds (e.g., 2, 3, 4 to increment spec Release)" description: "Release number for rebuilds (e.g., 2, 3, 4 to increment spec Release)"
required: false required: false
@@ -57,9 +56,8 @@ jobs:
} }
# Helper function to check dms stable tag # Helper function to check dms stable tag
# Sets LATEST_TAG variable in parent scope if update needed
check_dms_stable() { check_dms_stable() {
LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "\([^"]*\)".*/\1/' || echo "") local LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "v\?\([^"]*\)".*/\1/' || echo "")
local OBS_SPEC=$(curl -s -u "$OBS_USERNAME:$OBS_PASSWORD" "https://api.opensuse.org/source/home:AvengeMedia:dms/dms/dms.spec" 2>/dev/null || echo "") local OBS_SPEC=$(curl -s -u "$OBS_USERNAME:$OBS_PASSWORD" "https://api.opensuse.org/source/home:AvengeMedia:dms/dms/dms.spec" 2>/dev/null || echo "")
local OBS_VERSION=$(echo "$OBS_SPEC" | grep "^Version:" | awk '{print $2}' | xargs || echo "") local OBS_VERSION=$(echo "$OBS_SPEC" | grep "^Version:" | awk '{print $2}' | xargs || echo "")
@@ -75,8 +73,8 @@ jobs:
# Main logic # Main logic
REBUILD="${{ github.event.inputs.rebuild_release }}" REBUILD="${{ github.event.inputs.rebuild_release }}"
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" =~ ^refs/tags/ ]]; then
# Tag selected or pushed - always update stable package # Tag push - always update stable package
echo "packages=dms" >> $GITHUB_OUTPUT echo "packages=dms" >> $GITHUB_OUTPUT
VERSION="${GITHUB_REF#refs/tags/}" VERSION="${GITHUB_REF#refs/tags/}"
echo "version=$VERSION" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT
@@ -106,12 +104,7 @@ jobs:
# Check each package and build list of those needing updates # Check each package and build list of those needing updates
PACKAGES_TO_UPDATE=() PACKAGES_TO_UPDATE=()
check_dms_git && PACKAGES_TO_UPDATE+=("dms-git") check_dms_git && PACKAGES_TO_UPDATE+=("dms-git")
if check_dms_stable; then check_dms_stable && PACKAGES_TO_UPDATE+=("dms")
PACKAGES_TO_UPDATE+=("dms")
if [[ -n "$LATEST_TAG" ]]; then
echo "version=$LATEST_TAG" >> $GITHUB_OUTPUT
fi
fi
if [[ ${#PACKAGES_TO_UPDATE[@]} -gt 0 ]]; then if [[ ${#PACKAGES_TO_UPDATE[@]} -gt 0 ]]; then
echo "packages=${PACKAGES_TO_UPDATE[*]}" >> $GITHUB_OUTPUT echo "packages=${PACKAGES_TO_UPDATE[*]}" >> $GITHUB_OUTPUT
@@ -136,9 +129,6 @@ jobs:
if check_dms_stable; then if check_dms_stable; then
echo "packages=$PKG" >> $GITHUB_OUTPUT echo "packages=$PKG" >> $GITHUB_OUTPUT
echo "has_updates=true" >> $GITHUB_OUTPUT echo "has_updates=true" >> $GITHUB_OUTPUT
if [[ -n "$LATEST_TAG" ]]; then
echo "version=$LATEST_TAG" >> $GITHUB_OUTPUT
fi
else else
echo "packages=" >> $GITHUB_OUTPUT echo "packages=" >> $GITHUB_OUTPUT
echo "has_updates=false" >> $GITHUB_OUTPUT echo "has_updates=false" >> $GITHUB_OUTPUT
@@ -171,19 +161,12 @@ jobs:
- name: Determine packages to update - name: Determine packages to update
id: packages id: packages
run: | run: |
# Check if GITHUB_REF points to a tag (works for both push events and workflow_dispatch with tag selected) if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" =~ ^refs/tags/ ]]; then
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then # Tag push event - use the pushed tag
# Tag selected or pushed - use the tag from GITHUB_REF
echo "packages=dms" >> $GITHUB_OUTPUT echo "packages=dms" >> $GITHUB_OUTPUT
VERSION="${GITHUB_REF#refs/tags/}" VERSION="${GITHUB_REF#refs/tags/}"
echo "version=$VERSION" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Using tag from GITHUB_REF: $VERSION" echo "Triggered by tag: $VERSION"
# Check if check-updates already determined a version (from auto-detection)
elif [[ -n "${{ needs.check-updates.outputs.version }}" ]]; then
# Use version from check-updates job
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
echo "version=${{ needs.check-updates.outputs.version }}" >> $GITHUB_OUTPUT
echo "Using version from check-updates: ${{ needs.check-updates.outputs.version }}"
elif [[ "${{ github.event_name }}" == "schedule" ]]; then elif [[ "${{ github.event_name }}" == "schedule" ]]; then
# Scheduled run - dms-git only # Scheduled run - dms-git only
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
@@ -193,28 +176,22 @@ jobs:
# Determine version for dms stable # Determine version for dms stable
if [[ "${{ github.event.inputs.package }}" == "dms" ]]; then if [[ "${{ github.event.inputs.package }}" == "dms" ]]; then
# Use github.ref if tag selected, otherwise auto-detect latest # For explicit dms selection, require tag_version
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then if [[ -n "${{ github.event.inputs.tag_version }}" ]]; then
VERSION="${GITHUB_REF#refs/tags/}" VERSION="${{ github.event.inputs.tag_version }}"
echo "version=$VERSION" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Using tag from GITHUB_REF: $VERSION" echo "Using specified tag: $VERSION"
else else
# Auto-detect latest release for dms echo "ERROR: tag_version is required when package=dms"
LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "\([^"]*\)".*/\1/' || echo "") echo "Please specify a tag version (e.g., v1.0.2) or use package=all for auto-detection"
if [[ -n "$LATEST_TAG" ]]; then exit 1
echo "version=$LATEST_TAG" >> $GITHUB_OUTPUT
echo "Auto-detected latest release: $LATEST_TAG"
else
echo "ERROR: Could not auto-detect latest release"
exit 1
fi
fi fi
elif [[ "${{ github.event.inputs.package }}" == "all" ]]; then elif [[ "${{ github.event.inputs.package }}" == "all" ]]; then
# Use github.ref if tag selected, otherwise auto-detect latest # For "all", auto-detect if tag_version not specified
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then if [[ -n "${{ github.event.inputs.tag_version }}" ]]; then
VERSION="${GITHUB_REF#refs/tags/}" VERSION="${{ github.event.inputs.tag_version }}"
echo "version=$VERSION" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Using tag from GITHUB_REF: $VERSION" echo "Using specified tag: $VERSION"
else else
# Auto-detect latest release for "all" # Auto-detect latest release for "all"
LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "\([^"]*\)".*/\1/' || echo "") LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "\([^"]*\)".*/\1/' || echo "")
@@ -229,7 +206,7 @@ jobs:
fi fi
# Use filtered packages from check-updates when package="all" and no rebuild/tag specified # Use filtered packages from check-updates when package="all" and no rebuild/tag specified
if [[ "${{ github.event.inputs.package }}" == "all" ]] && [[ -z "${{ github.event.inputs.rebuild_release }}" ]] && [[ ! "${{ github.ref }}" =~ ^refs/tags/ ]]; then if [[ "${{ github.event.inputs.package }}" == "all" ]] && [[ -z "${{ github.event.inputs.rebuild_release }}" ]] && [[ -z "${{ github.event.inputs.tag_version }}" ]]; then
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
echo "Manual trigger: all (filtered to: ${{ needs.check-updates.outputs.packages }})" echo "Manual trigger: all (filtered to: ${{ needs.check-updates.outputs.packages }})"
else else
@@ -238,9 +215,6 @@ jobs:
fi fi
else else
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
if [[ -n "${{ needs.check-updates.outputs.version }}" ]]; then
echo "version=${{ needs.check-updates.outputs.version }}" >> $GITHUB_OUTPUT
fi
fi fi
- name: Update dms-git spec version - name: Update dms-git spec version

View File

@@ -43,6 +43,7 @@ install-shell:
@mkdir -p $(SHELL_INSTALL_DIR) @mkdir -p $(SHELL_INSTALL_DIR)
@cp -r $(SHELL_DIR)/* $(SHELL_INSTALL_DIR)/ @cp -r $(SHELL_DIR)/* $(SHELL_INSTALL_DIR)/
@rm -rf $(SHELL_INSTALL_DIR)/.git* $(SHELL_INSTALL_DIR)/.github @rm -rf $(SHELL_INSTALL_DIR)/.git* $(SHELL_INSTALL_DIR)/.github
@$(MAKE) --no-print-directory -C $(CORE_DIR) print-version > $(SHELL_INSTALL_DIR)/VERSION
@echo "Shell files installed" @echo "Shell files installed"
install-completions: install-completions:

View File

@@ -511,8 +511,6 @@ func getCommonCommands() []*cobra.Command {
colorCmd, colorCmd,
screenshotCmd, screenshotCmd,
notifyActionCmd, notifyActionCmd,
notifyCmd,
genericNotifyActionCmd,
matugenCmd, matugenCmd,
clipboardCmd, clipboardCmd,
doctorCmd, doctorCmd,

View File

@@ -1,68 +0,0 @@
package main
import (
"fmt"
"os"
"github.com/AvengeMedia/DankMaterialShell/core/internal/notify"
"github.com/spf13/cobra"
)
var (
notifyAppName string
notifyIcon string
notifyFile string
notifyTimeout int
)
var notifyCmd = &cobra.Command{
Use: "notify <summary> [body]",
Short: "Send a desktop notification",
Long: `Send a desktop notification with optional actions.
If --file is provided, the notification will have "Open" and "Open Folder" actions.
Examples:
dms notify "Hello" "World"
dms notify "File received" "photo.jpg" --file ~/Downloads/photo.jpg --icon smartphone
dms notify "Download complete" --file ~/Downloads/file.zip --app "My App"`,
Args: cobra.MinimumNArgs(1),
Run: runNotify,
}
var genericNotifyActionCmd = &cobra.Command{
Use: "notify-action-generic",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
notify.RunActionListener(args)
},
}
func init() {
notifyCmd.Flags().StringVar(&notifyAppName, "app", "DMS", "Application name")
notifyCmd.Flags().StringVar(&notifyIcon, "icon", "", "Icon name or path")
notifyCmd.Flags().StringVar(&notifyFile, "file", "", "File path (enables Open/Open Folder actions)")
notifyCmd.Flags().IntVar(&notifyTimeout, "timeout", 5000, "Timeout in milliseconds")
}
func runNotify(cmd *cobra.Command, args []string) {
summary := args[0]
body := ""
if len(args) > 1 {
body = args[1]
}
n := notify.Notification{
AppName: notifyAppName,
Icon: notifyIcon,
Summary: summary,
Body: body,
FilePath: notifyFile,
Timeout: int32(notifyTimeout),
}
if err := notify.Send(n); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}

View File

@@ -16,21 +16,21 @@ require (
github.com/spf13/cobra v1.10.2 github.com/spf13/cobra v1.10.2
github.com/stretchr/testify v1.11.1 github.com/stretchr/testify v1.11.1
go.etcd.io/bbolt v1.4.3 go.etcd.io/bbolt v1.4.3
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93
golang.org/x/image v0.35.0 golang.org/x/image v0.34.0
) )
require ( require (
github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.3.0 // indirect github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/clipperhouse/displaywidth v0.7.0 // indirect github.com/clipperhouse/displaywidth v0.6.2 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.6.2 // indirect github.com/cloudflare/circl v1.6.2 // indirect
github.com/cyphar/filepath-securejoin v0.6.1 // indirect github.com/cyphar/filepath-securejoin v0.6.1 // indirect
github.com/emirpasic/gods v1.18.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect
github.com/go-git/gcfg/v2 v2.0.2 // indirect github.com/go-git/gcfg/v2 v2.0.2 // indirect
github.com/go-git/go-billy/v6 v6.0.0-20260114122816-19306b749ecc // indirect github.com/go-git/go-billy/v6 v6.0.0-20251217170237-e9738f50a3cd // indirect
github.com/go-logfmt/logfmt v0.6.1 // indirect github.com/go-logfmt/logfmt v0.6.1 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/kevinburke/ssh_config v1.4.0 // indirect github.com/kevinburke/ssh_config v1.4.0 // indirect
@@ -38,8 +38,8 @@ require (
github.com/pjbgf/sha1cd v0.5.0 // indirect github.com/pjbgf/sha1cd v0.5.0 // indirect
github.com/sergi/go-diff v1.4.0 // indirect github.com/sergi/go-diff v1.4.0 // indirect
github.com/stretchr/objx v0.5.3 // indirect github.com/stretchr/objx v0.5.3 // indirect
golang.org/x/crypto v0.47.0 // indirect golang.org/x/crypto v0.46.0 // indirect
golang.org/x/net v0.49.0 // indirect golang.org/x/net v0.48.0 // indirect
) )
require ( require (
@@ -47,12 +47,12 @@ require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/colorprofile v0.4.1 // indirect github.com/charmbracelet/colorprofile v0.4.1 // indirect
github.com/charmbracelet/harmonica v0.2.0 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect
github.com/charmbracelet/x/ansi v0.11.4 // indirect github.com/charmbracelet/x/ansi v0.11.3 // indirect
github.com/charmbracelet/x/cellbuf v0.0.14 // indirect github.com/charmbracelet/x/cellbuf v0.0.14 // indirect
github.com/charmbracelet/x/term v0.2.2 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/go-git/go-git/v6 v6.0.0-20260114124804-a8db3a6585a6 github.com/go-git/go-git/v6 v6.0.0-20251231065035-29ae690a9f19
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 github.com/lucasb-eyer/go-colorful v1.3.0
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
@@ -66,7 +66,7 @@ require (
github.com/spf13/afero v1.15.0 github.com/spf13/afero v1.15.0
github.com/spf13/pflag v1.0.10 // indirect github.com/spf13/pflag v1.0.10 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/sys v0.40.0 golang.org/x/sys v0.39.0
golang.org/x/text v0.33.0 golang.org/x/text v0.32.0
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@@ -16,6 +16,8 @@ github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
github.com/charmbracelet/colorprofile v0.3.3 h1:DjJzJtLP6/NZ8p7Cgjno0CKGr7wwRJGxWUwh2IyhfAI=
github.com/charmbracelet/colorprofile v0.3.3/go.mod h1:nB1FugsAbzq284eJcjfah2nhdSLppN2NqvfotkfRYP4=
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
@@ -24,22 +26,24 @@ github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoF
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig= github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw= github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
github.com/charmbracelet/x/ansi v0.11.2 h1:XAG3FSjiVtFvgEgGrNBkCNNYrsucAt8c6bfxHyROLLs=
github.com/charmbracelet/x/ansi v0.11.2/go.mod h1:9tY2bzX5SiJCU0iWyskjBeI2BRQfvPqI+J760Mjf+Rg=
github.com/charmbracelet/x/ansi v0.11.3 h1:6DcVaqWI82BBVM/atTyq6yBoRLZFBsnoDoX9GCu2YOI= github.com/charmbracelet/x/ansi v0.11.3 h1:6DcVaqWI82BBVM/atTyq6yBoRLZFBsnoDoX9GCu2YOI=
github.com/charmbracelet/x/ansi v0.11.3/go.mod h1:yI7Zslym9tCJcedxz5+WBq+eUGMJT0bM06Fqy1/Y4dI= github.com/charmbracelet/x/ansi v0.11.3/go.mod h1:yI7Zslym9tCJcedxz5+WBq+eUGMJT0bM06Fqy1/Y4dI=
github.com/charmbracelet/x/ansi v0.11.4 h1:6G65PLu6HjmE858CnTUQY1LXT3ZUWwfvqEROLF8vqHI=
github.com/charmbracelet/x/ansi v0.11.4/go.mod h1:/5AZ+UfWExW3int5H5ugnsG/PWjNcSQcwYsHBlPFQN4=
github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4= github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4=
github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA= github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA=
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
github.com/clipperhouse/displaywidth v0.6.0 h1:k32vueaksef9WIKCNcoqRNyKbyvkvkysNYnAWz2fN4s=
github.com/clipperhouse/displaywidth v0.6.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo= github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo=
github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
github.com/clipperhouse/displaywidth v0.7.0 h1:QNv1GYsnLX9QBrcWUtMlogpTXuM5FVnBwKWp1O5NwmE=
github.com/clipperhouse/displaywidth v0.7.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cloudflare/circl v1.6.2 h1:hL7VBpHHKzrV5WTfHCaBsgx/HGbBYlgrwvNXEVDYYsQ= github.com/cloudflare/circl v1.6.2 h1:hL7VBpHHKzrV5WTfHCaBsgx/HGbBYlgrwvNXEVDYYsQ=
github.com/cloudflare/circl v1.6.2/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cloudflare/circl v1.6.2/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
@@ -48,6 +52,8 @@ github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
@@ -58,19 +64,22 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-git/gcfg/v2 v2.0.2 h1:MY5SIIfTGGEMhdA7d7JePuVVxtKL7Hp+ApGDJAJ7dpo= github.com/go-git/gcfg/v2 v2.0.2 h1:MY5SIIfTGGEMhdA7d7JePuVVxtKL7Hp+ApGDJAJ7dpo=
github.com/go-git/gcfg/v2 v2.0.2/go.mod h1:/lv2NsxvhepuMrldsFilrgct6pxzpGdSRC13ydTLSLs= github.com/go-git/gcfg/v2 v2.0.2/go.mod h1:/lv2NsxvhepuMrldsFilrgct6pxzpGdSRC13ydTLSLs=
github.com/go-git/go-billy/v6 v6.0.0-20251126203821-7f9c95185ee0 h1:eY5aB2GXiVdgTueBcqsBt53WuJTRZAuCdIS/86Pcq5c=
github.com/go-git/go-billy/v6 v6.0.0-20251126203821-7f9c95185ee0/go.mod h1:0NjwVNrwtVFZBReAp5OoGklGJIgJFEbVyHneAr4lc8k=
github.com/go-git/go-billy/v6 v6.0.0-20251217170237-e9738f50a3cd h1:Gd/f9cGi/3h1JOPaa6er+CkKUGyGX2DBJdFbDKVO+R0= github.com/go-git/go-billy/v6 v6.0.0-20251217170237-e9738f50a3cd h1:Gd/f9cGi/3h1JOPaa6er+CkKUGyGX2DBJdFbDKVO+R0=
github.com/go-git/go-billy/v6 v6.0.0-20251217170237-e9738f50a3cd/go.mod h1:d3XQcsHu1idnquxt48kAv+h+1MUiYKLH/e7LAzjP+pI= github.com/go-git/go-billy/v6 v6.0.0-20251217170237-e9738f50a3cd/go.mod h1:d3XQcsHu1idnquxt48kAv+h+1MUiYKLH/e7LAzjP+pI=
github.com/go-git/go-billy/v6 v6.0.0-20260114122816-19306b749ecc h1:rhkjrnRkamkRC7woapp425E4CAH6RPcqsS9X8LA93IY= github.com/go-git/go-git-fixtures/v5 v5.1.1 h1:OH8i1ojV9bWfr0ZfasfpgtUXQHQyVS8HXik/V1C099w=
github.com/go-git/go-billy/v6 v6.0.0-20260114122816-19306b749ecc/go.mod h1:X1oe0Z2qMsa9hkar3AAPuL9hu4Mi3ztXEjdqRhr6fcc= github.com/go-git/go-git-fixtures/v5 v5.1.1/go.mod h1:Altk43lx3b1ks+dVoAG2300o5WWUnktvfY3VI6bcaXU=
github.com/go-git/go-git-fixtures/v5 v5.1.2-0.20251229094738-4b14af179146 h1:xYfxAopYyL44ot6dMBIb1Z1njFM0ZBQ99HdIB99KxLs= github.com/go-git/go-git-fixtures/v5 v5.1.2-0.20251229094738-4b14af179146 h1:xYfxAopYyL44ot6dMBIb1Z1njFM0ZBQ99HdIB99KxLs=
github.com/go-git/go-git-fixtures/v5 v5.1.2-0.20251229094738-4b14af179146/go.mod h1:QE/75B8tBSLNGyUUbA9tw3EGHoFtYOtypa2h8YJxsWI= github.com/go-git/go-git/v6 v6.0.0-20251128074608-48f817f57805 h1:jxQ3BzYeErNRvlI/4+0mpwqMzvB4g97U+ksfgvrUEbY=
github.com/go-git/go-git/v6 v6.0.0-20251128074608-48f817f57805/go.mod h1:dIwT3uWK1ooHInyVnK2JS5VfQ3peVGYaw2QPqX7uFvs=
github.com/go-git/go-git/v6 v6.0.0-20251231065035-29ae690a9f19 h1:0lz2eJScP8v5YZQsrEw+ggWC5jNySjg4bIZo5BIh6iI= github.com/go-git/go-git/v6 v6.0.0-20251231065035-29ae690a9f19 h1:0lz2eJScP8v5YZQsrEw+ggWC5jNySjg4bIZo5BIh6iI=
github.com/go-git/go-git/v6 v6.0.0-20251231065035-29ae690a9f19/go.mod h1:L+Evfcs7EdTqxwv854354cb6+++7TFL3hJn3Wy4g+3w= github.com/go-git/go-git/v6 v6.0.0-20251231065035-29ae690a9f19/go.mod h1:L+Evfcs7EdTqxwv854354cb6+++7TFL3hJn3Wy4g+3w=
github.com/go-git/go-git/v6 v6.0.0-20260114124804-a8db3a6585a6 h1:Yo1MlE8LpvD0pr7mZ04b6hKZKQcPvLrQFgyY1jNMEyU=
github.com/go-git/go-git/v6 v6.0.0-20260114124804-a8db3a6585a6/go.mod h1:enMzPHv+9hL4B7tH7OJGQKNzCkMzXovUoaiXfsLF7Xs=
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.2.0 h1:3WexO+U+yg9T70v9FdHr9kCxYlazaAXUhx2VMkbfax8=
github.com/godbus/dbus/v5 v5.2.0/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
@@ -118,12 +127,16 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sblinch/kdl-go v0.0.0-20250930225324-bf4099d4614a h1:8ZZwZWIQKC0YVMyaCkbrdeI8faTjD1QBrRAAWc1TjMI=
github.com/sblinch/kdl-go v0.0.0-20250930225324-bf4099d4614a/go.mod h1:b3oNGuAKOQzhsCKmuLc/urEOPzgHj6fB8vl8bwTBh28=
github.com/sblinch/kdl-go v0.0.0-20251203232544-981d4ecc17c3 h1:msKaIZrrNpvofLPDzNBW3152PJBsnPZsoNNosOCS+C0= github.com/sblinch/kdl-go v0.0.0-20251203232544-981d4ecc17c3 h1:msKaIZrrNpvofLPDzNBW3152PJBsnPZsoNNosOCS+C0=
github.com/sblinch/kdl-go v0.0.0-20251203232544-981d4ecc17c3/go.mod h1:b3oNGuAKOQzhsCKmuLc/urEOPzgHj6fB8vl8bwTBh28= github.com/sblinch/kdl-go v0.0.0-20251203232544-981d4ecc17c3/go.mod h1:b3oNGuAKOQzhsCKmuLc/urEOPzgHj6fB8vl8bwTBh28=
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@@ -140,37 +153,33 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJu
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39 h1:DHNhtq3sNNzrvduZZIiFyXWOL9IWaDPHqTnLJp+rCBY=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0=
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0= golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU= golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU=
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
golang.org/x/image v0.34.0 h1:33gCkyw9hmwbZJeZkct8XyR11yH889EQt/QH4VmXMn8= golang.org/x/image v0.34.0 h1:33gCkyw9hmwbZJeZkct8XyR11yH889EQt/QH4VmXMn8=
golang.org/x/image v0.34.0/go.mod h1:2RNFBZRB+vnwwFil8GkMdRvrJOFd1AzdZI6vOY+eJVU= golang.org/x/image v0.34.0/go.mod h1:2RNFBZRB+vnwwFil8GkMdRvrJOFd1AzdZI6vOY+eJVU=
golang.org/x/image v0.35.0 h1:LKjiHdgMtO8z7Fh18nGY6KDcoEtVfsgLDPeLyguqb7I= golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/image v0.35.0/go.mod h1:MwPLTVgvxSASsxdLzKrl8BRFuyqMyGhLwmC+TO1Sybk= golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=

View File

@@ -199,6 +199,31 @@ func labToHex(L, a, b float64) string {
return fmt.Sprintf("#%02x%02x%02x", r, g, b2) return fmt.Sprintf("#%02x%02x%02x", r, g, b2)
} }
// Adjust brightness while keeping the same hue
func retoneToL(hex string, Ltarget float64) string {
rgb := HexToRGB(hex)
col := colorful.Color{R: rgb.R, G: rgb.G, B: rgb.B}
L, a, b := col.Lab()
L100 := L * 100.0
scale := 1.0
if L100 != 0 {
scale = Ltarget / L100
}
a2, b2 := a*scale, b*scale
// Don't let it get too saturated
maxChroma := 0.4
if math.Hypot(a2, b2) > maxChroma {
k := maxChroma / math.Hypot(a2, b2)
a2 *= k
b2 *= k
}
return labToHex(Ltarget, a2, b2)
}
func DeltaPhiStar(hexFg, hexBg string, negativePolarity bool) float64 { func DeltaPhiStar(hexFg, hexBg string, negativePolarity bool) float64 {
Lf := getLstar(hexFg) Lf := getLstar(hexFg)
Lb := getLstar(hexBg) Lb := getLstar(hexBg)
@@ -331,59 +356,6 @@ func EnsureContrastDPSLstar(hexColor, hexBg string, minLc float64, isLightMode b
return hexColor return hexColor
} }
// Bidirectional contrast - tries both lighter and darker, picks closest to original
func EnsureContrastDPSBidirectional(hexColor, hexBg string, minLc float64, isLightMode bool) string {
current := DeltaPhiStarContrast(hexColor, hexBg, isLightMode)
if current >= minLc {
return hexColor
}
fg := HexToRGB(hexColor)
cf := colorful.Color{R: fg.R, G: fg.G, B: fg.B}
origL, af, bf := cf.Lab()
var darkerResult, lighterResult string
darkerL, lighterL := origL, origL
darkerFound, lighterFound := false, false
step := 0.5
for i := range 120 {
if !darkerFound {
darkerL = math.Max(0, origL-float64(i)*step)
cand := labToHex(darkerL, af, bf)
if DeltaPhiStarContrast(cand, hexBg, isLightMode) >= minLc {
darkerResult = cand
darkerFound = true
}
}
if !lighterFound {
lighterL = math.Min(100, origL+float64(i)*step)
cand := labToHex(lighterL, af, bf)
if DeltaPhiStarContrast(cand, hexBg, isLightMode) >= minLc {
lighterResult = cand
lighterFound = true
}
}
if darkerFound && lighterFound {
break
}
}
if darkerFound && lighterFound {
if math.Abs(darkerL-origL) <= math.Abs(lighterL-origL) {
return darkerResult
}
return lighterResult
}
if darkerFound {
return darkerResult
}
if lighterFound {
return lighterResult
}
return hexColor
}
type PaletteOptions struct { type PaletteOptions struct {
IsLight bool IsLight bool
Background string Background string
@@ -397,29 +369,6 @@ func ensureContrastAuto(hexColor, hexBg string, target float64, opts PaletteOpti
return EnsureContrast(hexColor, hexBg, target, opts.IsLight) return EnsureContrast(hexColor, hexBg, target, opts.IsLight)
} }
func ensureContrastBidirectional(hexColor, hexBg string, target float64, opts PaletteOptions) string {
if opts.UseDPS {
return EnsureContrastDPSBidirectional(hexColor, hexBg, target, opts.IsLight)
}
return EnsureContrast(hexColor, hexBg, target, opts.IsLight)
}
func blendHue(base, target, factor float64) float64 {
diff := target - base
if diff > 0.5 {
diff -= 1.0
} else if diff < -0.5 {
diff += 1.0
}
result := base + diff*factor
if result < 0 {
result += 1.0
} else if result >= 1.0 {
result -= 1.0
}
return result
}
func DeriveContainer(primary string, isLight bool) string { func DeriveContainer(primary string, isLight bool) string {
rgb := HexToRGB(primary) rgb := HexToRGB(primary)
hsv := RGBToHSV(rgb) hsv := RGBToHSV(rgb)
@@ -440,9 +389,6 @@ func GeneratePalette(primaryColor string, opts PaletteOptions) Palette {
rgb := HexToRGB(baseColor) rgb := HexToRGB(baseColor)
hsv := RGBToHSV(rgb) hsv := RGBToHSV(rgb)
pr := HexToRGB(primaryColor)
ph := RGBToHSV(pr)
var palette Palette var palette Palette
var normalTextTarget, secondaryTarget float64 var normalTextTarget, secondaryTarget float64
@@ -464,136 +410,115 @@ func GeneratePalette(primaryColor string, opts PaletteOptions) Palette {
} }
palette.Color0 = NewColorInfo(bgColor) palette.Color0 = NewColorInfo(bgColor)
baseSat := math.Max(ph.S, 0.5) hueShift := (hsv.H - 0.6) * 0.12
baseVal := math.Max(ph.V, 0.5) satBoost := 1.15
redH := blendHue(0.0, ph.H, 0.12) redH := math.Mod(0.0+hueShift+1.0, 1.0)
greenH := blendHue(0.33, ph.H, 0.10) var redColor string
yellowH := blendHue(0.14, ph.H, 0.04) if opts.IsLight {
redColor = RGBToHex(HSVToRGB(HSV{H: redH, S: math.Min(0.80*satBoost, 1.0), V: 0.55}))
palette.Color1 = NewColorInfo(ensureContrastAuto(redColor, bgColor, normalTextTarget, opts))
} else {
redColor = RGBToHex(HSVToRGB(HSV{H: redH, S: math.Min(0.65*satBoost, 1.0), V: 0.80}))
palette.Color1 = NewColorInfo(ensureContrastAuto(redColor, bgColor, normalTextTarget, opts))
}
accentTarget := secondaryTarget * 0.7 greenH := math.Mod(0.33+hueShift+1.0, 1.0)
var greenColor string
if opts.IsLight {
greenColor = RGBToHex(HSVToRGB(HSV{H: greenH, S: math.Min(math.Max(hsv.S*0.9, 0.80)*satBoost, 1.0), V: 0.45}))
palette.Color2 = NewColorInfo(ensureContrastAuto(greenColor, bgColor, normalTextTarget, opts))
} else {
greenColor = RGBToHex(HSVToRGB(HSV{H: greenH, S: math.Min(0.42*satBoost, 1.0), V: 0.84}))
palette.Color2 = NewColorInfo(ensureContrastAuto(greenColor, bgColor, normalTextTarget, opts))
}
yellowH := math.Mod(0.15+hueShift+1.0, 1.0)
var yellowColor string
if opts.IsLight {
yellowColor = RGBToHex(HSVToRGB(HSV{H: yellowH, S: math.Min(0.75*satBoost, 1.0), V: 0.50}))
palette.Color3 = NewColorInfo(ensureContrastAuto(yellowColor, bgColor, normalTextTarget, opts))
} else {
yellowColor = RGBToHex(HSVToRGB(HSV{H: yellowH, S: math.Min(0.38*satBoost, 1.0), V: 0.86}))
palette.Color3 = NewColorInfo(ensureContrastAuto(yellowColor, bgColor, normalTextTarget, opts))
}
var blueColor string
if opts.IsLight {
blueColor = RGBToHex(HSVToRGB(HSV{H: hsv.H, S: math.Max(hsv.S*0.9, 0.7), V: hsv.V * 1.1}))
palette.Color4 = NewColorInfo(ensureContrastAuto(blueColor, bgColor, normalTextTarget, opts))
} else {
blueColor = RGBToHex(HSVToRGB(HSV{H: hsv.H, S: math.Max(hsv.S*0.8, 0.6), V: math.Min(hsv.V*1.6, 1.0)}))
palette.Color4 = NewColorInfo(ensureContrastAuto(blueColor, bgColor, normalTextTarget, opts))
}
magH := hsv.H - 0.03
if magH < 0 {
magH += 1.0
}
var magColor string
hr := HexToRGB(primaryColor)
hh := RGBToHSV(hr)
if opts.IsLight {
magColor = RGBToHex(HSVToRGB(HSV{H: hh.H, S: math.Max(hh.S*0.9, 0.7), V: hh.V * 0.85}))
palette.Color5 = NewColorInfo(ensureContrastAuto(magColor, bgColor, normalTextTarget, opts))
} else {
magColor = RGBToHex(HSVToRGB(HSV{H: hh.H, S: hh.S * 0.8, V: hh.V * 0.75}))
palette.Color5 = NewColorInfo(ensureContrastAuto(magColor, bgColor, normalTextTarget, opts))
}
cyanH := hsv.H + 0.08
if cyanH > 1.0 {
cyanH -= 1.0
}
palette.Color6 = NewColorInfo(ensureContrastAuto(primaryColor, bgColor, normalTextTarget, opts))
if opts.IsLight { if opts.IsLight {
redS := math.Min(baseSat*1.2, 1.0) palette.Color7 = NewColorInfo("#1a1a1a")
redV := baseVal * 0.95 palette.Color8 = NewColorInfo("#2e2e2e")
palette.Color1 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: redH, S: redS, V: redV})), bgColor, normalTextTarget, opts))
greenS := math.Min(baseSat*1.3, 1.0)
greenV := baseVal * 0.75
palette.Color2 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: greenH, S: greenS, V: greenV})), bgColor, normalTextTarget, opts))
yellowS := math.Min(baseSat*1.5, 1.0)
yellowV := math.Min(baseVal*1.2, 1.0)
palette.Color3 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: yellowH, S: yellowS, V: yellowV})), bgColor, accentTarget, opts))
blueS := math.Min(ph.S*1.05, 1.0)
blueV := math.Min(ph.V*1.05, 1.0)
palette.Color4 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: ph.H, S: blueS, V: blueV})), bgColor, normalTextTarget, opts))
// Color5 matches primary_container exactly (light container in light mode)
container5 := DeriveContainer(primaryColor, true)
palette.Color5 = NewColorInfo(container5)
palette.Color6 = NewColorInfo(primaryColor)
gray7S := baseSat * 0.08
gray7V := baseVal * 0.28
palette.Color7 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: hsv.H, S: gray7S, V: gray7V})), bgColor, normalTextTarget, opts))
gray8S := baseSat * 0.05
gray8V := baseVal * 0.85
dimTarget := secondaryTarget * 0.5
palette.Color8 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: hsv.H, S: gray8S, V: gray8V})), bgColor, dimTarget, opts))
brightRedS := math.Min(baseSat*1.0, 1.0)
brightRedV := math.Min(baseVal*1.2, 1.0)
palette.Color9 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: redH, S: brightRedS, V: brightRedV})), bgColor, accentTarget, opts))
brightGreenS := math.Min(baseSat*1.1, 1.0)
brightGreenV := math.Min(baseVal*1.1, 1.0)
palette.Color10 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: greenH, S: brightGreenS, V: brightGreenV})), bgColor, accentTarget, opts))
brightYellowS := math.Min(baseSat*1.4, 1.0)
brightYellowV := math.Min(baseVal*1.3, 1.0)
palette.Color11 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: yellowH, S: brightYellowS, V: brightYellowV})), bgColor, accentTarget, opts))
brightBlueS := math.Min(ph.S*1.1, 1.0)
brightBlueV := math.Min(ph.V*1.15, 1.0)
palette.Color12 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: ph.H, S: brightBlueS, V: brightBlueV})), bgColor, accentTarget, opts))
lightContainer := DeriveContainer(primaryColor, true)
palette.Color13 = NewColorInfo(lightContainer)
brightCyanS := ph.S * 0.5
brightCyanV := math.Min(ph.V*1.3, 1.0)
palette.Color14 = NewColorInfo(RGBToHex(HSVToRGB(HSV{H: ph.H, S: brightCyanS, V: brightCyanV})))
white15S := baseSat * 0.04
white15V := math.Min(baseVal*1.5, 1.0)
palette.Color15 = NewColorInfo(RGBToHex(HSVToRGB(HSV{H: hsv.H, S: white15S, V: white15V})))
} else { } else {
redS := math.Min(baseSat*1.1, 1.0) palette.Color7 = NewColorInfo("#abb2bf")
redV := math.Min(baseVal*1.15, 1.0) palette.Color8 = NewColorInfo("#5c6370")
palette.Color1 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: redH, S: redS, V: redV})), bgColor, normalTextTarget, opts)) }
greenS := math.Min(baseSat*1.0, 1.0) if opts.IsLight {
greenV := math.Min(baseVal*1.0, 1.0) brightRed := RGBToHex(HSVToRGB(HSV{H: redH, S: math.Min(0.70*satBoost, 1.0), V: 0.65}))
palette.Color2 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: greenH, S: greenS, V: greenV})), bgColor, normalTextTarget, opts)) palette.Color9 = NewColorInfo(ensureContrastAuto(brightRed, bgColor, secondaryTarget, opts))
brightGreen := RGBToHex(HSVToRGB(HSV{H: greenH, S: math.Min(math.Max(hsv.S*0.85, 0.75)*satBoost, 1.0), V: 0.55}))
palette.Color10 = NewColorInfo(ensureContrastAuto(brightGreen, bgColor, secondaryTarget, opts))
brightYellow := RGBToHex(HSVToRGB(HSV{H: yellowH, S: math.Min(0.68*satBoost, 1.0), V: 0.60}))
palette.Color11 = NewColorInfo(ensureContrastAuto(brightYellow, bgColor, secondaryTarget, opts))
hr := HexToRGB(primaryColor)
hh := RGBToHSV(hr)
brightBlue := RGBToHex(HSVToRGB(HSV{H: hh.H, S: math.Min(hh.S*1.1, 1.0), V: math.Min(hh.V*1.2, 1.0)}))
palette.Color12 = NewColorInfo(ensureContrastAuto(brightBlue, bgColor, secondaryTarget, opts))
brightMag := RGBToHex(HSVToRGB(HSV{H: magH, S: math.Max(hsv.S*0.9, 0.75), V: math.Min(hsv.V*1.25, 1.0)}))
palette.Color13 = NewColorInfo(ensureContrastAuto(brightMag, bgColor, secondaryTarget, opts))
brightCyan := RGBToHex(HSVToRGB(HSV{H: cyanH, S: math.Max(hsv.S*0.75, 0.65), V: math.Min(hsv.V*1.25, 1.0)}))
palette.Color14 = NewColorInfo(ensureContrastAuto(brightCyan, bgColor, secondaryTarget, opts))
} else {
brightRed := RGBToHex(HSVToRGB(HSV{H: redH, S: math.Min(0.50*satBoost, 1.0), V: 0.88}))
palette.Color9 = NewColorInfo(ensureContrastAuto(brightRed, bgColor, secondaryTarget, opts))
brightGreen := RGBToHex(HSVToRGB(HSV{H: greenH, S: math.Min(0.35*satBoost, 1.0), V: 0.88}))
palette.Color10 = NewColorInfo(ensureContrastAuto(brightGreen, bgColor, secondaryTarget, opts))
brightYellow := RGBToHex(HSVToRGB(HSV{H: yellowH, S: math.Min(0.30*satBoost, 1.0), V: 0.91}))
palette.Color11 = NewColorInfo(ensureContrastAuto(brightYellow, bgColor, secondaryTarget, opts))
brightBlue := retoneToL(primaryColor, 85.0)
palette.Color12 = NewColorInfo(brightBlue)
brightMag := RGBToHex(HSVToRGB(HSV{H: magH, S: math.Max(hsv.S*0.7, 0.6), V: math.Min(hsv.V*1.3, 0.9)}))
palette.Color13 = NewColorInfo(ensureContrastAuto(brightMag, bgColor, secondaryTarget, opts))
brightCyanH := hsv.H + 0.02
if brightCyanH > 1.0 {
brightCyanH -= 1.0
}
brightCyan := RGBToHex(HSVToRGB(HSV{H: brightCyanH, S: math.Max(hsv.S*0.6, 0.5), V: math.Min(hsv.V*1.2, 0.85)}))
palette.Color14 = NewColorInfo(ensureContrastAuto(brightCyan, bgColor, secondaryTarget, opts))
}
yellowS := math.Min(baseSat*1.1, 1.0) if opts.IsLight {
yellowV := math.Min(baseVal*1.25, 1.0) palette.Color15 = NewColorInfo("#1a1a1a")
palette.Color3 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: yellowH, S: yellowS, V: yellowV})), bgColor, normalTextTarget, opts)) } else {
palette.Color15 = NewColorInfo("#ffffff")
// Slightly more saturated variant of primary
blueS := math.Min(ph.S*1.2, 1.0)
blueV := ph.V * 0.95
palette.Color4 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: ph.H, S: blueS, V: blueV})), bgColor, normalTextTarget, opts))
// Color5 matches primary_container exactly (dark container in dark mode)
darkContainer := DeriveContainer(primaryColor, false)
palette.Color5 = NewColorInfo(darkContainer)
palette.Color6 = NewColorInfo(primaryColor)
gray7S := baseSat * 0.12
gray7V := math.Min(baseVal*1.05, 1.0)
palette.Color7 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: hsv.H, S: gray7S, V: gray7V})), bgColor, normalTextTarget, opts))
gray8S := baseSat * 0.15
gray8V := baseVal * 0.65
palette.Color8 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: hsv.H, S: gray8S, V: gray8V})), bgColor, secondaryTarget, opts))
brightRedS := math.Min(baseSat*0.75, 1.0)
brightRedV := math.Min(baseVal*1.35, 1.0)
palette.Color9 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: redH, S: brightRedS, V: brightRedV})), bgColor, accentTarget, opts))
brightGreenS := math.Min(baseSat*0.7, 1.0)
brightGreenV := math.Min(baseVal*1.2, 1.0)
palette.Color10 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: greenH, S: brightGreenS, V: brightGreenV})), bgColor, accentTarget, opts))
brightYellowS := math.Min(baseSat*0.7, 1.0)
brightYellowV := math.Min(baseVal*1.5, 1.0)
palette.Color11 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: yellowH, S: brightYellowS, V: brightYellowV})), bgColor, accentTarget, opts))
// Create a gradient of primary variants: Color12 -> Color13 -> Color14 -> Color15 (near white)
// Color12: Start of the lighter gradient - slightly desaturated
brightBlueS := ph.S * 0.85
brightBlueV := math.Min(ph.V*1.1, 1.0)
palette.Color12 = NewColorInfo(ensureContrastBidirectional(RGBToHex(HSVToRGB(HSV{H: ph.H, S: brightBlueS, V: brightBlueV})), bgColor, accentTarget, opts))
// Medium-high saturation pastel primary
color13S := ph.S * 0.7
color13V := math.Min(ph.V*1.3, 1.0)
palette.Color13 = NewColorInfo(RGBToHex(HSVToRGB(HSV{H: ph.H, S: color13S, V: color13V})))
// Lower saturation, lighter variant
color14S := ph.S * 0.45
color14V := math.Min(ph.V*1.4, 1.0)
palette.Color14 = NewColorInfo(RGBToHex(HSVToRGB(HSV{H: ph.H, S: color14S, V: color14V})))
white15S := baseSat * 0.05
white15V := math.Min(baseVal*1.45, 1.0)
palette.Color15 = NewColorInfo(ensureContrastAuto(RGBToHex(HSVToRGB(HSV{H: hsv.H, S: white15S, V: white15V})), bgColor, normalTextTarget, opts))
} }
return palette return palette

View File

@@ -366,19 +366,10 @@ func TestGeneratePalette(t *testing.T) {
t.Errorf("Light mode background = %s, expected #f8f8f8", result.Color0.Hex) t.Errorf("Light mode background = %s, expected #f8f8f8", result.Color0.Hex)
} }
// Color15 is now derived from primary, so just verify it's a valid color if tt.opts.IsLight && result.Color15.Hex != "#1a1a1a" {
// and has appropriate luminance for the mode (now theme-tinted, not pure white/black) t.Errorf("Light mode foreground = %s, expected #1a1a1a", result.Color15.Hex)
color15Lum := Luminance(result.Color15.Hex) } else if !tt.opts.IsLight && result.Color15.Hex != "#ffffff" {
if tt.opts.IsLight { t.Errorf("Dark mode foreground = %s, expected #ffffff", result.Color15.Hex)
// Light mode: Color15 should still be relatively light
if color15Lum < 0.5 {
t.Errorf("Light mode Color15 = %s (lum %.2f) is too dark", result.Color15.Hex, color15Lum)
}
} else {
// Dark mode: Color15 should be light (but may have theme tint, so lower threshold)
if color15Lum < 0.5 {
t.Errorf("Dark mode Color15 = %s (lum %.2f) is too dark", result.Color15.Hex, color15Lum)
}
} }
}) })
} }
@@ -588,10 +579,6 @@ func TestGeneratePaletteWithDPS(t *testing.T) {
bgColor := result.Color0.Hex bgColor := result.Color0.Hex
for i := 1; i < 8; i++ { for i := 1; i < 8; i++ {
// Skip Color5 (container) and Color6 (exact primary) - intentionally not contrast-adjusted
if i == 5 || i == 6 {
continue
}
lc := DeltaPhiStarContrast(colors[i].Hex, bgColor, tt.opts.IsLight) lc := DeltaPhiStarContrast(colors[i].Hex, bgColor, tt.opts.IsLight)
minLc := 30.0 minLc := 30.0
if lc < minLc && lc > 0 { if lc < minLc && lc > 0 {

View File

@@ -1,170 +0,0 @@
package notify
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"syscall"
"github.com/godbus/dbus/v5"
)
const (
notifyDest = "org.freedesktop.Notifications"
notifyPath = "/org/freedesktop/Notifications"
notifyInterface = "org.freedesktop.Notifications"
)
type Notification struct {
AppName string
Icon string
Summary string
Body string
FilePath string
Timeout int32
}
func Send(n Notification) error {
conn, err := dbus.SessionBus()
if err != nil {
return fmt.Errorf("dbus session failed: %w", err)
}
if n.AppName == "" {
n.AppName = "DMS"
}
if n.Timeout == 0 {
n.Timeout = 5000
}
var actions []string
if n.FilePath != "" {
actions = []string{
"open", "Open",
"folder", "Open Folder",
}
}
hints := map[string]dbus.Variant{}
if n.FilePath != "" {
hints["image_path"] = dbus.MakeVariant(n.FilePath)
}
obj := conn.Object(notifyDest, notifyPath)
call := obj.Call(
notifyInterface+".Notify",
0,
n.AppName,
uint32(0),
n.Icon,
n.Summary,
n.Body,
actions,
hints,
n.Timeout,
)
if call.Err != nil {
return fmt.Errorf("notify call failed: %w", call.Err)
}
var notificationID uint32
if err := call.Store(&notificationID); err != nil {
return fmt.Errorf("failed to get notification id: %w", err)
}
if len(actions) > 0 && n.FilePath != "" {
spawnActionListener(notificationID, n.FilePath)
}
return nil
}
func spawnActionListener(notificationID uint32, filePath string) {
exe, err := os.Executable()
if err != nil {
return
}
cmd := exec.Command(exe, "notify-action-generic", fmt.Sprintf("%d", notificationID), filePath)
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
cmd.Start()
}
func RunActionListener(args []string) {
if len(args) < 2 {
return
}
notificationID, err := strconv.ParseUint(args[0], 10, 32)
if err != nil {
return
}
filePath := args[1]
conn, err := dbus.SessionBus()
if err != nil {
return
}
if err := conn.AddMatchSignal(
dbus.WithMatchObjectPath(notifyPath),
dbus.WithMatchInterface(notifyInterface),
); err != nil {
return
}
signals := make(chan *dbus.Signal, 10)
conn.Signal(signals)
for sig := range signals {
switch sig.Name {
case notifyInterface + ".ActionInvoked":
if len(sig.Body) < 2 {
continue
}
id, ok := sig.Body[0].(uint32)
if !ok || id != uint32(notificationID) {
continue
}
action, ok := sig.Body[1].(string)
if !ok {
continue
}
handleAction(action, filePath)
return
case notifyInterface + ".NotificationClosed":
if len(sig.Body) < 1 {
continue
}
id, ok := sig.Body[0].(uint32)
if !ok || id != uint32(notificationID) {
continue
}
return
}
}
}
func handleAction(action, filePath string) {
switch action {
case "open", "default":
openPath(filePath)
case "folder":
openPath(filepath.Dir(filePath))
}
}
func openPath(path string) {
cmd := exec.Command("xdg-open", path)
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
cmd.Start()
}

View File

@@ -7,7 +7,6 @@ import (
"time" "time"
"github.com/AvengeMedia/DankMaterialShell/core/internal/log" "github.com/AvengeMedia/DankMaterialShell/core/internal/log"
"github.com/AvengeMedia/DankMaterialShell/core/pkg/dbusutil"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
) )
@@ -111,15 +110,17 @@ func (m *Manager) updateAdapterState() error {
if err != nil { if err != nil {
return err return err
} }
powered, _ := poweredVar.Value().(bool)
discoveringVar, err := obj.GetProperty(adapter1Iface + ".Discovering") discoveringVar, err := obj.GetProperty(adapter1Iface + ".Discovering")
if err != nil { if err != nil {
return err return err
} }
discovering, _ := discoveringVar.Value().(bool)
m.stateMutex.Lock() m.stateMutex.Lock()
m.state.Powered = dbusutil.AsOr(poweredVar, false) m.state.Powered = powered
m.state.Discovering = dbusutil.AsOr(discoveringVar, false) m.state.Discovering = discovering
m.stateMutex.Unlock() m.stateMutex.Unlock()
return nil return nil
@@ -168,20 +169,65 @@ func (m *Manager) updateDevices() error {
} }
func (m *Manager) deviceFromProps(path string, props map[string]dbus.Variant) Device { func (m *Manager) deviceFromProps(path string, props map[string]dbus.Variant) Device {
return Device{ dev := Device{Path: path}
Path: path,
Address: dbusutil.GetOr(props, "Address", ""), if v, ok := props["Address"]; ok {
Name: dbusutil.GetOr(props, "Name", ""), if addr, ok := v.Value().(string); ok {
Alias: dbusutil.GetOr(props, "Alias", ""), dev.Address = addr
Paired: dbusutil.GetOr(props, "Paired", false), }
Trusted: dbusutil.GetOr(props, "Trusted", false),
Blocked: dbusutil.GetOr(props, "Blocked", false),
Connected: dbusutil.GetOr(props, "Connected", false),
Class: dbusutil.GetOr(props, "Class", uint32(0)),
Icon: dbusutil.GetOr(props, "Icon", ""),
RSSI: dbusutil.GetOr(props, "RSSI", int16(0)),
LegacyPairing: dbusutil.GetOr(props, "LegacyPairing", false),
} }
if v, ok := props["Name"]; ok {
if name, ok := v.Value().(string); ok {
dev.Name = name
}
}
if v, ok := props["Alias"]; ok {
if alias, ok := v.Value().(string); ok {
dev.Alias = alias
}
}
if v, ok := props["Paired"]; ok {
if paired, ok := v.Value().(bool); ok {
dev.Paired = paired
}
}
if v, ok := props["Trusted"]; ok {
if trusted, ok := v.Value().(bool); ok {
dev.Trusted = trusted
}
}
if v, ok := props["Blocked"]; ok {
if blocked, ok := v.Value().(bool); ok {
dev.Blocked = blocked
}
}
if v, ok := props["Connected"]; ok {
if connected, ok := v.Value().(bool); ok {
dev.Connected = connected
}
}
if v, ok := props["Class"]; ok {
if class, ok := v.Value().(uint32); ok {
dev.Class = class
}
}
if v, ok := props["Icon"]; ok {
if icon, ok := v.Value().(string); ok {
dev.Icon = icon
}
}
if v, ok := props["RSSI"]; ok {
if rssi, ok := v.Value().(int16); ok {
dev.RSSI = rssi
}
}
if v, ok := props["LegacyPairing"]; ok {
if legacy, ok := v.Value().(bool); ok {
dev.LegacyPairing = legacy
}
}
return dev
} }
func (m *Manager) startAgent() error { func (m *Manager) startAgent() error {
@@ -282,13 +328,17 @@ func (m *Manager) handleAdapterPropertiesChanged(changed map[string]dbus.Variant
m.stateMutex.Lock() m.stateMutex.Lock()
dirty := false dirty := false
if powered, ok := dbusutil.Get[bool](changed, "Powered"); ok { if v, ok := changed["Powered"]; ok {
m.state.Powered = powered if powered, ok := v.Value().(bool); ok {
dirty = true m.state.Powered = powered
dirty = true
}
} }
if discovering, ok := dbusutil.Get[bool](changed, "Discovering"); ok { if v, ok := changed["Discovering"]; ok {
m.state.Discovering = discovering if discovering, ok := v.Value().(bool); ok {
dirty = true m.state.Discovering = discovering
dirty = true
}
} }
m.stateMutex.Unlock() m.stateMutex.Unlock()
@@ -299,28 +349,31 @@ func (m *Manager) handleAdapterPropertiesChanged(changed map[string]dbus.Variant
} }
func (m *Manager) handleDevicePropertiesChanged(path dbus.ObjectPath, changed map[string]dbus.Variant) { func (m *Manager) handleDevicePropertiesChanged(path dbus.ObjectPath, changed map[string]dbus.Variant) {
paired, hasPaired := dbusutil.Get[bool](changed, "Paired") pairedVar, hasPaired := changed["Paired"]
_, hasConnected := changed["Connected"] _, hasConnected := changed["Connected"]
_, hasTrusted := changed["Trusted"] _, hasTrusted := changed["Trusted"]
if hasPaired { if hasPaired {
devicePath := string(path) devicePath := string(path)
if paired { if paired, ok := pairedVar.Value().(bool); ok {
_, wasPending := m.pendingPairings.LoadAndDelete(devicePath) if paired {
if wasPending { _, wasPending := m.pendingPairings.LoadAndDelete(devicePath)
select {
case m.eventQueue <- func() { if wasPending {
time.Sleep(300 * time.Millisecond) select {
log.Infof("[Bluetooth] Auto-connecting newly paired device: %s", devicePath) case m.eventQueue <- func() {
if err := m.ConnectDevice(devicePath); err != nil { time.Sleep(300 * time.Millisecond)
log.Warnf("[Bluetooth] Auto-connect failed: %v", err) log.Infof("[Bluetooth] Auto-connecting newly paired device: %s", devicePath)
if err := m.ConnectDevice(devicePath); err != nil {
log.Warnf("[Bluetooth] Auto-connect failed: %v", err)
}
}:
default:
} }
}:
default:
} }
} else {
m.pendingPairings.Delete(devicePath)
} }
} else {
m.pendingPairings.Delete(devicePath)
} }
} }

View File

@@ -37,14 +37,6 @@ func HandleRequest(conn net.Conn, req models.Request, m *Manager) {
handleSetConfig(conn, req, m) handleSetConfig(conn, req, m)
case "clipboard.store": case "clipboard.store":
handleStore(conn, req, m) handleStore(conn, req, m)
case "clipboard.pinEntry":
handlePinEntry(conn, req, m)
case "clipboard.unpinEntry":
handleUnpinEntry(conn, req, m)
case "clipboard.getPinnedEntries":
handleGetPinnedEntries(conn, req, m)
case "clipboard.getPinnedCount":
handleGetPinnedCount(conn, req, m)
default: default:
models.RespondError(conn, req.ID, "unknown method: "+req.Method) models.RespondError(conn, req.ID, "unknown method: "+req.Method)
} }
@@ -213,9 +205,6 @@ func handleSetConfig(conn net.Conn, req models.Request, m *Manager) {
if v, ok := models.Get[bool](req, "disabled"); ok { if v, ok := models.Get[bool](req, "disabled"); ok {
cfg.Disabled = v cfg.Disabled = v
} }
if v, ok := models.Get[float64](req, "maxPinned"); ok {
cfg.MaxPinned = int(v)
}
if err := m.SetConfig(cfg); err != nil { if err := m.SetConfig(cfg); err != nil {
models.RespondError(conn, req.ID, err.Error()) models.RespondError(conn, req.ID, err.Error())
@@ -241,43 +230,3 @@ func handleStore(conn net.Conn, req models.Request, m *Manager) {
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "stored"}) models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "stored"})
} }
func handlePinEntry(conn net.Conn, req models.Request, m *Manager) {
id, err := params.Int(req.Params, "id")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
if err := m.PinEntry(uint64(id)); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "entry pinned"})
}
func handleUnpinEntry(conn net.Conn, req models.Request, m *Manager) {
id, err := params.Int(req.Params, "id")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
if err := m.UnpinEntry(uint64(id)); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "entry unpinned"})
}
func handleGetPinnedEntries(conn net.Conn, req models.Request, m *Manager) {
pinned := m.GetPinnedEntries()
models.Respond(conn, req.ID, pinned)
}
func handleGetPinnedCount(conn net.Conn, req models.Request, m *Manager) {
count := m.GetPinnedCount()
models.Respond(conn, req.ID, map[string]int{"count": count})
}

View File

@@ -389,11 +389,7 @@ func (m *Manager) trimLengthInTx(b *bolt.Bucket) error {
} }
c := b.Cursor() c := b.Cursor()
var count int var count int
for k, v := c.Last(); k != nil; k, v = c.Prev() { for k, _ := c.Last(); k != nil; k, _ = c.Prev() {
entry, err := decodeEntry(v)
if err == nil && entry.Pinned {
continue
}
if count < m.config.MaxHistory { if count < m.config.MaxHistory {
count++ count++
continue continue
@@ -423,11 +419,6 @@ func encodeEntry(e Entry) ([]byte, error) {
buf.WriteByte(0) buf.WriteByte(0)
} }
binary.Write(buf, binary.BigEndian, e.Hash) binary.Write(buf, binary.BigEndian, e.Hash)
if e.Pinned {
buf.WriteByte(1)
} else {
buf.WriteByte(0)
}
return buf.Bytes(), nil return buf.Bytes(), nil
} }
@@ -471,12 +462,6 @@ func decodeEntry(data []byte) (Entry, error) {
binary.Read(buf, binary.BigEndian, &e.Hash) binary.Read(buf, binary.BigEndian, &e.Hash)
} }
if buf.Len() >= 1 {
var pinnedByte byte
binary.Read(buf, binary.BigEndian, &pinnedByte)
e.Pinned = pinnedByte == 1
}
return e, nil return e, nil
} }
@@ -750,54 +735,19 @@ func (m *Manager) ClearHistory() {
return return
} }
// Delete only non-pinned entries
if err := m.db.Update(func(tx *bolt.Tx) error { if err := m.db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("clipboard")) if err := tx.DeleteBucket([]byte("clipboard")); err != nil {
if b == nil { return err
return nil
} }
_, err := tx.CreateBucket([]byte("clipboard"))
var toDelete [][]byte return err
c := b.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
entry, err := decodeEntry(v)
if err != nil || !entry.Pinned {
toDelete = append(toDelete, k)
}
}
for _, k := range toDelete {
if err := b.Delete(k); err != nil {
return err
}
}
return nil
}); err != nil { }); err != nil {
log.Errorf("Failed to clear clipboard history: %v", err) log.Errorf("Failed to clear clipboard history: %v", err)
return return
} }
pinnedCount := 0 if err := m.compactDB(); err != nil {
if err := m.db.View(func(tx *bolt.Tx) error { log.Errorf("Failed to compact database: %v", err)
b := tx.Bucket([]byte("clipboard"))
if b != nil {
c := b.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
entry, _ := decodeEntry(v)
if entry.Pinned {
pinnedCount++
}
}
}
return nil
}); err != nil {
log.Errorf("Failed to count pinned entries: %v", err)
}
if pinnedCount == 0 {
if err := m.compactDB(); err != nil {
log.Errorf("Failed to compact database: %v", err)
}
} }
m.updateState() m.updateState()
@@ -1010,10 +960,6 @@ func (m *Manager) clearOldEntries(days int) error {
if err != nil { if err != nil {
continue continue
} }
// Skip pinned entries
if entry.Pinned {
continue
}
if entry.Timestamp.Before(cutoff) { if entry.Timestamp.Before(cutoff) {
toDelete = append(toDelete, k) toDelete = append(toDelete, k)
} }
@@ -1304,153 +1250,3 @@ func (m *Manager) StoreData(data []byte, mimeType string) error {
return nil return nil
} }
func (m *Manager) PinEntry(id uint64) error {
if m.db == nil {
return fmt.Errorf("database not available")
}
// Check pinned count
cfg := m.getConfig()
pinnedCount := 0
if err := m.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("clipboard"))
if b == nil {
return nil
}
c := b.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
entry, err := decodeEntry(v)
if err == nil && entry.Pinned {
pinnedCount++
}
}
return nil
}); err != nil {
log.Errorf("Failed to count pinned entries: %v", err)
}
if pinnedCount >= cfg.MaxPinned {
return fmt.Errorf("maximum pinned entries reached (%d)", cfg.MaxPinned)
}
err := m.db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("clipboard"))
v := b.Get(itob(id))
if v == nil {
return fmt.Errorf("entry not found")
}
entry, err := decodeEntry(v)
if err != nil {
return err
}
entry.Pinned = true
encoded, err := encodeEntry(entry)
if err != nil {
return err
}
return b.Put(itob(id), encoded)
})
if err == nil {
m.updateState()
m.notifySubscribers()
}
return err
}
func (m *Manager) UnpinEntry(id uint64) error {
if m.db == nil {
return fmt.Errorf("database not available")
}
err := m.db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("clipboard"))
v := b.Get(itob(id))
if v == nil {
return fmt.Errorf("entry not found")
}
entry, err := decodeEntry(v)
if err != nil {
return err
}
entry.Pinned = false
encoded, err := encodeEntry(entry)
if err != nil {
return err
}
return b.Put(itob(id), encoded)
})
if err == nil {
m.updateState()
m.notifySubscribers()
}
return err
}
func (m *Manager) GetPinnedEntries() []Entry {
if m.db == nil {
return nil
}
var pinned []Entry
if err := m.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("clipboard"))
if b == nil {
return nil
}
c := b.Cursor()
for k, v := c.Last(); k != nil; k, v = c.Prev() {
entry, err := decodeEntry(v)
if err != nil {
continue
}
if entry.Pinned {
entry.Data = nil
pinned = append(pinned, entry)
}
}
return nil
}); err != nil {
log.Errorf("Failed to get pinned entries: %v", err)
}
return pinned
}
func (m *Manager) GetPinnedCount() int {
if m.db == nil {
return 0
}
count := 0
if err := m.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("clipboard"))
if b == nil {
return nil
}
c := b.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
entry, err := decodeEntry(v)
if err == nil && entry.Pinned {
count++
}
}
return nil
}); err != nil {
log.Errorf("Failed to count pinned entries: %v", err)
}
return count
}

View File

@@ -19,7 +19,6 @@ type Config struct {
AutoClearDays int `json:"autoClearDays"` AutoClearDays int `json:"autoClearDays"`
ClearAtStartup bool `json:"clearAtStartup"` ClearAtStartup bool `json:"clearAtStartup"`
Disabled bool `json:"disabled"` Disabled bool `json:"disabled"`
MaxPinned int `json:"maxPinned"`
} }
func DefaultConfig() Config { func DefaultConfig() Config {
@@ -28,7 +27,6 @@ func DefaultConfig() Config {
MaxEntrySize: 5 * 1024 * 1024, MaxEntrySize: 5 * 1024 * 1024,
AutoClearDays: 0, AutoClearDays: 0,
ClearAtStartup: false, ClearAtStartup: false,
MaxPinned: 25,
} }
} }
@@ -102,7 +100,6 @@ type Entry struct {
Timestamp time.Time `json:"timestamp"` Timestamp time.Time `json:"timestamp"`
IsImage bool `json:"isImage"` IsImage bool `json:"isImage"`
Hash uint64 `json:"hash,omitempty"` Hash uint64 `json:"hash,omitempty"`
Pinned bool `json:"pinned"`
} }
type State struct { type State struct {

View File

@@ -1,237 +0,0 @@
package dbus
import (
"fmt"
"net"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/params"
)
type objectParams struct {
bus string
dest string
path string
iface string
}
func extractObjectParams(p map[string]any, requirePath bool) (objectParams, error) {
bus, err := params.String(p, "bus")
if err != nil {
return objectParams{}, err
}
dest, err := params.String(p, "dest")
if err != nil {
return objectParams{}, err
}
var path string
if requirePath {
path, err = params.String(p, "path")
if err != nil {
return objectParams{}, err
}
} else {
path = params.StringOpt(p, "path", "/")
}
iface, err := params.String(p, "interface")
if err != nil {
return objectParams{}, err
}
return objectParams{bus: bus, dest: dest, path: path, iface: iface}, nil
}
func HandleRequest(conn net.Conn, req models.Request, m *Manager, clientID string) {
switch req.Method {
case "dbus.call":
handleCall(conn, req, m)
case "dbus.getProperty":
handleGetProperty(conn, req, m)
case "dbus.setProperty":
handleSetProperty(conn, req, m)
case "dbus.getAllProperties":
handleGetAllProperties(conn, req, m)
case "dbus.introspect":
handleIntrospect(conn, req, m)
case "dbus.listNames":
handleListNames(conn, req, m)
case "dbus.subscribe":
handleSubscribe(conn, req, m, clientID)
case "dbus.unsubscribe":
handleUnsubscribe(conn, req, m)
default:
models.RespondError(conn, req.ID, fmt.Sprintf("unknown method: %s", req.Method))
}
}
func handleCall(conn net.Conn, req models.Request, m *Manager) {
op, err := extractObjectParams(req.Params, true)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
method, err := params.String(req.Params, "method")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
var args []any
if argsRaw, ok := params.Any(req.Params, "args"); ok {
if argsSlice, ok := argsRaw.([]any); ok {
args = argsSlice
}
}
result, err := m.Call(op.bus, op.dest, op.path, op.iface, method, args)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, result)
}
func handleGetProperty(conn net.Conn, req models.Request, m *Manager) {
op, err := extractObjectParams(req.Params, true)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
property, err := params.String(req.Params, "property")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
result, err := m.GetProperty(op.bus, op.dest, op.path, op.iface, property)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, result)
}
func handleSetProperty(conn net.Conn, req models.Request, m *Manager) {
op, err := extractObjectParams(req.Params, true)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
property, err := params.String(req.Params, "property")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
value, ok := params.Any(req.Params, "value")
if !ok {
models.RespondError(conn, req.ID, "missing 'value' parameter")
return
}
if err := m.SetProperty(op.bus, op.dest, op.path, op.iface, property, value); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true})
}
func handleGetAllProperties(conn net.Conn, req models.Request, m *Manager) {
op, err := extractObjectParams(req.Params, true)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
result, err := m.GetAllProperties(op.bus, op.dest, op.path, op.iface)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, result)
}
func handleIntrospect(conn net.Conn, req models.Request, m *Manager) {
bus, err := params.String(req.Params, "bus")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
dest, err := params.String(req.Params, "dest")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
path := params.StringOpt(req.Params, "path", "/")
result, err := m.Introspect(bus, dest, path)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, result)
}
func handleListNames(conn net.Conn, req models.Request, m *Manager) {
bus, err := params.String(req.Params, "bus")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
result, err := m.ListNames(bus)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, result)
}
func handleSubscribe(conn net.Conn, req models.Request, m *Manager, clientID string) {
bus, err := params.String(req.Params, "bus")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
sender := params.StringOpt(req.Params, "sender", "")
path := params.StringOpt(req.Params, "path", "")
iface := params.StringOpt(req.Params, "interface", "")
member := params.StringOpt(req.Params, "member", "")
result, err := m.Subscribe(clientID, bus, sender, path, iface, member)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, result)
}
func handleUnsubscribe(conn net.Conn, req models.Request, m *Manager) {
subID, err := params.String(req.Params, "subscriptionId")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
if err := m.Unsubscribe(subID); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true})
}

View File

@@ -1,362 +0,0 @@
package dbus
import (
"crypto/rand"
"encoding/hex"
"fmt"
"strings"
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
"github.com/AvengeMedia/DankMaterialShell/core/pkg/dbusutil"
"github.com/godbus/dbus/v5"
)
func NewManager() (*Manager, error) {
systemConn, err := dbus.ConnectSystemBus()
if err != nil {
return nil, fmt.Errorf("failed to connect to system bus: %w", err)
}
sessionConn, err := dbus.ConnectSessionBus()
if err != nil {
systemConn.Close()
return nil, fmt.Errorf("failed to connect to session bus: %w", err)
}
m := &Manager{
systemConn: systemConn,
sessionConn: sessionConn,
}
go m.processSystemSignals()
go m.processSessionSignals()
return m, nil
}
func (m *Manager) getConn(bus string) (*dbus.Conn, error) {
switch bus {
case "system":
if m.systemConn == nil {
return nil, fmt.Errorf("system bus not connected")
}
return m.systemConn, nil
case "session":
if m.sessionConn == nil {
return nil, fmt.Errorf("session bus not connected")
}
return m.sessionConn, nil
default:
return nil, fmt.Errorf("invalid bus: %s (must be 'system' or 'session')", bus)
}
}
func (m *Manager) Call(bus, dest, path, iface, method string, args []any) (*CallResult, error) {
conn, err := m.getConn(bus)
if err != nil {
return nil, err
}
obj := conn.Object(dest, dbus.ObjectPath(path))
fullMethod := iface + "." + method
call := obj.Call(fullMethod, 0, args...)
if call.Err != nil {
return nil, fmt.Errorf("dbus call failed: %w", call.Err)
}
return &CallResult{Values: call.Body}, nil
}
func (m *Manager) GetProperty(bus, dest, path, iface, property string) (*PropertyResult, error) {
conn, err := m.getConn(bus)
if err != nil {
return nil, err
}
obj := conn.Object(dest, dbus.ObjectPath(path))
var variant dbus.Variant
err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, iface, property).Store(&variant)
if err != nil {
return nil, fmt.Errorf("failed to get property: %w", err)
}
return &PropertyResult{Value: dbusutil.Normalize(variant.Value())}, nil
}
func (m *Manager) SetProperty(bus, dest, path, iface, property string, value any) error {
conn, err := m.getConn(bus)
if err != nil {
return err
}
obj := conn.Object(dest, dbus.ObjectPath(path))
call := obj.Call("org.freedesktop.DBus.Properties.Set", 0, iface, property, dbus.MakeVariant(value))
if call.Err != nil {
return fmt.Errorf("failed to set property: %w", call.Err)
}
return nil
}
func (m *Manager) GetAllProperties(bus, dest, path, iface string) (map[string]any, error) {
conn, err := m.getConn(bus)
if err != nil {
return nil, err
}
obj := conn.Object(dest, dbus.ObjectPath(path))
var props map[string]dbus.Variant
err = obj.Call("org.freedesktop.DBus.Properties.GetAll", 0, iface).Store(&props)
if err != nil {
return nil, fmt.Errorf("failed to get properties: %w", err)
}
result := make(map[string]any)
for k, v := range props {
result[k] = dbusutil.Normalize(v.Value())
}
return result, nil
}
func (m *Manager) Introspect(bus, dest, path string) (*IntrospectResult, error) {
conn, err := m.getConn(bus)
if err != nil {
return nil, err
}
obj := conn.Object(dest, dbus.ObjectPath(path))
var xml string
err = obj.Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&xml)
if err != nil {
return nil, fmt.Errorf("failed to introspect: %w", err)
}
return &IntrospectResult{XML: xml}, nil
}
func (m *Manager) ListNames(bus string) (*ListNamesResult, error) {
conn, err := m.getConn(bus)
if err != nil {
return nil, err
}
var names []string
err = conn.BusObject().Call("org.freedesktop.DBus.ListNames", 0).Store(&names)
if err != nil {
return nil, fmt.Errorf("failed to list names: %w", err)
}
return &ListNamesResult{Names: names}, nil
}
func (m *Manager) Subscribe(clientID, bus, sender, path, iface, member string) (*SubscribeResult, error) {
conn, err := m.getConn(bus)
if err != nil {
return nil, err
}
subID := generateSubscriptionID()
parts := []string{"type='signal'"}
if sender != "" {
parts = append(parts, fmt.Sprintf("sender='%s'", sender))
}
if path != "" {
parts = append(parts, fmt.Sprintf("path='%s'", path))
}
if iface != "" {
parts = append(parts, fmt.Sprintf("interface='%s'", iface))
}
if member != "" {
parts = append(parts, fmt.Sprintf("member='%s'", member))
}
matchRule := strings.Join(parts, ",")
call := conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, matchRule)
if call.Err != nil {
return nil, fmt.Errorf("failed to add match rule: %w", call.Err)
}
sub := &signalSubscription{
Bus: bus,
Sender: sender,
Path: path,
Interface: iface,
Member: member,
ClientID: clientID,
}
m.subscriptions.Store(subID, sub)
log.Debugf("dbus: subscribed %s to %s", subID, matchRule)
return &SubscribeResult{SubscriptionID: subID}, nil
}
func (m *Manager) Unsubscribe(subID string) error {
sub, ok := m.subscriptions.LoadAndDelete(subID)
if !ok {
return fmt.Errorf("subscription not found: %s", subID)
}
conn, err := m.getConn(sub.Bus)
if err != nil {
return err
}
parts := []string{"type='signal'"}
if sub.Sender != "" {
parts = append(parts, fmt.Sprintf("sender='%s'", sub.Sender))
}
if sub.Path != "" {
parts = append(parts, fmt.Sprintf("path='%s'", sub.Path))
}
if sub.Interface != "" {
parts = append(parts, fmt.Sprintf("interface='%s'", sub.Interface))
}
if sub.Member != "" {
parts = append(parts, fmt.Sprintf("member='%s'", sub.Member))
}
matchRule := strings.Join(parts, ",")
call := conn.BusObject().Call("org.freedesktop.DBus.RemoveMatch", 0, matchRule)
if call.Err != nil {
log.Warnf("dbus: failed to remove match rule: %v", call.Err)
}
log.Debugf("dbus: unsubscribed %s", subID)
return nil
}
func (m *Manager) UnsubscribeClient(clientID string) {
var toDelete []string
m.subscriptions.Range(func(subID string, sub *signalSubscription) bool {
if sub.ClientID == clientID {
toDelete = append(toDelete, subID)
}
return true
})
for _, subID := range toDelete {
if err := m.Unsubscribe(subID); err != nil {
log.Warnf("dbus: failed to unsubscribe %s: %v", subID, err)
}
}
}
func (m *Manager) SubscribeSignals(clientID string) chan SignalEvent {
ch := make(chan SignalEvent, 64)
existing, loaded := m.signalSubscribers.LoadOrStore(clientID, ch)
if loaded {
return existing
}
return ch
}
func (m *Manager) UnsubscribeSignals(clientID string) {
if ch, ok := m.signalSubscribers.LoadAndDelete(clientID); ok {
close(ch)
}
m.UnsubscribeClient(clientID)
}
func (m *Manager) processSystemSignals() {
if m.systemConn == nil {
return
}
ch := make(chan *dbus.Signal, 256)
m.systemConn.Signal(ch)
for sig := range ch {
m.dispatchSignal("system", sig)
}
}
func (m *Manager) processSessionSignals() {
if m.sessionConn == nil {
return
}
ch := make(chan *dbus.Signal, 256)
m.sessionConn.Signal(ch)
for sig := range ch {
m.dispatchSignal("session", sig)
}
}
func (m *Manager) dispatchSignal(bus string, sig *dbus.Signal) {
path := string(sig.Path)
iface := ""
member := sig.Name
if idx := strings.LastIndex(sig.Name, "."); idx != -1 {
iface = sig.Name[:idx]
member = sig.Name[idx+1:]
}
m.subscriptions.Range(func(subID string, sub *signalSubscription) bool {
if sub.Bus != bus {
return true
}
if sub.Path != "" && sub.Path != path && !strings.HasPrefix(path, sub.Path) {
return true
}
if sub.Interface != "" && sub.Interface != iface {
return true
}
if sub.Member != "" && sub.Member != member {
return true
}
event := SignalEvent{
SubscriptionID: subID,
Sender: sig.Sender,
Path: path,
Interface: iface,
Member: member,
Body: dbusutil.NormalizeSlice(sig.Body),
}
ch, ok := m.signalSubscribers.Load(sub.ClientID)
if !ok {
return true
}
select {
case ch <- event:
default:
log.Warnf("dbus: channel full for %s, dropping signal", subID)
}
return true
})
}
func (m *Manager) Close() {
m.signalSubscribers.Range(func(clientID string, ch chan SignalEvent) bool {
close(ch)
m.signalSubscribers.Delete(clientID)
return true
})
if m.systemConn != nil {
m.systemConn.Close()
}
if m.sessionConn != nil {
m.sessionConn.Close()
}
}
func generateSubscriptionID() string {
b := make([]byte, 8)
if _, err := rand.Read(b); err != nil {
log.Warnf("dbus: failed to generate random subscription ID: %v", err)
}
return hex.EncodeToString(b)
}

View File

@@ -1,52 +0,0 @@
package dbus
import (
"github.com/AvengeMedia/DankMaterialShell/core/pkg/syncmap"
"github.com/godbus/dbus/v5"
)
type Manager struct {
systemConn *dbus.Conn
sessionConn *dbus.Conn
subscriptions syncmap.Map[string, *signalSubscription]
signalSubscribers syncmap.Map[string, chan SignalEvent]
}
type signalSubscription struct {
Bus string
Sender string
Path string
Interface string
Member string
ClientID string
}
type SignalEvent struct {
SubscriptionID string `json:"subscriptionId"`
Sender string `json:"sender"`
Path string `json:"path"`
Interface string `json:"interface"`
Member string `json:"member"`
Body []any `json:"body"`
}
type CallResult struct {
Values []any `json:"values"`
}
type PropertyResult struct {
Value any `json:"value"`
}
type IntrospectResult struct {
XML string `json:"xml"`
}
type ListNamesResult struct {
Names []string `json:"names"`
}
type SubscribeResult struct {
SubscriptionID string `json:"subscriptionId"`
}

View File

@@ -6,7 +6,6 @@ import (
"os" "os"
"sync" "sync"
"github.com/AvengeMedia/DankMaterialShell/core/pkg/dbusutil"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
) )
@@ -111,17 +110,61 @@ func (m *Manager) updateAccountsState() error {
m.stateMutex.Lock() m.stateMutex.Lock()
defer m.stateMutex.Unlock() defer m.stateMutex.Unlock()
m.state.Accounts.IconFile = dbusutil.GetOr(props, "IconFile", "") if v, ok := props["IconFile"]; ok {
m.state.Accounts.RealName = dbusutil.GetOr(props, "RealName", "") if val, ok := v.Value().(string); ok {
m.state.Accounts.UserName = dbusutil.GetOr(props, "UserName", "") m.state.Accounts.IconFile = val
m.state.Accounts.AccountType = dbusutil.GetOr(props, "AccountType", int32(0)) }
m.state.Accounts.HomeDirectory = dbusutil.GetOr(props, "HomeDirectory", "") }
m.state.Accounts.Shell = dbusutil.GetOr(props, "Shell", "") if v, ok := props["RealName"]; ok {
m.state.Accounts.Email = dbusutil.GetOr(props, "Email", "") if val, ok := v.Value().(string); ok {
m.state.Accounts.Language = dbusutil.GetOr(props, "Language", "") m.state.Accounts.RealName = val
m.state.Accounts.Location = dbusutil.GetOr(props, "Location", "") }
m.state.Accounts.Locked = dbusutil.GetOr(props, "Locked", false) }
m.state.Accounts.PasswordMode = dbusutil.GetOr(props, "PasswordMode", int32(0)) if v, ok := props["UserName"]; ok {
if val, ok := v.Value().(string); ok {
m.state.Accounts.UserName = val
}
}
if v, ok := props["AccountType"]; ok {
if val, ok := v.Value().(int32); ok {
m.state.Accounts.AccountType = val
}
}
if v, ok := props["HomeDirectory"]; ok {
if val, ok := v.Value().(string); ok {
m.state.Accounts.HomeDirectory = val
}
}
if v, ok := props["Shell"]; ok {
if val, ok := v.Value().(string); ok {
m.state.Accounts.Shell = val
}
}
if v, ok := props["Email"]; ok {
if val, ok := v.Value().(string); ok {
m.state.Accounts.Email = val
}
}
if v, ok := props["Language"]; ok {
if val, ok := v.Value().(string); ok {
m.state.Accounts.Language = val
}
}
if v, ok := props["Location"]; ok {
if val, ok := v.Value().(string); ok {
m.state.Accounts.Location = val
}
}
if v, ok := props["Locked"]; ok {
if val, ok := v.Value().(bool); ok {
m.state.Accounts.Locked = val
}
}
if v, ok := props["PasswordMode"]; ok {
if val, ok := v.Value().(int32); ok {
m.state.Accounts.PasswordMode = val
}
}
return nil return nil
} }
@@ -137,7 +180,7 @@ func (m *Manager) updateSettingsState() error {
return err return err
} }
if colorScheme, ok := dbusutil.As[uint32](variant); ok { if colorScheme, ok := variant.Value().(uint32); ok {
m.stateMutex.Lock() m.stateMutex.Lock()
m.state.Settings.ColorScheme = colorScheme m.state.Settings.ColorScheme = colorScheme
m.stateMutex.Unlock() m.stateMutex.Unlock()

View File

@@ -7,7 +7,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/AvengeMedia/DankMaterialShell/core/pkg/dbusutil"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
) )
@@ -133,15 +132,37 @@ func (m *Manager) updateSessionState() error {
m.stateMutex.Lock() m.stateMutex.Lock()
defer m.stateMutex.Unlock() defer m.stateMutex.Unlock()
m.state.Active = dbusutil.GetOr(props, "Active", m.state.Active) if v, ok := props["Active"]; ok {
m.state.IdleHint = dbusutil.GetOr(props, "IdleHint", m.state.IdleHint) if val, ok := v.Value().(bool); ok {
m.state.IdleSinceHint = dbusutil.GetOr(props, "IdleSinceHint", m.state.IdleSinceHint) m.state.Active = val
if lockedHint, ok := dbusutil.Get[bool](props, "LockedHint"); ok { }
m.state.LockedHint = lockedHint }
m.state.Locked = lockedHint if v, ok := props["IdleHint"]; ok {
if val, ok := v.Value().(bool); ok {
m.state.IdleHint = val
}
}
if v, ok := props["IdleSinceHint"]; ok {
if val, ok := v.Value().(uint64); ok {
m.state.IdleSinceHint = val
}
}
if v, ok := props["LockedHint"]; ok {
if val, ok := v.Value().(bool); ok {
m.state.LockedHint = val
m.state.Locked = val
}
}
if v, ok := props["Type"]; ok {
if val, ok := v.Value().(string); ok {
m.state.SessionType = val
}
}
if v, ok := props["Class"]; ok {
if val, ok := v.Value().(string); ok {
m.state.SessionClass = val
}
} }
m.state.SessionType = dbusutil.GetOr(props, "Type", m.state.SessionType)
m.state.SessionClass = dbusutil.GetOr(props, "Class", m.state.SessionClass)
if v, ok := props["User"]; ok { if v, ok := props["User"]; ok {
if userArr, ok := v.Value().([]any); ok && len(userArr) >= 1 { if userArr, ok := v.Value().([]any); ok && len(userArr) >= 1 {
if uid, ok := userArr[0].(uint32); ok { if uid, ok := userArr[0].(uint32); ok {
@@ -149,12 +170,36 @@ func (m *Manager) updateSessionState() error {
} }
} }
} }
m.state.UserName = dbusutil.GetOr(props, "Name", m.state.UserName) if v, ok := props["Name"]; ok {
m.state.RemoteHost = dbusutil.GetOr(props, "RemoteHost", m.state.RemoteHost) if val, ok := v.Value().(string); ok {
m.state.Service = dbusutil.GetOr(props, "Service", m.state.Service) m.state.UserName = val
m.state.TTY = dbusutil.GetOr(props, "TTY", m.state.TTY) }
m.state.Display = dbusutil.GetOr(props, "Display", m.state.Display) }
m.state.Remote = dbusutil.GetOr(props, "Remote", m.state.Remote) if v, ok := props["RemoteHost"]; ok {
if val, ok := v.Value().(string); ok {
m.state.RemoteHost = val
}
}
if v, ok := props["Service"]; ok {
if val, ok := v.Value().(string); ok {
m.state.Service = val
}
}
if v, ok := props["TTY"]; ok {
if val, ok := v.Value().(string); ok {
m.state.TTY = val
}
}
if v, ok := props["Display"]; ok {
if val, ok := v.Value().(string); ok {
m.state.Display = val
}
}
if v, ok := props["Remote"]; ok {
if val, ok := v.Value().(bool); ok {
m.state.Remote = val
}
}
if v, ok := props["Seat"]; ok { if v, ok := props["Seat"]; ok {
if seatArr, ok := v.Value().([]any); ok && len(seatArr) >= 1 { if seatArr, ok := v.Value().([]any); ok && len(seatArr) >= 1 {
if seatID, ok := seatArr[0].(string); ok { if seatID, ok := seatArr[0].(string); ok {
@@ -162,7 +207,11 @@ func (m *Manager) updateSessionState() error {
} }
} }
} }
m.state.VTNr = dbusutil.GetOr(props, "VTNr", m.state.VTNr) if v, ok := props["VTNr"]; ok {
if val, ok := v.Value().(uint32); ok {
m.state.VTNr = val
}
}
return nil return nil
} }

View File

@@ -3,7 +3,6 @@ package loginctl
import ( import (
"time" "time"
"github.com/AvengeMedia/DankMaterialShell/core/pkg/dbusutil"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
) )
@@ -118,28 +117,31 @@ func (m *Manager) handlePropertiesChanged(sig *dbus.Signal) {
for key, variant := range changes { for key, variant := range changes {
switch key { switch key {
case "Active": case "Active":
if val, ok := dbusutil.As[bool](variant); ok { if val, ok := variant.Value().(bool); ok {
m.stateMutex.Lock() m.stateMutex.Lock()
m.state.Active = val m.state.Active = val
m.stateMutex.Unlock() m.stateMutex.Unlock()
needsUpdate = true needsUpdate = true
} }
case "IdleHint": case "IdleHint":
if val, ok := dbusutil.As[bool](variant); ok { if val, ok := variant.Value().(bool); ok {
m.stateMutex.Lock() m.stateMutex.Lock()
m.state.IdleHint = val m.state.IdleHint = val
m.stateMutex.Unlock() m.stateMutex.Unlock()
needsUpdate = true needsUpdate = true
} }
case "IdleSinceHint": case "IdleSinceHint":
if val, ok := dbusutil.As[uint64](variant); ok { if val, ok := variant.Value().(uint64); ok {
m.stateMutex.Lock() m.stateMutex.Lock()
m.state.IdleSinceHint = val m.state.IdleSinceHint = val
m.stateMutex.Unlock() m.stateMutex.Unlock()
needsUpdate = true needsUpdate = true
} }
case "LockedHint": case "LockedHint":
if val, ok := dbusutil.As[bool](variant); ok { if val, ok := variant.Value().(bool); ok {
m.stateMutex.Lock() m.stateMutex.Lock()
m.state.LockedHint = val m.state.LockedHint = val
m.state.Locked = val m.state.Locked = val

View File

@@ -150,13 +150,21 @@ func (m *Manager) setConnectionPriority(connType string, autoconnectPriority int
} }
if err := exec.Command("nmcli", "con", "mod", connName, if err := exec.Command("nmcli", "con", "mod", connName,
"connection.autoconnect-priority", fmt.Sprintf("%d", autoconnectPriority), "connection.autoconnect-priority", fmt.Sprintf("%d", autoconnectPriority)).Run(); err != nil {
"ipv4.route-metric", fmt.Sprintf("%d", routeMetric), log.Warnf("Failed to set autoconnect-priority for %v: %v", connName, err)
"ipv6.route-metric", fmt.Sprintf("%d", routeMetric)).Run(); err != nil {
log.Warnf("Failed to set priority for %s: %v", connName, err)
continue continue
} }
if err := exec.Command("nmcli", "con", "mod", connName,
"ipv4.route-metric", fmt.Sprintf("%d", routeMetric)).Run(); err != nil {
log.Warnf("Failed to set ipv4.route-metric for %v: %v", connName, err)
}
if err := exec.Command("nmcli", "con", "mod", connName,
"ipv6.route-metric", fmt.Sprintf("%d", routeMetric)).Run(); err != nil {
log.Warnf("Failed to set ipv6.route-metric for %v: %v", connName, err)
}
log.Infof("Updated %v: autoconnect-priority=%d, route-metric=%d", connName, autoconnectPriority, routeMetric) log.Infof("Updated %v: autoconnect-priority=%d, route-metric=%d", connName, autoconnectPriority, routeMetric)
} }

View File

@@ -10,7 +10,6 @@ import (
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/brightness" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/brightness"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/clipboard" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/clipboard"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups"
serverDbus "github.com/AvengeMedia/DankMaterialShell/core/internal/server/dbus"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/dwl" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/dwl"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/extworkspace" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/extworkspace"
@@ -155,15 +154,6 @@ func RouteRequest(conn net.Conn, req models.Request) {
return return
} }
if strings.HasPrefix(req.Method, "dbus.") {
if dbusManager == nil {
models.RespondError(conn, req.ID, "dbus manager not initialized")
return
}
serverDbus.HandleRequest(conn, req, dbusManager, dbusClientID)
return
}
if strings.HasPrefix(req.Method, "clipboard.") { if strings.HasPrefix(req.Method, "clipboard.") {
switch req.Method { switch req.Method {
case "clipboard.getConfig": case "clipboard.getConfig":

View File

@@ -20,7 +20,6 @@ import (
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/brightness" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/brightness"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/clipboard" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/clipboard"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/cups"
serverDbus "github.com/AvengeMedia/DankMaterialShell/core/internal/server/dbus"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/dwl" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/dwl"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/evdev"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/extworkspace" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/extworkspace"
@@ -66,11 +65,8 @@ var brightnessManager *brightness.Manager
var wlrOutputManager *wlroutput.Manager var wlrOutputManager *wlroutput.Manager
var evdevManager *evdev.Manager var evdevManager *evdev.Manager
var clipboardManager *clipboard.Manager var clipboardManager *clipboard.Manager
var dbusManager *serverDbus.Manager
var wlContext *wlcontext.SharedContext var wlContext *wlcontext.SharedContext
const dbusClientID = "dms-dbus-client"
var capabilitySubscribers syncmap.Map[string, chan ServerInfo] var capabilitySubscribers syncmap.Map[string, chan ServerInfo]
var cupsSubscribers syncmap.Map[string, bool] var cupsSubscribers syncmap.Map[string, bool]
var cupsSubscriberCount atomic.Int32 var cupsSubscriberCount atomic.Int32
@@ -367,19 +363,6 @@ func InitializeClipboardManager() error {
return nil return nil
} }
func InitializeDbusManager() error {
manager, err := serverDbus.NewManager()
if err != nil {
log.Warnf("Failed to initialize dbus manager: %v", err)
return err
}
dbusManager = manager
log.Info("DBus manager initialized")
return nil
}
func handleConnection(conn net.Conn) { func handleConnection(conn net.Conn) {
defer conn.Close() defer conn.Close()
@@ -457,10 +440,6 @@ func getCapabilities() Capabilities {
caps = append(caps, "clipboard") caps = append(caps, "clipboard")
} }
if dbusManager != nil {
caps = append(caps, "dbus")
}
return Capabilities{Capabilities: caps} return Capabilities{Capabilities: caps}
} }
@@ -519,10 +498,6 @@ func getServerInfo() ServerInfo {
caps = append(caps, "clipboard") caps = append(caps, "clipboard")
} }
if dbusManager != nil {
caps = append(caps, "dbus")
}
return ServerInfo{ return ServerInfo{
APIVersion: APIVersion, APIVersion: APIVersion,
CLIVersion: CLIVersion, CLIVersion: CLIVersion,
@@ -1158,31 +1133,6 @@ func handleSubscribe(conn net.Conn, req models.Request) {
}() }()
} }
if shouldSubscribe("dbus") && dbusManager != nil {
wg.Add(1)
dbusChan := dbusManager.SubscribeSignals(dbusClientID)
go func() {
defer wg.Done()
defer dbusManager.UnsubscribeSignals(dbusClientID)
for {
select {
case event, ok := <-dbusChan:
if !ok {
return
}
select {
case eventChan <- ServiceEvent{Service: "dbus", Data: event}:
case <-stopChan:
return
}
case <-stopChan:
return
}
}
}()
}
go func() { go func() {
wg.Wait() wg.Wait()
close(eventChan) close(eventChan)
@@ -1248,9 +1198,6 @@ func cleanupManagers() {
if clipboardManager != nil { if clipboardManager != nil {
clipboardManager.Close() clipboardManager.Close()
} }
if dbusManager != nil {
dbusManager.Close()
}
if wlContext != nil { if wlContext != nil {
wlContext.Close() wlContext.Close()
} }
@@ -1543,14 +1490,6 @@ func Start(printDocs bool) error {
} }
}() }()
go func() {
if err := InitializeDbusManager(); err != nil {
log.Warnf("DBus manager unavailable: %v", err)
} else {
notifyCapabilityChange()
}
}()
log.Info("") log.Info("")
log.Infof("Ready! Capabilities: %v", getCapabilities().Capabilities) log.Infof("Ready! Capabilities: %v", getCapabilities().Capabilities)

View File

@@ -1,69 +0,0 @@
package dbusutil
import "github.com/godbus/dbus/v5"
func As[T any](v dbus.Variant) (T, bool) {
val, ok := v.Value().(T)
return val, ok
}
func AsOr[T any](v dbus.Variant, def T) T {
if val, ok := v.Value().(T); ok {
return val
}
return def
}
func Get[T any](m map[string]dbus.Variant, key string) (T, bool) {
v, ok := m[key]
if !ok {
var zero T
return zero, false
}
return As[T](v)
}
func GetOr[T any](m map[string]dbus.Variant, key string, def T) T {
v, ok := m[key]
if !ok {
return def
}
return AsOr(v, def)
}
func Normalize(v any) any {
switch val := v.(type) {
case dbus.Variant:
return Normalize(val.Value())
case dbus.ObjectPath:
return string(val)
case []dbus.ObjectPath:
result := make([]string, len(val))
for i, p := range val {
result[i] = string(p)
}
return result
case map[string]dbus.Variant:
result := make(map[string]any)
for k, vv := range val {
result[k] = Normalize(vv.Value())
}
return result
case []any:
result := make([]any, len(val))
for i, item := range val {
result[i] = Normalize(item)
}
return result
default:
return v
}
}
func NormalizeSlice(values []any) []any {
result := make([]any, len(values))
for i, v := range values {
result[i] = Normalize(v)
}
return result
}

View File

@@ -1,155 +0,0 @@
package dbusutil
import (
"testing"
"github.com/godbus/dbus/v5"
"github.com/stretchr/testify/assert"
)
func TestAs(t *testing.T) {
t.Run("string", func(t *testing.T) {
v := dbus.MakeVariant("hello")
val, ok := As[string](v)
assert.True(t, ok)
assert.Equal(t, "hello", val)
})
t.Run("bool", func(t *testing.T) {
v := dbus.MakeVariant(true)
val, ok := As[bool](v)
assert.True(t, ok)
assert.True(t, val)
})
t.Run("int32", func(t *testing.T) {
v := dbus.MakeVariant(int32(42))
val, ok := As[int32](v)
assert.True(t, ok)
assert.Equal(t, int32(42), val)
})
t.Run("wrong type", func(t *testing.T) {
v := dbus.MakeVariant("hello")
_, ok := As[int](v)
assert.False(t, ok)
})
}
func TestAsOr(t *testing.T) {
t.Run("exists", func(t *testing.T) {
v := dbus.MakeVariant("hello")
val := AsOr(v, "default")
assert.Equal(t, "hello", val)
})
t.Run("wrong type uses default", func(t *testing.T) {
v := dbus.MakeVariant(123)
val := AsOr(v, "default")
assert.Equal(t, "default", val)
})
}
func TestGet(t *testing.T) {
m := map[string]dbus.Variant{
"name": dbus.MakeVariant("test"),
"enabled": dbus.MakeVariant(true),
"count": dbus.MakeVariant(int32(5)),
}
t.Run("exists", func(t *testing.T) {
val, ok := Get[string](m, "name")
assert.True(t, ok)
assert.Equal(t, "test", val)
})
t.Run("missing key", func(t *testing.T) {
_, ok := Get[string](m, "missing")
assert.False(t, ok)
})
t.Run("wrong type", func(t *testing.T) {
_, ok := Get[int](m, "name")
assert.False(t, ok)
})
}
func TestGetOr(t *testing.T) {
m := map[string]dbus.Variant{
"name": dbus.MakeVariant("test"),
}
t.Run("exists", func(t *testing.T) {
val := GetOr(m, "name", "default")
assert.Equal(t, "test", val)
})
t.Run("missing uses default", func(t *testing.T) {
val := GetOr(m, "missing", "default")
assert.Equal(t, "default", val)
})
t.Run("wrong type uses default", func(t *testing.T) {
val := GetOr(m, "name", 42)
assert.Equal(t, 42, val)
})
}
func TestNormalize(t *testing.T) {
t.Run("variant unwrap", func(t *testing.T) {
v := dbus.MakeVariant("hello")
result := Normalize(v)
assert.Equal(t, "hello", result)
})
t.Run("nested variant", func(t *testing.T) {
v := dbus.MakeVariant(dbus.MakeVariant("nested"))
result := Normalize(v)
assert.Equal(t, "nested", result)
})
t.Run("object path", func(t *testing.T) {
v := dbus.ObjectPath("/org/test")
result := Normalize(v)
assert.Equal(t, "/org/test", result)
})
t.Run("object path slice", func(t *testing.T) {
v := []dbus.ObjectPath{"/org/a", "/org/b"}
result := Normalize(v)
assert.Equal(t, []string{"/org/a", "/org/b"}, result)
})
t.Run("variant map", func(t *testing.T) {
v := map[string]dbus.Variant{
"key": dbus.MakeVariant("value"),
}
result := Normalize(v)
expected := map[string]any{"key": "value"}
assert.Equal(t, expected, result)
})
t.Run("any slice", func(t *testing.T) {
v := []any{dbus.MakeVariant("a"), dbus.ObjectPath("/b")}
result := Normalize(v)
expected := []any{"a", "/b"}
assert.Equal(t, expected, result)
})
t.Run("passthrough primitives", func(t *testing.T) {
assert.Equal(t, "hello", Normalize("hello"))
assert.Equal(t, 42, Normalize(42))
assert.Equal(t, true, Normalize(true))
})
}
func TestNormalizeSlice(t *testing.T) {
input := []any{
dbus.MakeVariant("a"),
dbus.ObjectPath("/b"),
"c",
}
result := NormalizeSlice(input)
expected := []any{"a", "/b", "c"}
assert.Equal(t, expected, result)
}

View File

@@ -15,6 +15,7 @@ Depends: ${misc:Depends},
quickshell-git | quickshell, quickshell-git | quickshell,
accountsservice, accountsservice,
cava, cava,
cliphist,
danksearch, danksearch,
dgop, dgop,
matugen, matugen,
@@ -28,7 +29,8 @@ Depends: ${misc:Depends},
qml6-module-qtquick-layouts, qml6-module-qtquick-layouts,
qml6-module-qtquick-templates, qml6-module-qtquick-templates,
qml6-module-qtquick-window, qml6-module-qtquick-window,
qt6ct qt6ct,
wl-clipboard
Provides: dms Provides: dms
Conflicts: dms Conflicts: dms
Replaces: dms Replaces: dms

View File

@@ -14,6 +14,7 @@ Depends: ${misc:Depends},
quickshell | quickshell-git, quickshell | quickshell-git,
accountsservice, accountsservice,
cava, cava,
cliphist,
danksearch, danksearch,
dgop, dgop,
matugen, matugen,
@@ -27,7 +28,8 @@ Depends: ${misc:Depends},
qml6-module-qtquick-layouts, qml6-module-qtquick-layouts,
qml6-module-qtquick-templates, qml6-module-qtquick-templates,
qml6-module-qtquick-window, qml6-module-qtquick-window,
qt6ct qt6ct,
wl-clipboard
Conflicts: dms-git Conflicts: dms-git
Replaces: dms-git Replaces: dms-git
Description: DankMaterialShell - Modern Wayland Desktop Shell Description: DankMaterialShell - Modern Wayland Desktop Shell

View File

@@ -33,6 +33,7 @@ Recommends: cava
Recommends: danksearch Recommends: danksearch
Recommends: matugen Recommends: matugen
Recommends: quickshell-git Recommends: quickshell-git
Recommends: wl-clipboard
# Recommended system packages # Recommended system packages
Recommends: NetworkManager Recommends: NetworkManager

View File

@@ -24,8 +24,10 @@ Requires: dms-cli = %{version}-%{release}
Requires: dgop Requires: dgop
Recommends: cava Recommends: cava
Recommends: cliphist
Recommends: danksearch Recommends: danksearch
Recommends: matugen Recommends: matugen
Recommends: wl-clipboard
Recommends: NetworkManager Recommends: NetworkManager
Recommends: qt6-qtmultimedia Recommends: qt6-qtmultimedia
Suggests: qt6ct Suggests: qt6ct

View File

@@ -20,9 +20,12 @@ Requires: accountsservice
Requires: dgop Requires: dgop
Recommends: cava Recommends: cava
Recommends: cliphist
Recommends: danksearch Recommends: danksearch
Recommends: matugen Recommends: matugen
Recommends: quickshell-git Recommends: quickshell-git
Recommends: wl-clipboard
Recommends: NetworkManager Recommends: NetworkManager
Recommends: qt6-qtmultimedia Recommends: qt6-qtmultimedia
Suggests: qt6ct Suggests: qt6ct

View File

@@ -23,10 +23,12 @@ Requires: dgop
# Core utilities (Highly recommended for DMS functionality) # Core utilities (Highly recommended for DMS functionality)
Recommends: cava Recommends: cava
Recommends: cliphist
Recommends: danksearch Recommends: danksearch
Recommends: matugen Recommends: matugen
Recommends: NetworkManager Recommends: NetworkManager
Recommends: qt6-qtmultimedia Recommends: qt6-qtmultimedia
Recommends: wl-clipboard
Suggests: qt6ct Suggests: qt6ct
%description %description

View File

@@ -15,6 +15,7 @@ Depends: ${misc:Depends},
quickshell-git | quickshell, quickshell-git | quickshell,
accountsservice, accountsservice,
cava, cava,
cliphist,
danksearch, danksearch,
dgop, dgop,
matugen, matugen,
@@ -28,7 +29,8 @@ Depends: ${misc:Depends},
qml6-module-qtquick-layouts, qml6-module-qtquick-layouts,
qml6-module-qtquick-templates, qml6-module-qtquick-templates,
qml6-module-qtquick-window, qml6-module-qtquick-window,
qt6ct qt6ct,
wl-clipboard
Provides: dms Provides: dms
Conflicts: dms Conflicts: dms
Replaces: dms Replaces: dms

View File

@@ -14,6 +14,7 @@ Depends: ${misc:Depends},
quickshell | quickshell-git, quickshell | quickshell-git,
accountsservice, accountsservice,
cava, cava,
cliphist,
danksearch, danksearch,
dgop, dgop,
matugen, matugen,
@@ -27,7 +28,8 @@ Depends: ${misc:Depends},
qml6-module-qtquick-layouts, qml6-module-qtquick-layouts,
qml6-module-qtquick-templates, qml6-module-qtquick-templates,
qml6-module-qtquick-window, qml6-module-qtquick-window,
qt6ct qt6ct,
wl-clipboard
Conflicts: dms-git Conflicts: dms-git
Replaces: dms-git Replaces: dms-git
Description: DankMaterialShell - Modern Wayland Desktop Shell Description: DankMaterialShell - Modern Wayland Desktop Shell

View File

@@ -78,7 +78,7 @@
inherit version; inherit version;
pname = "dms-shell"; pname = "dms-shell";
src = ./core; src = ./core;
vendorHash = "sha256-lXqOJ0yNlOcXuR3vcuVjFI02Hskmavcasb1Ntf3UlPM="; vendorHash = "sha256-9CnZFtjXXWYELRiBX2UbZvWopnl9Y1ILuK+xP6YQZ9U=";
subPackages = [ "cmd/dms" ]; subPackages = [ "cmd/dms" ];

View File

@@ -1 +1 @@
Saffron Bloom Spicy Miso

View File

@@ -206,7 +206,6 @@ Singleton {
property bool reverseScrolling: false property bool reverseScrolling: false
property bool dwlShowAllTags: false property bool dwlShowAllTags: false
property string workspaceColorMode: "default" property string workspaceColorMode: "default"
property string workspaceOccupiedColorMode: "default"
property string workspaceUnfocusedColorMode: "default" property string workspaceUnfocusedColorMode: "default"
property string workspaceUrgentColorMode: "default" property string workspaceUrgentColorMode: "default"
property bool workspaceFocusedBorderEnabled: false property bool workspaceFocusedBorderEnabled: false
@@ -367,7 +366,6 @@ Singleton {
property bool showDock: false property bool showDock: false
property bool dockAutoHide: false property bool dockAutoHide: false
property bool dockSmartAutoHide: false
property bool dockGroupByApp: false property bool dockGroupByApp: false
property bool dockOpenOnOverview: false property bool dockOpenOnOverview: false
property int dockPosition: SettingsData.Position.Bottom property int dockPosition: SettingsData.Position.Bottom
@@ -395,7 +393,6 @@ Singleton {
property bool lockScreenShowDate: true property bool lockScreenShowDate: true
property bool lockScreenShowProfileImage: true property bool lockScreenShowProfileImage: true
property bool lockScreenShowPasswordField: true property bool lockScreenShowPasswordField: true
property bool lockScreenPowerOffMonitorsOnLock: false
property bool enableFprint: false property bool enableFprint: false
property int maxFprintTries: 15 property int maxFprintTries: 15
@@ -495,8 +492,7 @@ Singleton {
"shadowIntensity": 0, "shadowIntensity": 0,
"shadowOpacity": 60, "shadowOpacity": 60,
"shadowColorMode": "text", "shadowColorMode": "text",
"shadowCustomColor": "#000000", "shadowCustomColor": "#000000"
"clickThrough": false
} }
] ]

View File

@@ -100,7 +100,6 @@ var SPEC = {
reverseScrolling: { def: false }, reverseScrolling: { def: false },
dwlShowAllTags: { def: false }, dwlShowAllTags: { def: false },
workspaceColorMode: { def: "default" }, workspaceColorMode: { def: "default" },
workspaceOccupiedColorMode: { def: "default" },
workspaceUnfocusedColorMode: { def: "default" }, workspaceUnfocusedColorMode: { def: "default" },
workspaceUrgentColorMode: { def: "default" }, workspaceUrgentColorMode: { def: "default" },
workspaceFocusedBorderEnabled: { def: false }, workspaceFocusedBorderEnabled: { def: false },
@@ -232,7 +231,6 @@ var SPEC = {
showDock: { def: false }, showDock: { def: false },
dockAutoHide: { def: false }, dockAutoHide: { def: false },
dockSmartAutoHide: { def: false },
dockGroupByApp: { def: false }, dockGroupByApp: { def: false },
dockOpenOnOverview: { def: false }, dockOpenOnOverview: { def: false },
dockPosition: { def: 1 }, dockPosition: { def: 1 },
@@ -260,7 +258,6 @@ var SPEC = {
lockScreenShowDate: { def: true }, lockScreenShowDate: { def: true },
lockScreenShowProfileImage: { def: true }, lockScreenShowProfileImage: { def: true },
lockScreenShowPasswordField: { def: true }, lockScreenShowPasswordField: { def: true },
lockScreenPowerOffMonitorsOnLock: { def: false },
enableFprint: { def: false }, enableFprint: { def: false },
maxFprintTries: { def: 15 }, maxFprintTries: { def: 15 },
fprintdAvailable: { def: false, persist: false }, fprintdAvailable: { def: false, persist: false },
@@ -358,8 +355,7 @@ var SPEC = {
shadowIntensity: 0, shadowIntensity: 0,
shadowOpacity: 60, shadowOpacity: 60,
shadowColorMode: "text", shadowColorMode: "text",
shadowCustomColor: "#000000", shadowCustomColor: "#000000"
clickThrough: false
}], onChange: "updateBarConfigs" }, }], onChange: "updateBarConfigs" },
desktopClockEnabled: { def: false }, desktopClockEnabled: { def: false },

View File

@@ -966,17 +966,6 @@ Item {
return success ? `PLUGIN_DISABLE_SUCCESS: ${pluginId}` : `PLUGIN_DISABLE_FAILED: ${pluginId}`; return success ? `PLUGIN_DISABLE_SUCCESS: ${pluginId}` : `PLUGIN_DISABLE_FAILED: ${pluginId}`;
} }
function toggle(pluginId: string): string {
if (!pluginId)
return "ERROR: No plugin ID specified";
if (!PluginService.availablePlugins[pluginId])
return `PLUGIN_NOT_FOUND: ${pluginId}`;
const success = PluginService.togglePlugin(pluginId);
return success ? `PLUGIN_TOGGLE_SUCCESS: ${pluginId}` : `PLUGIN_TOGGLE_FAILED: ${pluginId}`;
}
function list(): string { function list(): string {
const plugins = PluginService.getAvailablePlugins(); const plugins = PluginService.getAvailablePlugins();
if (plugins.length === 0) if (plugins.length === 0)

View File

@@ -25,10 +25,7 @@ Item {
width: parent.width width: parent.width
totalCount: modal.totalCount totalCount: modal.totalCount
showKeyboardHints: modal.showKeyboardHints showKeyboardHints: modal.showKeyboardHints
activeTab: modal.activeTab
pinnedCount: modal.pinnedCount
onKeyboardHintsToggled: modal.showKeyboardHints = !modal.showKeyboardHints onKeyboardHintsToggled: modal.showKeyboardHints = !modal.showKeyboardHints
onTabChanged: tabName => modal.activeTab = tabName
onClearAllClicked: { onClearAllClicked: {
clearConfirmDialog.show(I18n.tr("Clear All History?"), I18n.tr("This will permanently delete all clipboard history."), function () { clearConfirmDialog.show(I18n.tr("Clear All History?"), I18n.tr("This will permanently delete all clipboard history."), function () {
modal.clearAll(); modal.clearAll();
@@ -73,20 +70,18 @@ Item {
Rectangle { Rectangle {
width: parent.width width: parent.width
height: parent.height - y - keyboardHintsContainer.height - Theme.spacingL height: parent.height - ClipboardConstants.headerHeight - 70
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: "transparent" color: "transparent"
clip: true clip: true
// Recents Tab
DankListView { DankListView {
id: clipboardListView id: clipboardListView
anchors.fill: parent anchors.fill: parent
model: ScriptModel { model: ScriptModel {
values: clipboardContent.modal.unpinnedEntries values: clipboardContent.modal.clipboardEntries
objectProp: "id" objectProp: "id"
} }
visible: modal.activeTab === "recents"
currentIndex: clipboardContent.modal ? clipboardContent.modal.selectedIndex : 0 currentIndex: clipboardContent.modal ? clipboardContent.modal.selectedIndex : 0
spacing: Theme.spacingXS spacing: Theme.spacingXS
@@ -119,11 +114,11 @@ Item {
} }
StyledText { StyledText {
text: I18n.tr("No recent clipboard entries found") text: I18n.tr("No clipboard entries found")
anchors.centerIn: parent anchors.centerIn: parent
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
visible: clipboardContent.modal.unpinnedEntries.length === 0 visible: clipboardContent.modal.clipboardEntries.length === 0
} }
delegate: ClipboardEntry { delegate: ClipboardEntry {
@@ -140,60 +135,11 @@ Item {
listView: clipboardListView listView: clipboardListView
onCopyRequested: clipboardContent.modal.copyEntry(modelData) onCopyRequested: clipboardContent.modal.copyEntry(modelData)
onDeleteRequested: clipboardContent.modal.deleteEntry(modelData) onDeleteRequested: clipboardContent.modal.deleteEntry(modelData)
onPinRequested: clipboardContent.modal.pinEntry(modelData)
onUnpinRequested: clipboardContent.modal.unpinEntry(modelData)
}
}
// Saved Tab
DankListView {
id: savedListView
anchors.fill: parent
model: ScriptModel {
values: clipboardContent.modal.pinnedEntries
objectProp: "id"
}
visible: modal.activeTab === "saved"
spacing: Theme.spacingXS
interactive: true
flickDeceleration: 1500
maximumFlickVelocity: 2000
boundsBehavior: Flickable.DragAndOvershootBounds
boundsMovement: Flickable.FollowBoundsBehavior
pressDelay: 0
flickableDirection: Flickable.VerticalFlick
StyledText {
text: I18n.tr("No saved clipboard entries")
anchors.centerIn: parent
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
visible: clipboardContent.modal.pinnedEntries.length === 0
}
delegate: ClipboardEntry {
required property int index
required property var modelData
width: savedListView.width
height: ClipboardConstants.itemHeight
entry: modelData
entryIndex: index + 1
itemIndex: index
isSelected: false
modal: clipboardContent.modal
listView: savedListView
onCopyRequested: clipboardContent.modal.copyEntry(modelData)
onDeleteRequested: clipboardContent.modal.deletePinnedEntry(modelData)
onPinRequested: clipboardContent.modal.pinEntry(modelData)
onUnpinRequested: clipboardContent.modal.unpinEntry(modelData)
} }
} }
} }
Item { Item {
id: keyboardHintsContainer
width: parent.width width: parent.width
height: modal.showKeyboardHints ? ClipboardConstants.keyboardHintsHeight + Theme.spacingL : 0 height: modal.showKeyboardHints ? ClipboardConstants.keyboardHintsHeight + Theme.spacingL : 0

View File

@@ -14,8 +14,6 @@ Rectangle {
signal copyRequested signal copyRequested
signal deleteRequested signal deleteRequested
signal pinRequested
signal unpinRequested
readonly property string entryType: modal ? modal.getEntryType(entry) : "text" readonly property string entryType: modal ? modal.getEntryType(entry) : "text"
readonly property string entryPreview: modal ? modal.getEntryPreview(entry) : "" readonly property string entryPreview: modal ? modal.getEntryPreview(entry) : ""
@@ -52,7 +50,7 @@ Rectangle {
Row { Row {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: parent.width - 110 width: parent.width - 68
spacing: Theme.spacingM spacing: Theme.spacingM
ClipboardThumbnail { ClipboardThumbnail {
@@ -102,32 +100,20 @@ Rectangle {
} }
} }
Row { DankActionButton {
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Theme.spacingM anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS iconName: "close"
iconSize: Theme.iconSize - 6
DankActionButton { iconColor: Theme.surfaceText
iconName: "push_pin" onClicked: deleteRequested()
iconSize: Theme.iconSize - 6
iconColor: entry.pinned ? Theme.primary : Theme.surfaceText
backgroundColor: entry.pinned ? Theme.primarySelected : "transparent"
onClicked: entry.pinned ? unpinRequested() : pinRequested()
}
DankActionButton {
iconName: "close"
iconSize: Theme.iconSize - 6
iconColor: Theme.surfaceText
onClicked: deleteRequested()
}
} }
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 80 anchors.rightMargin: 40
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: copyRequested() onClicked: copyRequested()

View File

@@ -8,13 +8,10 @@ Item {
property int totalCount: 0 property int totalCount: 0
property bool showKeyboardHints: false property bool showKeyboardHints: false
property string activeTab: "recents"
property int pinnedCount: 0
signal keyboardHintsToggled signal keyboardHintsToggled
signal clearAllClicked signal clearAllClicked
signal closeClicked signal closeClicked
signal tabChanged(string tabName)
height: ClipboardConstants.headerHeight height: ClipboardConstants.headerHeight
@@ -44,22 +41,6 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS spacing: Theme.spacingS
DankActionButton {
iconName: "history"
iconSize: Theme.iconSize - 4
iconColor: header.activeTab === "recents" ? Theme.primary : Theme.surfaceText
onClicked: tabChanged("recents")
}
DankActionButton {
iconName: "push_pin"
iconSize: Theme.iconSize - 4
iconColor: header.activeTab === "saved" ? Theme.primary : Theme.surfaceText
opacity: header.pinnedCount > 0 ? 1 : 0
enabled: header.pinnedCount > 0
onClicked: tabChanged("saved")
}
DankActionButton { DankActionButton {
iconName: "info" iconName: "info"
iconSize: Theme.iconSize - 4 iconSize: Theme.iconSize - 4

View File

@@ -19,8 +19,6 @@ DankModal {
property int totalCount: 0 property int totalCount: 0
property var clipboardEntries: [] property var clipboardEntries: []
property var pinnedEntries: []
property int pinnedCount: 0
property string searchText: "" property string searchText: ""
property int selectedIndex: 0 property int selectedIndex: 0
property bool keyboardNavigationActive: false property bool keyboardNavigationActive: false
@@ -76,37 +74,22 @@ DankModal {
function updateFilteredModel() { function updateFilteredModel() {
const query = searchText.trim(); const query = searchText.trim();
let filtered = [];
if (query.length === 0) { if (query.length === 0) {
filtered = internalEntries; clipboardEntries = internalEntries;
} else { } else {
const lowerQuery = query.toLowerCase(); const lowerQuery = query.toLowerCase();
filtered = internalEntries.filter(entry => clipboardEntries = internalEntries.filter(entry => entry.preview.toLowerCase().includes(lowerQuery));
entry.preview.toLowerCase().includes(lowerQuery)
);
} }
// Sort: pinned first, then by ID descending
filtered.sort((a, b) => {
if (a.pinned !== b.pinned) return b.pinned ? 1 : -1;
return b.id - a.id;
});
clipboardEntries = filtered;
unpinnedEntries = filtered.filter(e => !e.pinned);
totalCount = clipboardEntries.length; totalCount = clipboardEntries.length;
if (unpinnedEntries.length === 0) { if (clipboardEntries.length === 0) {
keyboardNavigationActive = false; keyboardNavigationActive = false;
selectedIndex = 0; selectedIndex = 0;
} else if (selectedIndex >= unpinnedEntries.length) { } else if (selectedIndex >= clipboardEntries.length) {
selectedIndex = unpinnedEntries.length - 1; selectedIndex = clipboardEntries.length - 1;
} }
} }
property var internalEntries: [] property var internalEntries: []
property var unpinnedEntries: []
property string activeTab: "recents"
function toggle() { function toggle() {
if (shouldBeVisible) { if (shouldBeVisible) {
@@ -152,10 +135,6 @@ DankModal {
return; return;
} }
internalEntries = response.result || []; internalEntries = response.result || [];
pinnedEntries = internalEntries.filter(e => e.pinned);
pinnedCount = pinnedEntries.length;
updateFilteredModel(); updateFilteredModel();
}); });
} }
@@ -192,85 +171,16 @@ DankModal {
}); });
} }
function deletePinnedEntry(entry) {
clearConfirmDialog.show(
I18n.tr("Delete Saved Item?"),
I18n.tr("This will permanently remove this saved clipboard item. This action cannot be undone."),
function () {
DMSService.sendRequest("clipboard.deleteEntry", {
"id": entry.id
}, function (response) {
if (response.error) {
console.warn("ClipboardHistoryModal: Failed to delete entry:", response.error);
return;
}
internalEntries = internalEntries.filter(e => e.id !== entry.id);
updateFilteredModel();
ToastService.showInfo(I18n.tr("Saved item deleted"));
});
},
function () {}
);
}
function pinEntry(entry) {
DMSService.sendRequest("clipboard.getPinnedCount", null, function (countResponse) {
if (countResponse.error) {
ToastService.showError(I18n.tr("Failed to check pin limit"));
return;
}
const maxPinned = 25; // TODO: Get from config
if (countResponse.result.count >= maxPinned) {
ToastService.showError(I18n.tr("Maximum pinned entries reached") + " (" + maxPinned + ")");
return;
}
DMSService.sendRequest("clipboard.pinEntry", { "id": entry.id }, function (response) {
if (response.error) {
ToastService.showError(I18n.tr("Failed to pin entry"));
return;
}
ToastService.showInfo(I18n.tr("Entry pinned"));
refreshClipboard();
});
});
}
function unpinEntry(entry) {
DMSService.sendRequest("clipboard.unpinEntry", { "id": entry.id }, function (response) {
if (response.error) {
ToastService.showError(I18n.tr("Failed to unpin entry"));
return;
}
ToastService.showInfo(I18n.tr("Entry unpinned"));
refreshClipboard();
});
}
function clearAll() { function clearAll() {
const hasPinned = pinnedCount > 0; DMSService.sendRequest("clipboard.clearHistory", null, function (response) {
const message = hasPinned if (response.error) {
? I18n.tr("This will delete all unpinned entries. %1 pinned entries will be kept.").arg(pinnedCount) console.warn("ClipboardHistoryModal: Failed to clear history:", response.error);
: I18n.tr("This will permanently delete all clipboard history."); return;
}
clearConfirmDialog.show( internalEntries = [];
I18n.tr("Clear History?"), clipboardEntries = [];
message, totalCount = 0;
function () { });
DMSService.sendRequest("clipboard.clearHistory", null, function (response) {
if (response.error) {
console.warn("ClipboardHistoryModal: Failed to clear history:", response.error);
return;
}
refreshClipboard();
if (hasPinned) {
ToastService.showInfo(I18n.tr("History cleared. %1 pinned entries kept.").arg(pinnedCount));
}
});
},
function () {}
);
} }
function getEntryPreview(entry) { function getEntryPreview(entry) {

View File

@@ -11,8 +11,7 @@ FloatingWindow {
id: processListModal id: processListModal
property int currentTab: 0 property int currentTab: 0
property string searchText: "" property var tabNames: ["Processes", "Performance", "System"]
property string expandedPid: ""
property bool shouldHaveFocus: visible property bool shouldHaveFocus: visible
property alias shouldBeVisible: processListModal.visible property alias shouldBeVisible: processListModal.visible
@@ -28,8 +27,9 @@ FloatingWindow {
function hide() { function hide() {
visible = false; visible = false;
if (processContextMenu.visible) if (processContextMenu.visible) {
processContextMenu.close(); processContextMenu.close();
}
} }
function toggle() { function toggle() {
@@ -61,39 +61,46 @@ FloatingWindow {
show(); show();
} }
function formatBytes(bytes) {
if (bytes < 1024)
return bytes.toFixed(0) + " B/s";
if (bytes < 1024 * 1024)
return (bytes / 1024).toFixed(1) + " KB/s";
if (bytes < 1024 * 1024 * 1024)
return (bytes / (1024 * 1024)).toFixed(1) + " MB/s";
return (bytes / (1024 * 1024 * 1024)).toFixed(2) + " GB/s";
}
objectName: "processListModal" objectName: "processListModal"
title: I18n.tr("System Monitor", "sysmon window title") title: I18n.tr("System Monitor", "sysmon window title")
minimumSize: Qt.size(750, 550) minimumSize: Qt.size(650, 400)
implicitWidth: 1000 implicitWidth: 900
implicitHeight: 720 implicitHeight: 680
color: Theme.surfaceContainer color: Theme.surfaceContainer
visible: false visible: false
onVisibleChanged: { onVisibleChanged: {
if (!visible) { if (!visible) {
closingModal(); closingModal();
searchText = "";
expandedPid = "";
DgopService.removeRef(["cpu", "memory", "network", "disk", "system"]);
} else { } else {
DgopService.addRef(["cpu", "memory", "network", "disk", "system"]);
Qt.callLater(() => { Qt.callLater(() => {
if (contentFocusScope) if (contentFocusScope) {
contentFocusScope.forceActiveFocus(); contentFocusScope.forceActiveFocus();
}
}); });
} }
} }
Component {
id: processesTabComponent
ProcessesTab {
contextMenu: processContextMenu
}
}
Component {
id: performanceTabComponent
PerformanceTab {}
}
Component {
id: systemTabComponent
SystemTab {}
}
ProcessContextMenu { ProcessContextMenu {
id: processContextMenu id: processContextMenu
} }
@@ -121,26 +128,6 @@ FloatingWindow {
currentTab = 2; currentTab = 2;
event.accepted = true; event.accepted = true;
return; return;
case Qt.Key_4:
currentTab = 3;
event.accepted = true;
return;
case Qt.Key_Escape:
if (searchText.length > 0) {
searchText = "";
event.accepted = true;
return;
}
hide();
event.accepted = true;
return;
case Qt.Key_F:
if (event.modifiers & Qt.ControlModifier) {
searchField.forceActiveFocus();
event.accepted = true;
return;
}
break;
} }
} }
@@ -174,7 +161,7 @@ FloatingWindow {
} }
StyledText { StyledText {
text: I18n.tr("The 'dgop' tool is required for system monitoring.\nPlease install dgop to use this feature.", "dgop unavailable error message") text: I18n.tr("The 'dgop' tool is required for system monitoring.\nPlease install dgop to use this feature.")
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
@@ -184,14 +171,14 @@ FloatingWindow {
} }
} }
ColumnLayout { Column {
anchors.fill: parent anchors.fill: parent
spacing: 0 spacing: 0
visible: DgopService.dgopAvailable visible: DgopService.dgopAvailable
Item { Item {
Layout.fillWidth: true width: parent.width
Layout.preferredHeight: 48 height: 48
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
@@ -246,276 +233,166 @@ FloatingWindow {
} }
} }
RowLayout { Item {
Layout.fillWidth: true width: parent.width
Layout.preferredHeight: 52 height: parent.height - 48
Layout.leftMargin: Theme.spacingL
Layout.rightMargin: Theme.spacingL
spacing: Theme.spacingL
Row { ColumnLayout {
spacing: 2
Repeater {
model: [
{
text: I18n.tr("Processes"),
icon: "list_alt"
},
{
text: I18n.tr("Performance"),
icon: "analytics"
},
{
text: I18n.tr("Disks"),
icon: "storage"
},
{
text: I18n.tr("System"),
icon: "computer"
}
]
Rectangle {
width: 120
height: 44
radius: Theme.cornerRadius
color: currentTab === index ? Theme.primaryPressed : (tabMouseArea.containsMouse ? Theme.primaryHoverLight : "transparent")
border.color: currentTab === index ? Theme.primary : "transparent"
border.width: currentTab === index ? 1 : 0
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: modelData.icon
size: Theme.iconSize - 2
color: currentTab === index ? Theme.primary : Theme.surfaceText
opacity: currentTab === index ? 1 : 0.7
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: modelData.text
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: currentTab === index ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: tabMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: currentTab = index
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}
Item {
Layout.fillWidth: true
}
DankTextField {
id: searchField
Layout.preferredWidth: 250
Layout.preferredHeight: 40
placeholderText: I18n.tr("Search processes...", "process search placeholder")
leftIconName: "search"
showClearButton: true
text: searchText
visible: currentTab === 0
onTextChanged: searchText = text
}
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: Theme.spacingL
Layout.topMargin: Theme.spacingM
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Theme.outlineLight
border.width: 1
clip: true
Loader {
id: processesTabLoader
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.leftMargin: Theme.spacingL
active: processListModal.visible && currentTab === 0 anchors.rightMargin: Theme.spacingL
visible: currentTab === 0 anchors.bottomMargin: Theme.spacingL
sourceComponent: ProcessesView { anchors.topMargin: 0
searchText: processListModal.searchText
expandedPid: processListModal.expandedPid
contextMenu: processContextMenu
onExpandedPidChanged: processListModal.expandedPid = expandedPid
}
}
Loader {
id: performanceTabLoader
anchors.fill: parent
anchors.margins: Theme.spacingS
active: processListModal.visible && currentTab === 1
visible: currentTab === 1
sourceComponent: PerformanceView {}
}
Loader {
id: disksTabLoader
anchors.fill: parent
anchors.margins: Theme.spacingS
active: processListModal.visible && currentTab === 2
visible: currentTab === 2
sourceComponent: DisksView {}
}
Loader {
id: systemTabLoader
anchors.fill: parent
anchors.margins: Theme.spacingS
active: processListModal.visible && currentTab === 3
visible: currentTab === 3
sourceComponent: SystemView {}
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 32
Layout.leftMargin: Theme.spacingL
Layout.rightMargin: Theme.spacingL
Layout.bottomMargin: Theme.spacingM
color: "transparent"
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingL spacing: Theme.spacingL
Row { Rectangle {
spacing: Theme.spacingXS Layout.fillWidth: true
height: 52
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
radius: Theme.cornerRadius
border.color: Theme.outlineLight
border.width: 1
StyledText { Row {
text: I18n.tr("Processes:", "process count label in footer") anchors.fill: parent
font.pixelSize: Theme.fontSizeSmall anchors.margins: 4
color: Theme.surfaceVariantText spacing: 2
}
StyledText { Repeater {
text: DgopService.processCount.toString() model: tabNames
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold Rectangle {
color: Theme.surfaceText width: (parent.width - (tabNames.length - 1) * 2) / tabNames.length
height: 44
radius: Theme.cornerRadius
color: currentTab === index ? Theme.primaryPressed : (tabMouseArea.containsMouse ? Theme.primaryHoverLight : "transparent")
border.color: currentTab === index ? Theme.primary : "transparent"
border.width: currentTab === index ? 1 : 0
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: {
const tabIcons = ["list_alt", "analytics", "settings"];
return tabIcons[index] || "tab";
}
size: Theme.iconSize - 2
color: currentTab === index ? Theme.primary : Theme.surfaceText
opacity: currentTab === index ? 1 : 0.7
anchors.verticalCenter: parent.verticalCenter
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
StyledText {
text: modelData
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: currentTab === index ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -1
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
MouseArea {
id: tabMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: () => {
currentTab = index;
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
Behavior on border.color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
} }
} }
Row { Rectangle {
spacing: Theme.spacingXS Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Theme.outlineLight
border.width: 1
StyledText { Loader {
text: I18n.tr("Uptime:", "uptime label in footer") id: processesTab
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText anchors.fill: parent
anchors.margins: Theme.spacingS
active: processListModal.visible && currentTab === 0
visible: currentTab === 0
opacity: currentTab === 0 ? 1 : 0
sourceComponent: processesTabComponent
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
} }
StyledText { Loader {
text: DgopService.shortUptime || "--" id: performanceTab
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
}
Row { anchors.fill: parent
anchors.right: parent.right anchors.margins: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter active: processListModal.visible && currentTab === 1
spacing: Theme.spacingL visible: currentTab === 1
opacity: currentTab === 1 ? 1 : 0
sourceComponent: performanceTabComponent
Row { Behavior on opacity {
spacing: Theme.spacingXS NumberAnimation {
duration: Theme.mediumDuration
DankIcon { easing.type: Theme.emphasizedEasing
name: "swap_horiz" }
size: 14 }
color: Theme.info
anchors.verticalCenter: parent.verticalCenter
} }
StyledText { Loader {
text: "↓" + formatBytes(DgopService.networkRxRate) + " ↑" + formatBytes(DgopService.networkTxRate) id: systemTab
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
}
}
Row { anchors.fill: parent
spacing: Theme.spacingXS anchors.margins: Theme.spacingS
active: processListModal.visible && currentTab === 2
visible: currentTab === 2
opacity: currentTab === 2 ? 1 : 0
sourceComponent: systemTabComponent
DankIcon { Behavior on opacity {
name: "storage" NumberAnimation {
size: 14 duration: Theme.mediumDuration
color: Theme.warning easing.type: Theme.emphasizedEasing
anchors.verticalCenter: parent.verticalCenter }
} }
StyledText {
text: "↓" + formatBytes(DgopService.diskReadRate) + " ↑" + formatBytes(DgopService.diskWriteRate)
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
}
}
Row {
spacing: Theme.spacingXS
DankIcon {
name: "memory"
size: 14
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: DgopService.cpuUsage.toFixed(1) + "%"
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: DgopService.cpuUsage > 80 ? Theme.error : Theme.surfaceText
}
}
Row {
spacing: Theme.spacingXS
DankIcon {
name: "sd_card"
size: 14
color: Theme.secondary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: DgopService.formatSystemMemory(DgopService.usedMemoryKB) + " / " + DgopService.formatSystemMemory(DgopService.totalMemoryKB)
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: DgopService.memoryUsage > 90 ? Theme.error : Theme.surfaceText
} }
} }
} }

View File

@@ -296,9 +296,6 @@ Item {
width: parent.width width: parent.width
anchors.centerIn: parent anchors.centerIn: parent
implicitWidth: isVertical ? widgetThickness : totalSize
implicitHeight: isVertical ? totalSize : widgetThickness
Timer { Timer {
id: layoutTimer id: layoutTimer
interval: 0 interval: 0
@@ -368,7 +365,6 @@ Item {
onContentItemReady: contentItem => { onContentItemReady: contentItem => {
contentItem.widthChanged.connect(() => layoutTimer.restart()); contentItem.widthChanged.connect(() => layoutTimer.restart());
contentItem.heightChanged.connect(() => layoutTimer.restart()); contentItem.heightChanged.connect(() => layoutTimer.restart());
layoutTimer.restart();
} }
onActiveChanged: layoutTimer.restart() onActiveChanged: layoutTimer.restart()

View File

@@ -20,13 +20,6 @@ Item {
readonly property real innerPadding: barConfig?.innerPadding ?? 4 readonly property real innerPadding: barConfig?.innerPadding ?? 4
property alias hLeftSection: hLeftSection
property alias hCenterSection: hCenterSection
property alias hRightSection: hRightSection
property alias vLeftSection: vLeftSection
property alias vCenterSection: vCenterSection
property alias vRightSection: vRightSection
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Math.max(Theme.spacingXS, innerPadding * 0.8) anchors.leftMargin: Math.max(Theme.spacingXS, innerPadding * 0.8)
anchors.rightMargin: Math.max(Theme.spacingXS, innerPadding * 0.8) anchors.rightMargin: Math.max(Theme.spacingXS, innerPadding * 0.8)

View File

@@ -500,78 +500,8 @@ PanelWindow {
height: axis.isVertical ? parent.height : maskThickness height: axis.isVertical ? parent.height : maskThickness
} }
readonly property bool clickThroughEnabled: barConfig?.clickThrough ?? false
readonly property var _leftSection: topBarContent ? (barWindow.isVertical ? topBarContent.vLeftSection : topBarContent.hLeftSection) : null
readonly property var _centerSection: topBarContent ? (barWindow.isVertical ? topBarContent.vCenterSection : topBarContent.hCenterSection) : null
readonly property var _rightSection: topBarContent ? (barWindow.isVertical ? topBarContent.vRightSection : topBarContent.hRightSection) : null
function sectionRect(section, isCenter) {
if (!section)
return {
"x": 0,
"y": 0,
"w": 0,
"h": 0
};
const pos = section.mapToItem(barWindow.contentItem, 0, 0);
const implW = section.implicitWidth || 0;
const implH = section.implicitHeight || 0;
const offsetX = isCenter && !barWindow.isVertical ? (section.width - implW) / 2 : 0;
const offsetY = !barWindow.isVertical ? (section.height - implH) / 2 : (isCenter ? (section.height - implH) / 2 : 0);
const edgePad = 2;
return {
"x": pos.x + offsetX - edgePad,
"y": pos.y + offsetY - edgePad,
"w": implW + edgePad * 2,
"h": implH + edgePad * 2
};
}
mask: Region { mask: Region {
item: clickThroughEnabled ? null : inputMask item: inputMask
Region {
readonly property var r: barWindow.clickThroughEnabled ? barWindow.sectionRect(barWindow._leftSection, false) : {
"x": 0,
"y": 0,
"w": 0,
"h": 0
}
x: r.x
y: r.y
width: r.w
height: r.h
}
Region {
readonly property var r: barWindow.clickThroughEnabled ? barWindow.sectionRect(barWindow._centerSection, true) : {
"x": 0,
"y": 0,
"w": 0,
"h": 0
}
x: r.x
y: r.y
width: r.w
height: r.h
}
Region {
readonly property var r: barWindow.clickThroughEnabled ? barWindow.sectionRect(barWindow._rightSection, false) : {
"x": 0,
"y": 0,
"w": 0,
"h": 0
}
x: r.x
y: r.y
width: r.w
height: r.h
}
} }
Item { Item {

View File

@@ -731,8 +731,7 @@ Item {
Flow { Flow {
id: workspaceRow id: workspaceRow
x: isVertical ? visualBackground.x : (parent.width - implicitWidth) / 2 anchors.centerIn: parent
y: isVertical ? (parent.height - implicitHeight) / 2 : visualBackground.y
spacing: Theme.spacingS spacing: Theme.spacingS
flow: isVertical ? Flow.TopToBottom : Flow.LeftToRight flow: isVertical ? Flow.TopToBottom : Flow.LeftToRight
@@ -755,16 +754,6 @@ Item {
return !!(modelData && modelData.num === root.currentWorkspace); return !!(modelData && modelData.num === root.currentWorkspace);
return modelData === root.currentWorkspace; return modelData === root.currentWorkspace;
} }
property bool isOccupied: {
if (CompositorService.isHyprland)
return Array.from(Hyprland.toplevels?.values || [])
.some(tl => tl.workspace?.id === modelData?.id);
if (CompositorService.isDwl)
return modelData.clients > 0;
if (CompositorService.isNiri)
return NiriService.windows?.some(win => win.workspace_id === modelData?.id) ?? false;
return false;
}
property bool isPlaceholder: { property bool isPlaceholder: {
if (root.useExtWorkspace) if (root.useExtWorkspace)
return !!(modelData && modelData.hidden); return !!(modelData && modelData.hidden);
@@ -846,21 +835,6 @@ Item {
} }
} }
readonly property color occupiedColor: {
switch (SettingsData.workspaceOccupiedColorMode) {
case "s":
return Theme.surface;
case "sc":
return Theme.surfaceContainer;
case "sch":
return Theme.surfaceContainerHigh;
case "none":
return unfocusedColor;
default:
return Theme.secondary;
}
}
readonly property color urgentColor: { readonly property color urgentColor: {
switch (SettingsData.workspaceUrgentColorMode) { switch (SettingsData.workspaceUrgentColorMode) {
case "primary": case "primary":
@@ -994,13 +968,12 @@ Item {
dataUpdateTimer.restart(); dataUpdateTimer.restart();
} }
width: root.isVertical ? root.widgetHeight : visualWidth width: root.isVertical ? root.barThickness : visualWidth
height: root.isVertical ? visualHeight : root.widgetHeight height: root.isVertical ? visualHeight : root.barThickness
Rectangle { Rectangle {
id: focusedBorderRing id: focusedBorderRing
x: root.isVertical ? (root.widgetHeight - width) / 2 : (parent.width - width) / 2 anchors.centerIn: parent
y: root.isVertical ? (parent.height - height) / 2 : (root.widgetHeight - height) / 2
width: { width: {
const borderWidth = (SettingsData.workspaceFocusedBorderEnabled && isActive && !isPlaceholder) ? SettingsData.workspaceFocusedBorderThickness : 0; const borderWidth = (SettingsData.workspaceFocusedBorderEnabled && isActive && !isPlaceholder) ? SettingsData.workspaceFocusedBorderThickness : 0;
return delegateRoot.visualWidth + borderWidth * 2; return delegateRoot.visualWidth + borderWidth * 2;
@@ -1047,10 +1020,9 @@ Item {
id: visualContent id: visualContent
width: delegateRoot.visualWidth width: delegateRoot.visualWidth
height: delegateRoot.visualHeight height: delegateRoot.visualHeight
x: root.isVertical ? (root.widgetHeight - width) / 2 : (parent.width - width) / 2 anchors.centerIn: parent
y: root.isVertical ? (parent.height - height) / 2 : (root.widgetHeight - height) / 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: isActive ? activeColor : isUrgent ? urgentColor : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.withAlpha(unfocusedColor, 0.7) : isOccupied ? occupiedColor : unfocusedColor color: isActive ? activeColor : isUrgent ? urgentColor : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.withAlpha(unfocusedColor, 0.7) : unfocusedColor
border.width: isUrgent ? 2 : 0 border.width: isUrgent ? 2 : 0
border.color: isUrgent ? urgentColor : "transparent" border.color: isUrgent ? urgentColor : "transparent"

View File

@@ -2,7 +2,6 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Shapes import QtQuick.Shapes
import Quickshell import Quickshell
import Quickshell.Hyprland
import Quickshell.Wayland import Quickshell.Wayland
import qs.Common import qs.Common
import qs.Services import qs.Services
@@ -29,7 +28,7 @@ Variants {
} }
property var modelData: item property var modelData: item
property bool autoHide: SettingsData.dockAutoHide || SettingsData.dockSmartAutoHide property bool autoHide: SettingsData.dockAutoHide
property real backgroundTransparency: SettingsData.dockTransparency property real backgroundTransparency: SettingsData.dockTransparency
property bool groupByApp: SettingsData.dockGroupByApp property bool groupByApp: SettingsData.dockGroupByApp
readonly property int borderThickness: SettingsData.dockBorderEnabled ? SettingsData.dockBorderThickness : 0 readonly property int borderThickness: SettingsData.dockBorderEnabled ? SettingsData.dockBorderThickness : 0
@@ -112,133 +111,6 @@ Variants {
property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData) property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData)
property bool revealSticky: false property bool revealSticky: false
readonly property bool shouldHideForWindows: {
if (!SettingsData.dockSmartAutoHide)
return false;
if (!CompositorService.isNiri && !CompositorService.isHyprland)
return false;
const screenName = dock.modelData?.name ?? "";
const dockThickness = effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin;
const screenWidth = dock.screen?.width ?? 0;
const screenHeight = dock.screen?.height ?? 0;
if (CompositorService.isNiri) {
NiriService.windows;
let currentWorkspaceId = null;
for (let i = 0; i < NiriService.allWorkspaces.length; i++) {
const ws = NiriService.allWorkspaces[i];
if (ws.output === screenName && ws.is_active) {
currentWorkspaceId = ws.id;
break;
}
}
if (currentWorkspaceId === null)
return false;
for (let i = 0; i < NiriService.windows.length; i++) {
const win = NiriService.windows[i];
if (win.workspace_id !== currentWorkspaceId)
continue;
// Get window position and size from layout data
const tilePos = win.layout?.tile_pos_in_workspace_view;
const winSize = win.layout?.window_size || win.layout?.tile_size;
if (tilePos && winSize) {
const winX = tilePos[0];
const winY = tilePos[1];
const winW = winSize[0];
const winH = winSize[1];
switch (SettingsData.dockPosition) {
case SettingsData.Position.Top:
if (winY < dockThickness)
return true;
break;
case SettingsData.Position.Bottom:
if (winY + winH > screenHeight - dockThickness)
return true;
break;
case SettingsData.Position.Left:
if (winX < dockThickness)
return true;
break;
case SettingsData.Position.Right:
if (winX + winW > screenWidth - dockThickness)
return true;
break;
}
} else if (!win.is_floating) {
return true;
}
}
return false;
}
// Hyprland implementation
const filtered = CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, screenName);
if (filtered.length === 0)
return false;
for (let i = 0; i < filtered.length; i++) {
const toplevel = filtered[i];
let hyprToplevel = null;
if (Hyprland.toplevels) {
const hyprToplevels = Array.from(Hyprland.toplevels.values);
for (let j = 0; j < hyprToplevels.length; j++) {
if (hyprToplevels[j].wayland === toplevel) {
hyprToplevel = hyprToplevels[j];
break;
}
}
}
if (!hyprToplevel?.lastIpcObject)
continue;
const ipc = hyprToplevel.lastIpcObject;
const at = ipc.at;
const size = ipc.size;
if (!at || !size)
continue;
const monX = hyprToplevel.monitor?.x ?? 0;
const monY = hyprToplevel.monitor?.y ?? 0;
const winX = at[0] - monX;
const winY = at[1] - monY;
const winW = size[0];
const winH = size[1];
switch (SettingsData.dockPosition) {
case SettingsData.Position.Top:
if (winY < dockThickness)
return true;
break;
case SettingsData.Position.Bottom:
if (winY + winH > screenHeight - dockThickness)
return true;
break;
case SettingsData.Position.Left:
if (winX < dockThickness)
return true;
break;
case SettingsData.Position.Right:
if (winX + winW > screenWidth - dockThickness)
return true;
break;
}
}
return false;
}
Timer { Timer {
id: revealHold id: revealHold
interval: 250 interval: 250
@@ -250,15 +122,6 @@ Variants {
if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) { if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) {
return true; return true;
} }
// Smart auto-hide: show dock when no windows overlap, hide when they do
if (SettingsData.dockSmartAutoHide) {
if (shouldHideForWindows)
return dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky;
return true; // No overlapping windows - show dock
}
// Regular auto-hide: always hide unless hovering
return !autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky; return !autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky;
} }

View File

@@ -12,34 +12,8 @@ Scope {
property string sharedPasswordBuffer: "" property string sharedPasswordBuffer: ""
property bool shouldLock: false property bool shouldLock: false
onShouldLockChanged: {
if (shouldLock && lockPowerOffArmed) {
lockStateCheck.restart();
}
}
Timer {
id: lockStateCheck
interval: 100
repeat: false
onTriggered: {
if (sessionLock.locked && lockPowerOffArmed) {
pendingLock = false;
IdleService.monitorsOff = true;
CompositorService.powerOffMonitors();
lockWakeAllowed = false;
lockWakeDebounce.restart();
lockPowerOffArmed = false;
dpmsReapplyTimer.start();
}
}
}
property bool lockInitiatedLocally: false property bool lockInitiatedLocally: false
property bool pendingLock: false property bool pendingLock: false
property bool lockPowerOffArmed: false
property bool lockWakeAllowed: false
Component.onCompleted: { Component.onCompleted: {
IdleService.lockComponent = this; IdleService.lockComponent = this;
@@ -63,7 +37,6 @@ Scope {
return; return;
lockInitiatedLocally = true; lockInitiatedLocally = true;
lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock;
if (!SessionService.active && SessionService.loginctlAvailable) { if (!SessionService.active && SessionService.loginctlAvailable) {
pendingLock = true; pendingLock = true;
@@ -105,7 +78,6 @@ Scope {
return; return;
} }
lockInitiatedLocally = false; lockInitiatedLocally = false;
lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock;
shouldLock = true; shouldLock = true;
} }
@@ -124,13 +96,11 @@ Scope {
if (SessionService.active && pendingLock) { if (SessionService.active && pendingLock) {
pendingLock = false; pendingLock = false;
lockInitiatedLocally = true; lockInitiatedLocally = true;
lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock;
shouldLock = true; shouldLock = true;
return; return;
} }
if (SessionService.locked && !shouldLock && !pendingLock) { if (SessionService.locked && !shouldLock && !pendingLock) {
lockInitiatedLocally = false; lockInitiatedLocally = false;
lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock;
shouldLock = true; shouldLock = true;
} }
} }
@@ -149,6 +119,13 @@ Scope {
locked: shouldLock locked: shouldLock
onLockedChanged: {
if (locked) {
pendingLock = false;
dpmsReapplyTimer.start();
}
}
WlSessionLockSurface { WlSessionLockSurface {
id: lockSurface id: lockSurface
@@ -178,33 +155,7 @@ Scope {
} }
} }
Connections {
target: sessionLock
function onLockedChanged() {
if (sessionLock.locked) {
pendingLock = false;
if (lockPowerOffArmed && SettingsData.lockScreenPowerOffMonitorsOnLock) {
IdleService.monitorsOff = true;
CompositorService.powerOffMonitors();
lockWakeAllowed = false;
lockWakeDebounce.restart();
}
lockPowerOffArmed = false;
dpmsReapplyTimer.start();
return;
}
lockWakeAllowed = false;
if (IdleService.monitorsOff && SettingsData.lockScreenPowerOffMonitorsOnLock) {
IdleService.monitorsOff = false;
CompositorService.powerOnMonitors();
}
}
}
LockScreenDemo { LockScreenDemo {
id: demoWindow id: demoWindow
} }
@@ -249,46 +200,4 @@ Scope {
repeat: false repeat: false
onTriggered: IdleService.reapplyDpmsIfNeeded() onTriggered: IdleService.reapplyDpmsIfNeeded()
} }
Timer {
id: lockWakeDebounce
interval: 200
repeat: false
onTriggered: {
if (!sessionLock.locked)
return;
if (!SettingsData.lockScreenPowerOffMonitorsOnLock)
return;
if (!IdleService.monitorsOff) {
lockWakeAllowed = true;
return;
}
if (lockWakeAllowed) {
IdleService.monitorsOff = false;
CompositorService.powerOnMonitors();
} else {
lockWakeAllowed = true;
}
}
}
MouseArea {
anchors.fill: parent
enabled: sessionLock.locked
hoverEnabled: enabled
onPressed: lockWakeDebounce.restart()
onPositionChanged: lockWakeDebounce.restart()
onWheel: lockWakeDebounce.restart()
}
FocusScope {
anchors.fill: parent
focus: sessionLock.locked
Keys.onPressed: event => {
if (!sessionLock.locked)
return;
lockWakeDebounce.restart();
}
}
} }

View File

@@ -1,6 +1,5 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import Quickshell
import Quickshell.Io import Quickshell.Io
import qs.Common import qs.Common
import qs.Modals.Common import qs.Modals.Common
@@ -52,9 +51,7 @@ Item {
if (tabIndex === NotepadStorageService.currentTabIndex && hasUnsavedChanges()) { if (tabIndex === NotepadStorageService.currentTabIndex && hasUnsavedChanges()) {
root.pendingAction = "close_tab_" + tabIndex; root.pendingAction = "close_tab_" + tabIndex;
root.confirmationDialogOpen = true; root.confirmationDialogOpen = true;
confirmationDialogLoader.active = true; confirmationDialog.open();
if (confirmationDialogLoader.item)
confirmationDialogLoader.item.open();
} else { } else {
performCloseTab(tabIndex); performCloseTab(tabIndex);
} }
@@ -104,9 +101,7 @@ Item {
root.pendingFileUrl = fileUrl; root.pendingFileUrl = fileUrl;
root.pendingAction = "load_file"; root.pendingAction = "load_file";
root.confirmationDialogOpen = true; root.confirmationDialogOpen = true;
confirmationDialogLoader.active = true; confirmationDialog.open();
if (confirmationDialogLoader.item)
confirmationDialogLoader.item.open();
} else { } else {
performLoadFromFile(fileUrl); performLoadFromFile(fileUrl);
} }
@@ -175,9 +170,7 @@ Item {
saveToFile(fileUrl); saveToFile(fileUrl);
} else { } else {
root.fileDialogOpen = true; root.fileDialogOpen = true;
saveBrowserLoader.active = true; saveBrowser.open();
if (saveBrowserLoader.item)
saveBrowserLoader.item.open();
} }
} }
@@ -185,14 +178,10 @@ Item {
if (hasUnsavedChanges()) { if (hasUnsavedChanges()) {
root.pendingAction = "open"; root.pendingAction = "open";
root.confirmationDialogOpen = true; root.confirmationDialogOpen = true;
confirmationDialogLoader.active = true; confirmationDialog.open();
if (confirmationDialogLoader.item)
confirmationDialogLoader.item.open();
} else { } else {
root.fileDialogOpen = true; root.fileDialogOpen = true;
loadBrowserLoader.active = true; loadBrowser.open();
if (loadBrowserLoader.item)
loadBrowserLoader.item.open();
} }
} }
@@ -200,9 +189,7 @@ Item {
if (hasUnsavedChanges()) { if (hasUnsavedChanges()) {
root.pendingAction = "new"; root.pendingAction = "new";
root.confirmationDialogOpen = true; root.confirmationDialogOpen = true;
confirmationDialogLoader.active = true; confirmationDialog.open();
if (confirmationDialogLoader.item)
confirmationDialogLoader.item.open();
} else { } else {
createNewTab(); createNewTab();
} }
@@ -262,259 +249,238 @@ Item {
onLoadFailed: error => {} onLoadFailed: error => {}
} }
LazyLoader { FileBrowserModal {
id: saveBrowserLoader id: saveBrowser
active: false
FileBrowserModal { browserTitle: I18n.tr("Save Notepad File")
id: saveBrowser browserIcon: "save"
browserType: "notepad_save"
fileExtensions: ["*.txt", "*.md", "*.*"]
allowStacking: true
saveMode: true
defaultFileName: {
if (currentTab && currentTab.title && currentTab.title !== "Untitled") {
return currentTab.title;
} else if (currentTab && !currentTab.isTemporary && currentTab.filePath) {
return currentTab.filePath.split('/').pop();
} else {
return "note.txt";
}
}
browserTitle: I18n.tr("Save Notepad File") onFileSelected: path => {
browserIcon: "save" root.fileDialogOpen = false;
browserType: "notepad_save" const cleanPath = path.toString().replace(/^file:\/\//, '');
fileExtensions: ["*.txt", "*.md", "*.*"] const fileName = cleanPath.split('/').pop();
allowStacking: true const fileUrl = "file://" + cleanPath;
saveMode: true
defaultFileName: { root.currentFileName = fileName;
if (currentTab && currentTab.title && currentTab.title !== "Untitled") { root.currentFileUrl = fileUrl;
return currentTab.title;
} else if (currentTab && !currentTab.isTemporary && currentTab.filePath) { if (currentTab) {
return currentTab.filePath.split('/').pop(); NotepadStorageService.saveTabAs(NotepadStorageService.currentTabIndex, cleanPath);
} else {
return "note.txt";
}
} }
onFileSelected: path => { saveToFile(fileUrl);
root.fileDialogOpen = false;
const cleanPath = path.toString().replace(/^file:\/\//, '');
const fileName = cleanPath.split('/').pop();
const fileUrl = "file://" + cleanPath;
root.currentFileName = fileName; if (root.pendingAction === "new") {
root.currentFileUrl = fileUrl; Qt.callLater(() => {
createNewTab();
if (currentTab) { });
NotepadStorageService.saveTabAs(NotepadStorageService.currentTabIndex, cleanPath); } else if (root.pendingAction === "open") {
} Qt.callLater(() => {
root.fileDialogOpen = true;
saveToFile(fileUrl); loadBrowser.open();
});
if (root.pendingAction === "new") { } else if (root.pendingAction.startsWith("close_tab_")) {
Qt.callLater(() => { Qt.callLater(() => {
createNewTab(); var tabIndex = parseInt(root.pendingAction.split("_")[2]);
}); performCloseTab(tabIndex);
} else if (root.pendingAction === "open") { });
Qt.callLater(() => {
root.fileDialogOpen = true;
loadBrowserLoader.active = true;
if (loadBrowserLoader.item)
loadBrowserLoader.item.open();
});
} else if (root.pendingAction.startsWith("close_tab_")) {
Qt.callLater(() => {
var tabIndex = parseInt(root.pendingAction.split("_")[2]);
performCloseTab(tabIndex);
});
}
root.pendingAction = "";
close();
} }
root.pendingAction = "";
onDialogClosed: { close();
root.fileDialogOpen = false; }
}
onDialogClosed: {
root.fileDialogOpen = false;
} }
} }
LazyLoader { FileBrowserModal {
id: loadBrowserLoader id: loadBrowser
active: false
FileBrowserModal { browserTitle: I18n.tr("Open Notepad File")
id: loadBrowser browserIcon: "folder_open"
browserType: "notepad_load"
fileExtensions: ["*.txt", "*.md", "*.*"]
allowStacking: true
browserTitle: I18n.tr("Open Notepad File") onFileSelected: path => {
browserIcon: "folder_open" root.fileDialogOpen = false;
browserType: "notepad_load" const cleanPath = path.toString().replace(/^file:\/\//, '');
fileExtensions: ["*.txt", "*.md", "*.*"] const fileName = cleanPath.split('/').pop();
allowStacking: true const fileUrl = "file://" + cleanPath;
onFileSelected: path => { root.currentFileName = fileName;
root.fileDialogOpen = false; root.currentFileUrl = fileUrl;
const cleanPath = path.toString().replace(/^file:\/\//, '');
const fileName = cleanPath.split('/').pop();
const fileUrl = "file://" + cleanPath;
root.currentFileName = fileName; loadFromFile(fileUrl);
root.currentFileUrl = fileUrl; close();
}
loadFromFile(fileUrl); onDialogClosed: {
close(); root.fileDialogOpen = false;
}
onDialogClosed: {
root.fileDialogOpen = false;
}
} }
} }
LazyLoader { DankModal {
id: confirmationDialogLoader id: confirmationDialog
active: false
DankModal { width: 400
id: confirmationDialog height: 180
shouldBeVisible: false
allowStacking: true
width: 400 onBackgroundClicked: {
height: 180 close();
shouldBeVisible: false root.confirmationDialogOpen = false;
allowStacking: true }
onBackgroundClicked: { content: Component {
close(); FocusScope {
root.confirmationDialogOpen = false; anchors.fill: parent
} focus: true
content: Component { Keys.onEscapePressed: event => {
FocusScope { confirmationDialog.close();
anchors.fill: parent root.confirmationDialogOpen = false;
focus: true event.accepted = true;
}
Keys.onEscapePressed: event => { Column {
confirmationDialog.close(); anchors.centerIn: parent
root.confirmationDialogOpen = false; width: parent.width - Theme.spacingM * 2
event.accepted = true; spacing: Theme.spacingM
Row {
width: parent.width
Column {
width: parent.width - 40
spacing: Theme.spacingXS
StyledText {
text: I18n.tr("Unsaved Changes")
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
}
StyledText {
text: root.pendingAction === "new" ? I18n.tr("You have unsaved changes. Save before creating a new file?") : root.pendingAction.startsWith("close_tab_") ? I18n.tr("You have unsaved changes. Save before closing this tab?") : root.pendingAction === "load_file" || root.pendingAction === "open" ? I18n.tr("You have unsaved changes. Save before opening a file?") : I18n.tr("You have unsaved changes. Save before continuing?")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceTextMedium
width: parent.width
wrapMode: Text.Wrap
}
}
DankActionButton {
iconName: "close"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: {
confirmationDialog.close();
root.confirmationDialogOpen = false;
}
}
} }
Column { Item {
anchors.centerIn: parent width: parent.width
width: parent.width - Theme.spacingM * 2 height: 40
spacing: Theme.spacingM
Row { Row {
width: parent.width anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
Column { Rectangle {
width: parent.width - 40 width: Math.max(80, discardText.contentWidth + Theme.spacingM * 2)
spacing: Theme.spacingXS height: 36
radius: Theme.cornerRadius
color: discardArea.containsMouse ? Theme.surfaceTextHover : "transparent"
border.color: Theme.surfaceVariantAlpha
border.width: 1
StyledText { StyledText {
text: I18n.tr("Unsaved Changes") id: discardText
font.pixelSize: Theme.fontSizeLarge anchors.centerIn: parent
text: I18n.tr("Don't Save")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Medium font.weight: Font.Medium
} }
StyledText { MouseArea {
text: root.pendingAction === "new" ? I18n.tr("You have unsaved changes. Save before creating a new file?") : root.pendingAction.startsWith("close_tab_") ? I18n.tr("You have unsaved changes. Save before closing this tab?") : root.pendingAction === "load_file" || root.pendingAction === "open" ? I18n.tr("You have unsaved changes. Save before opening a file?") : I18n.tr("You have unsaved changes. Save before continuing?") id: discardArea
font.pixelSize: Theme.fontSizeMedium anchors.fill: parent
color: Theme.surfaceTextMedium hoverEnabled: true
width: parent.width cursorShape: Qt.PointingHandCursor
wrapMode: Text.Wrap onClicked: {
} confirmationDialog.close();
} root.confirmationDialogOpen = false;
if (root.pendingAction === "new") {
DankActionButton { createNewTab();
iconName: "close" } else if (root.pendingAction === "open") {
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: {
confirmationDialog.close();
root.confirmationDialogOpen = false;
}
}
}
Item {
width: parent.width
height: 40
Row {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
Rectangle {
width: Math.max(80, discardText.contentWidth + Theme.spacingM * 2)
height: 36
radius: Theme.cornerRadius
color: discardArea.containsMouse ? Theme.surfaceTextHover : "transparent"
border.color: Theme.surfaceVariantAlpha
border.width: 1
StyledText {
id: discardText
anchors.centerIn: parent
text: I18n.tr("Don't Save")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
MouseArea {
id: discardArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
confirmationDialog.close();
root.confirmationDialogOpen = false;
if (root.pendingAction === "new") {
createNewTab();
} else if (root.pendingAction === "open") {
root.fileDialogOpen = true;
loadBrowserLoader.active = true;
if (loadBrowserLoader.item)
loadBrowserLoader.item.open();
} else if (root.pendingAction === "load_file") {
performLoadFromFile(root.pendingFileUrl);
} else if (root.pendingAction.startsWith("close_tab_")) {
var tabIndex = parseInt(root.pendingAction.split("_")[2]);
performCloseTab(tabIndex);
}
root.pendingAction = "";
root.pendingFileUrl = "";
}
}
}
Rectangle {
width: Math.max(70, saveAsText.contentWidth + Theme.spacingM * 2)
height: 36
radius: Theme.cornerRadius
color: saveAsArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
StyledText {
id: saveAsText
anchors.centerIn: parent
text: I18n.tr("Save")
font.pixelSize: Theme.fontSizeMedium
color: Theme.background
font.weight: Font.Medium
}
MouseArea {
id: saveAsArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
confirmationDialog.close();
root.confirmationDialogOpen = false;
root.fileDialogOpen = true; root.fileDialogOpen = true;
saveBrowserLoader.active = true; loadBrowser.open();
if (saveBrowserLoader.item) } else if (root.pendingAction === "load_file") {
saveBrowserLoader.item.open(); performLoadFromFile(root.pendingFileUrl);
} else if (root.pendingAction.startsWith("close_tab_")) {
var tabIndex = parseInt(root.pendingAction.split("_")[2]);
performCloseTab(tabIndex);
} }
root.pendingAction = "";
root.pendingFileUrl = "";
} }
}
}
Behavior on color { Rectangle {
ColorAnimation { width: Math.max(70, saveAsText.contentWidth + Theme.spacingM * 2)
duration: Theme.shortDuration height: 36
easing.type: Theme.standardEasing radius: Theme.cornerRadius
} color: saveAsArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
StyledText {
id: saveAsText
anchors.centerIn: parent
text: I18n.tr("Save")
font.pixelSize: Theme.fontSizeMedium
color: Theme.background
font.weight: Font.Medium
}
MouseArea {
id: saveAsArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
confirmationDialog.close();
root.confirmationDialogOpen = false;
root.fileDialogOpen = true;
saveBrowser.open();
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -9,7 +9,6 @@ Column {
property string detailsText: "" property string detailsText: ""
property bool showCloseButton: false property bool showCloseButton: false
property var closePopout: null property var closePopout: null
property alias headerActions: headerActionsLoader.sourceComponent
readonly property int headerHeight: popoutHeader.visible ? popoutHeader.height : 0 readonly property int headerHeight: popoutHeader.visible ? popoutHeader.height : 0
readonly property int detailsHeight: popoutDetails.visible ? popoutDetails.implicitHeight : 0 readonly property int detailsHeight: popoutDetails.visible ? popoutDetails.implicitHeight : 0
@@ -32,40 +31,31 @@ Column {
color: Theme.surfaceText color: Theme.surfaceText
} }
Row { Rectangle {
id: closeButton
width: 32
height: 32
radius: 16
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS color: closeArea.containsMouse ? Theme.errorHover : "transparent"
visible: root.showCloseButton
Loader { DankIcon {
id: headerActionsLoader anchors.centerIn: parent
anchors.verticalCenter: parent.verticalCenter name: "close"
size: Theme.iconSize - 4
color: closeArea.containsMouse ? Theme.error : Theme.surfaceText
} }
Rectangle { MouseArea {
id: closeButton id: closeArea
width: 32 anchors.fill: parent
height: 32 hoverEnabled: true
radius: 16 cursorShape: Qt.PointingHandCursor
color: closeArea.containsMouse ? Theme.errorHover : "transparent" onPressed: {
visible: root.showCloseButton if (root.closePopout) {
root.closePopout();
DankIcon {
anchors.centerIn: parent
name: "close"
size: Theme.iconSize - 4
color: closeArea.containsMouse ? Theme.error : Theme.surfaceText
}
MouseArea {
id: closeArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: {
if (root.closePopout) {
root.closePopout();
}
} }
} }
} }

View File

@@ -1,346 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
function formatSpeed(bytesPerSec) {
if (bytesPerSec < 1024)
return bytesPerSec.toFixed(0) + " B/s";
if (bytesPerSec < 1024 * 1024)
return (bytesPerSec / 1024).toFixed(1) + " KB/s";
if (bytesPerSec < 1024 * 1024 * 1024)
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s";
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(2) + " GB/s";
}
Component.onCompleted: {
DgopService.addRef(["disk", "diskmounts"]);
}
Component.onDestruction: {
DgopService.removeRef(["disk", "diskmounts"]);
}
ColumnLayout {
anchors.fill: parent
spacing: Theme.spacingM
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 80
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
RowLayout {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingXL
Column {
Layout.fillWidth: true
spacing: Theme.spacingXS
Row {
spacing: Theme.spacingS
DankIcon {
name: "storage"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Disk I/O", "disk io header in system monitor")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
spacing: Theme.spacingL
Row {
spacing: Theme.spacingXS
StyledText {
text: I18n.tr("Read:", "disk read label")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
StyledText {
text: root.formatSpeed(DgopService.diskReadRate)
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.primary
}
}
Row {
spacing: Theme.spacingXS
StyledText {
text: I18n.tr("Write:", "disk write label")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
StyledText {
text: root.formatSpeed(DgopService.diskWriteRate)
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.warning
}
}
}
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
ColumnLayout {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
Row {
spacing: Theme.spacingS
DankIcon {
name: "folder"
size: Theme.iconSize - 2
color: Theme.secondary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Mount Points", "mount points header in system monitor")
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Bold
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Theme.outlineLight
}
DankListView {
id: mountListView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
spacing: 4
model: DgopService.diskMounts
delegate: Rectangle {
required property var modelData
required property int index
width: mountListView.width
height: 60
radius: Theme.cornerRadius
color: mountMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06) : "transparent"
readonly property real usedPct: {
const pctStr = modelData?.percent ?? "0%";
return parseFloat(pctStr.replace("%", "")) / 100;
}
MouseArea {
id: mountMouseArea
anchors.fill: parent
hoverEnabled: true
}
RowLayout {
anchors.fill: parent
anchors.margins: Theme.spacingS
spacing: Theme.spacingM
Column {
Layout.fillWidth: true
spacing: Theme.spacingXS
Row {
spacing: Theme.spacingS
DankIcon {
name: {
const mp = modelData?.mount ?? "";
if (mp === "/")
return "home";
if (mp === "/home")
return "person";
if (mp.includes("boot"))
return "memory";
if (mp.includes("media") || mp.includes("mnt"))
return "usb";
return "folder";
}
size: Theme.iconSize - 4
color: Theme.surfaceText
opacity: 0.8
}
StyledText {
text: modelData?.mount ?? ""
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
color: Theme.surfaceText
}
}
Row {
spacing: Theme.spacingS
StyledText {
text: modelData?.device ?? ""
font.pixelSize: Theme.fontSizeSmall - 2
font.family: SettingsData.monoFontFamily
color: Theme.surfaceVariantText
}
StyledText {
text: "•"
font.pixelSize: Theme.fontSizeSmall - 2
color: Theme.surfaceVariantText
}
StyledText {
text: modelData?.fstype ?? ""
font.pixelSize: Theme.fontSizeSmall - 2
font.family: SettingsData.monoFontFamily
color: Theme.surfaceVariantText
}
}
}
Column {
Layout.preferredWidth: 200
spacing: Theme.spacingXS
Rectangle {
width: parent.width
height: 8
radius: 4
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
Rectangle {
width: parent.width * Math.min(1, parent.parent.parent.parent.usedPct)
height: parent.height
radius: 4
color: {
const pct = parent.parent.parent.parent.usedPct;
if (pct > 0.95)
return Theme.error;
if (pct > 0.85)
return Theme.warning;
return Theme.primary;
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
}
}
}
}
Row {
anchors.right: parent.right
spacing: Theme.spacingS
StyledText {
text: modelData?.used ?? ""
font.pixelSize: Theme.fontSizeSmall - 2
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
}
StyledText {
text: "/"
font.pixelSize: Theme.fontSizeSmall - 2
color: Theme.surfaceVariantText
}
StyledText {
text: modelData?.size ?? ""
font.pixelSize: Theme.fontSizeSmall - 2
font.family: SettingsData.monoFontFamily
color: Theme.surfaceVariantText
}
}
}
StyledText {
Layout.preferredWidth: 50
text: modelData?.percent ?? ""
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: {
const pct = parent.parent.usedPct;
if (pct > 0.95)
return Theme.error;
if (pct > 0.85)
return Theme.warning;
return Theme.surfaceText;
}
horizontalAlignment: Text.AlignRight
}
}
}
Rectangle {
anchors.centerIn: parent
width: 300
height: 80
radius: Theme.cornerRadius
color: "transparent"
visible: DgopService.diskMounts.length === 0
Column {
anchors.centerIn: parent
spacing: Theme.spacingM
DankIcon {
name: "storage"
size: 32
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: I18n.tr("No mount points found", "empty state in disk mounts list")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,451 @@
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
Column {
function formatNetworkSpeed(bytesPerSec) {
if (bytesPerSec < 1024) {
return bytesPerSec.toFixed(0) + " B/s";
} else if (bytesPerSec < 1024 * 1024) {
return (bytesPerSec / 1024).toFixed(1) + " KB/s";
} else if (bytesPerSec < 1024 * 1024 * 1024) {
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s";
} else {
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s";
}
}
function formatDiskSpeed(bytesPerSec) {
if (bytesPerSec < 1024 * 1024) {
return (bytesPerSec / 1024).toFixed(1) + " KB/s";
} else if (bytesPerSec < 1024 * 1024 * 1024) {
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s";
} else {
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s";
}
}
anchors.fill: parent
spacing: Theme.spacingM
Component.onCompleted: {
DgopService.addRef(["cpu", "memory", "network", "disk"]);
}
Component.onDestruction: {
DgopService.removeRef(["cpu", "memory", "network", "disk"]);
}
Rectangle {
width: parent.width
height: 200
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
border.width: 1
Column {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
Row {
width: parent.width
height: 32
spacing: Theme.spacingM
StyledText {
text: "CPU"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
width: 80
height: 24
radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: `${DgopService.cpuUsage.toFixed(1)}%`
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.primary
anchors.centerIn: parent
}
}
Item {
width: parent.width - 280
height: 1
}
StyledText {
text: `${DgopService.cpuCores} cores`
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
}
DankFlickable {
clip: true
width: parent.width
height: parent.height - 40
contentHeight: coreUsageColumn.implicitHeight
Column {
id: coreUsageColumn
width: parent.width
spacing: 6
Repeater {
model: DgopService.perCoreCpuUsage
Row {
width: parent.width
height: 20
spacing: Theme.spacingS
StyledText {
text: `C${index}`
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
width: 24
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
width: parent.width - 80
height: 6
radius: 3
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
anchors.verticalCenter: parent.verticalCenter
Rectangle {
width: parent.width * Math.min(1, modelData / 100)
height: parent.height
radius: parent.radius
color: {
const usage = modelData;
if (usage > 80) {
return Theme.error;
}
if (usage > 60) {
return Theme.warning;
}
return Theme.primary;
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
}
}
}
}
StyledText {
text: modelData ? `${modelData.toFixed(0)}%` : "0%"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
width: 32
horizontalAlignment: Text.AlignRight
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
}
}
Row {
width: parent.width
height: 80
spacing: Theme.spacingM
Rectangle {
width: (parent.width - Theme.spacingM) / 2
height: 80
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
border.width: 1
Row {
anchors.centerIn: parent
spacing: Theme.spacingM
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 4
StyledText {
text: I18n.tr("Memory")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
}
StyledText {
text: `${DgopService.formatSystemMemory(DgopService.usedMemoryKB)} / ${DgopService.formatSystemMemory(DgopService.totalMemoryKB)}`
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
}
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 4
width: 120
Rectangle {
width: parent.width
height: 16
radius: 8
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
Rectangle {
width: DgopService.totalMemoryKB > 0 ? parent.width * (DgopService.usedMemoryKB / DgopService.totalMemoryKB) : 0
height: parent.height
radius: parent.radius
color: {
const usage = DgopService.totalMemoryKB > 0 ? (DgopService.usedMemoryKB / DgopService.totalMemoryKB) : 0;
if (usage > 0.9) {
return Theme.error;
}
if (usage > 0.7) {
return Theme.warning;
}
return Theme.secondary;
}
Behavior on width {
NumberAnimation {
duration: Theme.mediumDuration
}
}
}
}
StyledText {
text: DgopService.totalMemoryKB > 0 ? `${((DgopService.usedMemoryKB / DgopService.totalMemoryKB) * 100).toFixed(1)}% used` : "No data"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
}
}
Rectangle {
width: (parent.width - Theme.spacingM) / 2
height: 80
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
border.width: 1
Row {
anchors.centerIn: parent
spacing: Theme.spacingM
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 4
StyledText {
text: I18n.tr("Swap")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
}
StyledText {
text: DgopService.totalSwapKB > 0 ? `${DgopService.formatSystemMemory(DgopService.usedSwapKB)} / ${DgopService.formatSystemMemory(DgopService.totalSwapKB)}` : "No swap"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
}
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 4
width: 120
Rectangle {
width: parent.width
height: 16
radius: 8
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
Rectangle {
width: DgopService.totalSwapKB > 0 ? parent.width * (DgopService.usedSwapKB / DgopService.totalSwapKB) : 0
height: parent.height
radius: parent.radius
color: {
if (!DgopService.totalSwapKB) {
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3);
}
const usage = DgopService.usedSwapKB / DgopService.totalSwapKB;
if (usage > 0.9) {
return Theme.error;
}
if (usage > 0.7) {
return Theme.warning;
}
return Theme.info;
}
Behavior on width {
NumberAnimation {
duration: Theme.mediumDuration
}
}
}
}
StyledText {
text: DgopService.totalSwapKB > 0 ? `${((DgopService.usedSwapKB / DgopService.totalSwapKB) * 100).toFixed(1)}% used` : "N/A"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
}
}
}
Row {
width: parent.width
height: 80
spacing: Theme.spacingM
Rectangle {
width: (parent.width - Theme.spacingM) / 2
height: 80
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
border.width: 1
Column {
anchors.centerIn: parent
spacing: Theme.spacingXS
StyledText {
text: I18n.tr("Network")
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Bold
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
Row {
spacing: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
Row {
spacing: 4
StyledText {
text: "↓"
font.pixelSize: Theme.fontSizeSmall
color: Theme.info
}
StyledText {
text: DgopService.networkRxRate > 0 ? formatNetworkSpeed(DgopService.networkRxRate) : "0 B/s"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
Row {
spacing: 4
StyledText {
text: "↑"
font.pixelSize: Theme.fontSizeSmall
color: Theme.error
}
StyledText {
text: DgopService.networkTxRate > 0 ? formatNetworkSpeed(DgopService.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.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
border.width: 1
Column {
anchors.centerIn: parent
spacing: Theme.spacingXS
StyledText {
text: I18n.tr("Disk")
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Bold
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
Row {
spacing: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
Row {
spacing: 4
StyledText {
text: "R"
font.pixelSize: Theme.fontSizeSmall
color: Theme.primary
}
StyledText {
text: formatDiskSpeed(DgopService.diskReadRate)
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
Row {
spacing: 4
StyledText {
text: "W"
font.pixelSize: Theme.fontSizeSmall
color: Theme.warning
}
StyledText {
text: formatDiskSpeed(DgopService.diskWriteRate)
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
}
}
}
}
}
}
}

View File

@@ -1,304 +0,0 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
readonly property int historySize: 60
property var cpuHistory: []
property var memoryHistory: []
property var networkRxHistory: []
property var networkTxHistory: []
property var diskReadHistory: []
property var diskWriteHistory: []
function formatBytes(bytes) {
if (bytes < 1024)
return bytes.toFixed(0) + " B/s";
if (bytes < 1024 * 1024)
return (bytes / 1024).toFixed(1) + " KB/s";
if (bytes < 1024 * 1024 * 1024)
return (bytes / (1024 * 1024)).toFixed(1) + " MB/s";
return (bytes / (1024 * 1024 * 1024)).toFixed(2) + " GB/s";
}
function addToHistory(arr, val) {
const newArr = arr.slice();
newArr.push(val);
if (newArr.length > historySize)
newArr.shift();
return newArr;
}
function sampleData() {
cpuHistory = addToHistory(cpuHistory, DgopService.cpuUsage);
memoryHistory = addToHistory(memoryHistory, DgopService.memoryUsage);
networkRxHistory = addToHistory(networkRxHistory, DgopService.networkRxRate);
networkTxHistory = addToHistory(networkTxHistory, DgopService.networkTxRate);
diskReadHistory = addToHistory(diskReadHistory, DgopService.diskReadRate);
diskWriteHistory = addToHistory(diskWriteHistory, DgopService.diskWriteRate);
}
Component.onCompleted: {
DgopService.addRef(["cpu", "memory", "network", "disk", "diskmounts", "system"]);
}
Component.onDestruction: {
DgopService.removeRef(["cpu", "memory", "network", "disk", "diskmounts", "system"]);
}
SystemClock {
id: sampleClock
precision: SystemClock.Seconds
onDateChanged: {
if (date.getSeconds() % 1 === 0)
root.sampleData();
}
}
ColumnLayout {
anchors.fill: parent
spacing: Theme.spacingM
RowLayout {
Layout.fillWidth: true
Layout.preferredHeight: (root.height - Theme.spacingM * 2) / 2
spacing: Theme.spacingM
PerformanceCard {
Layout.fillWidth: true
Layout.fillHeight: true
title: "CPU"
icon: "memory"
value: DgopService.cpuUsage.toFixed(1) + "%"
subtitle: DgopService.cpuModel || (DgopService.cpuCores + " cores")
accentColor: Theme.primary
history: root.cpuHistory
maxValue: 100
showSecondary: false
extraInfo: DgopService.cpuTemperature > 0 ? (DgopService.cpuTemperature.toFixed(0) + "°C") : ""
extraInfoColor: DgopService.cpuTemperature > 80 ? Theme.error : (DgopService.cpuTemperature > 60 ? Theme.warning : Theme.surfaceVariantText)
}
PerformanceCard {
Layout.fillWidth: true
Layout.fillHeight: true
title: I18n.tr("Memory")
icon: "sd_card"
value: DgopService.memoryUsage.toFixed(1) + "%"
subtitle: DgopService.formatSystemMemory(DgopService.usedMemoryKB) + " / " + DgopService.formatSystemMemory(DgopService.totalMemoryKB)
accentColor: Theme.secondary
history: root.memoryHistory
maxValue: 100
showSecondary: false
extraInfo: DgopService.totalSwapKB > 0 ? ("Swap: " + DgopService.formatSystemMemory(DgopService.usedSwapKB)) : ""
extraInfoColor: Theme.surfaceVariantText
}
}
RowLayout {
Layout.fillWidth: true
Layout.preferredHeight: (root.height - Theme.spacingM * 2) / 2
spacing: Theme.spacingM
PerformanceCard {
Layout.fillWidth: true
Layout.fillHeight: true
title: I18n.tr("Network")
icon: "swap_horiz"
value: "↓ " + root.formatBytes(DgopService.networkRxRate)
subtitle: "↑ " + root.formatBytes(DgopService.networkTxRate)
accentColor: Theme.info
history: root.networkRxHistory
history2: root.networkTxHistory
maxValue: 0
showSecondary: true
extraInfo: ""
extraInfoColor: Theme.surfaceVariantText
}
PerformanceCard {
Layout.fillWidth: true
Layout.fillHeight: true
title: I18n.tr("Disk")
icon: "storage"
value: "R: " + root.formatBytes(DgopService.diskReadRate)
subtitle: "W: " + root.formatBytes(DgopService.diskWriteRate)
accentColor: Theme.warning
history: root.diskReadHistory
history2: root.diskWriteHistory
maxValue: 0
showSecondary: true
extraInfo: {
const rootMount = DgopService.diskMounts.find(m => m.mountpoint === "/");
if (rootMount) {
const usedPct = ((rootMount.used || 0) / Math.max(1, rootMount.total || 1) * 100).toFixed(0);
return "/ " + usedPct + "% used";
}
return "";
}
extraInfoColor: Theme.surfaceVariantText
}
}
}
component PerformanceCard: Rectangle {
id: card
property string title: ""
property string icon: ""
property string value: ""
property string subtitle: ""
property color accentColor: Theme.primary
property var history: []
property var history2: null
property real maxValue: 100
property bool showSecondary: false
property string extraInfo: ""
property color extraInfoColor: Theme.surfaceVariantText
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Theme.outlineLight
border.width: 1
Canvas {
id: graphCanvas
anchors.fill: parent
anchors.margins: 4
renderStrategy: Canvas.Cooperative
property var hist: card.history
property var hist2: card.history2
onHistChanged: requestPaint()
onHist2Changed: requestPaint()
onWidthChanged: requestPaint()
onHeightChanged: requestPaint()
onPaint: {
const ctx = getContext("2d");
ctx.reset();
ctx.clearRect(0, 0, width, height);
if (!hist || hist.length < 2)
return;
let max = card.maxValue;
if (max <= 0) {
max = 1;
for (let k = 0; k < hist.length; k++)
max = Math.max(max, hist[k]);
if (hist2) {
for (let l = 0; l < hist2.length; l++)
max = Math.max(max, hist2[l]);
}
max *= 1.1;
}
const c = card.accentColor;
const grad = ctx.createLinearGradient(0, 0, 0, height);
grad.addColorStop(0, Qt.rgba(c.r, c.g, c.b, 0.25));
grad.addColorStop(1, Qt.rgba(c.r, c.g, c.b, 0.02));
ctx.fillStyle = grad;
ctx.beginPath();
ctx.moveTo(0, height);
for (let i = 0; i < hist.length; i++) {
const x = (width / (root.historySize - 1)) * i;
const y = height - (hist[i] / max) * height * 0.8;
ctx.lineTo(x, y);
}
ctx.lineTo((width / (root.historySize - 1)) * (hist.length - 1), height);
ctx.closePath();
ctx.fill();
ctx.strokeStyle = Qt.rgba(c.r, c.g, c.b, 0.8);
ctx.lineWidth = 2;
ctx.beginPath();
for (let j = 0; j < hist.length; j++) {
const px = (width / (root.historySize - 1)) * j;
const py = height - (hist[j] / max) * height * 0.8;
j === 0 ? ctx.moveTo(px, py) : ctx.lineTo(px, py);
}
ctx.stroke();
if (hist2 && hist2.length >= 2 && card.showSecondary) {
ctx.strokeStyle = Qt.rgba(c.r, c.g, c.b, 0.4);
ctx.lineWidth = 1.5;
ctx.setLineDash([4, 4]);
ctx.beginPath();
for (let m = 0; m < hist2.length; m++) {
const sx = (width / (root.historySize - 1)) * m;
const sy = height - (hist2[m] / max) * height * 0.8;
m === 0 ? ctx.moveTo(sx, sy) : ctx.lineTo(sx, sy);
}
ctx.stroke();
ctx.setLineDash([]);
}
}
}
ColumnLayout {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingXS
RowLayout {
Layout.fillWidth: true
spacing: Theme.spacingS
DankIcon {
name: card.icon
size: Theme.iconSize
color: card.accentColor
}
StyledText {
text: card.title
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
}
Item {
Layout.fillWidth: true
}
StyledText {
text: card.extraInfo
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: card.extraInfoColor
visible: card.extraInfo.length > 0
}
}
Item {
Layout.fillHeight: true
}
StyledText {
text: card.value
font.pixelSize: Theme.fontSizeXLarge
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
}
StyledText {
text: card.subtitle
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceVariantText
elide: Text.ElideRight
Layout.fillWidth: true
}
}
}
}

View File

@@ -19,10 +19,13 @@ Popup {
const menuWidth = processContextMenu.width; const menuWidth = processContextMenu.width;
const menuHeight = processContextMenu.height; const menuHeight = processContextMenu.height;
if (finalX + menuWidth > parentWidth) if (finalX + menuWidth > parentWidth) {
finalX = Math.max(0, parentWidth - menuWidth); finalX = Math.max(0, parentWidth - menuWidth);
if (finalY + menuHeight > parentHeight) }
if (finalY + menuHeight > parentHeight) {
finalY = Math.max(0, parentHeight - menuHeight); finalY = Math.max(0, parentHeight - menuHeight);
}
} }
processContextMenu.x = finalX; processContextMenu.x = finalX;
@@ -30,19 +33,25 @@ Popup {
open(); open();
} }
width: 200 width: 180
height: menuColumn.implicitHeight + Theme.spacingS * 2 height: menuColumn.implicitHeight + Theme.spacingS * 2
padding: 0 padding: 0
modal: false modal: false
closePolicy: Popup.CloseOnEscape closePolicy: Popup.CloseOnEscape
onClosed: {
onClosed: closePolicy = Popup.CloseOnEscape closePolicy = Popup.CloseOnEscape;
onOpened: outsideClickTimer.start() }
onOpened: {
outsideClickTimer.start();
}
Timer { Timer {
id: outsideClickTimer id: outsideClickTimer
interval: 100 interval: 100
onTriggered: processContextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside onTriggered: {
processContextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside;
}
} }
background: Rectangle { background: Rectangle {
@@ -50,6 +59,8 @@ Popup {
} }
contentItem: Rectangle { contentItem: Rectangle {
id: menuContent
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency) color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
radius: Theme.cornerRadius radius: Theme.cornerRadius
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)
@@ -57,140 +68,157 @@ Popup {
Column { Column {
id: menuColumn id: menuColumn
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.margins: Theme.spacingS
spacing: 1 spacing: 1
MenuItem { Rectangle {
text: I18n.tr("Copy PID") width: parent.width
iconName: "tag" height: 28
onClicked: { radius: Theme.cornerRadius
if (processContextMenu.processData) color: copyPidArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
Quickshell.execDetached(["dms", "cl", "copy", processContextMenu.processData.pid.toString()]);
processContextMenu.close(); StyledText {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
text: I18n.tr("Copy PID")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
}
MouseArea {
id: copyPidArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (processContextMenu.processData) {
Quickshell.execDetached(["dms", "cl", "copy", processContextMenu.processData.pid.toString()]);
}
processContextMenu.close();
}
} }
} }
MenuItem { Rectangle {
text: I18n.tr("Copy Name") width: parent.width
iconName: "content_copy" height: 28
onClicked: { radius: Theme.cornerRadius
if (processContextMenu.processData) { color: copyNameArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
const name = processContextMenu.processData.command || "";
Quickshell.execDetached(["dms", "cl", "copy", name]);
}
processContextMenu.close();
}
}
MenuItem { StyledText {
text: I18n.tr("Copy Full Command") anchors.left: parent.left
iconName: "code" anchors.leftMargin: Theme.spacingS
onClicked: { anchors.verticalCenter: parent.verticalCenter
if (processContextMenu.processData) { text: I18n.tr("Copy Process Name")
const fullCmd = processContextMenu.processData.fullCommand || processContextMenu.processData.command || ""; font.pixelSize: Theme.fontSizeSmall
Quickshell.execDetached(["dms", "cl", "copy", fullCmd]); color: Theme.surfaceText
font.weight: Font.Normal
}
MouseArea {
id: copyNameArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (processContextMenu.processData) {
const processName = processContextMenu.processData.displayName || processContextMenu.processData.command;
Quickshell.execDetached(["dms", "cl", "copy", processName]);
}
processContextMenu.close();
} }
processContextMenu.close();
} }
} }
Rectangle { Rectangle {
width: parent.width - Theme.spacingS * 2 width: parent.width - Theme.spacingS * 2
height: 1 height: 5
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.15) color: "transparent"
Rectangle {
anchors.centerIn: parent
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
} }
MenuItem { Rectangle {
text: I18n.tr("Kill Process") width: parent.width
iconName: "close" height: 28
dangerous: true radius: Theme.cornerRadius
color: killArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
enabled: processContextMenu.processData enabled: processContextMenu.processData
onClicked: { opacity: enabled ? 1 : 0.5
if (processContextMenu.processData)
Quickshell.execDetached(["kill", processContextMenu.processData.pid.toString()]); StyledText {
processContextMenu.close(); anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
text: I18n.tr("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)
font.weight: Font.Normal
}
MouseArea {
id: killArea
anchors.fill: parent
hoverEnabled: true
cursorShape: parent.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: parent.enabled
onClicked: {
if (processContextMenu.processData) {
Quickshell.execDetached(["kill", processContextMenu.processData.pid.toString()]);
}
processContextMenu.close();
}
} }
} }
MenuItem { Rectangle {
text: I18n.tr("Force Kill (SIGKILL)") width: parent.width
iconName: "dangerous" height: 28
dangerous: true radius: Theme.cornerRadius
color: forceKillArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
enabled: processContextMenu.processData && processContextMenu.processData.pid > 1000 enabled: processContextMenu.processData && processContextMenu.processData.pid > 1000
onClicked: { opacity: enabled ? 1 : 0.5
if (processContextMenu.processData)
Quickshell.execDetached(["kill", "-9", processContextMenu.processData.pid.toString()]); StyledText {
processContextMenu.close(); anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
text: I18n.tr("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)
font.weight: Font.Normal
}
MouseArea {
id: forceKillArea
anchors.fill: parent
hoverEnabled: true
cursorShape: parent.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: parent.enabled
onClicked: {
if (processContextMenu.processData) {
Quickshell.execDetached(["kill", "-9", processContextMenu.processData.pid.toString()]);
}
processContextMenu.close();
}
} }
} }
} }
} }
component MenuItem: Rectangle {
id: menuItem
property string text: ""
property string iconName: ""
property bool dangerous: false
property bool enabled: true
signal clicked
width: parent.width
height: 32
radius: Theme.cornerRadius
color: {
if (!enabled)
return "transparent";
if (dangerous)
return menuItemArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent";
return menuItemArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent";
}
opacity: enabled ? 1 : 0.5
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: menuItem.iconName
size: 16
color: {
if (!menuItem.enabled)
return Theme.surfaceVariantText;
if (menuItem.dangerous && menuItemArea.containsMouse)
return Theme.error;
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: menuItem.text
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Normal
color: {
if (!menuItem.enabled)
return Theme.surfaceVariantText;
if (menuItem.dangerous && menuItemArea.containsMouse)
return Theme.error;
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: menuItemArea
anchors.fill: parent
hoverEnabled: true
cursorShape: menuItem.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: menuItem.enabled
onClicked: menuItem.clicked()
}
}
} }

View File

@@ -0,0 +1,200 @@
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
Rectangle {
id: processItem
property var process: null
property var contextMenu: null
width: parent ? parent.width : 0
height: 40
radius: Theme.cornerRadius
color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.withAlpha(Theme.primary, 0)
border.color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0)
border.width: 1
MouseArea {
id: processMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: (mouse) => {
if (mouse.button === Qt.RightButton) {
if (process && process.pid > 0 && contextMenu) {
contextMenu.processData = process;
const globalPos = processMouseArea.mapToGlobal(mouse.x, mouse.y);
const 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;
const globalPos = processMouseArea.mapToGlobal(processMouseArea.width / 2, processMouseArea.height / 2);
contextMenu.show(globalPos.x, globalPos.y);
}
}
}
Item {
anchors.fill: parent
anchors.margins: 8
DankIcon {
id: processIcon
name: DgopService.getProcessIcon(process ? process.command : "")
size: Theme.iconSize - 4
color: {
if (process && process.cpu > 80) {
return Theme.error;
}
return Theme.surfaceText;
}
opacity: 0.8
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: process ? process.displayName : ""
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
color: Theme.surfaceText
width: 250
elide: Text.ElideRight
anchors.left: processIcon.right
anchors.leftMargin: 8
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
id: cpuBadge
width: 80
height: 20
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.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08);
}
anchors.right: parent.right
anchors.rightMargin: 194
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: DgopService.formatCpuUsage(process ? process.cpu : 0)
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: {
if (process && process.cpu > 80) {
return Theme.error;
}
return Theme.surfaceText;
}
anchors.centerIn: parent
}
}
Rectangle {
id: memoryBadge
width: 80
height: 20
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.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08);
}
anchors.right: parent.right
anchors.rightMargin: 102
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: DgopService.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.surfaceText;
}
anchors.centerIn: parent
}
}
StyledText {
text: process ? process.pid.toString() : ""
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
opacity: 0.7
width: 50
horizontalAlignment: Text.AlignRight
anchors.right: parent.right
anchors.rightMargin: 40
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
id: menuButton
width: 28
height: 28
radius: Theme.cornerRadius
color: menuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : Theme.withAlpha(Theme.surfaceText, 0)
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
DankIcon {
name: "more_vert"
size: Theme.iconSize - 2
color: Theme.surfaceText
opacity: 0.6
anchors.centerIn: parent
}
MouseArea {
id: menuButtonArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (process && process.pid > 0 && contextMenu) {
contextMenu.processData = process;
const globalPos = menuButtonArea.mapToGlobal(menuButtonArea.width / 2, menuButtonArea.height);
const localPos = contextMenu.parent ? contextMenu.parent.mapFromGlobal(globalPos.x, globalPos.y) : globalPos;
contextMenu.show(localPos.x, localPos.y);
}
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}

View File

@@ -12,37 +12,30 @@ DankPopout {
property var parentWidget: null property var parentWidget: null
property var triggerScreen: null property var triggerScreen: null
property string searchText: ""
property string expandedPid: ""
function hide() { function hide() {
close(); close();
if (processContextMenu.visible) if (processContextMenu.visible) {
processContextMenu.close(); processContextMenu.close();
}
} }
function show() { function show() {
open(); open();
} }
popupWidth: 650 popupWidth: 600
popupHeight: 550 popupHeight: 600
triggerWidth: 55 triggerWidth: 55
positioning: "" positioning: ""
screen: triggerScreen screen: triggerScreen
shouldBeVisible: false shouldBeVisible: false
onBackgroundClicked: { onBackgroundClicked: {
if (processContextMenu.visible) if (processContextMenu.visible) {
processContextMenu.close(); processContextMenu.close();
close();
}
onShouldBeVisibleChanged: {
if (!shouldBeVisible) {
searchText = "";
expandedPid = "";
} }
close();
} }
Ref { Ref {
@@ -62,247 +55,55 @@ DankPopout {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: "transparent" color: "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
clip: true clip: true
antialiasing: true
smooth: true
focus: true focus: true
Component.onCompleted: { Component.onCompleted: {
if (processListPopout.shouldBeVisible) if (processListPopout.shouldBeVisible) {
forceActiveFocus(); forceActiveFocus();
}
processContextMenu.parent = processListContent; processContextMenu.parent = processListContent;
} }
Keys.onPressed: event => { Keys.onPressed: event => {
switch (event.key) { if (event.key === Qt.Key_Escape) {
case Qt.Key_Escape:
if (processListPopout.searchText.length > 0) {
processListPopout.searchText = "";
event.accepted = true;
return;
}
processListPopout.close(); processListPopout.close();
event.accepted = true; event.accepted = true;
return;
case Qt.Key_F:
if (event.modifiers & Qt.ControlModifier) {
searchField.forceActiveFocus();
event.accepted = true;
return;
}
break;
} }
} }
Connections { Connections {
target: processListPopout
function onShouldBeVisibleChanged() { function onShouldBeVisibleChanged() {
if (processListPopout.shouldBeVisible) { if (processListPopout.shouldBeVisible) {
Qt.callLater(() => processListContent.forceActiveFocus()); Qt.callLater(() => {
processListContent.forceActiveFocus();
});
} }
} }
target: processListPopout
} }
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.margins: Theme.spacingL
spacing: Theme.spacingS spacing: Theme.spacingL
RowLayout { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Theme.spacingM height: systemOverview.height + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
Row { SystemOverview {
spacing: Theme.spacingS id: systemOverview
DankIcon { anchors.centerIn: parent
name: "analytics" width: parent.width - Theme.spacingM * 2
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Processes")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Item {
Layout.fillWidth: true
}
DankTextField {
id: searchField
Layout.preferredWidth: Theme.fontSizeMedium * 14
Layout.preferredHeight: Theme.fontSizeMedium * 2.5
placeholderText: I18n.tr("Search...")
leftIconName: "search"
showClearButton: true
text: processListPopout.searchText
onTextChanged: processListPopout.searchText = text
}
}
Item {
id: statsContainer
Layout.fillWidth: true
Layout.preferredHeight: Math.max(leftInfo.height, gaugesRow.height) + Theme.spacingS
function compactMem(kb) {
if (kb < 1024 * 1024) {
const mb = kb / 1024;
return mb >= 100 ? mb.toFixed(0) + " MB" : mb.toFixed(1) + " MB";
}
const gb = kb / (1024 * 1024);
return gb >= 10 ? gb.toFixed(0) + " GB" : gb.toFixed(1) + " GB";
}
readonly property real gaugeSize: Theme.fontSizeMedium * 6.5
readonly property var enabledGpusWithTemp: {
if (!SessionData.enabledGpuPciIds || SessionData.enabledGpuPciIds.length === 0)
return [];
const result = [];
for (const gpu of DgopService.availableGpus) {
if (SessionData.enabledGpuPciIds.indexOf(gpu.pciId) !== -1 && gpu.temperature > 0)
result.push(gpu);
}
return result;
}
readonly property bool hasGpu: enabledGpusWithTemp.length > 0
Row {
id: leftInfo
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
Rectangle {
width: Theme.fontSizeMedium * 3
height: width
radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1)
SystemLogo {
anchors.centerIn: parent
width: parent.width * 0.7
height: width
colorOverride: Theme.primary
}
}
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS / 2
StyledText {
text: DgopService.hostname || "localhost"
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Bold
color: Theme.surfaceText
}
StyledText {
text: DgopService.distribution || "Linux"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
Row {
spacing: Theme.spacingS
Row {
spacing: Theme.spacingXS
DankIcon {
name: "schedule"
size: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: DgopService.shortUptime || "--"
font.pixelSize: Theme.fontSizeSmall - 1
font.family: SettingsData.monoFontFamily
color: Theme.surfaceVariantText
}
}
StyledText {
text: "•"
font.pixelSize: Theme.fontSizeSmall - 1
color: Theme.surfaceVariantText
}
StyledText {
text: DgopService.processCount + " " + I18n.tr("procs", "short for processes")
font.pixelSize: Theme.fontSizeSmall - 1
font.family: SettingsData.monoFontFamily
color: Theme.surfaceVariantText
}
}
}
}
Row {
id: gaugesRow
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
CircleGauge {
width: statsContainer.gaugeSize
height: statsContainer.gaugeSize
value: DgopService.cpuUsage / 100
label: DgopService.cpuUsage.toFixed(0) + "%"
sublabel: "CPU"
detail: DgopService.cpuTemperature > 0 ? (DgopService.cpuTemperature.toFixed(0) + "°") : ""
accentColor: DgopService.cpuUsage > 80 ? Theme.error : (DgopService.cpuUsage > 50 ? Theme.warning : Theme.primary)
detailColor: DgopService.cpuTemperature > 85 ? Theme.error : (DgopService.cpuTemperature > 70 ? Theme.warning : Theme.surfaceVariantText)
}
CircleGauge {
width: statsContainer.gaugeSize
height: statsContainer.gaugeSize
value: DgopService.memoryUsage / 100
label: statsContainer.compactMem(DgopService.usedMemoryKB)
sublabel: I18n.tr("Memory")
detail: DgopService.totalSwapKB > 0 ? ("+" + statsContainer.compactMem(DgopService.usedSwapKB)) : ""
accentColor: DgopService.memoryUsage > 90 ? Theme.error : (DgopService.memoryUsage > 70 ? Theme.warning : Theme.secondary)
}
CircleGauge {
width: statsContainer.gaugeSize
height: statsContainer.gaugeSize
visible: statsContainer.hasGpu
readonly property var gpu: statsContainer.enabledGpusWithTemp[0] ?? null
readonly property color vendorColor: {
const vendor = (gpu?.vendor ?? "").toLowerCase();
if (vendor.includes("nvidia"))
return Theme.success;
if (vendor.includes("amd"))
return Theme.error;
if (vendor.includes("intel"))
return Theme.info;
return Theme.info;
}
value: Math.min(1, (gpu?.temperature ?? 0) / 100)
label: (gpu?.temperature ?? 0) > 0 ? ((gpu?.temperature ?? 0).toFixed(0) + "°C") : "--"
sublabel: "GPU"
accentColor: {
const temp = gpu?.temperature ?? 0;
if (temp > 85)
return Theme.error;
if (temp > 70)
return Theme.warning;
return vendorColor;
}
}
} }
} }
@@ -311,176 +112,16 @@ DankPopout {
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
clip: true border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
border.width: 0
ProcessesView { ProcessListView {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.margins: Theme.spacingS
searchText: processListPopout.searchText
expandedPid: processListPopout.expandedPid
contextMenu: processContextMenu contextMenu: processContextMenu
onExpandedPidChanged: processListPopout.expandedPid = expandedPid
} }
} }
} }
} }
} }
component CircleGauge: Item {
id: gaugeRoot
property real value: 0
property string label: ""
property string sublabel: ""
property string detail: ""
property color accentColor: Theme.primary
property color detailColor: Theme.surfaceVariantText
readonly property real thickness: Math.max(4, Math.min(width, height) / 15)
readonly property real glowExtra: thickness * 1.4
readonly property real arcPadding: thickness / 1.3
readonly property real innerDiameter: width - (arcPadding + thickness + glowExtra) * 2
readonly property real maxTextWidth: innerDiameter * 0.9
readonly property real baseLabelSize: Math.round(width * 0.18)
readonly property real labelSize: Math.round(Math.min(baseLabelSize, maxTextWidth / Math.max(1, label.length * 0.65)))
readonly property real sublabelSize: Math.round(Math.min(width * 0.13, maxTextWidth / Math.max(1, sublabel.length * 0.7)))
readonly property real detailSize: Math.round(Math.min(width * 0.12, maxTextWidth / Math.max(1, detail.length * 0.65)))
property real animValue: 0
onValueChanged: animValue = Math.min(1, Math.max(0, value))
Behavior on animValue {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Easing.OutCubic
}
}
Component.onCompleted: animValue = Math.min(1, Math.max(0, value))
Canvas {
id: glowCanvas
anchors.fill: parent
onPaint: {
const ctx = getContext("2d");
ctx.reset();
const cx = width / 2;
const cy = height / 2;
const radius = (Math.min(width, height) / 2) - gaugeRoot.arcPadding;
const startAngle = -Math.PI * 0.5;
const endAngle = Math.PI * 1.5;
ctx.lineCap = "round";
if (gaugeRoot.animValue > 0) {
const prog = startAngle + (endAngle - startAngle) * gaugeRoot.animValue;
ctx.beginPath();
ctx.arc(cx, cy, radius, startAngle, prog);
ctx.strokeStyle = Qt.rgba(gaugeRoot.accentColor.r, gaugeRoot.accentColor.g, gaugeRoot.accentColor.b, 0.2);
ctx.lineWidth = gaugeRoot.thickness + gaugeRoot.glowExtra;
ctx.stroke();
}
}
Connections {
target: gaugeRoot
function onAnimValueChanged() {
glowCanvas.requestPaint();
}
function onAccentColorChanged() {
glowCanvas.requestPaint();
}
function onWidthChanged() {
glowCanvas.requestPaint();
}
function onHeightChanged() {
glowCanvas.requestPaint();
}
}
Component.onCompleted: requestPaint()
}
Canvas {
id: arcCanvas
anchors.fill: parent
onPaint: {
const ctx = getContext("2d");
ctx.reset();
const cx = width / 2;
const cy = height / 2;
const radius = (Math.min(width, height) / 2) - gaugeRoot.arcPadding;
const startAngle = -Math.PI * 0.5;
const endAngle = Math.PI * 1.5;
ctx.lineCap = "round";
ctx.beginPath();
ctx.arc(cx, cy, radius, startAngle, endAngle);
ctx.strokeStyle = Qt.rgba(gaugeRoot.accentColor.r, gaugeRoot.accentColor.g, gaugeRoot.accentColor.b, 0.1);
ctx.lineWidth = gaugeRoot.thickness;
ctx.stroke();
if (gaugeRoot.animValue > 0) {
const prog = startAngle + (endAngle - startAngle) * gaugeRoot.animValue;
ctx.beginPath();
ctx.arc(cx, cy, radius, startAngle, prog);
ctx.strokeStyle = gaugeRoot.accentColor;
ctx.lineWidth = gaugeRoot.thickness;
ctx.stroke();
}
}
Connections {
target: gaugeRoot
function onAnimValueChanged() {
arcCanvas.requestPaint();
}
function onAccentColorChanged() {
arcCanvas.requestPaint();
}
function onWidthChanged() {
arcCanvas.requestPaint();
}
function onHeightChanged() {
arcCanvas.requestPaint();
}
}
Component.onCompleted: requestPaint()
}
Column {
anchors.centerIn: parent
spacing: 1
StyledText {
text: gaugeRoot.label
font.pixelSize: gaugeRoot.labelSize
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: gaugeRoot.sublabel
font.pixelSize: gaugeRoot.sublabelSize
font.weight: Font.Medium
color: gaugeRoot.accentColor
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: gaugeRoot.detail
font.pixelSize: gaugeRoot.detailSize
font.family: SettingsData.monoFontFamily
color: gaugeRoot.detailColor
anchors.horizontalCenter: parent.horizontalCenter
visible: gaugeRoot.detail.length > 0
}
}
}
} }

View File

@@ -0,0 +1,264 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Column {
id: root
property var contextMenu: null
Component.onCompleted: {
DgopService.addRef(["processes"]);
}
Component.onDestruction: {
DgopService.removeRef(["processes"]);
}
Item {
id: columnHeaders
width: parent.width
anchors.leftMargin: 8
height: 24
Rectangle {
width: 60
height: 20
color: {
if (DgopService.currentSort === "name") {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
}
return processHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : Theme.withAlpha(Theme.surfaceText, 0);
}
radius: Theme.cornerRadius
anchors.left: parent.left
anchors.leftMargin: 0
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: I18n.tr("Process")
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: DgopService.currentSort === "name" ? Font.Bold : Font.Medium
color: Theme.surfaceText
opacity: DgopService.currentSort === "name" ? 1 : 0.7
anchors.centerIn: parent
}
MouseArea {
id: processHeaderArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
DgopService.setSortBy("name");
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
Rectangle {
width: 80
height: 20
color: {
if (DgopService.currentSort === "cpu") {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
}
return cpuHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : Theme.withAlpha(Theme.surfaceText, 0);
}
radius: Theme.cornerRadius
anchors.right: parent.right
anchors.rightMargin: 200
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: "CPU"
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: DgopService.currentSort === "cpu" ? Font.Bold : Font.Medium
color: Theme.surfaceText
opacity: DgopService.currentSort === "cpu" ? 1 : 0.7
anchors.centerIn: parent
}
MouseArea {
id: cpuHeaderArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
DgopService.setSortBy("cpu");
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
Rectangle {
width: 80
height: 20
color: {
if (DgopService.currentSort === "memory") {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
}
return memoryHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : Theme.withAlpha(Theme.surfaceText, 0);
}
radius: Theme.cornerRadius
anchors.right: parent.right
anchors.rightMargin: 112
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: "RAM"
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: DgopService.currentSort === "memory" ? Font.Bold : Font.Medium
color: Theme.surfaceText
opacity: DgopService.currentSort === "memory" ? 1 : 0.7
anchors.centerIn: parent
}
MouseArea {
id: memoryHeaderArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
DgopService.setSortBy("memory");
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
Rectangle {
width: 50
height: 20
color: {
if (DgopService.currentSort === "pid") {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
}
return pidHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : Theme.withAlpha(Theme.surfaceText, 0);
}
radius: Theme.cornerRadius
anchors.right: parent.right
anchors.rightMargin: 53
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: "PID"
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: DgopService.currentSort === "pid" ? Font.Bold : Font.Medium
color: Theme.surfaceText
opacity: DgopService.currentSort === "pid" ? 1 : 0.7
horizontalAlignment: Text.AlignHCenter
anchors.centerIn: parent
}
MouseArea {
id: pidHeaderArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
DgopService.setSortBy("pid");
}
}
Behavior on color {
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) : Theme.withAlpha(Theme.surfaceText, 0)
anchors.right: parent.right
anchors.rightMargin: 8
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: DgopService.sortDescending ? "↓" : "↑"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
anchors.centerIn: parent
}
MouseArea {
// TODO: Re-implement sort order toggle
id: sortOrderArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
DankListView {
id: processListView
property string keyRoleName: "pid"
width: parent.width
height: parent.height - columnHeaders.height
clip: true
spacing: 4
model: ScriptModel {
values: DgopService.processes
objectProp: "pid"
}
delegate: ProcessListItem {
process: modelData
contextMenu: root.contextMenu
}
}
}

View File

@@ -0,0 +1,28 @@
import QtQuick
import QtQuick.Layouts
import qs.Common
import qs.Modules.ProcessList
import qs.Services
ColumnLayout {
id: processesTab
property var contextMenu: null
anchors.fill: parent
spacing: Theme.spacingM
SystemOverview {
Layout.fillWidth: true
}
ProcessListView {
Layout.fillWidth: true
Layout.fillHeight: true
contextMenu: processesTab.contextMenu
}
ProcessContextMenu {
id: localContextMenu
}
}

View File

@@ -1,607 +0,0 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
property string searchText: ""
property string expandedPid: ""
property var contextMenu: null
property bool hoveringExpandedItem: false
readonly property bool pauseUpdates: hoveringExpandedItem || (contextMenu?.visible ?? false)
property var cachedProcesses: []
onFilteredProcessesChanged: {
if (!pauseUpdates)
cachedProcesses = filteredProcesses;
}
onPauseUpdatesChanged: {
if (!pauseUpdates)
cachedProcesses = filteredProcesses;
}
readonly property var filteredProcesses: {
if (!DgopService.allProcesses || DgopService.allProcesses.length === 0)
return [];
let procs = DgopService.allProcesses.slice();
if (searchText.length > 0) {
const search = searchText.toLowerCase();
procs = procs.filter(p => {
const cmd = (p.command || "").toLowerCase();
const fullCmd = (p.fullCommand || "").toLowerCase();
const pid = p.pid.toString();
return cmd.includes(search) || fullCmd.includes(search) || pid.includes(search);
});
}
const asc = DgopService.sortAscending;
procs.sort((a, b) => {
let valueA, valueB, result;
switch (DgopService.currentSort) {
case "cpu":
valueA = a.cpu || 0;
valueB = b.cpu || 0;
result = valueB - valueA;
break;
case "memory":
valueA = a.memoryKB || 0;
valueB = b.memoryKB || 0;
result = valueB - valueA;
break;
case "name":
valueA = (a.command || "").toLowerCase();
valueB = (b.command || "").toLowerCase();
result = valueA.localeCompare(valueB);
break;
case "pid":
valueA = a.pid || 0;
valueB = b.pid || 0;
result = valueA - valueB;
break;
default:
return 0;
}
return asc ? -result : result;
});
return procs;
}
Component.onCompleted: {
DgopService.addRef(["processes", "cpu", "memory", "system"]);
cachedProcesses = filteredProcesses;
}
Component.onDestruction: {
DgopService.removeRef(["processes", "cpu", "memory", "system"]);
}
ColumnLayout {
anchors.fill: parent
spacing: 0
Item {
Layout.fillWidth: true
Layout.preferredHeight: 36
RowLayout {
anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
spacing: 0
SortableHeader {
Layout.fillWidth: true
Layout.minimumWidth: 200
text: I18n.tr("Name")
sortKey: "name"
currentSort: DgopService.currentSort
sortAscending: DgopService.sortAscending
onClicked: DgopService.toggleSort("name")
alignment: Text.AlignLeft
}
SortableHeader {
Layout.preferredWidth: 100
text: "CPU"
sortKey: "cpu"
currentSort: DgopService.currentSort
sortAscending: DgopService.sortAscending
onClicked: DgopService.toggleSort("cpu")
}
SortableHeader {
Layout.preferredWidth: 100
text: I18n.tr("Memory")
sortKey: "memory"
currentSort: DgopService.currentSort
sortAscending: DgopService.sortAscending
onClicked: DgopService.toggleSort("memory")
}
SortableHeader {
Layout.preferredWidth: 80
text: "PID"
sortKey: "pid"
currentSort: DgopService.currentSort
sortAscending: DgopService.sortAscending
onClicked: DgopService.toggleSort("pid")
}
Item {
Layout.preferredWidth: 40
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Theme.outlineLight
}
DankListView {
id: processListView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
spacing: 2
model: ScriptModel {
values: root.cachedProcesses
objectProp: "pid"
}
delegate: ProcessItem {
required property var modelData
width: processListView.width
process: modelData
isExpanded: root.expandedPid === (modelData?.pid ?? -1).toString()
contextMenu: root.contextMenu
onToggleExpand: {
const pidStr = (modelData?.pid ?? -1).toString();
root.expandedPid = (root.expandedPid === pidStr) ? "" : pidStr;
}
onHoveringExpandedChanged: {
if (hoveringExpanded)
root.hoveringExpandedItem = true;
else
Qt.callLater(() => {
root.hoveringExpandedItem = false;
});
}
}
Rectangle {
anchors.centerIn: parent
width: 300
height: 100
radius: Theme.cornerRadius
color: "transparent"
visible: root.cachedProcesses.length === 0
Column {
anchors.centerIn: parent
spacing: Theme.spacingM
DankIcon {
name: root.searchText.length > 0 ? "search_off" : "hourglass_empty"
size: 32
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: I18n.tr("No matching processes", "empty state in process list")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
visible: root.searchText.length > 0
}
}
}
}
}
component SortableHeader: Item {
id: headerItem
property string text: ""
property string sortKey: ""
property string currentSort: ""
property bool sortAscending: false
property int alignment: Text.AlignHCenter
signal clicked
readonly property bool isActive: sortKey === currentSort
height: 36
Rectangle {
anchors.fill: parent
anchors.margins: 2
radius: Theme.cornerRadius
color: headerItem.isActive ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : (headerMouseArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.06) : "transparent")
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
RowLayout {
anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
spacing: 4
Item {
Layout.fillWidth: headerItem.alignment === Text.AlignLeft
visible: headerItem.alignment !== Text.AlignLeft
}
StyledText {
text: headerItem.text
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: headerItem.isActive ? Font.Bold : Font.Medium
color: headerItem.isActive ? Theme.primary : Theme.surfaceText
opacity: headerItem.isActive ? 1 : 0.8
}
DankIcon {
name: headerItem.sortAscending ? "arrow_upward" : "arrow_downward"
size: Theme.fontSizeSmall
color: Theme.primary
visible: headerItem.isActive
}
Item {
Layout.fillWidth: headerItem.alignment !== Text.AlignLeft
visible: headerItem.alignment === Text.AlignLeft
}
}
MouseArea {
id: headerMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: headerItem.clicked()
}
}
component ProcessItem: Rectangle {
id: processItemRoot
property var process: null
property bool isExpanded: false
property var contextMenu: null
readonly property bool hoveringExpanded: (isExpanded && processMouseArea.containsMouse) || copyMouseArea.containsMouse
signal toggleExpand
readonly property int processPid: process?.pid ?? 0
readonly property real processCpu: process?.cpu ?? 0
readonly property int processMemKB: process?.memoryKB ?? 0
readonly property string processCmd: process?.command ?? ""
readonly property string processFullCmd: process?.fullCommand ?? processCmd
height: isExpanded ? (44 + expandedRect.height + Theme.spacingXS) : 44
radius: Theme.cornerRadius
color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06) : "transparent"
border.color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
border.width: 1
clip: true
Behavior on height {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
MouseArea {
id: processMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: mouse => {
if (mouse.button === Qt.RightButton) {
if (processItemRoot.processPid > 0 && processItemRoot.contextMenu) {
processItemRoot.contextMenu.processData = processItemRoot.process;
const globalPos = processMouseArea.mapToGlobal(mouse.x, mouse.y);
const localPos = processItemRoot.contextMenu.parent ? processItemRoot.contextMenu.parent.mapFromGlobal(globalPos.x, globalPos.y) : globalPos;
processItemRoot.contextMenu.show(localPos.x, localPos.y);
}
return;
}
processItemRoot.toggleExpand();
}
}
Column {
anchors.fill: parent
spacing: 0
Item {
width: parent.width
height: 44
RowLayout {
anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
spacing: 0
Item {
Layout.fillWidth: true
Layout.minimumWidth: 200
height: parent.height
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: DgopService.getProcessIcon(processItemRoot.processCmd)
size: Theme.iconSize - 4
color: {
if (processItemRoot.processCpu > 80)
return Theme.error;
if (processItemRoot.processCpu > 50)
return Theme.warning;
return Theme.surfaceText;
}
opacity: 0.8
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: processItemRoot.processCmd
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
color: Theme.surfaceText
elide: Text.ElideRight
width: Math.min(implicitWidth, 280)
anchors.verticalCenter: parent.verticalCenter
}
}
}
Item {
Layout.preferredWidth: 100
height: parent.height
Rectangle {
anchors.centerIn: parent
width: 70
height: 24
radius: Theme.cornerRadius
color: {
if (processItemRoot.processCpu > 80)
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.15);
if (processItemRoot.processCpu > 50)
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.06);
}
StyledText {
anchors.centerIn: parent
text: DgopService.formatCpuUsage(processItemRoot.processCpu)
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: {
if (processItemRoot.processCpu > 80)
return Theme.error;
if (processItemRoot.processCpu > 50)
return Theme.warning;
return Theme.surfaceText;
}
}
}
}
Item {
Layout.preferredWidth: 100
height: parent.height
Rectangle {
anchors.centerIn: parent
width: 70
height: 24
radius: Theme.cornerRadius
color: {
if (processItemRoot.processMemKB > 2 * 1024 * 1024)
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.15);
if (processItemRoot.processMemKB > 1024 * 1024)
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.06);
}
StyledText {
anchors.centerIn: parent
text: DgopService.formatMemoryUsage(processItemRoot.processMemKB)
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: {
if (processItemRoot.processMemKB > 2 * 1024 * 1024)
return Theme.error;
if (processItemRoot.processMemKB > 1024 * 1024)
return Theme.warning;
return Theme.surfaceText;
}
}
}
}
Item {
Layout.preferredWidth: 80
height: parent.height
StyledText {
anchors.centerIn: parent
text: processItemRoot.processPid > 0 ? processItemRoot.processPid.toString() : ""
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceVariantText
}
}
Item {
Layout.preferredWidth: 40
height: parent.height
DankIcon {
anchors.centerIn: parent
name: processItemRoot.isExpanded ? "expand_less" : "expand_more"
size: Theme.iconSize - 4
color: Theme.surfaceVariantText
}
}
}
}
Rectangle {
id: expandedRect
width: parent.width - Theme.spacingM * 2
height: processItemRoot.isExpanded ? (expandedContent.implicitHeight + Theme.spacingS * 2) : 0
anchors.horizontalCenter: parent.horizontalCenter
radius: Theme.cornerRadius - 2
color: Qt.rgba(Theme.surfaceContainerHigh.r, Theme.surfaceContainerHigh.g, Theme.surfaceContainerHigh.b, 0.6)
clip: true
visible: processItemRoot.isExpanded
Behavior on height {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Column {
id: expandedContent
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Theme.spacingS
spacing: Theme.spacingXS
RowLayout {
width: parent.width
spacing: Theme.spacingS
StyledText {
id: cmdLabel
text: I18n.tr("Full Command:", "process detail label")
font.pixelSize: Theme.fontSizeSmall - 2
font.weight: Font.Bold
color: Theme.surfaceVariantText
Layout.alignment: Qt.AlignVCenter
}
StyledText {
id: cmdText
text: processItemRoot.processFullCmd
font.pixelSize: Theme.fontSizeSmall - 2
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
elide: Text.ElideMiddle
}
Rectangle {
id: copyBtn
Layout.preferredWidth: 24
Layout.preferredHeight: 24
Layout.alignment: Qt.AlignVCenter
radius: Theme.cornerRadius - 2
color: copyMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15) : "transparent"
DankIcon {
anchors.centerIn: parent
name: "content_copy"
size: 14
color: copyMouseArea.containsMouse ? Theme.primary : Theme.surfaceVariantText
}
MouseArea {
id: copyMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
Quickshell.execDetached(["dms", "cl", "copy", processItemRoot.processFullCmd]);
}
}
}
}
Row {
spacing: Theme.spacingL
Row {
spacing: Theme.spacingXS
StyledText {
text: "PPID:"
font.pixelSize: Theme.fontSizeSmall - 2
font.weight: Font.Bold
color: Theme.surfaceVariantText
}
StyledText {
text: (processItemRoot.process?.ppid ?? 0) > 0 ? processItemRoot.process.ppid.toString() : "--"
font.pixelSize: Theme.fontSizeSmall - 2
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
}
}
Row {
spacing: Theme.spacingXS
StyledText {
text: "Mem:"
font.pixelSize: Theme.fontSizeSmall - 2
font.weight: Font.Bold
color: Theme.surfaceVariantText
}
StyledText {
text: (processItemRoot.process?.memoryPercent ?? 0).toFixed(1) + "%"
font.pixelSize: Theme.fontSizeSmall - 2
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,435 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Services
import qs.Widgets
Row {
width: parent.width
spacing: Theme.spacingM
Component.onCompleted: {
DgopService.addRef(["cpu", "memory", "system"]);
}
Component.onDestruction: {
DgopService.removeRef(["cpu", "memory", "system"]);
}
Rectangle {
width: (parent.width - Theme.spacingM * 2) / 3
height: 80
radius: Theme.cornerRadius
color: {
if (DgopService.sortBy === "cpu") {
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);
} else {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08);
}
}
border.color: DgopService.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: DgopService.sortBy === "cpu" ? 2 : 1
MouseArea {
id: cpuCardMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
DgopService.setSortBy("cpu");
}
}
Column {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: 2
StyledText {
text: I18n.tr("CPU")
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: DgopService.sortBy === "cpu" ? Theme.primary : Theme.secondary
opacity: DgopService.sortBy === "cpu" ? 1 : 0.8
}
Row {
spacing: Theme.spacingS
StyledText {
text: {
if (DgopService.cpuUsage === undefined || DgopService.cpuUsage === null) {
return "--%";
}
return DgopService.cpuUsage.toFixed(1) + "%";
}
font.pixelSize: Theme.fontSizeLarge
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
width: 1
height: 20
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (DgopService.cpuTemperature === undefined || DgopService.cpuTemperature === null || DgopService.cpuTemperature <= 0) {
return "--°";
}
return Math.round(DgopService.cpuTemperature) + "°";
}
font.pixelSize: Theme.fontSizeMedium
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
color: {
if (DgopService.cpuTemperature > 80) {
return Theme.error;
}
if (DgopService.cpuTemperature > 60) {
return Theme.warning;
}
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: `${DgopService.cpuCores} cores`
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.cornerRadius
color: {
if (DgopService.sortBy === "memory") {
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);
} else {
return Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08);
}
}
border.color: DgopService.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: DgopService.sortBy === "memory" ? 2 : 1
MouseArea {
id: memoryCardMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
DgopService.setSortBy("memory");
}
}
Column {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: 2
StyledText {
text: I18n.tr("Memory")
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: DgopService.sortBy === "memory" ? Theme.primary : Theme.secondary
opacity: DgopService.sortBy === "memory" ? 1 : 0.8
}
Row {
spacing: Theme.spacingS
StyledText {
text: DgopService.formatSystemMemory(DgopService.usedMemoryKB)
font.pixelSize: Theme.fontSizeLarge
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
width: 1
height: 20
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
anchors.verticalCenter: parent.verticalCenter
visible: DgopService.totalSwapKB > 0
}
StyledText {
text: DgopService.totalSwapKB > 0 ? DgopService.formatSystemMemory(DgopService.usedSwapKB) : ""
font.pixelSize: Theme.fontSizeMedium
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
visible: DgopService.totalSwapKB > 0
}
}
StyledText {
text: {
if (DgopService.totalSwapKB > 0) {
return "of " + DgopService.formatSystemMemory(DgopService.totalMemoryKB) + " + swap";
}
return "of " + DgopService.formatSystemMemory(DgopService.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.cornerRadius
color: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
if (gpuCardMouseArea.containsMouse && DgopService.availableGpus.length > 1) {
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.16);
} else {
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08);
}
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
const vendor = gpu.vendor.toLowerCase();
if (vendor.includes("nvidia")) {
if (gpuCardMouseArea.containsMouse && DgopService.availableGpus.length > 1) {
return Qt.rgba(Theme.success.r, Theme.success.g, Theme.success.b, 0.2);
} else {
return Qt.rgba(Theme.success.r, Theme.success.g, Theme.success.b, 0.12);
}
} else if (vendor.includes("amd")) {
if (gpuCardMouseArea.containsMouse && DgopService.availableGpus.length > 1) {
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.2);
} else {
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12);
}
} else if (vendor.includes("intel")) {
if (gpuCardMouseArea.containsMouse && DgopService.availableGpus.length > 1) {
return Qt.rgba(Theme.info.r, Theme.info.g, Theme.info.b, 0.2);
} else {
return Qt.rgba(Theme.info.r, Theme.info.g, Theme.info.b, 0.12);
}
}
if (gpuCardMouseArea.containsMouse && DgopService.availableGpus.length > 1) {
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.16);
} else {
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08);
}
}
border.color: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2);
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
const vendor = gpu.vendor.toLowerCase();
if (vendor.includes("nvidia")) {
return Qt.rgba(Theme.success.r, Theme.success.g, Theme.success.b, 0.3);
} else if (vendor.includes("amd")) {
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3);
} else if (vendor.includes("intel")) {
return Qt.rgba(Theme.info.r, Theme.info.g, Theme.info.b, 0.3);
}
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2);
}
border.width: 1
MouseArea {
id: gpuCardMouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: DgopService.availableGpus.length > 1 ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: (mouse) => {
if (mouse.button === Qt.LeftButton) {
if (DgopService.availableGpus.length > 1) {
const nextIndex = (SessionData.selectedGpuIndex + 1) % DgopService.availableGpus.length;
SessionData.setSelectedGpuIndex(nextIndex);
}
} else if (mouse.button === Qt.RightButton) {
gpuContextMenu.popup();
}
}
}
Column {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: 2
StyledText {
text: I18n.tr("GPU")
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.secondary
opacity: 0.8
}
StyledText {
text: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return "No GPU";
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
// Check if temperature monitoring is enabled for this GPU
const tempEnabled = SessionData.enabledGpuPciIds && SessionData.enabledGpuPciIds.indexOf(gpu.pciId) !== -1;
const temp = gpu.temperature;
const hasTemp = tempEnabled && temp !== undefined && temp !== null && temp !== 0;
if (hasTemp) {
return Math.round(temp) + "°";
} else {
return gpu.vendor;
}
}
font.pixelSize: Theme.fontSizeLarge
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return Theme.surfaceText;
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
const tempEnabled = SessionData.enabledGpuPciIds && SessionData.enabledGpuPciIds.indexOf(gpu.pciId) !== -1;
const temp = gpu.temperature || 0;
if (tempEnabled && temp > 80) {
return Theme.error;
}
if (tempEnabled && temp > 60) {
return Theme.warning;
}
return Theme.surfaceText;
}
}
StyledText {
text: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return "No GPUs detected";
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
const tempEnabled = SessionData.enabledGpuPciIds && SessionData.enabledGpuPciIds.indexOf(gpu.pciId) !== -1;
const temp = gpu.temperature;
const hasTemp = tempEnabled && temp !== undefined && temp !== null && temp !== 0;
if (hasTemp) {
return gpu.vendor + " " + gpu.displayName;
} else {
return gpu.displayName;
}
}
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
opacity: 0.7
width: parent.parent.width - Theme.spacingM * 2
elide: Text.ElideRight
maximumLineCount: 1
}
}
Menu {
id: gpuContextMenu
MenuItem {
text: I18n.tr("Enable GPU Temperature")
checkable: true
checked: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return false;
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
if (!gpu.pciId) {
return false;
}
return SessionData.enabledGpuPciIds ? SessionData.enabledGpuPciIds.indexOf(gpu.pciId) !== -1 : false;
}
onTriggered: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return;
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
if (!gpu.pciId) {
return;
}
const enabledIds = SessionData.enabledGpuPciIds ? SessionData.enabledGpuPciIds.slice() : [];
const index = enabledIds.indexOf(gpu.pciId);
if (checked && index === -1) {
enabledIds.push(gpu.pciId);
DgopService.addGpuPciId(gpu.pciId);
} else if (!checked && index !== -1) {
enabledIds.splice(index, 1);
DgopService.removeGpuPciId(gpu.pciId);
}
SessionData.setEnabledGpuPciIds(enabledIds);
}
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}

View File

@@ -0,0 +1,591 @@
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
DankFlickable {
anchors.fill: parent
contentHeight: systemColumn.implicitHeight
clip: true
Component.onCompleted: {
DgopService.addRef(["system", "diskmounts"]);
}
Component.onDestruction: {
DgopService.removeRef(["system", "diskmounts"]);
}
Column {
id: systemColumn
width: parent.width
spacing: Theme.spacingM
Rectangle {
width: parent.width
height: systemInfoColumn.implicitHeight + 2 * Theme.spacingL
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.width: 0
Column {
id: systemInfoColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Theme.spacingL
spacing: Theme.spacingL
Row {
width: parent.width
spacing: Theme.spacingL
SystemLogo {
width: 80
height: 80
}
Column {
width: parent.width - 80 - Theme.spacingL
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
StyledText {
text: DgopService.hostname
font.pixelSize: Theme.fontSizeXLarge
font.family: SettingsData.monoFontFamily
font.weight: Font.Light
color: Theme.surfaceText
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: `${DgopService.distribution} ${DgopService.architecture} ${DgopService.kernelVersion}`
font.pixelSize: Theme.fontSizeMedium
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: `${DgopService.uptime} Boot: ${DgopService.bootTime}`
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: `Load: ${DgopService.loadAverage} ${DgopService.processCount} processes, ${DgopService.threadCount} threads`
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
Row {
width: parent.width
spacing: Theme.spacingXL
Rectangle {
width: (parent.width - Theme.spacingXL) / 2
height: hardwareColumn.implicitHeight + Theme.spacingL
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.width: 1
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
Column {
id: hardwareColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Theme.spacingM
spacing: Theme.spacingXS
Row {
width: parent.width
spacing: Theme.spacingS
DankIcon {
name: "memory"
size: Theme.iconSizeSmall
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("System")
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: DgopService.cpuModel
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
color: Theme.surfaceText
width: parent.width
elide: Text.ElideRight
wrapMode: Text.NoWrap
maximumLineCount: 1
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: DgopService.motherboard
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
width: parent.width
elide: Text.ElideRight
wrapMode: Text.NoWrap
maximumLineCount: 1
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: `BIOS ${DgopService.biosVersion}`
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
width: parent.width
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: `${DgopService.formatSystemMemory(DgopService.totalMemoryKB)} RAM`
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
width: parent.width
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle {
width: (parent.width - Theme.spacingXL) / 2
height: gpuColumn.implicitHeight + Theme.spacingL
radius: Theme.cornerRadius
color: {
const baseColor = Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency);
const hoverColor = Qt.rgba(Theme.surfaceContainerHigh.r, Theme.surfaceContainerHigh.g, Theme.surfaceContainerHigh.b, Theme.popupTransparency * 1.5);
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return gpuCardMouseArea.containsMouse && DgopService.availableGpus.length > 1 ? hoverColor : baseColor;
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
const vendor = gpu.fullName.split(' ')[0].toLowerCase();
let tintColor;
if (vendor.includes("nvidia")) {
tintColor = Theme.success;
} else if (vendor.includes("amd")) {
tintColor = Theme.error;
} else if (vendor.includes("intel")) {
tintColor = Theme.info;
} else {
return gpuCardMouseArea.containsMouse && DgopService.availableGpus.length > 1 ? hoverColor : baseColor;
}
if (gpuCardMouseArea.containsMouse && DgopService.availableGpus.length > 1) {
return Qt.rgba((hoverColor.r + tintColor.r * 0.1) / 1.1, (hoverColor.g + tintColor.g * 0.1) / 1.1, (hoverColor.b + tintColor.b * 0.1) / 1.1, 0.6);
} else {
return Qt.rgba((baseColor.r + tintColor.r * 0.08) / 1.08, (baseColor.g + tintColor.g * 0.08) / 1.08, (baseColor.b + tintColor.b * 0.08) / 1.08, 0.4);
}
}
border.width: 1
border.color: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1);
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
const vendor = gpu.fullName.split(' ')[0].toLowerCase();
if (vendor.includes("nvidia")) {
return Qt.rgba(Theme.success.r, Theme.success.g, Theme.success.b, 0.3);
} else if (vendor.includes("amd")) {
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3);
} else if (vendor.includes("intel")) {
return Qt.rgba(Theme.info.r, Theme.info.g, Theme.info.b, 0.3);
}
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1);
}
MouseArea {
id: gpuCardMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: DgopService.availableGpus.length > 1 ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
if (DgopService.availableGpus.length > 1) {
const nextIndex = (SessionData.selectedGpuIndex + 1) % DgopService.availableGpus.length;
SessionData.setSelectedGpuIndex(nextIndex);
}
}
}
Column {
id: gpuColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Theme.spacingM
spacing: Theme.spacingXS
Row {
width: parent.width
spacing: Theme.spacingS
DankIcon {
name: "auto_awesome_mosaic"
size: Theme.iconSizeSmall
color: Theme.secondary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "GPU"
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.secondary
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return "No GPUs detected";
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
return gpu.fullName;
}
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Medium
color: Theme.surfaceText
width: parent.width
elide: Text.ElideRight
maximumLineCount: 1
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return "Device: N/A";
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
return `Device: ${gpu.pciId}`;
}
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
width: parent.width
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
textFormat: Text.RichText
}
StyledText {
text: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return "Driver: N/A";
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
return `Driver: ${gpu.driver}`;
}
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
width: parent.width
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return "Temp: --°";
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
const temp = gpu.temperature;
return `Temp: ${(temp === undefined || temp === null || temp === 0) ? '--°' : `${Math.round(temp)}°C`}`;
}
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7);
}
const gpu = DgopService.availableGpus[Math.min(SessionData.selectedGpuIndex, DgopService.availableGpus.length - 1)];
const temp = gpu.temperature || 0;
if (temp > 80) {
return Theme.error;
}
if (temp > 60) {
return Theme.warning;
}
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7);
}
width: parent.width
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}
}
Rectangle {
width: parent.width
height: storageColumn.implicitHeight + 2 * Theme.spacingL
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.width: 0
Column {
id: storageColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Theme.spacingL
spacing: Theme.spacingS
Row {
width: parent.width
spacing: Theme.spacingS
DankIcon {
name: "storage"
size: Theme.iconSize
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Storage & Disks")
font.pixelSize: Theme.fontSizeLarge
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
width: parent.width
spacing: 2
Row {
width: parent.width
height: 24
spacing: Theme.spacingS
StyledText {
text: I18n.tr("Device")
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
width: parent.width * 0.25
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: I18n.tr("Mount")
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
width: parent.width * 0.2
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: I18n.tr("Size")
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
width: parent.width * 0.15
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: I18n.tr("Used")
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
width: parent.width * 0.15
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: I18n.tr("Available")
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
width: parent.width * 0.15
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: I18n.tr("Use%")
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
font.weight: Font.Bold
color: Theme.surfaceText
width: parent.width * 0.1
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
}
Repeater {
id: diskMountRepeater
model: DgopService.diskMounts
Rectangle {
width: parent.width
height: 24
radius: Theme.cornerRadius
color: diskMouseArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.04) : "transparent"
MouseArea {
id: diskMouseArea
anchors.fill: parent
hoverEnabled: true
}
Row {
anchors.fill: parent
spacing: Theme.spacingS
StyledText {
text: modelData.device
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
width: parent.width * 0.25
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: modelData.mount
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
width: parent.width * 0.2
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: modelData.size
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
width: parent.width * 0.15
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: modelData.used
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
width: parent.width * 0.15
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: modelData.avail
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
width: parent.width * 0.15
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
}
StyledText {
text: modelData.percent
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: {
const percent = parseInt(modelData.percent);
if (percent > 90) {
return Theme.error;
}
if (percent > 75) {
return Theme.warning;
}
return Theme.surfaceText;
}
width: parent.width * 0.1
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
}
}
}
}

View File

@@ -1,386 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
Component.onCompleted: {
DgopService.addRef(["system", "cpu"]);
}
Component.onDestruction: {
DgopService.removeRef(["system", "cpu"]);
}
ColumnLayout {
anchors.fill: parent
spacing: Theme.spacingM
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: systemInfoColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
ColumnLayout {
id: systemInfoColumn
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingM
Row {
spacing: Theme.spacingS
DankIcon {
name: "computer"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("System Information", "system info header in system monitor")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
GridLayout {
Layout.fillWidth: true
columns: 2
rowSpacing: Theme.spacingS
columnSpacing: Theme.spacingXL
InfoRow {
label: I18n.tr("Hostname", "system info label")
value: DgopService.hostname || "--"
}
InfoRow {
label: I18n.tr("Distribution", "system info label")
value: DgopService.distribution || "--"
}
InfoRow {
label: I18n.tr("Kernel", "system info label")
value: DgopService.kernelVersion || "--"
}
InfoRow {
label: I18n.tr("Architecture", "system info label")
value: DgopService.architecture || "--"
}
InfoRow {
label: I18n.tr("CPU")
value: DgopService.cpuModel || ("" + DgopService.cpuCores + " cores")
}
InfoRow {
label: I18n.tr("Uptime")
value: DgopService.uptime || "--"
}
InfoRow {
label: I18n.tr("Load Average", "system info label")
value: DgopService.loadAverage || "--"
}
InfoRow {
label: I18n.tr("Processes")
value: DgopService.processCount > 0 ? DgopService.processCount.toString() : "--"
}
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
ColumnLayout {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingM
Row {
spacing: Theme.spacingS
DankIcon {
name: "developer_board"
size: Theme.iconSize
color: Theme.secondary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("GPU Monitoring", "gpu section header in system monitor")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Theme.outlineLight
}
DankListView {
id: gpuListView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
spacing: 8
model: DgopService.availableGpus
delegate: Rectangle {
required property var modelData
required property int index
width: gpuListView.width
height: 80
radius: Theme.cornerRadius
color: {
const vendor = (modelData?.vendor ?? "").toLowerCase();
if (vendor.includes("nvidia"))
return Qt.rgba(Theme.success.r, Theme.success.g, Theme.success.b, 0.08);
if (vendor.includes("amd"))
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08);
if (vendor.includes("intel"))
return Qt.rgba(Theme.info.r, Theme.info.g, Theme.info.b, 0.08);
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08);
}
border.color: {
const vendor = (modelData?.vendor ?? "").toLowerCase();
if (vendor.includes("nvidia"))
return Qt.rgba(Theme.success.r, Theme.success.g, Theme.success.b, 0.2);
if (vendor.includes("amd"))
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.2);
if (vendor.includes("intel"))
return Qt.rgba(Theme.info.r, Theme.info.g, Theme.info.b, 0.2);
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2);
}
border.width: 1
readonly property bool tempEnabled: {
const pciId = modelData?.pciId ?? "";
if (!pciId)
return false;
return SessionData.enabledGpuPciIds ? SessionData.enabledGpuPciIds.indexOf(pciId) !== -1 : false;
}
RowLayout {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingM
DankIcon {
name: "developer_board"
size: Theme.iconSize + 4
color: {
const vendor = (modelData?.vendor ?? "").toLowerCase();
if (vendor.includes("nvidia"))
return Theme.success;
if (vendor.includes("amd"))
return Theme.error;
if (vendor.includes("intel"))
return Theme.info;
return Theme.surfaceVariantText;
}
}
Column {
Layout.fillWidth: true
spacing: Theme.spacingXS
StyledText {
text: modelData?.displayName ?? I18n.tr("Unknown GPU", "fallback gpu name")
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Bold
color: Theme.surfaceText
}
Row {
spacing: Theme.spacingS
StyledText {
text: modelData?.vendor ?? ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
StyledText {
text: "•"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
visible: (modelData?.driver ?? "").length > 0
}
StyledText {
text: modelData?.driver ?? ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
visible: (modelData?.driver ?? "").length > 0
}
}
StyledText {
text: modelData?.pciId ?? ""
font.pixelSize: Theme.fontSizeSmall - 2
font.family: SettingsData.monoFontFamily
color: Theme.surfaceVariantText
opacity: 0.7
}
}
Rectangle {
width: 70
height: 32
radius: Theme.cornerRadius
color: parent.parent.tempEnabled ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.15)
border.color: tempMouseArea.containsMouse ? Theme.outline : "transparent"
border.width: 1
Row {
id: tempRow
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "thermostat"
size: 16
color: {
if (!parent.parent.parent.parent.tempEnabled)
return Theme.surfaceVariantText;
const temp = modelData?.temperature ?? 0;
if (temp > 85)
return Theme.error;
if (temp > 70)
return Theme.warning;
return Theme.surfaceText;
}
opacity: parent.parent.parent.parent.tempEnabled ? 1 : 0.5
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (!parent.parent.parent.parent.tempEnabled)
return I18n.tr("Off");
const temp = modelData?.temperature ?? 0;
return temp > 0 ? (temp.toFixed(0) + "°C") : "--";
}
font.pixelSize: Theme.fontSizeSmall
font.family: parent.parent.parent.parent.tempEnabled ? SettingsData.monoFontFamily : ""
font.weight: parent.parent.parent.parent.tempEnabled ? Font.Bold : Font.Normal
color: {
if (!parent.parent.parent.parent.tempEnabled)
return Theme.surfaceVariantText;
const temp = modelData?.temperature ?? 0;
if (temp > 85)
return Theme.error;
if (temp > 70)
return Theme.warning;
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: tempMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const pciId = modelData?.pciId;
if (!pciId)
return;
const enabledIds = SessionData.enabledGpuPciIds ? SessionData.enabledGpuPciIds.slice() : [];
const idx = enabledIds.indexOf(pciId);
const wasEnabled = idx !== -1;
if (!wasEnabled) {
enabledIds.push(pciId);
DgopService.addGpuPciId(pciId);
} else {
enabledIds.splice(idx, 1);
DgopService.removeGpuPciId(pciId);
}
SessionData.setEnabledGpuPciIds(enabledIds);
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}
Rectangle {
anchors.centerIn: parent
width: 300
height: 100
radius: Theme.cornerRadius
color: "transparent"
visible: DgopService.availableGpus.length === 0
Column {
anchors.centerIn: parent
spacing: Theme.spacingM
DankIcon {
name: "developer_board_off"
size: 32
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: I18n.tr("No GPUs detected", "empty state in gpu list")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}
}
}
component InfoRow: RowLayout {
property string label: ""
property string value: ""
Layout.fillWidth: true
spacing: Theme.spacingS
StyledText {
text: label + ":"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceVariantText
Layout.preferredWidth: 100
}
StyledText {
text: value
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Theme.surfaceText
Layout.fillWidth: true
elide: Text.ElideRight
}
}
}

View File

@@ -125,33 +125,6 @@ Item {
} }
] ]
readonly property var maxPinnedOptions: [
{
text: "5",
value: 5
},
{
text: "10",
value: 10
},
{
text: "15",
value: 15
},
{
text: "25",
value: 25
},
{
text: "50",
value: 50
},
{
text: "100",
value: 100
}
]
function getMaxHistoryText(value) { function getMaxHistoryText(value) {
if (value <= 0) if (value <= 0)
return "∞"; return "∞";
@@ -179,14 +152,6 @@ Item {
return value + " " + I18n.tr("days"); return value + " " + I18n.tr("days");
} }
function getMaxPinnedText(value) {
for (let opt of maxPinnedOptions) {
if (opt.value === value)
return opt.text;
}
return value.toString();
}
function loadConfig() { function loadConfig() {
configLoaded = false; configLoaded = false;
configError = false; configError = false;
@@ -330,24 +295,6 @@ Item {
} }
} }
} }
SettingsDropdownRow {
tab: "clipboard"
tags: ["clipboard", "pinned", "max", "limit"]
settingKey: "maxPinned"
text: I18n.tr("Maximum Pinned Entries")
description: I18n.tr("Maximum number of entries that can be saved")
currentValue: root.getMaxPinnedText(root.config.maxPinned ?? 25)
options: root.maxPinnedOptions.map(opt => opt.text)
onValueChanged: value => {
for (let opt of root.maxPinnedOptions) {
if (opt.text === value) {
root.saveConfig("maxPinned", opt.value);
return;
}
}
}
}
} }
SettingsCard { SettingsCard {

View File

@@ -373,9 +373,7 @@ Item {
StyledText { StyledText {
text: { text: {
SettingsData.barConfigs; switch (barCard.modelData.position) {
const cfg = SettingsData.getBarConfig(barCard.modelData.id);
switch (cfg?.position ?? SettingsData.Position.Top) {
case SettingsData.Position.Top: case SettingsData.Position.Top:
return I18n.tr("Top"); return I18n.tr("Top");
case SettingsData.Position.Bottom: case SettingsData.Position.Bottom:
@@ -400,9 +398,7 @@ Item {
StyledText { StyledText {
text: { text: {
SettingsData.barConfigs; const prefs = barCard.modelData.screenPreferences || ["all"];
const cfg = SettingsData.getBarConfig(barCard.modelData.id);
const prefs = cfg?.screenPreferences || ["all"];
if (prefs.includes("all") || (typeof prefs[0] === "string" && prefs[0] === "all")) if (prefs.includes("all") || (typeof prefs[0] === "string" && prefs[0] === "all"))
return I18n.tr("All displays"); return I18n.tr("All displays");
return I18n.tr("%1 display(s)").replace("%1", prefs.length); return I18n.tr("%1 display(s)").replace("%1", prefs.length);
@@ -419,11 +415,9 @@ Item {
StyledText { StyledText {
text: { text: {
SettingsData.barConfigs; const left = barCard.modelData.leftWidgets?.length || 0;
const cfg = SettingsData.getBarConfig(barCard.modelData.id); const center = barCard.modelData.centerWidgets?.length || 0;
const left = cfg?.leftWidgets?.length || 0; const right = barCard.modelData.rightWidgets?.length || 0;
const center = cfg?.centerWidgets?.length || 0;
const right = cfg?.rightWidgets?.length || 0;
return I18n.tr("%1 widgets").replace("%1", left + center + right); return I18n.tr("%1 widgets").replace("%1", left + center + right);
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
@@ -434,22 +428,14 @@ Item {
text: "•" text: "•"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
visible: { visible: !barCard.modelData.enabled && barCard.modelData.id !== "default"
SettingsData.barConfigs;
const cfg = SettingsData.getBarConfig(barCard.modelData.id);
return !cfg?.enabled && barCard.modelData.id !== "default";
}
} }
StyledText { StyledText {
text: I18n.tr("Disabled") text: I18n.tr("Disabled")
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.error color: Theme.error
visible: { visible: !barCard.modelData.enabled && barCard.modelData.id !== "default"
SettingsData.barConfigs;
const cfg = SettingsData.getBarConfig(barCard.modelData.id);
return !cfg?.enabled && barCard.modelData.id !== "default";
}
} }
} }
} }
@@ -759,21 +745,6 @@ Item {
} }
} }
Rectangle {
width: parent.width
height: 1
color: Theme.outline
opacity: 0.15
}
SettingsToggleRow {
text: I18n.tr("Click Through")
checked: selectedBarConfig?.clickThrough ?? false
onToggled: toggled => SettingsData.updateBarConfig(selectedBarId, {
clickThrough: toggled
})
}
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 1 height: 1
@@ -1086,7 +1057,6 @@ Item {
} }
SettingsCard { SettingsCard {
id: shadowCard
iconName: "layers" iconName: "layers"
title: I18n.tr("Shadow", "bar shadow settings card") title: I18n.tr("Shadow", "bar shadow settings card")
visible: selectedBarConfig?.enabled visible: selectedBarConfig?.enabled
@@ -1106,7 +1076,7 @@ Item {
} }
SettingsSliderRow { SettingsSliderRow {
visible: shadowCard.shadowActive visible: parent.shadowActive
text: I18n.tr("Opacity") text: I18n.tr("Opacity")
minimum: 10 minimum: 10
maximum: 100 maximum: 100
@@ -1118,7 +1088,7 @@ Item {
} }
Column { Column {
visible: shadowCard.shadowActive visible: parent.shadowActive
width: parent.width width: parent.width
spacing: Theme.spacingS spacing: Theme.spacingS

View File

@@ -86,30 +86,10 @@ Item {
settingKey: "dockAutoHide" settingKey: "dockAutoHide"
tags: ["dock", "autohide", "hide", "hover"] tags: ["dock", "autohide", "hide", "hover"]
text: I18n.tr("Auto-hide Dock") text: I18n.tr("Auto-hide Dock")
description: I18n.tr("Always hide the dock and reveal it when hovering near the dock area") description: I18n.tr("Hide the dock when not in use and reveal it when hovering near the dock area")
checked: SettingsData.dockAutoHide checked: SettingsData.dockAutoHide
visible: SettingsData.showDock visible: SettingsData.showDock
onToggled: checked => { onToggled: checked => SettingsData.set("dockAutoHide", checked)
if (checked && SettingsData.dockSmartAutoHide) {
SettingsData.set("dockSmartAutoHide", false);
}
SettingsData.set("dockAutoHide", checked);
}
}
SettingsToggleRow {
settingKey: "dockSmartAutoHide"
tags: ["dock", "smart", "autohide", "windows", "overlap", "intelligent"]
text: I18n.tr("Intelligent Auto-hide")
description: I18n.tr("Show dock when floating windows don't overlap its area")
checked: SettingsData.dockSmartAutoHide
visible: SettingsData.showDock && (CompositorService.isNiri || CompositorService.isHyprland)
onToggled: checked => {
if (checked && SettingsData.dockAutoHide) {
SettingsData.set("dockAutoHide", false);
}
SettingsData.set("dockSmartAutoHide", checked);
}
} }
SettingsToggleRow { SettingsToggleRow {

View File

@@ -131,15 +131,6 @@ Item {
onToggled: checked => SettingsData.set("lockBeforeSuspend", checked) onToggled: checked => SettingsData.set("lockBeforeSuspend", checked)
} }
SettingsToggleRow {
settingKey: "lockScreenPowerOffMonitorsOnLock"
tags: ["lock", "screen", "monitor", "display", "dpms", "power"]
text: I18n.tr("Power off monitors on lock")
description: I18n.tr("Turn off all displays immediately when the lock screen activates")
checked: SettingsData.lockScreenPowerOffMonitorsOnLock
onToggled: checked => SettingsData.set("lockScreenPowerOffMonitorsOnLock", checked)
}
SettingsToggleRow { SettingsToggleRow {
settingKey: "enableFprint" settingKey: "enableFprint"
tags: ["lock", "screen", "fingerprint", "authentication", "biometric", "fprint"] tags: ["lock", "screen", "fingerprint", "authentication", "biometric", "fprint"]

View File

@@ -199,46 +199,6 @@ Item {
opacity: 0.15 opacity: 0.15
} }
SettingsButtonGroupRow {
text: I18n.tr("Occupied Color")
model: ["sec", "s", "sc", "sch", "none"]
visible: CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isDwl
buttonHeight: 22
minButtonWidth: 36
buttonPadding: Theme.spacingS
checkIconSize: Theme.iconSizeSmall - 2
textSize: Theme.fontSizeSmall - 1
spacing: 1
currentIndex: {
switch (SettingsData.wokspaceColorMode) {
case "s":
return 1;
case "sc":
return 2;
case "sch":
return 3;
case "none":
return 4;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
const modes = ["default", "s", "sc", "sch", "none"];
SettingsData.set("workspaceOccupiedColorMode", modes[index]);
}
}
Rectangle {
width: parent.width
height: 1
color: Theme.outline
opacity: 0.15
visible: CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isDwl
}
SettingsButtonGroupRow { SettingsButtonGroupRow {
text: I18n.tr("Unfocused Color") text: I18n.tr("Unfocused Color")
model: ["def", "s", "sc", "sch"] model: ["def", "s", "sc", "sch"]

View File

@@ -11,7 +11,7 @@ Singleton {
id: root id: root
readonly property string currentVersion: "1.2" readonly property string currentVersion: "1.2"
readonly property bool changelogEnabled: false readonly property bool changelogEnabled: true
readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)) + "/DankMaterialShell" readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)) + "/DankMaterialShell"
readonly property string changelogMarkerPath: configDir + "/.changelog-" + currentVersion readonly property string changelogMarkerPath: configDir + "/.changelog-" + currentVersion

View File

@@ -64,7 +64,7 @@ Singleton {
property bool screensaverInhibited: false property bool screensaverInhibited: false
property var screensaverInhibitors: [] property var screensaverInhibitors: []
property var activeSubscriptions: ["network", "network.credentials", "loginctl", "freedesktop", "freedesktop.screensaver", "gamma", "bluetooth", "bluetooth.pairing", "dwl", "brightness", "wlroutput", "evdev", "browser", "dbus"] property var activeSubscriptions: ["network", "network.credentials", "loginctl", "freedesktop", "freedesktop.screensaver", "gamma", "bluetooth", "bluetooth.pairing", "dwl", "brightness", "wlroutput", "evdev", "browser"]
Component.onCompleted: { Component.onCompleted: {
if (socketPath && socketPath.length > 0) { if (socketPath && socketPath.length > 0) {
@@ -191,19 +191,17 @@ Singleton {
if (!line || line.length === 0) if (!line || line.length === 0)
return; return;
let response;
try { try {
response = JSON.parse(line); const response = JSON.parse(line);
const isClipboard = clipboardRequestIds[response.id];
if (isClipboard)
delete clipboardRequestIds[response.id];
else
console.log("DMSService: Request socket <<", line);
handleResponse(response);
} catch (e) { } catch (e) {
console.warn("DMSService: Failed to parse request response:", line.substring(0, 100)); console.warn("DMSService: Failed to parse request response");
return;
} }
const isClipboard = clipboardRequestIds[response.id];
if (isClipboard)
delete clipboardRequestIds[response.id];
else
console.log("DMSService: Request socket <<", line);
handleResponse(response);
} }
} }
} }
@@ -225,16 +223,14 @@ Singleton {
if (!line || line.length === 0) if (!line || line.length === 0)
return; return;
let response;
try { try {
response = JSON.parse(line); const response = JSON.parse(line);
if (!line.includes("clipboard"))
console.log("DMSService: Subscribe socket <<", line);
handleSubscriptionEvent(response);
} catch (e) { } catch (e) {
console.warn("DMSService: Failed to parse subscription event:", line.substring(0, 100)); console.warn("DMSService: Failed to parse subscription event");
return;
} }
if (!line.includes("clipboard"))
console.log("DMSService: Subscribe socket <<", line);
handleSubscriptionEvent(response);
} }
} }
} }
@@ -304,7 +300,7 @@ Singleton {
excludeServices = [excludeServices]; excludeServices = [excludeServices];
} }
const allServices = ["network", "loginctl", "freedesktop", "gamma", "bluetooth", "cups", "dwl", "brightness", "extworkspace", "browser", "dbus"]; const allServices = ["network", "loginctl", "freedesktop", "gamma", "bluetooth", "cups", "dwl", "brightness", "extworkspace", "browser"];
const filtered = allServices.filter(s => !excludeServices.includes(s)); const filtered = allServices.filter(s => !excludeServices.includes(s));
subscribe(filtered); subscribe(filtered);
} }
@@ -387,8 +383,6 @@ Singleton {
screensaverInhibited = data.inhibited || false; screensaverInhibited = data.inhibited || false;
screensaverInhibitors = data.inhibitors || []; screensaverInhibitors = data.inhibitors || [];
screensaverStateUpdate(data); screensaverStateUpdate(data);
} else if (service === "dbus") {
dbusSignalReceived(data.subscriptionId || "", data);
} }
} }
@@ -652,89 +646,4 @@ Singleton {
"token": token "token": token
}, callback); }, callback);
} }
signal dbusSignalReceived(string subscriptionId, var data)
property var dbusSubscriptions: ({})
function dbusCall(bus, dest, path, iface, method, args, callback) {
sendRequest("dbus.call", {
"bus": bus,
"dest": dest,
"path": path,
"interface": iface,
"method": method,
"args": args || []
}, callback);
}
function dbusGetProperty(bus, dest, path, iface, property, callback) {
sendRequest("dbus.getProperty", {
"bus": bus,
"dest": dest,
"path": path,
"interface": iface,
"property": property
}, callback);
}
function dbusSetProperty(bus, dest, path, iface, property, value, callback) {
sendRequest("dbus.setProperty", {
"bus": bus,
"dest": dest,
"path": path,
"interface": iface,
"property": property,
"value": value
}, callback);
}
function dbusGetAllProperties(bus, dest, path, iface, callback) {
sendRequest("dbus.getAllProperties", {
"bus": bus,
"dest": dest,
"path": path,
"interface": iface
}, callback);
}
function dbusIntrospect(bus, dest, path, callback) {
sendRequest("dbus.introspect", {
"bus": bus,
"dest": dest,
"path": path || "/"
}, callback);
}
function dbusListNames(bus, callback) {
sendRequest("dbus.listNames", {
"bus": bus
}, callback);
}
function dbusSubscribe(bus, sender, path, iface, member, callback) {
sendRequest("dbus.subscribe", {
"bus": bus,
"sender": sender || "",
"path": path || "",
"interface": iface || "",
"member": member || ""
}, response => {
if (!response.error && response.result?.subscriptionId) {
dbusSubscriptions[response.result.subscriptionId] = true;
}
if (callback) callback(response);
});
}
function dbusUnsubscribe(subscriptionId, callback) {
sendRequest("dbus.unsubscribe", {
"subscriptionId": subscriptionId
}, response => {
if (!response.error) {
delete dbusSubscriptions[subscriptionId];
}
if (callback) callback(response);
});
}
} }

View File

@@ -21,7 +21,6 @@ Singleton {
property int processLimit: 20 property int processLimit: 20
property string processSort: "cpu" property string processSort: "cpu"
property bool noCpu: false property bool noCpu: false
property int dgopProcessPid: 0
// Cursor data for accurate CPU calculations // Cursor data for accurate CPU calculations
property string cpuCursor: "" property string cpuCursor: ""
@@ -60,7 +59,6 @@ Singleton {
property var processes: [] property var processes: []
property var allProcesses: [] property var allProcesses: []
property string currentSort: "cpu" property string currentSort: "cpu"
property bool sortAscending: false
property var availableGpus: [] property var availableGpus: []
property string kernelVersion: "" property string kernelVersion: ""
@@ -95,8 +93,10 @@ Singleton {
if (modules) { if (modules) {
const modulesToAdd = Array.isArray(modules) ? modules : [modules]; const modulesToAdd = Array.isArray(modules) ? modules : [modules];
for (const module of modulesToAdd) { for (const module of modulesToAdd) {
// Increment reference count for this module
const currentCount = moduleRefCounts[module] || 0; const currentCount = moduleRefCounts[module] || 0;
moduleRefCounts[module] = currentCount + 1; moduleRefCounts[module] = currentCount + 1;
console.log("Adding ref for module:", module, "count:", moduleRefCounts[module]);
// Add to enabled modules if not already there // Add to enabled modules if not already there
if (enabledModules.indexOf(module) === -1) { if (enabledModules.indexOf(module) === -1) {
@@ -126,13 +126,17 @@ Singleton {
for (const module of modulesToRemove) { for (const module of modulesToRemove) {
const currentCount = moduleRefCounts[module] || 0; const currentCount = moduleRefCounts[module] || 0;
if (currentCount > 1) { if (currentCount > 1) {
// Decrement reference count
moduleRefCounts[module] = currentCount - 1; moduleRefCounts[module] = currentCount - 1;
console.log("Removing ref for module:", module, "count:", moduleRefCounts[module]);
} else if (currentCount === 1) { } else if (currentCount === 1) {
// Remove completely when count reaches 0
delete moduleRefCounts[module]; delete moduleRefCounts[module];
const index = enabledModules.indexOf(module); const index = enabledModules.indexOf(module);
if (index > -1) { if (index > -1) {
enabledModules.splice(index, 1); enabledModules.splice(index, 1);
modulesChanged = true; modulesChanged = true;
console.log("Disabling module:", module, "(no more refs)");
} }
} }
} }
@@ -167,13 +171,17 @@ Singleton {
gpuPciIds = gpuPciIds.concat([pciId]); gpuPciIds = gpuPciIds.concat([pciId]);
} }
console.log("Adding GPU PCI ID ref:", pciId, "count:", gpuPciIdRefCounts[pciId]);
// Force property change notification
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts); gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts);
} }
function removeGpuPciId(pciId) { function removeGpuPciId(pciId) {
const currentCount = gpuPciIdRefCounts[pciId] || 0; const currentCount = gpuPciIdRefCounts[pciId] || 0;
if (currentCount > 1) { if (currentCount > 1) {
// Decrement reference count
gpuPciIdRefCounts[pciId] = currentCount - 1; gpuPciIdRefCounts[pciId] = currentCount - 1;
console.log("Removing GPU PCI ID ref:", pciId, "count:", gpuPciIdRefCounts[pciId]);
} else if (currentCount === 1) { } else if (currentCount === 1) {
// Remove completely when count reaches 0 // Remove completely when count reaches 0
delete gpuPciIdRefCounts[pciId]; delete gpuPciIdRefCounts[pciId];
@@ -195,6 +203,8 @@ Singleton {
} }
availableGpus = updatedGpus; availableGpus = updatedGpus;
} }
console.log("Removing GPU PCI ID completely:", pciId);
} }
// Force property change notification // Force property change notification
@@ -379,12 +389,8 @@ Singleton {
if (data.processes && Array.isArray(data.processes)) { if (data.processes && Array.isArray(data.processes)) {
const newProcesses = []; const newProcesses = [];
processSampleCount++; processSampleCount++;
const ourPid = dgopProcessPid;
for (const proc of data.processes) { for (const proc of data.processes) {
if (ourPid > 0 && proc.pid === ourPid)
continue;
const cpuUsage = processSampleCount >= 2 ? (proc.cpu || 0) : 0; const cpuUsage = processSampleCount >= 2 ? (proc.cpu || 0) : 0;
newProcesses.push({ newProcesses.push({
@@ -571,55 +577,39 @@ Singleton {
function setSortBy(newSortBy) { function setSortBy(newSortBy) {
if (newSortBy !== currentSort) { if (newSortBy !== currentSort) {
currentSort = newSortBy; currentSort = newSortBy;
sortAscending = false;
applySorting(); applySorting();
} }
} }
function toggleSort(column) {
if (column === currentSort) {
sortAscending = !sortAscending;
} else {
currentSort = column;
sortAscending = false;
}
applySorting();
}
function applySorting() { function applySorting() {
if (!allProcesses || allProcesses.length === 0) if (!allProcesses || allProcesses.length === 0) {
return; return;
}
const asc = sortAscending;
const sorted = allProcesses.slice(); const sorted = allProcesses.slice();
sorted.sort((a, b) => { sorted.sort((a, b) => {
let valueA, valueB, result; let valueA, valueB;
switch (currentSort) { switch (currentSort) {
case "cpu": case "cpu":
valueA = a.cpu || 0; valueA = a.cpu || 0;
valueB = b.cpu || 0; valueB = b.cpu || 0;
result = valueB - valueA; return valueB - valueA;
break;
case "memory": case "memory":
valueA = a.memoryKB || 0; valueA = a.memoryKB || 0;
valueB = b.memoryKB || 0; valueB = b.memoryKB || 0;
result = valueB - valueA; return valueB - valueA;
break;
case "name": case "name":
valueA = (a.command || "").toLowerCase(); valueA = (a.command || "").toLowerCase();
valueB = (b.command || "").toLowerCase(); valueB = (b.command || "").toLowerCase();
result = valueA.localeCompare(valueB); return valueA.localeCompare(valueB);
break;
case "pid": case "pid":
valueA = a.pid || 0; valueA = a.pid || 0;
valueB = b.pid || 0; valueB = b.pid || 0;
result = valueA - valueB; return valueA - valueB;
break;
default: default:
return 0; return 0;
} }
return asc ? -result : result;
}); });
processes = sorted.slice(0, processLimit); processes = sorted.slice(0, processLimit);
@@ -638,7 +628,10 @@ Singleton {
id: dgopProcess id: dgopProcess
command: root.buildDgopCommand() command: root.buildDgopCommand()
running: false running: false
onStarted: dgopProcessPid = processId ?? 0 onCommandChanged:
//console.log("DgopService command:", JSON.stringify(command))
{}
onExited: exitCode => { onExited: exitCode => {
if (exitCode !== 0) { if (exitCode !== 0) {
console.warn("Dgop process failed with exit code:", exitCode); console.warn("Dgop process failed with exit code:", exitCode);

View File

@@ -556,33 +556,6 @@ Singleton {
return loadPlugin(pluginId, true); return loadPlugin(pluginId, true);
} }
function togglePlugin(pluginId) {
let instance = pluginInstances[pluginId];
// Lazy instantiate daemon plugins on first toggle
// This respects the daemon lifecycle (not instantiated on load)
// while supporting toggle functionality for slideout-capable daemons
if (!instance && pluginDaemonComponents[pluginId]) {
const comp = pluginDaemonComponents[pluginId];
const newInstance = comp.createObject(root, {
"pluginId": pluginId,
"pluginService": root
});
if (newInstance) {
const newInstances = Object.assign({}, pluginInstances);
newInstances[pluginId] = newInstance;
pluginInstances = newInstances;
instance = newInstance;
}
}
if (instance && typeof instance.toggle === "function") {
instance.toggle();
return true;
}
return false;
}
function savePluginData(pluginId, key, value) { function savePluginData(pluginId, key, value) {
SettingsData.setPluginSetting(pluginId, key, value); SettingsData.setPluginSetting(pluginId, key, value);
pluginDataChanged(pluginId); pluginDataChanged(pluginId);

View File

@@ -1 +1 @@
v1.4-unstable v1.2.3

View File

@@ -13,7 +13,6 @@ StyledRect {
property bool enabled: true property bool enabled: true
property int buttonSize: 32 property int buttonSize: 32
property var tooltipText: null property var tooltipText: null
property string tooltipSide: "bottom"
signal clicked signal clicked
signal entered signal entered
@@ -39,6 +38,5 @@ StyledRect {
onEntered: root.entered() onEntered: root.entered()
onExited: root.exited() onExited: root.exited()
tooltipText: root.tooltipText tooltipText: root.tooltipText
tooltipSide: root.tooltipSide
} }
} }

View File

@@ -59,6 +59,7 @@ Flow {
animationTimer.restart(); animationTimer.restart();
} else { } else {
const oldIndex = currentIndex; const oldIndex = currentIndex;
currentIndex = index;
selectionChanged(index, true); selectionChanged(index, true);
if (oldIndex !== index && oldIndex >= 0) { if (oldIndex !== index && oldIndex >= 0) {
selectionChanged(oldIndex, false); selectionChanged(oldIndex, false);

View File

@@ -8,7 +8,6 @@ MouseArea {
property color stateColor: Theme.surfaceText property color stateColor: Theme.surfaceText
property real cornerRadius: parent && parent.radius !== undefined ? parent.radius : Theme.cornerRadius property real cornerRadius: parent && parent.radius !== undefined ? parent.radius : Theme.cornerRadius
property var tooltipText: null property var tooltipText: null
property string tooltipSide: "bottom"
readonly property real stateOpacity: disabled ? 0 : pressed ? 0.12 : containsMouse ? 0.08 : 0 readonly property real stateOpacity: disabled ? 0 : pressed ? 0.12 : containsMouse ? 0.08 : 0
@@ -27,7 +26,7 @@ MouseArea {
interval: 400 interval: 400
repeat: false repeat: false
onTriggered: { onTriggered: {
tooltip.show(root.tooltipText, root, 0, 0, root.tooltipSide); tooltip.show(root.tooltipText, root, 0, 0, "bottom");
} }
} }

View File

@@ -202,7 +202,7 @@
{ {
"scope": ["keyword"], "scope": ["keyword"],
"settings": { "settings": {
"foreground": "{{dank16.color6.dark.hex}}" "foreground": "{{dank16.color5.dark.hex}}"
} }
}, },
{ {
@@ -320,7 +320,7 @@
"foreground": "{{dank16.color12.dark.hex}}" "foreground": "{{dank16.color12.dark.hex}}"
}, },
"keyword": { "keyword": {
"foreground": "{{dank16.color6.dark.hex}}" "foreground": "{{dank16.color5.dark.hex}}"
}, },
"comment": { "comment": {
"foreground": "{{dank16.color8.dark.hex}}" "foreground": "{{dank16.color8.dark.hex}}"

View File

@@ -148,7 +148,7 @@
{ {
"scope": ["keyword"], "scope": ["keyword"],
"settings": { "settings": {
"foreground": "{{dank16.color6.default.hex}}" "foreground": "{{dank16.color5.default.hex}}"
} }
}, },
{ {
@@ -272,7 +272,7 @@
"foreground": "{{dank16.color12.default.hex}}" "foreground": "{{dank16.color12.default.hex}}"
}, },
"keyword": { "keyword": {
"foreground": "{{dank16.color6.default.hex}}" "foreground": "{{dank16.color5.default.hex}}"
}, },
"comment": { "comment": {
"foreground": "{{colors.outline.default.hex}}" "foreground": "{{colors.outline.default.hex}}"

View File

@@ -190,7 +190,7 @@
"storage.type" "storage.type"
], ],
"settings": { "settings": {
"foreground": "{{dank16.color6.light.hex}}" "foreground": "{{dank16.color5.light.hex}}"
} }
}, },
{ {
@@ -444,7 +444,7 @@
"foreground": "{{colors.outline.light.hex}}" "foreground": "{{colors.outline.light.hex}}"
}, },
"keyword": { "keyword": {
"foreground": "{{dank16.color6.light.hex}}" "foreground": "{{dank16.color5.light.hex}}"
}, },
"operator": { "operator": {
"foreground": "{{colors.on_surface.light.hex}}" "foreground": "{{colors.on_surface.light.hex}}"

View File

@@ -24,8 +24,7 @@ LANGUAGES = {
"es": "es.json", "es": "es.json",
"he": "he.json", "he": "he.json",
"hu": "hu.json", "hu": "hu.json",
"fa": "fa.json", "fa": "fa.json"
"fr": "fr.json"
} }
def error(msg): def error(msg):

File diff suppressed because it is too large Load Diff

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "Mostrar siempre el porcentaje" "Always Show Percentage": "Mostrar siempre el porcentaje"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "Iconos fijos" "Always on icons": "Iconos fijos"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "Borrar todos los trabajos" "Clear All Jobs": "Borrar todos los trabajos"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "Limpiar todo el historial cuando el servidor inicia" "Clear all history when server starts": "Limpiar todo el historial cuando el servidor inicia"
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "" "Copy": ""
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "Copiar ID del Proceso" "Copy PID": "Copiar ID del Proceso"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "Eliminar impresora" "Delete Printer": "Eliminar impresora"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "Eliminar VPN" "Delete VPN": "Eliminar VPN"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "Uso de disco" "Disk Usage": "Uso de disco"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "Descartar" "Dismiss": "Descartar"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "Empresa" "Enterprise": "Empresa"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "Error" "Error": "Error"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "Error al cancelar el trabajo seleccionado" "Failed to cancel selected job": "Error al cancelar el trabajo seleccionado"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "Hubo un error al conectar con la VPN" "Failed to connect VPN": "Hubo un error al conectar con la VPN"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "Error al pausar la impresora" "Failed to pause printer": "Error al pausar la impresora"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "Error al imprimir la página de prueba" "Failed to print test page": "Error al imprimir la página de prueba"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "Error al iniciar la conexión con %1" "Failed to start connection to %1": "Error al iniciar la conexión con %1"
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "Error al actualizar VPN" "Failed to update VPN": "Error al actualizar VPN"
}, },
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "Forzar HDR" "Force HDR": "Forzar HDR"
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "Forzar terminar el proceso" "Force Kill Process": "Forzar terminar el proceso"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "Control de gamma no disponible. Requiere DMS API v6+." "Gamma control not available. Requires DMS API v6+.": "Control de gamma no disponible. Requiere DMS API v6+."
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "GitHub" "GitHub": "GitHub"
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "Ajustes de historial" "History Settings": "Ajustes de historial"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "Duración de pulsación" "Hold Duration": "Duración de pulsación"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "Instalar complementos de los registros de complementos DMS" "Install plugins from the DMS plugin registry": "Instalar complementos de los registros de complementos DMS"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "Interfaz:" "Interface:": "Interfaz:"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "Trabajos:" "Jobs: ": "Trabajos:"
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "Mantener despierto" "Keep Awake": "Mantener despierto"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "Historial máxima" "Maximum History": "Historial máxima"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "Número máximo de entradas del portapapeles a conservar" "Maximum number of clipboard entries to keep": "Número máximo de entradas del portapapeles a conservar"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "Tamaño máximo por entrada en el portapapeles" "Maximum size per clipboard entry": "Tamaño máximo por entrada en el portapapeles"
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "No se encontraron impresoras" "No printers found": "No se encontraron impresoras"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "No hay variantes creadas. Haga clic en Añadir para crear un nuevo widget de monitor." "No variants created. Click Add to create a new monitor widget.": "No hay variantes creadas. Haga clic en Añadir para crear un nuevo widget de monitor."
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "Posición OSD" "OSD Position": "Posición OSD"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "Apagado" "Off": "Apagado"
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "Porcentaje" "Percentage": "Porcentaje"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "Permiso denegado para poner la imagen de perfil." "Permission denied to set profile image.": "Permiso denegado para poner la imagen de perfil."
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "Perfil de Energía Degradada" "Power Profile Degradation": "Perfil de Energía Degradada"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "Gestión del perfil de potencia disponible" "Power profile management available": "Gestión del perfil de potencia disponible"
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "Conteo de procesos" "Process Count": "Conteo de procesos"
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "Procesando" "Processing": "Procesando"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "Configuraciones guardadas" "Saved Configurations": "Configuraciones guardadas"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "Escala" "Scale": "Escala"
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "Ciencia" "Science": "Ciencia"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "Compartir pantalla" "Screen sharing": "Compartir pantalla"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "Oscurecer el fondo al abrir un modal" "Show darkened overlay behind modal dialogs": "Oscurecer el fondo al abrir un modal"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Mostrar la superposición del lanzador al escribir en la vista general de Niri. Desactivar para utilizar otro lanzador." "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Mostrar la superposición del lanzador al escribir en la vista general de Niri. Desactivar para utilizar otro lanzador."
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Este widget evita que la GPU entre en estados de apagado y puede afectar significativamente la batería en portátiles. No se recomienda usarlo en portátiles con gráficos híbridos." "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Este widget evita que la GPU entre en estados de apagado y puede afectar significativamente la batería en portátiles. No se recomienda usarlo en portátiles con gráficos híbridos."
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "Esto eliminará permanentemente todo el historial del portapapeles." "This will permanently delete all clipboard history.": "Esto eliminará permanentemente todo el historial del portapapeles."
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "Mosaico" "Tiling": "Mosaico"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "" "Trigger Prefix": ""
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "Apagar monitores después de" "Turn off monitors after": "Apagar monitores después de"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "Actualizar complemento" "Update Plugin": "Actualizar complemento"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "" "Urgent Color": ""
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "dgop no disponible" "dgop not available": "dgop no disponible"
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl existe pero no está incluido en config.kdl. Las combinaciones de teclas personalizadas no funcionarán hasta que esto se solucione." "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl existe pero no está incluido en config.kdl. Las combinaciones de teclas personalizadas no funcionarán hasta que esto se solucione."
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "No se han encontrado plugins" "No plugins found": "No se han encontrado plugins"
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "No se han encontrado temas" "No themes found": "No se han encontrado temas"
}, },
"events": { "events": {
"events": "eventos" "events": "eventos"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "archivos" "files": "archivos"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "Temas de color inspirados en Material Design" "Material Design inspired color themes": "Temas de color inspirados en Material Design"
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "" "Back": ""
}, },
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "minutos" "minutes": "minutos"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "ms" "ms": "ms"
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "Buscar complementos..." "Search plugins...": "Buscar complementos..."
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "Elegir foto de perfil" "Select Profile Image": "Elegir foto de perfil"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "" "Intensity": ""
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "fuente" "source": "fuente"
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "Monitor del sistema" "System Monitor": "Monitor del sistema"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "Instalar tema de colores desde el repositorio de temas de DMS" "Install color themes from the DMS theme registry": "Instalar tema de colores desde el repositorio de temas de DMS"
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "Actualizar dms para integración con NM." "update dms for NM integration.": "Actualizar dms para integración con NM."
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "" "Requires %1": ""
}, },

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "همیشه درصد را نشان بده" "Always Show Percentage": "همیشه درصد را نشان بده"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "آیکون‌ها همیشه فعال" "Always on icons": "آیکون‌ها همیشه فعال"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "پاک‌کردن همه کار‌های چاپ" "Clear All Jobs": "پاک‌کردن همه کار‌های چاپ"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "هنگام راه‌اندازی سرور تمام تاریخچه را پاک کن" "Clear all history when server starts": "هنگام راه‌اندازی سرور تمام تاریخچه را پاک کن"
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "" "Copy": ""
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "کپی PID" "Copy PID": "کپی PID"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "حذف چاپگر" "Delete Printer": "حذف چاپگر"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "حذف VPN" "Delete VPN": "حذف VPN"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "میزان مصرف دیسک" "Disk Usage": "میزان مصرف دیسک"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "رد کردن" "Dismiss": "رد کردن"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "شرکت" "Enterprise": "شرکت"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "خطا" "Error": "خطا"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "لغو کار چاپ انتخاب شده ناموفق بود" "Failed to cancel selected job": "لغو کار چاپ انتخاب شده ناموفق بود"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "اتصال به VPN ناموفق بود" "Failed to connect VPN": "اتصال به VPN ناموفق بود"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "توقف چاپگر ناموفق بود" "Failed to pause printer": "توقف چاپگر ناموفق بود"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "چاپ صفحه تست ناموفق بود" "Failed to print test page": "چاپ صفحه تست ناموفق بود"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "شروع اتصال به %1 ناموفق بود" "Failed to start connection to %1": "شروع اتصال به %1 ناموفق بود"
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "بروزرسانی VPN ناموفق بود" "Failed to update VPN": "بروزرسانی VPN ناموفق بود"
}, },
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "اجبار HDR" "Force HDR": "اجبار HDR"
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "بستن اجباری فرایند" "Force Kill Process": "بستن اجباری فرایند"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "کنترل گاما در دسترس نیست. نیاز به DMS API نسخه ۶ به بالا دارد." "Gamma control not available. Requires DMS API v6+.": "کنترل گاما در دسترس نیست. نیاز به DMS API نسخه ۶ به بالا دارد."
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "گیت‌هاب" "GitHub": "گیت‌هاب"
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "تنظیمات تاریخچه" "History Settings": "تنظیمات تاریخچه"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "مدت زمان نگه‌داشتن" "Hold Duration": "مدت زمان نگه‌داشتن"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "نصب افزونه‌ها از مخزن افزونه DMS" "Install plugins from the DMS plugin registry": "نصب افزونه‌ها از مخزن افزونه DMS"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "اینترفیس:" "Interface:": "اینترفیس:"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "کار‌های چاپ: " "Jobs: ": "کار‌های چاپ: "
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "بیدار نگه‌ دار" "Keep Awake": "بیدار نگه‌ دار"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "حداکثر تاریخچه" "Maximum History": "حداکثر تاریخچه"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "بیشینه تعداد ورودی‌های کلیپ‌بورد برای نگه‌داری" "Maximum number of clipboard entries to keep": "بیشینه تعداد ورودی‌های کلیپ‌بورد برای نگه‌داری"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "بیشینه اندازه برای هر ورودی کلیپ‌بورد" "Maximum size per clipboard entry": "بیشینه اندازه برای هر ورودی کلیپ‌بورد"
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "چاپگری یافت نشد" "No printers found": "چاپگری یافت نشد"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "هیچ گونه‌ی دیگری ایجاد نشد. برای ایجاد یک ابزارک مانیتور جدید، روی افزودن کلیک کنید." "No variants created. Click Add to create a new monitor widget.": "هیچ گونه‌ی دیگری ایجاد نشد. برای ایجاد یک ابزارک مانیتور جدید، روی افزودن کلیک کنید."
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "موقعیت OSD" "OSD Position": "موقعیت OSD"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "خاموش" "Off": "خاموش"
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "درصد" "Percentage": "درصد"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "اجازه تنظیم تصویر نمایه داده نشد." "Permission denied to set profile image.": "اجازه تنظیم تصویر نمایه داده نشد."
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "تنزل‌دادن پروفایل پاور" "Power Profile Degradation": "تنزل‌دادن پروفایل پاور"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "مدیریت پروفایل پاور در دسترس" "Power profile management available": "مدیریت پروفایل پاور در دسترس"
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "تعداد فرایند‌ها" "Process Count": "تعداد فرایند‌ها"
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "درحال پردازش" "Processing": "درحال پردازش"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "پیکربندی‌های ذخیره شده" "Saved Configurations": "پیکربندی‌های ذخیره شده"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "بزرگنمایی" "Scale": "بزرگنمایی"
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "علمی" "Science": "علمی"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "اشتراک‌گذاری صفحه" "Screen sharing": "اشتراک‌گذاری صفحه"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "نمایش overlay تیره پشت پنجره مودال" "Show darkened overlay behind modal dialogs": "نمایش overlay تیره پشت پنجره مودال"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "overlay لانچر را هنگام تایپ در نمای کلی نیری نمایش بده. برای استفاده از لانچر دیگری غیرفعال کنید." "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "overlay لانچر را هنگام تایپ در نمای کلی نیری نمایش بده. برای استفاده از لانچر دیگری غیرفعال کنید."
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "این ابزارک از حالت‌های خاموش شدن GPU جلوگیری می‌کند، که ​​می‌تواند به طور قابل توجهی بر عمر باتری لپ‌تاپ‌ها تأثیر بگذارد. استفاده از این ابزارک در لپ‌تاپ‌هایی با گرافیک هیبریدی توصیه نمی‌شود." "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "این ابزارک از حالت‌های خاموش شدن GPU جلوگیری می‌کند، که ​​می‌تواند به طور قابل توجهی بر عمر باتری لپ‌تاپ‌ها تأثیر بگذارد. استفاده از این ابزارک در لپ‌تاپ‌هایی با گرافیک هیبریدی توصیه نمی‌شود."
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "این کار تمام تاریخچه کلیپ‌بورد را برای همیشه حذف می‌کند." "This will permanently delete all clipboard history.": "این کار تمام تاریخچه کلیپ‌بورد را برای همیشه حذف می‌کند."
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "تایلینگ" "Tiling": "تایلینگ"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "" "Trigger Prefix": ""
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "خاموش‌کردن مانیتور پس از" "Turn off monitors after": "خاموش‌کردن مانیتور پس از"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "بروزرسانی افزونه" "Update Plugin": "بروزرسانی افزونه"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "" "Urgent Color": ""
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "dgop در دسترس نیست" "dgop not available": "dgop در دسترس نیست"
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "فایل dms/binds.kdl وجود دارد اما در config.kdl گنجانده نشده است. کلیدهای ترکیبی سفارشی تا زمانی که این مشکل برطرف نشود، کار نخواهند کرد." "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "فایل dms/binds.kdl وجود دارد اما در config.kdl گنجانده نشده است. کلیدهای ترکیبی سفارشی تا زمانی که این مشکل برطرف نشود، کار نخواهند کرد."
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "هیچ افزونه‌ای یافت نشد" "No plugins found": "هیچ افزونه‌ای یافت نشد"
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "هیچ تمی یافت نشد" "No themes found": "هیچ تمی یافت نشد"
}, },
"events": { "events": {
"events": "رویداد‌ها" "events": "رویداد‌ها"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "فایل" "files": "فایل"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "رنگ‌های تم الهام گرفته شده از متریال دیزاین" "Material Design inspired color themes": "رنگ‌های تم الهام گرفته شده از متریال دیزاین"
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "بازگشت" "Back": "بازگشت"
}, },
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "دقیقه" "minutes": "دقیقه"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "ms" "ms": "ms"
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "جستجوی افزونه‌ها..." "Search plugins...": "جستجوی افزونه‌ها..."
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "انتخاب تصویر نمایه" "Select Profile Image": "انتخاب تصویر نمایه"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "" "Intensity": ""
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "منبع" "source": "منبع"
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "ناظر سیستم" "System Monitor": "ناظر سیستم"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "نصب تم رنگ‌ها از مخزن تم DMS" "Install color themes from the DMS theme registry": "نصب تم رنگ‌ها از مخزن تم DMS"
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "DMS را برای یکپارچه‌سازی NM بروز کنید." "update dms for NM integration.": "DMS را برای یکپارچه‌سازی NM بروز کنید."
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "" "Requires %1": ""
}, },

File diff suppressed because it is too large Load Diff

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "הצג/י תמיד אחוזים" "Always Show Percentage": "הצג/י תמיד אחוזים"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "סמלים דולקים תמיד" "Always on icons": "סמלים דולקים תמיד"
}, },
@@ -492,7 +489,7 @@
"Behavior": "התנהגות" "Behavior": "התנהגות"
}, },
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": { "Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": {
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": "מקשר את מסך הנעילה לאותות D-Bus מloginctl. יש להשבית אם משתמשים במסך נעילה חיצוני." "Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": "קשירת מסך הנעילה לאותות D-Bus מloginctl. יש להשבית אם משתמשים במסך נעילה חיצוני."
}, },
"Binds Include Missing": { "Binds Include Missing": {
"Binds Include Missing": "קובץ includes של קיצורי מקלדת חסר" "Binds Include Missing": "קובץ includes של קיצורי מקלדת חסר"
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "נקה/י את כל העבודות" "Clear All Jobs": "נקה/י את כל העבודות"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "נקה/י את כל ההיסטוריה כאשר השרת מופעל" "Clear all history when server starts": "נקה/י את כל ההיסטוריה כאשר השרת מופעל"
}, },
@@ -759,7 +753,7 @@
"Clipboard service not available": "שירות לוח ההעתקה אינו זמין" "Clipboard service not available": "שירות לוח ההעתקה אינו זמין"
}, },
"Clipboard works but nothing saved to disk": { "Clipboard works but nothing saved to disk": {
"Clipboard works but nothing saved to disk": "לוח ההעתקה יעבוד אך שום דבר לא יישמר לדיסק" "Clipboard works but nothing saved to disk": "לוח ההעתקה עובד אך שום דבר לא נשמר לדיסק"
}, },
"Clock": { "Clock": {
"Clock": "שעון" "Clock": "שעון"
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "העתק/י" "Copy": "העתק/י"
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "העתק/י PID" "Copy PID": "העתק/י PID"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "מחק/י מדפסת" "Delete Printer": "מחק/י מדפסת"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "מחק/י VPN" "Delete VPN": "מחק/י VPN"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "שימוש בדיסק" "Disk Usage": "שימוש בדיסק"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "סגירה" "Dismiss": "סגירה"
}, },
@@ -1239,10 +1221,10 @@
"Display Settings": "הגדרות תצוגה" "Display Settings": "הגדרות תצוגה"
}, },
"Display a dock with pinned and running applications": { "Display a dock with pinned and running applications": {
"Display a dock with pinned and running applications": "הצג/י את הDock עם אפליקציות מוצמדות ופעילות" "Display a dock with pinned and running applications": "הצג/י Dock עם יישומים מוצמדים ופעילים"
}, },
"Display all priorities over fullscreen apps": { "Display all priorities over fullscreen apps": {
"Display all priorities over fullscreen apps": "הצג/י את כל ההתראות מעל אפליקציות במסך מלא" "Display all priorities over fullscreen apps": "הצג/י את כל רמות העדיפות מעל אפליקציות במסך מלא"
}, },
"Display and switch DWL layouts": { "Display and switch DWL layouts": {
"Display and switch DWL layouts": "הצג/י והחלף/י פריסות DWL" "Display and switch DWL layouts": "הצג/י והחלף/י פריסות DWL"
@@ -1389,7 +1371,7 @@
"Enable fingerprint authentication": "הפעלת אימות באמצעות טביעת אצבע" "Enable fingerprint authentication": "הפעלת אימות באמצעות טביעת אצבע"
}, },
"Enable loginctl lock integration": { "Enable loginctl lock integration": {
"Enable loginctl lock integration": "הפעלת האינטגרציה עם loginctl" "Enable loginctl lock integration": "הפעל/י שילוב נעילה עם loginctl"
}, },
"Enable password field display on the lock screen window": { "Enable password field display on the lock screen window": {
"Show Password Field": "הצג/י שדה סיסמה" "Show Password Field": "הצג/י שדה סיסמה"
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "ארגוני" "Enterprise": "ארגוני"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "שגיאה" "Error": "שגיאה"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "ביטול העבודה שנבחרה נכשל" "Failed to cancel selected job": "ביטול העבודה שנבחרה נכשל"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "החיבור לVPN נכשל" "Failed to connect VPN": "החיבור לVPN נכשל"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "השהיית המדפסת נכשלה" "Failed to pause printer": "השהיית המדפסת נכשלה"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "הדפסת דף בדיקה נכשלה" "Failed to print test page": "הדפסת דף בדיקה נכשלה"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "התחלת החיבור ל%1 נכשלה" "Failed to start connection to %1": "התחלת החיבור ל%1 נכשלה"
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "עדכון הVPN נכשל" "Failed to update VPN": "עדכון הVPN נכשל"
}, },
@@ -1722,7 +1689,7 @@
"Focused Window": "חלון ממוקד" "Focused Window": "חלון ממוקד"
}, },
"Follow Monitor Focus": { "Follow Monitor Focus": {
"Follow Monitor Focus": "מעקב אחרי המסך הממוקד" "Follow Monitor Focus": "עקוב/י אחר מיקוד צג"
}, },
"Follow focus": { "Follow focus": {
"Follow focus": "עקוב/י אחר מיקוד" "Follow focus": "עקוב/י אחר מיקוד"
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "אלץ/י HDR" "Force HDR": "אלץ/י HDR"
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "אילוץ סיום תהליך" "Force Kill Process": "אילוץ סיום תהליך"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "בקרת גאמה אינה זמינה. נדרש API של DMS גרסה 6 ומעלה." "Gamma control not available. Requires DMS API v6+.": "בקרת גאמה אינה זמינה. נדרש API של DMS גרסה 6 ומעלה."
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "GitHub" "GitHub": "GitHub"
}, },
@@ -1821,7 +1782,7 @@
"Gradually fade the screen before locking with a configurable grace period": "הפעל/י דהייה הדרגתית של המסך לפני הנעילה עם תקופת חסד הניתנת להגדרה" "Gradually fade the screen before locking with a configurable grace period": "הפעל/י דהייה הדרגתית של המסך לפני הנעילה עם תקופת חסד הניתנת להגדרה"
}, },
"Gradually fade the screen before turning off monitors with a configurable grace period": { "Gradually fade the screen before turning off monitors with a configurable grace period": {
"Gradually fade the screen before turning off monitors with a configurable grace period": "הפעל/י דהייה הדרגתית של התצוגה לפני כיבוי המסכים עם תקופת חסד הניתנת להגדרה" "Gradually fade the screen before turning off monitors with a configurable grace period": "דהייה הדרגתית של התצוגה לפני כיבוי מסכים עם תקופת חסד הניתנת להגדרה"
}, },
"Graph Time Range": { "Graph Time Range": {
"Graph Time Range": "טווח זמן לגרף" "Graph Time Range": "טווח זמן לגרף"
@@ -1839,7 +1800,7 @@
"Group": "קבוצה" "Group": "קבוצה"
}, },
"Group Workspace Apps": { "Group Workspace Apps": {
"Group Workspace Apps": "קיבוץ האפליקציות של סביבת העבודה" "Group Workspace Apps": "קיבוץ יישומי שולחן עבודה"
}, },
"Group by App": { "Group by App": {
"Group by App": "קבץ/י לפי אפליקציה" "Group by App": "קבץ/י לפי אפליקציה"
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "הגדרות היסטוריה" "History Settings": "הגדרות היסטוריה"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "משך הלחיצה" "Hold Duration": "משך הלחיצה"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "התקן/י תוספים ממאגר התוספים של DMS" "Install plugins from the DMS plugin registry": "התקן/י תוספים ממאגר התוספים של DMS"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "ממשק:" "Interface:": "ממשק:"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "עבודות: " "Jobs: ": "עבודות: "
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "השאר/י ער" "Keep Awake": "השאר/י ער"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "היסטוריה מקסימלית" "Maximum History": "היסטוריה מקסימלית"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "מספר מקסימלי של רשומות לוח ההעתקה לשמירה" "Maximum number of clipboard entries to keep": "מספר מקסימלי של רשומות לוח ההעתקה לשמירה"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "גודל מקסימלי לרשומת לוח ההעתקה" "Maximum size per clipboard entry": "גודל מקסימלי לרשומת לוח ההעתקה"
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "לא נמצאו מדפסות" "No printers found": "לא נמצאו מדפסות"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "לא נוצרו גרסאות. לחץ/י על הוספה כדי ליצור ווידג׳ט תצוגה חדש." "No variants created. Click Add to create a new monitor widget.": "לא נוצרו גרסאות. לחץ/י על הוספה כדי ליצור ווידג׳ט תצוגה חדש."
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "מיקום OSD" "OSD Position": "מיקום OSD"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "כבוי" "Off": "כבוי"
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "אחוזים" "Percentage": "אחוזים"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "ההרשאה להגדרת תמונת הפרופיל נדחתה." "Permission denied to set profile image.": "ההרשאה להגדרת תמונת הפרופיל נדחתה."
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "ירידת ביצועים בפרופיל צריכת החשמל" "Power Profile Degradation": "ירידת ביצועים בפרופיל צריכת החשמל"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "ניהול פרופיל חשמל זמין" "Power profile management available": "ניהול פרופיל חשמל זמין"
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "מספר תהליכים" "Process Count": "מספר תהליכים"
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "מעבד" "Processing": "מעבד"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "תצורות שמורות" "Saved Configurations": "תצורות שמורות"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "קנה מידה" "Scale": "קנה מידה"
}, },
@@ -3393,14 +3158,11 @@
"Science": { "Science": {
"Science": "מדע" "Science": "מדע"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "שיתוף מסך" "Screen sharing": "שיתוף מסך"
}, },
"Scroll Wheel": { "Scroll Wheel": {
"Scroll Wheel": "גלגל הגלילה" "Scroll Wheel": "גלגל גלילה"
}, },
"Scroll on widget changes media volume": { "Scroll on widget changes media volume": {
"Scroll on widget changes media volume": "גלילה על הווידג׳ט משנה עוצמת מדיה" "Scroll on widget changes media volume": "גלילה על הווידג׳ט משנה עוצמת מדיה"
@@ -3412,7 +3174,7 @@
"Scroll title if it doesn't fit in widget": "גלילה של הכותרת אם היא לא נכנסת במלואה בווידג׳ט" "Scroll title if it doesn't fit in widget": "גלילה של הכותרת אם היא לא נכנסת במלואה בווידג׳ט"
}, },
"Scroll wheel behavior on media widget": { "Scroll wheel behavior on media widget": {
"Scroll wheel behavior on media widget": "התנהגות גלגל הגלילה על ווידג׳ט המדיה" "Scroll wheel behavior on media widget": "התנהגות גלגל גלילה על ווידג׳ט מדיה"
}, },
"Scrolling": { "Scrolling": {
"Scrolling": "גלילה" "Scrolling": "גלילה"
@@ -3571,7 +3333,7 @@
"Show Disk": "הצג/י דיסק" "Show Disk": "הצג/י דיסק"
}, },
"Show Dock": { "Show Dock": {
"Show Dock": "הצג/י את הDock" "Show Dock": "הצג/י Dock"
}, },
"Show Feels Like Temperature": { "Show Feels Like Temperature": {
"Show Feels Like Temperature": "הצג/י טמפרטורה מורגשת" "Show Feels Like Temperature": "הצג/י טמפרטורה מורגשת"
@@ -3622,7 +3384,7 @@
"Show Network Graph": "הצג/י גרף רשת" "Show Network Graph": "הצג/י גרף רשת"
}, },
"Show Occupied Workspaces Only": { "Show Occupied Workspaces Only": {
"Show Occupied Workspaces Only": "הצג/י רק סביבות עבודה שאינן ריקות" "Show Occupied Workspaces Only": "הצג/י רק סביבות עבודה שתפוסות"
}, },
"Show Power Off": { "Show Power Off": {
"Show Power Off": "הצג/י כיבוי" "Show Power Off": "הצג/י כיבוי"
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "הצג/י שכבה כהה מאחורי חלוניות שיח" "Show darkened overlay behind modal dialogs": "הצג/י שכבה כהה מאחורי חלוניות שיח"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "הצג/י שכבת משגר בעת הקלדה בסקירה של Niri. השבת/י כדי להשתמש במשגר אחר." "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "הצג/י שכבת משגר בעת הקלדה בסקירה של Niri. השבת/י כדי להשתמש במשגר אחר."
}, },
@@ -3742,7 +3501,7 @@
"Show workspace name on horizontal bars, and first letter on vertical bars": "הצג/י את השם של סביבת העבודה על סרגלים אופקיים, ואות ראשונה על סרגלים אנכיים" "Show workspace name on horizontal bars, and first letter on vertical bars": "הצג/י את השם של סביבת העבודה על סרגלים אופקיים, ואות ראשונה על סרגלים אנכיים"
}, },
"Show workspaces of the currently focused monitor": { "Show workspaces of the currently focused monitor": {
"Show workspaces of the currently focused monitor": "הצג/י סביבות עבודה שפעילות על המסך שכרגע ממוקד" "Show workspaces of the currently focused monitor": "הצג/י סביבות עבודה שפעילות על המסך הממוקד שכרגע ממוקד"
}, },
"Shows all running applications with focus indication": { "Shows all running applications with focus indication": {
"Shows all running applications with focus indication": "מציג את כל האפליקציות הפעילות עם סימון למיקוד" "Shows all running applications with focus indication": "מציג את כל האפליקציות הפעילות עם סימון למיקוד"
@@ -3898,7 +3657,7 @@
"System": "מערכת" "System": "מערכת"
}, },
"System App Theming": { "System App Theming": {
"System App Theming": "ערכת נושא לאפליקציות מערכת" "System App Theming": "ערכת נושא ליישומי מערכת"
}, },
"System Monitor Unavailable": { "System Monitor Unavailable": {
"System Monitor Unavailable": "מנטר המערכת אינו זמין" "System Monitor Unavailable": "מנטר המערכת אינו זמין"
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "ווידג׳ט זה מונע מהGPU לעבור למצב כבוי, דבר שעלול להשפיע משמעותית על חיי הסוללה במחשבים ניידים. לא מומלץ להשתמש בו במחשבים ניידים עם גרפיקה היברידית." "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "ווידג׳ט זה מונע מהGPU לעבור למצב כבוי, דבר שעלול להשפיע משמעותית על חיי הסוללה במחשבים ניידים. לא מומלץ להשתמש בו במחשבים ניידים עם גרפיקה היברידית."
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "פעולה זו תמחק לצמיתות את כל היסטוריית לוח ההעתקה." "This will permanently delete all clipboard history.": "פעולה זו תמחק לצמיתות את כל היסטוריית לוח ההעתקה."
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "ריצוף" "Tiling": "ריצוף"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "קידומת מפעיל" "Trigger Prefix": "קידומת מפעיל"
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "כבה/י את כל המסכים לאחר" "Turn off monitors after": "כבה/י את כל המסכים לאחר"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "עדכן/י תוסף" "Update Plugin": "עדכן/י תוסף"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "צבע דחוף" "Urgent Color": "צבע דחוף"
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "dgop אינו זמין" "dgop not available": "dgop אינו זמין"
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl קיים אך אינו כלול בconfig.kdl. קיצורי מקלדת מותאמים אישית לא יעבדו עד שהבעיה תתוקן." "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl קיים אך אינו כלול בconfig.kdl. קיצורי מקלדת מותאמים אישית לא יעבדו עד שהבעיה תתוקן."
}, },
@@ -4584,7 +4319,7 @@
"Dynamic colors from wallpaper": "צבעים דינמיים מתמונת הרקע" "Dynamic colors from wallpaper": "צבעים דינמיים מתמונת הרקע"
}, },
"dynamic theme description": { "dynamic theme description": {
"Material colors generated from wallpaper": "צבעי Material שנוצרו מהרקע" "Material colors generated from wallpaper": "צבעי Material שנוצרו מטפט"
}, },
"dynamic theme name": { "dynamic theme name": {
"Dynamic": "דינמי" "Dynamic": "דינמי"
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "לא נמצאו תוספים" "No plugins found": "לא נמצאו תוספים"
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "לא נמצאו ערכות נושא" "No themes found": "לא נמצאו ערכות נושא"
}, },
"events": { "events": {
"events": "אירועים" "events": "אירועים"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "קבצים" "files": "קבצים"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "ערכות צבעים בהשראת Material Design" "Material Design inspired color themes": "ערכות צבעים בהשראת Material Design"
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "חזרה" "Back": "חזרה"
}, },
@@ -4684,7 +4404,7 @@
}, },
"greeter feature card description": { "greeter feature card description": {
"Background app icons": "סמלי אפליקציות ברקע", "Background app icons": "סמלי אפליקציות ברקע",
"Colors from wallpaper": "צבעים מתמונת רקע", "Colors from wallpaper": "צבעים מטפט",
"Community themes": "ערכות נושא קהילתיות", "Community themes": "ערכות נושא קהילתיות",
"Extensible architecture": "ארכיטקטורה ניתנת להרחבה", "Extensible architecture": "ארכיטקטורה ניתנת להרחבה",
"GTK, Qt, IDEs, more": "GTK, Qt, סביבות פיתוח, ועוד", "GTK, Qt, IDEs, more": "GTK, Qt, סביבות פיתוח, ועוד",
@@ -4707,7 +4427,7 @@
"Plugins": "תוספים" "Plugins": "תוספים"
}, },
"greeter feature card title | greeter settings link": { "greeter feature card title | greeter settings link": {
"DankBar": "Dank Bar" "DankBar": "DankBar"
}, },
"greeter feature card title | lock screen notifications settings card": { "greeter feature card title | lock screen notifications settings card": {
"Lock Screen": "מסך הנעילה" "Lock Screen": "מסך הנעילה"
@@ -4806,7 +4526,7 @@
"Lock Screen": "מסך הנעילה" "Lock Screen": "מסך הנעילה"
}, },
"loginctl not available - lock integration requires DMS socket connection": { "loginctl not available - lock integration requires DMS socket connection": {
"loginctl not available - lock integration requires DMS socket connection": "loginctl אינו זמין, אינטגרציה של הנעילה דורשת חיבור socket לDMS" "loginctl not available - lock integration requires DMS socket connection": "loginctl אינו זמין, שילוב הנעילה דורש חיבור socket לDMS"
}, },
"matugen error": { "matugen error": {
"matugen not found - install matugen package for dynamic theming": "matugen לא נמצא - התקן/י את החבילה של matugen כדי לאפשר עיצוב דינמי" "matugen not found - install matugen package for dynamic theming": "matugen לא נמצא - התקן/י את החבילה של matugen כדי לאפשר עיצוב דינמי"
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "דקות" "minutes": "דקות"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "מילישניות" "ms": "מילישניות"
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "חפש/י תוספים..." "Search plugins...": "חפש/י תוספים..."
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "בחר/י תמונת פרופיל" "Select Profile Image": "בחר/י תמונת פרופיל"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "עוצמה" "Intensity": "עוצמה"
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "קוד מקור" "source": "קוד מקור"
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "מנטר המערכת" "System Monitor": "מנטר המערכת"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "התקן/י ערכות צבעים ממאגר ערכות הנושא של DMS" "Install color themes from the DMS theme registry": "התקן/י ערכות צבעים ממאגר ערכות הנושא של DMS"
}, },
@@ -4978,10 +4673,7 @@
"Unknown": "לא ידוע" "Unknown": "לא ידוע"
}, },
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "עדכן/י את DMS כדי לאפשר אינטגרציה עם NM." "update dms for NM integration.": "עדכן/י את dms עבור שילוב עם NM."
},
"uptime label in footer": {
"Uptime:": ""
}, },
"version requirement": { "version requirement": {
"Requires %1": "גרסה %1 נדרשת" "Requires %1": "גרסה %1 נדרשת"

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "Mindig mutassa a százalékot" "Always Show Percentage": "Mindig mutassa a százalékot"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "Mindig látható ikonok" "Always on icons": "Mindig látható ikonok"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "Összes feladat törlése" "Clear All Jobs": "Összes feladat törlése"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "Minden előzmény törlése a szerver indításakor" "Clear all history when server starts": "Minden előzmény törlése a szerver indításakor"
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "Másolás" "Copy": "Másolás"
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "PID másolása" "Copy PID": "PID másolása"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "Nyomtató törlése" "Delete Printer": "Nyomtató törlése"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "VPN törlése" "Delete VPN": "VPN törlése"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "Lemezhasználat" "Disk Usage": "Lemezhasználat"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "Bezárás" "Dismiss": "Bezárás"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "Vállalati" "Enterprise": "Vállalati"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "Hiba" "Error": "Hiba"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "Nem sikerült a kiválasztott feladatot törölni" "Failed to cancel selected job": "Nem sikerült a kiválasztott feladatot törölni"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "Nem sikerült csatlakozni a VPN-hez" "Failed to connect VPN": "Nem sikerült csatlakozni a VPN-hez"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "Nem sikerült a nyomtatót szüneteltetetni" "Failed to pause printer": "Nem sikerült a nyomtatót szüneteltetetni"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "Nem sikerült kinyomtatni a tesztoldalt" "Failed to print test page": "Nem sikerült kinyomtatni a tesztoldalt"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "Nem sikerült elindítani a csatlakozást ehhez: %1" "Failed to start connection to %1": "Nem sikerült elindítani a csatlakozást ehhez: %1"
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "Nem sikerült frissíteni a VPN-t" "Failed to update VPN": "Nem sikerült frissíteni a VPN-t"
}, },
@@ -1692,7 +1659,7 @@
"Fix Now": "Javítás most" "Fix Now": "Javítás most"
}, },
"Fixing...": { "Fixing...": {
"Fixing...": "Javítás" "Fixing...": "Javítás..."
}, },
"Flags": { "Flags": {
"Flags": "Jelzők" "Flags": "Jelzők"
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "HDR kényszerítése" "Force HDR": "HDR kényszerítése"
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "Folyamat kényszerített leállítása" "Force Kill Process": "Folyamat kényszerített leállítása"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "Gamma vezérlés nem érhető el. DMS API v6+ szükséges." "Gamma control not available. Requires DMS API v6+.": "Gamma vezérlés nem érhető el. DMS API v6+ szükséges."
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "GitHub" "GitHub": "GitHub"
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "Előzménybeállítások" "History Settings": "Előzménybeállítások"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "Nyomva tartás időtartama" "Hold Duration": "Nyomva tartás időtartama"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "Bővítmények telepítése a DMS bővítményregisztrációból" "Install plugins from the DMS plugin registry": "Bővítmények telepítése a DMS bővítményregisztrációból"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "Interfész:" "Interface:": "Interfész:"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "Munkák: " "Jobs: ": "Munkák: "
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "Ébren tartás" "Keep Awake": "Ébren tartás"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "Maximális előzmény" "Maximum History": "Maximális előzmény"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "Megtartandó vágólap-bejegyzések maximális száma" "Maximum number of clipboard entries to keep": "Megtartandó vágólap-bejegyzések maximális száma"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "Maximális méret vágólap-bejegyzésenként" "Maximum size per clipboard entry": "Maximális méret vágólap-bejegyzésenként"
}, },
@@ -2653,7 +2439,7 @@
"New York, NY": "New York, NY" "New York, NY": "New York, NY"
}, },
"New group name...": { "New group name...": {
"New group name...": "Új csoportnév" "New group name...": "Új csoportnév..."
}, },
"Next Transition": { "Next Transition": {
"Next Transition": "Következő átmenet" "Next Transition": "Következő átmenet"
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "Nem található nyomtató" "No printers found": "Nem található nyomtató"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "Nincsenek létrehozott variánsok. Kattints a Hozzáadás gombra új monitor widget létrehozásához." "No variants created. Click Add to create a new monitor widget.": "Nincsenek létrehozott variánsok. Kattints a Hozzáadás gombra új monitor widget létrehozásához."
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "OSD pozíció" "OSD Position": "OSD pozíció"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "Kikapcsolva" "Off": "Kikapcsolva"
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "Százalék" "Percentage": "Százalék"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "Engedély megtagadva a profilkép beállításához." "Permission denied to set profile image.": "Engedély megtagadva a profilkép beállításához."
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "Energiaprofil romlása" "Power Profile Degradation": "Energiaprofil romlása"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "Energia profil kezelés elérhető" "Power profile management available": "Energia profil kezelés elérhető"
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "Folyamatszám" "Process Count": "Folyamatszám"
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "Feldolgozás" "Processing": "Feldolgozás"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "Mentett konfigurációk" "Saved Configurations": "Mentett konfigurációk"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "Skála" "Scale": "Skála"
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "Tudomány" "Science": "Tudomány"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "Képernyő megosztás" "Screen sharing": "Képernyő megosztás"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "Sötétített átfedés megjelenítése a modális párbeszédablakok mögött" "Show darkened overlay behind modal dialogs": "Sötétített átfedés megjelenítése a modális párbeszédablakok mögött"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Indító átfedés megjelenítése, amikor gépelsz a Niri-áttekintésben. Kapcsold ki, ha másik indítót használsz." "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Indító átfedés megjelenítése, amikor gépelsz a Niri-áttekintésben. Kapcsold ki, ha másik indítót használsz."
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Ez a widget megakadályozza a GPU kikapcsolt állapotát, ami jelentősen befolyásolhatja a laptopok akkumulátor élettartamát. Nem ajánlott hibrid grafikus kártyával rendelkező laptopokon használni." "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Ez a widget megakadályozza a GPU kikapcsolt állapotát, ami jelentősen befolyásolhatja a laptopok akkumulátor élettartamát. Nem ajánlott hibrid grafikus kártyával rendelkező laptopokon használni."
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "Ez véglegesen törölni fogja a vágólapelőzményeket." "This will permanently delete all clipboard history.": "Ez véglegesen törölni fogja a vágólapelőzményeket."
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "Csempézés" "Tiling": "Csempézés"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "Indító előtag" "Trigger Prefix": "Indító előtag"
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "Monitorok kikapcsolása ennyi idő után:" "Turn off monitors after": "Monitorok kikapcsolása ennyi idő után:"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "Bővítmény frissítése" "Update Plugin": "Bővítmény frissítése"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "Sürgős szín" "Urgent Color": "Sürgős szín"
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "dgop nem elérhető" "dgop not available": "dgop nem elérhető"
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "A dms/binds.kdl létezik, de nincs benne a config.kdl-ben. Az egyéni gyorsbillentyűk nem fognak működni, amíg ez nincs javítva." "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "A dms/binds.kdl létezik, de nincs benne a config.kdl-ben. Az egyéni gyorsbillentyűk nem fognak működni, amíg ez nincs javítva."
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "Nem található bővítmény" "No plugins found": "Nem található bővítmény"
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "Nem található téma" "No themes found": "Nem található téma"
}, },
"events": { "events": {
"events": "események" "events": "események"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "fájlok" "files": "fájlok"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "Material Design ihlette színtémák" "Material Design inspired color themes": "Material Design ihlette színtémák"
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "Vissza" "Back": "Vissza"
}, },
@@ -4662,7 +4382,7 @@
"%1 issue(s) found": "%1 hiba található" "%1 issue(s) found": "%1 hiba található"
}, },
"greeter doctor page loading text": { "greeter doctor page loading text": {
"Analyzing configuration...": "Konfiguráció elemzése" "Analyzing configuration...": "Konfiguráció elemzése..."
}, },
"greeter doctor page status card": { "greeter doctor page status card": {
"Errors": "Hibák", "Errors": "Hibák",
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "percek" "minutes": "percek"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "ms" "ms": "ms"
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "Bővítmények keresése…" "Search plugins...": "Bővítmények keresése…"
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "Profilkép kiválasztása" "Select Profile Image": "Profilkép kiválasztása"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "Intenzitás" "Intensity": "Intenzitás"
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "forrás" "source": "forrás"
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "Rendszerfigyelő" "System Monitor": "Rendszerfigyelő"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "Színtémák telepítése a DMS téma-regiszterből" "Install color themes from the DMS theme registry": "Színtémák telepítése a DMS téma-regiszterből"
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "dms frissítése a NM integrációhoz." "update dms for NM integration.": "dms frissítése a NM integrációhoz."
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "%1 szükséges" "Requires %1": "%1 szükséges"
}, },

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "Mostra sempre percentuale" "Always Show Percentage": "Mostra sempre percentuale"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "Icone sempre attive" "Always on icons": "Icone sempre attive"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "Elimina Tutte le Stampe" "Clear All Jobs": "Elimina Tutte le Stampe"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "Cancella tutta la cronologia all'avvio del server" "Clear all history when server starts": "Cancella tutta la cronologia all'avvio del server"
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "Copia" "Copy": "Copia"
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "Copia PID" "Copy PID": "Copia PID"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "Elimina Stampante" "Delete Printer": "Elimina Stampante"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "Elimina VPN" "Delete VPN": "Elimina VPN"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "Uso Disco" "Disk Usage": "Uso Disco"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "Ignora" "Dismiss": "Ignora"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "Enterprise" "Enterprise": "Enterprise"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "Errore" "Error": "Errore"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "Impossibile cancellare la stampa selezionata" "Failed to cancel selected job": "Impossibile cancellare la stampa selezionata"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "Impossibile connettersi alla VPN" "Failed to connect VPN": "Impossibile connettersi alla VPN"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "Impossibile mettere in pausa la stampante" "Failed to pause printer": "Impossibile mettere in pausa la stampante"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "Impossibile stampare la pagina di prova" "Failed to print test page": "Impossibile stampare la pagina di prova"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "Impossibile avviare la connessione a %1" "Failed to start connection to %1": "Impossibile avviare la connessione a %1"
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "Impossibile aggiornare la VPN" "Failed to update VPN": "Impossibile aggiornare la VPN"
}, },
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "Forza HDR" "Force HDR": "Forza HDR"
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "Forza Arresto Processo" "Force Kill Process": "Forza Arresto Processo"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "Controllo gamma non disponibile. Richiede API DMS v6+." "Gamma control not available. Requires DMS API v6+.": "Controllo gamma non disponibile. Richiede API DMS v6+."
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "GitHub" "GitHub": "GitHub"
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "Impostazioni Cronologia" "History Settings": "Impostazioni Cronologia"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "Durata della pressione" "Hold Duration": "Durata della pressione"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "Installa plugin dal registro dei plugin DMS" "Install plugins from the DMS plugin registry": "Installa plugin dal registro dei plugin DMS"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "Interfaccia" "Interface:": "Interfaccia"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "Stampe: " "Jobs: ": "Stampe: "
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "Mantieni Attivo" "Keep Awake": "Mantieni Attivo"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "Cronologia Massima" "Maximum History": "Cronologia Massima"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "Numero massimo di voci degli appunti da conservare" "Maximum number of clipboard entries to keep": "Numero massimo di voci degli appunti da conservare"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "Dimensione massima per ogni voce degli appunti" "Maximum size per clipboard entry": "Dimensione massima per ogni voce degli appunti"
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "Nessuna stampante trovata" "No printers found": "Nessuna stampante trovata"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "Nessuna variante creata. Fai clic su Aggiungi per creare un nuovo widget monitor." "No variants created. Click Add to create a new monitor widget.": "Nessuna variante creata. Fai clic su Aggiungi per creare un nuovo widget monitor."
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "Posizione OSD" "OSD Position": "Posizione OSD"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "Disattivato" "Off": "Disattivato"
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "Percentuale" "Percentage": "Percentuale"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "Impossibile impostare immagine profilo: Permesso negato." "Permission denied to set profile image.": "Impossibile impostare immagine profilo: Permesso negato."
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "Riduzione Prestazioni Energetiche" "Power Profile Degradation": "Riduzione Prestazioni Energetiche"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "Gestione dei profili energetici disponibile" "Power profile management available": "Gestione dei profili energetici disponibile"
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "Numero di Processi" "Process Count": "Numero di Processi"
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "In Elaborazione" "Processing": "In Elaborazione"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "Configurazioni Salvate" "Saved Configurations": "Configurazioni Salvate"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "Scala" "Scale": "Scala"
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "Scienza" "Science": "Scienza"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "Condivisione schermo" "Screen sharing": "Condivisione schermo"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "Mostra la sovrapposizione oscurata dietro le finestre di dialogo modali" "Show darkened overlay behind modal dialogs": "Mostra la sovrapposizione oscurata dietro le finestre di dialogo modali"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Mostra la sovrapposizione del launcher durante la digitazione nella panoramica di Niri. Disabilita per usare un altro launcher." "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Mostra la sovrapposizione del launcher durante la digitazione nella panoramica di Niri. Disabilita per usare un altro launcher."
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Questo widget impedisce gli stati di spegnimento della GPU, che possono influire in modo significativo sulla durata della batteria sui laptop. Non è consigliabile utilizzarlo su laptop con grafica ibrida." "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Questo widget impedisce gli stati di spegnimento della GPU, che possono influire in modo significativo sulla durata della batteria sui laptop. Non è consigliabile utilizzarlo su laptop con grafica ibrida."
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "La cronologia degli appunti verrà cancellata definitivamente." "This will permanently delete all clipboard history.": "La cronologia degli appunti verrà cancellata definitivamente."
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "Tiling" "Tiling": "Tiling"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "Prefisso Attivatore" "Trigger Prefix": "Prefisso Attivatore"
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "Spegni monitor dopo" "Turn off monitors after": "Spegni monitor dopo"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "Aggiorna Plugin" "Update Plugin": "Aggiorna Plugin"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "Colore Urgente" "Urgent Color": "Colore Urgente"
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "dgop non disponibile" "dgop not available": "dgop non disponibile"
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl esiste ma non è incluso in config.kdl. Le scorciatoie personalizzate non funzioneranno finché questo non sarà risolto." "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl esiste ma non è incluso in config.kdl. Le scorciatoie personalizzate non funzioneranno finché questo non sarà risolto."
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "Nessun plugin trovato" "No plugins found": "Nessun plugin trovato"
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "Nessun tema trovato" "No themes found": "Nessun tema trovato"
}, },
"events": { "events": {
"events": "eventi" "events": "eventi"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "file" "files": "file"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "Temi colore ispirati al Material Design" "Material Design inspired color themes": "Temi colore ispirati al Material Design"
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "Indietro" "Back": "Indietro"
}, },
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "minuti" "minutes": "minuti"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "ms" "ms": "ms"
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "Cerca plugin..." "Search plugins...": "Cerca plugin..."
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "Seleziona Immagine Profilo" "Select Profile Image": "Seleziona Immagine Profilo"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "Intensità" "Intensity": "Intensità"
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "sorgente" "source": "sorgente"
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "Monitor Sistema" "System Monitor": "Monitor Sistema"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "Installa temi colore dal registro temi DMS" "Install color themes from the DMS theme registry": "Installa temi colore dal registro temi DMS"
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "aggiorna dms per l'integrazione NM." "update dms for NM integration.": "aggiorna dms per l'integrazione NM."
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "Richiede %1" "Requires %1": "Richiede %1"
}, },

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "" "Always Show Percentage": ""
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "常時表示アイコン" "Always on icons": "常時表示アイコン"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "" "Clear All Jobs": ""
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "" "Clear all history when server starts": ""
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "" "Copy": ""
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "PIDをコピー" "Copy PID": "PIDをコピー"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "" "Delete Printer": ""
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "" "Delete VPN": ""
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "ディスク使用率" "Disk Usage": "ディスク使用率"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "解除" "Dismiss": "解除"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "" "Enterprise": ""
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "エラー" "Error": "エラー"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "選ばれたジョブの取り消しに失敗しました" "Failed to cancel selected job": "選ばれたジョブの取り消しに失敗しました"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "VPNへの接続が失敗しました" "Failed to connect VPN": "VPNへの接続が失敗しました"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "プリンターの一時中断に失敗しました" "Failed to pause printer": "プリンターの一時中断に失敗しました"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "" "Failed to print test page": ""
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "" "Failed to start connection to %1": ""
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "" "Failed to update VPN": ""
}, },
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "" "Force HDR": ""
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "プロセスを強制終了" "Force Kill Process": "プロセスを強制終了"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "ガンマ制御は使用できません。DMS API v6+ が必要です。" "Gamma control not available. Requires DMS API v6+.": "ガンマ制御は使用できません。DMS API v6+ が必要です。"
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "" "GitHub": ""
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "" "History Settings": ""
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "" "Hold Duration": ""
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "DMSプラグインレジストリからプラグインをインストールする" "Install plugins from the DMS plugin registry": "DMSプラグインレジストリからプラグインをインストールする"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "" "Interface:": ""
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "ジョブ: " "Jobs: ": "ジョブ: "
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "活動状態を維持" "Keep Awake": "活動状態を維持"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "" "Maximum History": ""
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "" "Maximum number of clipboard entries to keep": ""
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "" "Maximum size per clipboard entry": ""
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "" "No printers found": ""
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "" "No variants created. Click Add to create a new monitor widget.": ""
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "OSD位置" "OSD Position": "OSD位置"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "" "Off": ""
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "百分率" "Percentage": "百分率"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "プロフィール画像の設定権限が拒否されました。" "Permission denied to set profile image.": "プロフィール画像の設定権限が拒否されました。"
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "電源プロファイルの劣化" "Power Profile Degradation": "電源プロファイルの劣化"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "" "Power profile management available": ""
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "" "Process Count": ""
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "進行中" "Processing": "進行中"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "" "Saved Configurations": ""
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "" "Scale": ""
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "科学" "Science": "科学"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "画面共有" "Screen sharing": "画面共有"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "モーダルダイアログの背後に暗いオーバーレイを表示" "Show darkened overlay behind modal dialogs": "モーダルダイアログの背後に暗いオーバーレイを表示"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "" "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": ""
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "このウィジェットはGPUの省電力状態を防ぎ、ートパソコンのバッテリー寿命に大きな影響を与える可能性があります。ハイブリッドグラフィックス搭載のートパソコンでの使用は推奨されません。" "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "このウィジェットはGPUの省電力状態を防ぎ、ートパソコンのバッテリー寿命に大きな影響を与える可能性があります。ハイブリッドグラフィックス搭載のートパソコンでの使用は推奨されません。"
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "これはすべてのクリップボード履歴を完全に削除します。" "This will permanently delete all clipboard history.": "これはすべてのクリップボード履歴を完全に削除します。"
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "タイリング" "Tiling": "タイリング"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "" "Trigger Prefix": ""
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "後にモニターの電源を切る" "Turn off monitors after": "後にモニターの電源を切る"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "プラグインを更新" "Update Plugin": "プラグインを更新"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "" "Urgent Color": ""
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "" "dgop not available": ""
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "" "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": ""
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "" "No plugins found": ""
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "" "No themes found": ""
}, },
"events": { "events": {
"events": "イベント" "events": "イベント"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "" "files": ""
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "" "Material Design inspired color themes": ""
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "" "Back": ""
}, },
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "" "minutes": ""
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "" "ms": ""
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "" "Search plugins...": ""
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "プロファイル画像を選んでください" "Select Profile Image": "プロファイル画像を選んでください"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "" "Intensity": ""
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "" "source": ""
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "システムモニタ" "System Monitor": "システムモニタ"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "" "Install color themes from the DMS theme registry": ""
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "NM統合のためにDMSを更新します。" "update dms for NM integration.": "NM統合のためにDMSを更新します。"
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "" "Requires %1": ""
}, },

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "Zawsze pokazuj procenty" "Always Show Percentage": "Zawsze pokazuj procenty"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "Ikony zawsze włączone" "Always on icons": "Ikony zawsze włączone"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "Wyczyść wszystkie zadania" "Clear All Jobs": "Wyczyść wszystkie zadania"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "Wyczyść historię gdy serwer startuje" "Clear all history when server starts": "Wyczyść historię gdy serwer startuje"
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "" "Copy": ""
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "Kopiuj PID" "Copy PID": "Kopiuj PID"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "Usuń drukarkę" "Delete Printer": "Usuń drukarkę"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "Usuń VPN" "Delete VPN": "Usuń VPN"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "Użycie dysku" "Disk Usage": "Użycie dysku"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "Odrzuć" "Dismiss": "Odrzuć"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "Korporacyjny" "Enterprise": "Korporacyjny"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "Błąd" "Error": "Błąd"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "Anulowanie wybranego zadania nie powiodło się" "Failed to cancel selected job": "Anulowanie wybranego zadania nie powiodło się"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "Nie udało się połączyć z VPN" "Failed to connect VPN": "Nie udało się połączyć z VPN"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "Wstrzymanie drukarki nie powiodło się" "Failed to pause printer": "Wstrzymanie drukarki nie powiodło się"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "Nie udało się wydrukować strony testowej" "Failed to print test page": "Nie udało się wydrukować strony testowej"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "Rozpoczęcie połączenia do %1 nie powiodło się" "Failed to start connection to %1": "Rozpoczęcie połączenia do %1 nie powiodło się"
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "Nie udało się zaktualizować VPN" "Failed to update VPN": "Nie udało się zaktualizować VPN"
}, },
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "Wymuś HDR" "Force HDR": "Wymuś HDR"
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "Wymuś zamknięcie procesu" "Force Kill Process": "Wymuś zamknięcie procesu"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "Kontrola gamma niedostępna. Wymaga DMS API w wersji 6+." "Gamma control not available. Requires DMS API v6+.": "Kontrola gamma niedostępna. Wymaga DMS API w wersji 6+."
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "GitHub" "GitHub": "GitHub"
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "Ustawienia Historii" "History Settings": "Ustawienia Historii"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "Czas przytrzymania" "Hold Duration": "Czas przytrzymania"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "Instaluj wtyczki z rejestru wtyczek DMS" "Install plugins from the DMS plugin registry": "Instaluj wtyczki z rejestru wtyczek DMS"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "Interfejs:" "Interface:": "Interfejs:"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "Zadania: " "Jobs: ": "Zadania: "
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "Utrzymuj aktywność" "Keep Awake": "Utrzymuj aktywność"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "Maksymalna historia" "Maximum History": "Maksymalna historia"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "Maksymalna liczba wpisów schowka" "Maximum number of clipboard entries to keep": "Maksymalna liczba wpisów schowka"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "Maksymalny rozmiar per wpis schowka" "Maximum size per clipboard entry": "Maksymalny rozmiar per wpis schowka"
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "Nie znaleziono drukarek" "No printers found": "Nie znaleziono drukarek"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "Nie stworzono wariantów. Kliknij Dodaj by stworzyć nowy widżet monitora." "No variants created. Click Add to create a new monitor widget.": "Nie stworzono wariantów. Kliknij Dodaj by stworzyć nowy widżet monitora."
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "Pozycja OSD" "OSD Position": "Pozycja OSD"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "Wyłączony" "Off": "Wyłączony"
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "Procent" "Percentage": "Procent"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "Odmowa uprawnień do ustawienia zdjęcia profilowego." "Permission denied to set profile image.": "Odmowa uprawnień do ustawienia zdjęcia profilowego."
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "Pogorszenie profilu zasilania" "Power Profile Degradation": "Pogorszenie profilu zasilania"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "Zarządzanie profilami zasilania dostępne" "Power profile management available": "Zarządzanie profilami zasilania dostępne"
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "Liczba procesów" "Process Count": "Liczba procesów"
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "Przetwarzanie" "Processing": "Przetwarzanie"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "Zapisane konfiguracje" "Saved Configurations": "Zapisane konfiguracje"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "Skala" "Scale": "Skala"
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "Nauka" "Science": "Nauka"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "Udostępnianie ekranu" "Screen sharing": "Udostępnianie ekranu"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "Pokaż przyciemnioną nakładkę za oknami modalnymi" "Show darkened overlay behind modal dialogs": "Pokaż przyciemnioną nakładkę za oknami modalnymi"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Pokaż nakładkę launchera podczas pisania w przeglądzie Niri. Wyłączy by użyć innego launchera." "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Pokaż nakładkę launchera podczas pisania w przeglądzie Niri. Wyłączy by użyć innego launchera."
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Ten widżet zapobiega wyłączaniu zasilania GPU, co może znacznie wpłynąć na żywotność baterii w laptopach. Nie zaleca się używania go na laptopach z hybrydową grafiką." "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Ten widżet zapobiega wyłączaniu zasilania GPU, co może znacznie wpłynąć na żywotność baterii w laptopach. Nie zaleca się używania go na laptopach z hybrydową grafiką."
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "To trwale usunie całą historię schowka." "This will permanently delete all clipboard history.": "To trwale usunie całą historię schowka."
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "Dekarstwo" "Tiling": "Dekarstwo"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "" "Trigger Prefix": ""
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "Wyłącz monitory po" "Turn off monitors after": "Wyłącz monitory po"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "Zaktualizuj wtyczkę" "Update Plugin": "Zaktualizuj wtyczkę"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "" "Urgent Color": ""
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "dgop niedostępne" "dgop not available": "dgop niedostępne"
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "Plik dms/binds.kdl istnieje, ale nie jest uwzględniony w pliku config.kdl. Niestandardowe skróty klawiszowe nie będą działać, dopóki ten problem nie zostanie rozwiązany." "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "Plik dms/binds.kdl istnieje, ale nie jest uwzględniony w pliku config.kdl. Niestandardowe skróty klawiszowe nie będą działać, dopóki ten problem nie zostanie rozwiązany."
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "Nie znaleziono wtyczek" "No plugins found": "Nie znaleziono wtyczek"
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "Nie znaleziono motywów" "No themes found": "Nie znaleziono motywów"
}, },
"events": { "events": {
"events": "wydarzenia" "events": "wydarzenia"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "akta" "files": "akta"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "Motywy inspirowane Material Design" "Material Design inspired color themes": "Motywy inspirowane Material Design"
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "" "Back": ""
}, },
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "protokół" "minutes": "protokół"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "ms" "ms": "ms"
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "Szukaj wtyczek..." "Search plugins...": "Szukaj wtyczek..."
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "Wybierz obraz profilowy" "Select Profile Image": "Wybierz obraz profilowy"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "" "Intensity": ""
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "źródło" "source": "źródło"
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "Monitor systemu" "System Monitor": "Monitor systemu"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "Zainstaluj motywy z rejestru DMS" "Install color themes from the DMS theme registry": "Zainstaluj motywy z rejestru DMS"
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "zaktualizuj dms dla integracji z NM." "update dms for NM integration.": "zaktualizuj dms dla integracji z NM."
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "" "Requires %1": ""
}, },

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "Sempre Mostrar Porcentagem" "Always Show Percentage": "Sempre Mostrar Porcentagem"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "Ícones sempre ligados" "Always on icons": "Ícones sempre ligados"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "Limpar Todos os Trabalhos" "Clear All Jobs": "Limpar Todos os Trabalhos"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "Limpar todo o histórico quando o servidor iniciar" "Clear all history when server starts": "Limpar todo o histórico quando o servidor iniciar"
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "" "Copy": ""
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "Copiar PID" "Copy PID": "Copiar PID"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "Excluir Impressora" "Delete Printer": "Excluir Impressora"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "Excluir VPN" "Delete VPN": "Excluir VPN"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "Uso de Disco" "Disk Usage": "Uso de Disco"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "Descartar" "Dismiss": "Descartar"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "Enterprise" "Enterprise": "Enterprise"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "Erro" "Error": "Erro"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "Falha ao cancelar o trabalho selecionado" "Failed to cancel selected job": "Falha ao cancelar o trabalho selecionado"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "Erro ao conectar à VPN" "Failed to connect VPN": "Erro ao conectar à VPN"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "Falha ao pausar impressora" "Failed to pause printer": "Falha ao pausar impressora"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "Falha ao imprimir página de testes" "Failed to print test page": "Falha ao imprimir página de testes"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "" "Failed to start connection to %1": ""
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "Falha ao atualizar VPN" "Failed to update VPN": "Falha ao atualizar VPN"
}, },
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "" "Force HDR": ""
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "Forçar Fechamento do Processo" "Force Kill Process": "Forçar Fechamento do Processo"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "Controle de gama não disponível. Necessário DMS API v6+." "Gamma control not available. Requires DMS API v6+.": "Controle de gama não disponível. Necessário DMS API v6+."
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "" "GitHub": ""
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "Configurações do Histórico" "History Settings": "Configurações do Histórico"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "Duração do Pressionamento" "Hold Duration": "Duração do Pressionamento"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "Instale plugins a partir do registro de plugins do DMS" "Install plugins from the DMS plugin registry": "Instale plugins a partir do registro de plugins do DMS"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "Interface:" "Interface:": "Interface:"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "Trabalhos:" "Jobs: ": "Trabalhos:"
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "Manter Ligado" "Keep Awake": "Manter Ligado"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "Histórico Máximo" "Maximum History": "Histórico Máximo"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "Número máximo de entradas da área de transferência para guardar" "Maximum number of clipboard entries to keep": "Número máximo de entradas da área de transferência para guardar"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "Tamanho máximo por entrada da área de transferência" "Maximum size per clipboard entry": "Tamanho máximo por entrada da área de transferência"
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "Nenhuma impressora encontrada" "No printers found": "Nenhuma impressora encontrada"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "" "No variants created. Click Add to create a new monitor widget.": ""
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "Posição do OSD" "OSD Position": "Posição do OSD"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "" "Off": ""
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "Porcetagem" "Percentage": "Porcetagem"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "Permissão negada ao definir imagem de perfil." "Permission denied to set profile image.": "Permissão negada ao definir imagem de perfil."
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "Degradação do Perfil de Energia" "Power Profile Degradation": "Degradação do Perfil de Energia"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "" "Power profile management available": ""
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "" "Process Count": ""
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "Processando" "Processing": "Processando"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "Configurações Salvas" "Saved Configurations": "Configurações Salvas"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "" "Scale": ""
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "Ciência" "Science": "Ciência"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "Compartilhamento de tela" "Screen sharing": "Compartilhamento de tela"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "Exibir sobreposição escurecida atrás de diálogos modais" "Show darkened overlay behind modal dialogs": "Exibir sobreposição escurecida atrás de diálogos modais"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "" "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": ""
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Este widget mantém a GPU ativa, podendo reduzir a duração da bateria. Não recomendado em laptops com gráficos híbridos." "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Este widget mantém a GPU ativa, podendo reduzir a duração da bateria. Não recomendado em laptops com gráficos híbridos."
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "Isso vai apagar permanentemetne todo o histórico da área de transferência." "This will permanently delete all clipboard history.": "Isso vai apagar permanentemetne todo o histórico da área de transferência."
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "Tiling" "Tiling": "Tiling"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "" "Trigger Prefix": ""
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "Desligar monitores depois de" "Turn off monitors after": "Desligar monitores depois de"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "Atualizar Plugin" "Update Plugin": "Atualizar Plugin"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "" "Urgent Color": ""
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "" "dgop not available": ""
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "" "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": ""
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "" "No plugins found": ""
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "" "No themes found": ""
}, },
"events": { "events": {
"events": "eventos" "events": "eventos"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "arquivos" "files": "arquivos"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "" "Material Design inspired color themes": ""
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "" "Back": ""
}, },
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "minutos" "minutes": "minutos"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "" "ms": ""
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "" "Search plugins...": ""
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "Selecionar Imagem de Perfil" "Select Profile Image": "Selecionar Imagem de Perfil"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "" "Intensity": ""
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "" "source": ""
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "Monitor do Sistema" "System Monitor": "Monitor do Sistema"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "" "Install color themes from the DMS theme registry": ""
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "atualize dms para integração com o NM." "update dms for NM integration.": "atualize dms para integração com o NM."
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "" "Requires %1": ""
}, },

View File

@@ -15,7 +15,7 @@
"%1 connected": "%1 bağlı" "%1 connected": "%1 bağlı"
}, },
"%1 days ago": { "%1 days ago": {
"%1 days ago": "%1 gün önce" "%1 days ago": ""
}, },
"%1 display(s)": { "%1 display(s)": {
"%1 display(s)": "%1 ekran" "%1 display(s)": "%1 ekran"
@@ -42,7 +42,7 @@
"%1 widgets": "%1 widget" "%1 widgets": "%1 widget"
}, },
"%1m ago": { "%1m ago": {
"%1m ago": "%1dk önce" "%1m ago": ""
}, },
"(Unnamed)": { "(Unnamed)": {
"(Unnamed)": "(İsimsiz)" "(Unnamed)": "(İsimsiz)"
@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "Yüzdeyi Her Zaman Göster" "Always Show Percentage": "Yüzdeyi Her Zaman Göster"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "Her zaman açık simgeler" "Always on icons": "Her zaman açık simgeler"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "Tüm İşleri Temizle" "Clear All Jobs": "Tüm İşleri Temizle"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "Sunucu başladığında tüm geçmişi temizle" "Clear all history when server starts": "Sunucu başladığında tüm geçmişi temizle"
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "" "Copy": ""
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "PID'i Kopyala" "Copy PID": "PID'i Kopyala"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "Yazıcı Sil" "Delete Printer": "Yazıcı Sil"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "VPN'i Sil" "Delete VPN": "VPN'i Sil"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "Disk Kullanımı" "Disk Usage": "Disk Kullanımı"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "Reddet" "Dismiss": "Reddet"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "Kurumsal" "Enterprise": "Kurumsal"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "Hata" "Error": "Hata"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "Seçilen işler iptal edemedi" "Failed to cancel selected job": "Seçilen işler iptal edemedi"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "VPN bağlantısı kurulamadı" "Failed to connect VPN": "VPN bağlantısı kurulamadı"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "Yazıcıyı duraklatma başarısız" "Failed to pause printer": "Yazıcıyı duraklatma başarısız"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "Test sayfası yazdırılamadı" "Failed to print test page": "Test sayfası yazdırılamadı"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "%1 bağlantı başlatılamadı" "Failed to start connection to %1": "%1 bağlantı başlatılamadı"
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "VPN güncellenemedi" "Failed to update VPN": "VPN güncellenemedi"
}, },
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "Zorla HDR" "Force HDR": "Zorla HDR"
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "Süreci Zorla Kapat" "Force Kill Process": "Süreci Zorla Kapat"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "Gama kontrolü mevcut değil. DMS API V6+ gerekir." "Gamma control not available. Requires DMS API v6+.": "Gama kontrolü mevcut değil. DMS API V6+ gerekir."
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "GitHub" "GitHub": "GitHub"
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "Geçmiş Ayarları" "History Settings": "Geçmiş Ayarları"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "Tutma Süresi" "Hold Duration": "Tutma Süresi"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "DMS eklenti defterinden eklentiler yükle" "Install plugins from the DMS plugin registry": "DMS eklenti defterinden eklentiler yükle"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "Arayüz:" "Interface:": "Arayüz:"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "İşler:" "Jobs: ": "İşler:"
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "Uyanık Tut" "Keep Awake": "Uyanık Tut"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "Maksimum Geçmiş" "Maximum History": "Maksimum Geçmiş"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "Saklanacak maksimum pano kaydı sayısı" "Maximum number of clipboard entries to keep": "Saklanacak maksimum pano kaydı sayısı"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "Pano kaydı başına maksimum boyut" "Maximum size per clipboard entry": "Pano kaydı başına maksimum boyut"
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "Hiçbir yazıcı bulunmadı" "No printers found": "Hiçbir yazıcı bulunmadı"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "Hiçbir varyant oluşturulmadı. Yeni bir monitör widget'ı oluşturmak için Ekle'ye tıklayın." "No variants created. Click Add to create a new monitor widget.": "Hiçbir varyant oluşturulmadı. Yeni bir monitör widget'ı oluşturmak için Ekle'ye tıklayın."
}, },
@@ -2797,7 +2577,7 @@
"Not connected": "Bağlı değil" "Not connected": "Bağlı değil"
}, },
"Not detected": { "Not detected": {
"Not detected": "Algılanmadı" "Not detected": ""
}, },
"Note: this only changes the percentage, it does not actually limit charging.": { "Note: this only changes the percentage, it does not actually limit charging.": {
"Note: this only changes the percentage, it does not actually limit charging.": "Not: Bu sadece yüzdeyi değiştirir, şarjı sınırlamaz." "Note: this only changes the percentage, it does not actually limit charging.": "Not: Bu sadece yüzdeyi değiştirir, şarjı sınırlamaz."
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "OSD Pozisyonu" "OSD Position": "OSD Pozisyonu"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "Kapalı" "Off": "Kapalı"
}, },
@@ -2920,7 +2697,7 @@
"Override": "Geçersiz Kıl" "Override": "Geçersiz Kıl"
}, },
"Override Border Size": { "Override Border Size": {
"Override Border Size": "Kenar boyutunu geçersiz kıl" "Override Border Size": ""
}, },
"Override Corner Radius": { "Override Corner Radius": {
"Override Corner Radius": "Köşe Yarıçapını Değiştir" "Override Corner Radius": "Köşe Yarıçapını Değiştir"
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "Yüzde" "Percentage": "Yüzde"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "Profil resmi ayarlama izni reddedildi." "Permission denied to set profile image.": "Profil resmi ayarlama izni reddedildi."
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "Güç Profili Dejenerasyonu" "Power Profile Degradation": "Güç Profili Dejenerasyonu"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "Güç profili yönetimi mevcut" "Power profile management available": "Güç profili yönetimi mevcut"
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "Süreç Sayısı" "Process Count": "Süreç Sayısı"
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "İşleniyor" "Processing": "İşleniyor"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "Kaydedilen Yapılandırmalar" "Saved Configurations": "Kaydedilen Yapılandırmalar"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "Ölçek" "Scale": "Ölçek"
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "Bilim" "Science": "Bilim"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "Ekran paylaşımı" "Screen sharing": "Ekran paylaşımı"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "Modal diyalogların arkasında karartılmış kaplama göster" "Show darkened overlay behind modal dialogs": "Modal diyalogların arkasında karartılmış kaplama göster"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Niri genel görünümde yazarken başlatıcı katmanını göster. Başka bir başlatıcı kullanmak için devre dışı bırakın." "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "Niri genel görünümde yazarken başlatıcı katmanını göster. Başka bir başlatıcı kullanmak için devre dışı bırakın."
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Bu widget, dizüstü bilgisayarlarda pil ömrünü önemli ölçüde etkileyebilen GPU güç kapatma durumlarını önler. Hibrit grafik kartına sahip dizüstü bilgisayarlarda kullanılması önerilmez." "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "Bu widget, dizüstü bilgisayarlarda pil ömrünü önemli ölçüde etkileyebilen GPU güç kapatma durumlarını önler. Hibrit grafik kartına sahip dizüstü bilgisayarlarda kullanılması önerilmez."
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "Bu, tüm pano geçmişini kalıcı olarak siler." "This will permanently delete all clipboard history.": "Bu, tüm pano geçmişini kalıcı olarak siler."
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "Döşeme" "Tiling": "Döşeme"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "" "Trigger Prefix": ""
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "Şu zaman sonra monitörleri kapat" "Turn off monitors after": "Şu zaman sonra monitörleri kapat"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "Eklentiyi Güncelle" "Update Plugin": "Eklentiyi Güncelle"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "" "Urgent Color": ""
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "dgop mevcut değil" "dgop not available": "dgop mevcut değil"
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl dosyası mevcut ancak config.kdl dosyasına dahil edilmemiştir. Bu sorun giderilene kadar özel tuş atamaları çalışmayacaktır." "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl dosyası mevcut ancak config.kdl dosyasına dahil edilmemiştir. Bu sorun giderilene kadar özel tuş atamaları çalışmayacaktır."
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "Eklenti bulunamadı" "No plugins found": "Eklenti bulunamadı"
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "Tema bulunmadı" "No themes found": "Tema bulunmadı"
}, },
"events": { "events": {
"events": "etkinlikler" "events": "etkinlikler"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "dosyalar" "files": "dosyalar"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "Malzeme Tasarımı'ndan ilham alan renk temaları" "Material Design inspired color themes": "Malzeme Tasarımı'ndan ilham alan renk temaları"
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "" "Back": ""
}, },
@@ -4654,9 +4374,9 @@
}, },
"greeter doctor page empty state": { "greeter doctor page empty state": {
"No checks passed": "", "No checks passed": "",
"No errors": "Sorun yok", "No errors": "",
"No info items": "", "No info items": "",
"No warnings": "Uyarı yok" "No warnings": ""
}, },
"greeter doctor page error count": { "greeter doctor page error count": {
"%1 issue(s) found": "" "%1 issue(s) found": ""
@@ -4665,9 +4385,9 @@
"Analyzing configuration...": "" "Analyzing configuration...": ""
}, },
"greeter doctor page status card": { "greeter doctor page status card": {
"Errors": "Hatalar", "Errors": "",
"Info": "Bilgi", "Info": "",
"OK": "Tamam", "OK": "",
"Warnings": "" "Warnings": ""
}, },
"greeter doctor page success": { "greeter doctor page success": {
@@ -4689,7 +4409,7 @@
"Extensible architecture": "", "Extensible architecture": "",
"GTK, Qt, IDEs, more": "", "GTK, Qt, IDEs, more": "",
"Modular widget bar": "", "Modular widget bar": "",
"Night mode & gamma": "Gece modu & gamma", "Night mode & gamma": "",
"Per-screen config": "", "Per-screen config": "",
"Quick system toggles": "", "Quick system toggles": "",
"Security & privacy": "" "Security & privacy": ""
@@ -4704,7 +4424,7 @@
"Theme Registry": "" "Theme Registry": ""
}, },
"greeter feature card title | greeter plugins link": { "greeter feature card title | greeter plugins link": {
"Plugins": "Eklentiler" "Plugins": ""
}, },
"greeter feature card title | greeter settings link": { "greeter feature card title | greeter settings link": {
"DankBar": "" "DankBar": ""
@@ -4716,7 +4436,7 @@
"Finish": "" "Finish": ""
}, },
"greeter first page button": { "greeter first page button": {
"Get Started": "Başlarken" "Get Started": ""
}, },
"greeter keybinds niri description": { "greeter keybinds niri description": {
"niri shortcuts config": "" "niri shortcuts config": ""
@@ -4728,7 +4448,7 @@
"Welcome": "" "Welcome": ""
}, },
"greeter next button": { "greeter next button": {
"Next": "Devam et" "Next": ""
}, },
"greeter no keybinds message": { "greeter no keybinds message": {
"No DMS shortcuts configured": "" "No DMS shortcuts configured": ""
@@ -4739,8 +4459,8 @@
"greeter settings link": { "greeter settings link": {
"Displays": "", "Displays": "",
"Dock": "", "Dock": "",
"Keybinds": "Kısayollar", "Keybinds": "",
"Notifications": "Bildirimler", "Notifications": "",
"Theme & Colors": "", "Theme & Colors": "",
"Wallpaper": "" "Wallpaper": ""
}, },
@@ -4803,7 +4523,7 @@
"Notification Display": "" "Notification Display": ""
}, },
"lock screen notifications settings card": { "lock screen notifications settings card": {
"Lock Screen": "Kilit ekranı" "Lock Screen": ""
}, },
"loginctl not available - lock integration requires DMS socket connection": { "loginctl not available - lock integration requires DMS socket connection": {
"loginctl not available - lock integration requires DMS socket connection": "loginctl kullanılabilir değil - kilit entegrasyonu DMS soket bağlantısı gerektirir" "loginctl not available - lock integration requires DMS socket connection": "loginctl kullanılabilir değil - kilit entegrasyonu DMS soket bağlantısı gerektirir"
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "dakika" "minutes": "dakika"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "ms" "ms": "ms"
}, },
@@ -4836,11 +4553,11 @@
"No wallpaper selected": "Duvar kağıdı seçilmedi" "No wallpaper selected": "Duvar kağıdı seçilmedi"
}, },
"notification center tab": { "notification center tab": {
"Current": "Şu an", "Current": "",
"History": "" "History": ""
}, },
"notification history filter": { "notification history filter": {
"All": "Tümü", "All": "",
"Last hour": "", "Last hour": "",
"Today": "", "Today": "",
"Yesterday": "" "Yesterday": ""
@@ -4849,23 +4566,23 @@
"Older": "" "Older": ""
}, },
"notification history filter | notification history retention option": { "notification history filter | notification history retention option": {
"30 days": "30 günlük", "30 days": "",
"7 days": "7 günlük" "7 days": ""
}, },
"notification history limit": { "notification history limit": {
"Maximum number of notifications to keep": "" "Maximum number of notifications to keep": ""
}, },
"notification history retention option": { "notification history retention option": {
"1 day": "1 günlük", "1 day": "",
"14 days": "14 günlük", "14 days": "",
"3 days": "3 günlük", "3 days": "",
"Forever": "" "Forever": ""
}, },
"notification history retention settings label": { "notification history retention settings label": {
"History Retention": "" "History Retention": ""
}, },
"notification history setting": { "notification history setting": {
"Auto-delete notifications older than this": "Bildirimler şundan eskiyse otomatik sil", "Auto-delete notifications older than this": "",
"Save critical priority notifications to history": "", "Save critical priority notifications to history": "",
"Save low priority notifications to history": "", "Save low priority notifications to history": "",
"Save normal priority notifications to history": "" "Save normal priority notifications to history": ""
@@ -4874,7 +4591,7 @@
"Save dismissed notifications to history": "" "Save dismissed notifications to history": ""
}, },
"notification history toggle label": { "notification history toggle label": {
"Enable History": "Geçmişi Aç" "Enable History": ""
}, },
"now": { "now": {
"now": "" "now": ""
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "Eklenti ara..." "Search plugins...": "Eklenti ara..."
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "Profil Resmi Seç" "Select Profile Image": "Profil Resmi Seç"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "" "Intensity": ""
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "kaynak" "source": "kaynak"
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "Sistem Monitörü" "System Monitor": "Sistem Monitörü"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "DMS tema kayıt defterinden renk temaları yükle" "Install color themes from the DMS theme registry": "DMS tema kayıt defterinden renk temaları yükle"
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "NM entegrasyonu için dms'yi güncelle" "update dms for NM integration.": "NM entegrasyonu için dms'yi güncelle"
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "" "Requires %1": ""
}, },

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "始终显示百分比" "Always Show Percentage": "始终显示百分比"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "总显示的图标" "Always on icons": "总显示的图标"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "清除所有任务" "Clear All Jobs": "清除所有任务"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "当服务器启动时清除所有纪录" "Clear all history when server starts": "当服务器启动时清除所有纪录"
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "复制" "Copy": "复制"
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "复制进程ID" "Copy PID": "复制进程ID"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "删除打印机" "Delete Printer": "删除打印机"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "删除 VPN" "Delete VPN": "删除 VPN"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "磁盘占用" "Disk Usage": "磁盘占用"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "忽略" "Dismiss": "忽略"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "企业" "Enterprise": "企业"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "错误" "Error": "错误"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "无法取消所选的任务" "Failed to cancel selected job": "无法取消所选的任务"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "连接 VPN 失败" "Failed to connect VPN": "连接 VPN 失败"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "无法暂停打印机" "Failed to pause printer": "无法暂停打印机"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "打印测试页失败" "Failed to print test page": "打印测试页失败"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "连接至%1失败" "Failed to start connection to %1": "连接至%1失败"
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "更新 VPN 失败" "Failed to update VPN": "更新 VPN 失败"
}, },
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "强制HDR" "Force HDR": "强制HDR"
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "强制结束进程" "Force Kill Process": "强制结束进程"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "伽玛控制不可用,需要 DMS API v6+。" "Gamma control not available. Requires DMS API v6+.": "伽玛控制不可用,需要 DMS API v6+。"
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "GitHub" "GitHub": "GitHub"
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "历史设置" "History Settings": "历史设置"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "按住持续时间" "Hold Duration": "按住持续时间"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "从 DMS 插件库安装插件" "Install plugins from the DMS plugin registry": "从 DMS 插件库安装插件"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "接口:" "Interface:": "接口:"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "任务: " "Jobs: ": "任务: "
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "保持活动" "Keep Awake": "保持活动"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "最多历史数" "Maximum History": "最多历史数"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "剪切板项目记住的最大数量" "Maximum number of clipboard entries to keep": "剪切板项目记住的最大数量"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "每个剪切板项目的最大尺寸" "Maximum size per clipboard entry": "每个剪切板项目的最大尺寸"
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "未找到打印机" "No printers found": "未找到打印机"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "没有任何变体。点击添加以创建新的显示器小部件。" "No variants created. Click Add to create a new monitor widget.": "没有任何变体。点击添加以创建新的显示器小部件。"
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "OSD位置" "OSD Position": "OSD位置"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "关闭" "Off": "关闭"
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "占用率" "Percentage": "占用率"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "因权限问题,无法设置个人资料图片。" "Permission denied to set profile image.": "因权限问题,无法设置个人资料图片。"
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "电源配置性能下降" "Power Profile Degradation": "电源配置性能下降"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "电源配置文件管理可用" "Power profile management available": "电源配置文件管理可用"
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "进程计数" "Process Count": "进程计数"
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "处理中" "Processing": "处理中"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "已保存的配置" "Saved Configurations": "已保存的配置"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "缩放" "Scale": "缩放"
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "科学" "Science": "科学"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "屏幕分享" "Screen sharing": "屏幕分享"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "在对话框后显示暗色遮罩" "Show darkened overlay behind modal dialogs": "在对话框后显示暗色遮罩"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "在Niri概览中打字时显示启动器叠加层。禁用该项以使用其他启动器。" "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "在Niri概览中打字时显示启动器叠加层。禁用该项以使用其他启动器。"
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "此部件会阻止 GPU 进入省电状态,可能会显著影响笔记本的电池续航。不建议在配备混合显卡的笔记本上使用。" "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "此部件会阻止 GPU 进入省电状态,可能会显著影响笔记本的电池续航。不建议在配备混合显卡的笔记本上使用。"
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "此操作会清空剪贴板历史,且无法恢复。" "This will permanently delete all clipboard history.": "此操作会清空剪贴板历史,且无法恢复。"
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "平铺" "Tiling": "平铺"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "触发前缀" "Trigger Prefix": "触发前缀"
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "在此时间后关闭显示器" "Turn off monitors after": "在此时间后关闭显示器"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "更新插件" "Update Plugin": "更新插件"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "高亮颜色" "Urgent Color": "高亮颜色"
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "dgop不可用" "dgop not available": "dgop不可用"
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl 存在,但未包含在 config.kdl 中。除非修复此问题,否则自定义键绑定将无法工作。" "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl 存在,但未包含在 config.kdl 中。除非修复此问题,否则自定义键绑定将无法工作。"
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "未找到插件" "No plugins found": "未找到插件"
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "未找到主题" "No themes found": "未找到主题"
}, },
"events": { "events": {
"events": "事件" "events": "事件"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "文件" "files": "文件"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "受Material设计启发的色彩主题" "Material Design inspired color themes": "受Material设计启发的色彩主题"
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "返回" "Back": "返回"
}, },
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "分钟" "minutes": "分钟"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "毫秒" "ms": "毫秒"
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "插件搜索中..." "Search plugins...": "插件搜索中..."
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "选择个人信息图像" "Select Profile Image": "选择个人信息图像"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "强度" "Intensity": "强度"
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "源" "source": "源"
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "系统监视器" "System Monitor": "系统监视器"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "从DMS主题注册表安装色彩主题" "Install color themes from the DMS theme registry": "从DMS主题注册表安装色彩主题"
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "更新 DMS 以集成 NM" "update dms for NM integration.": "更新 DMS 以集成 NM"
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "需要%1" "Requires %1": "需要%1"
}, },

View File

@@ -251,9 +251,6 @@
"Always Show Percentage": { "Always Show Percentage": {
"Always Show Percentage": "始終顯示百分比" "Always Show Percentage": "始終顯示百分比"
}, },
"Always hide the dock and reveal it when hovering near the dock area": {
"Always hide the dock and reveal it when hovering near the dock area": ""
},
"Always on icons": { "Always on icons": {
"Always on icons": "始終顯示圖示" "Always on icons": "始終顯示圖示"
}, },
@@ -710,9 +707,6 @@
"Clear All Jobs": { "Clear All Jobs": {
"Clear All Jobs": "清除所有工作" "Clear All Jobs": "清除所有工作"
}, },
"Clear History?": {
"Clear History?": ""
},
"Clear all history when server starts": { "Clear all history when server starts": {
"Clear all history when server starts": "伺服器啟動時清除所有歷史紀錄" "Clear all history when server starts": "伺服器啟動時清除所有歷史紀錄"
}, },
@@ -923,12 +917,6 @@
"Copy": { "Copy": {
"Copy": "複製" "Copy": "複製"
}, },
"Copy Full Command": {
"Copy Full Command": ""
},
"Copy Name": {
"Copy Name": ""
},
"Copy PID": { "Copy PID": {
"Copy PID": "複製 PID" "Copy PID": "複製 PID"
}, },
@@ -1136,9 +1124,6 @@
"Delete Printer": { "Delete Printer": {
"Delete Printer": "刪除印表機" "Delete Printer": "刪除印表機"
}, },
"Delete Saved Item?": {
"Delete Saved Item?": ""
},
"Delete VPN": { "Delete VPN": {
"Delete VPN": "刪除 VPN" "Delete VPN": "刪除 VPN"
}, },
@@ -1223,9 +1208,6 @@
"Disk Usage": { "Disk Usage": {
"Disk Usage": "硬碟使用率" "Disk Usage": "硬碟使用率"
}, },
"Disks": {
"Disks": ""
},
"Dismiss": { "Dismiss": {
"Dismiss": "忽略" "Dismiss": "忽略"
}, },
@@ -1460,12 +1442,6 @@
"Enterprise": { "Enterprise": {
"Enterprise": "企業" "Enterprise": "企業"
}, },
"Entry pinned": {
"Entry pinned": ""
},
"Entry unpinned": {
"Entry unpinned": ""
},
"Error": { "Error": {
"Error": "錯誤" "Error": "錯誤"
}, },
@@ -1508,9 +1484,6 @@
"Failed to cancel selected job": { "Failed to cancel selected job": {
"Failed to cancel selected job": "取消選定工作失敗" "Failed to cancel selected job": "取消選定工作失敗"
}, },
"Failed to check pin limit": {
"Failed to check pin limit": ""
},
"Failed to connect VPN": { "Failed to connect VPN": {
"Failed to connect VPN": "VPN 連線失敗" "Failed to connect VPN": "VPN 連線失敗"
}, },
@@ -1586,9 +1559,6 @@
"Failed to pause printer": { "Failed to pause printer": {
"Failed to pause printer": "無法暫停印表機" "Failed to pause printer": "無法暫停印表機"
}, },
"Failed to pin entry": {
"Failed to pin entry": ""
},
"Failed to print test page": { "Failed to print test page": {
"Failed to print test page": "無法列印測試頁" "Failed to print test page": "無法列印測試頁"
}, },
@@ -1634,9 +1604,6 @@
"Failed to start connection to %1": { "Failed to start connection to %1": {
"Failed to start connection to %1": "無法啟動連線至 %1" "Failed to start connection to %1": "無法啟動連線至 %1"
}, },
"Failed to unpin entry": {
"Failed to unpin entry": ""
},
"Failed to update VPN": { "Failed to update VPN": {
"Failed to update VPN": "更新 VPN 失敗" "Failed to update VPN": "更新 VPN 失敗"
}, },
@@ -1742,9 +1709,6 @@
"Force HDR": { "Force HDR": {
"Force HDR": "強制 HDR" "Force HDR": "強制 HDR"
}, },
"Force Kill (SIGKILL)": {
"Force Kill (SIGKILL)": ""
},
"Force Kill Process": { "Force Kill Process": {
"Force Kill Process": "強制結束程序" "Force Kill Process": "強制結束程序"
}, },
@@ -1799,9 +1763,6 @@
"Gamma control not available. Requires DMS API v6+.": { "Gamma control not available. Requires DMS API v6+.": {
"Gamma control not available. Requires DMS API v6+.": "Gamma 控制不可用。需要 DMS API v6+。" "Gamma control not available. Requires DMS API v6+.": "Gamma 控制不可用。需要 DMS API v6+。"
}, },
"Generic device name | Generic device name fallback": {
"device": ""
},
"GitHub": { "GitHub": {
"GitHub": "GitHub" "GitHub": "GitHub"
}, },
@@ -1919,9 +1880,6 @@
"History Settings": { "History Settings": {
"History Settings": "歷史紀錄設定" "History Settings": "歷史紀錄設定"
}, },
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": ""
},
"Hold Duration": { "Hold Duration": {
"Hold Duration": "按住持續時間" "Hold Duration": "按住持續時間"
}, },
@@ -2036,9 +1994,6 @@
"Install plugins from the DMS plugin registry": { "Install plugins from the DMS plugin registry": {
"Install plugins from the DMS plugin registry": "從 DMS 插件註冊表安裝插件" "Install plugins from the DMS plugin registry": "從 DMS 插件註冊表安裝插件"
}, },
"Intelligent Auto-hide": {
"Intelligent Auto-hide": ""
},
"Interface:": { "Interface:": {
"Interface:": "介面:" "Interface:": "介面:"
}, },
@@ -2066,166 +2021,6 @@
"Jobs: ": { "Jobs: ": {
"Jobs: ": "工作: " "Jobs: ": "工作: "
}, },
"KDE Connect SMS action": {
"Opening SMS": "",
"Opening SMS app": ""
},
"KDE Connect SMS dialog title": {
"Send SMS": ""
},
"KDE Connect SMS message input placeholder": {
"Message": ""
},
"KDE Connect SMS phone input placeholder": {
"Phone number": ""
},
"KDE Connect SMS send button": {
"Send": ""
},
"KDE Connect SMS tooltip": {
"SMS": ""
},
"KDE Connect accept pairing button": {
"Accept": ""
},
"KDE Connect browse action": {
"Opening file browser": "",
"Opening files": ""
},
"KDE Connect browse tooltip": {
"Browse Files": ""
},
"KDE Connect clipboard action": {
"Clipboard sent": ""
},
"KDE Connect clipboard tooltip": {
"Send Clipboard": ""
},
"KDE Connect connected status": {
"Connected": ""
},
"KDE Connect daemon hint": {
"Start kdeconnectd to use this plugin": ""
},
"KDE Connect error": {
"Failed to accept pairing": "",
"Failed to browse device": "",
"Failed to launch SMS app": "",
"Failed to reject pairing": "",
"Failed to ring device": "",
"Failed to send clipboard": "",
"Failed to send ping": "",
"Failed to share": "",
"Pairing failed": "",
"Unpair failed": ""
},
"KDE Connect file share notification": {
"File received from": ""
},
"KDE Connect hint message": {
"Make sure KDE Connect is running on your other devices": ""
},
"KDE Connect no devices message": {
"No devices found": ""
},
"KDE Connect no devices status": {
"No devices": ""
},
"KDE Connect not paired status": {
"Not paired": ""
},
"KDE Connect offline status": {
"Offline": ""
},
"KDE Connect open SMS app button": {
"Open App": ""
},
"KDE Connect open app hint": {
"Open KDE Connect on your phone": ""
},
"KDE Connect pair button": {
"Pair": ""
},
"KDE Connect pairing action": {
"Device paired": "",
"Pairing request sent": ""
},
"KDE Connect pairing in progress status": {
"Pairing": ""
},
"KDE Connect pairing request notification": {
"Pairing request from": ""
},
"KDE Connect pairing requested status": {
"Pairing requested": ""
},
"KDE Connect pairing verification key label": {
"Verification": ""
},
"KDE Connect ping action": {
"Ping sent": "",
"Ping sent to": ""
},
"KDE Connect ping tooltip": {
"Ping": ""
},
"KDE Connect refresh button | KDE Connect refresh tooltip": {
"Refresh": ""
},
"KDE Connect reject pairing button": {
"Reject": ""
},
"KDE Connect request pairing button": {
"Request Pairing": ""
},
"KDE Connect ring action": {
"Ringing": ""
},
"KDE Connect ring tooltip": {
"Ring": ""
},
"KDE Connect service unavailable message": {
"KDE Connect unavailable": ""
},
"KDE Connect share URL button": {
"Share URL": ""
},
"KDE Connect share button | KDE Connect share dialog title | KDE Connect share tooltip": {
"Share": ""
},
"KDE Connect share input placeholder": {
"Enter URL or text to share": ""
},
"KDE Connect share success": {
"Shared": ""
},
"KDE Connect start daemon hint": {
"Start kdeconnectd to connect devices": ""
},
"KDE Connect status": {
"No devices connected": ""
},
"KDE Connect status multiple devices": {
"devices connected": ""
},
"KDE Connect status single device": {
"1 device connected": ""
},
"KDE Connect unavailable error title": {
"KDE Connect Not Available": ""
},
"KDE Connect unavailable status": {
"Unavailable": ""
},
"KDE Connect unknown device status | unknown author": {
"Unknown": ""
},
"KDE Connect unpair action": {
"Device unpaired": ""
},
"KDE Connect unpair tooltip": {
"Unpair": ""
},
"Keep Awake": { "Keep Awake": {
"Keep Awake": "保持喚醒" "Keep Awake": "保持喚醒"
}, },
@@ -2460,18 +2255,9 @@
"Maximum History": { "Maximum History": {
"Maximum History": "歷史紀錄上限" "Maximum History": "歷史紀錄上限"
}, },
"Maximum Pinned Entries": {
"Maximum Pinned Entries": ""
},
"Maximum number of clipboard entries to keep": { "Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "剪貼簿項目保留數量上限" "Maximum number of clipboard entries to keep": "剪貼簿項目保留數量上限"
}, },
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": ""
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": ""
},
"Maximum size per clipboard entry": { "Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "每個剪貼簿項目的最大大小" "Maximum size per clipboard entry": "每個剪貼簿項目的最大大小"
}, },
@@ -2763,12 +2549,6 @@
"No printers found": { "No printers found": {
"No printers found": "找不到印表機" "No printers found": "找不到印表機"
}, },
"No recent clipboard entries found": {
"No recent clipboard entries found": ""
},
"No saved clipboard entries": {
"No saved clipboard entries": ""
},
"No variants created. Click Add to create a new monitor widget.": { "No variants created. Click Add to create a new monitor widget.": {
"No variants created. Click Add to create a new monitor widget.": "尚未建立任何變體。按一下「新增」以建立新的顯示器小工具。" "No variants created. Click Add to create a new monitor widget.": "尚未建立任何變體。按一下「新增」以建立新的顯示器小工具。"
}, },
@@ -2844,9 +2624,6 @@
"OSD Position": { "OSD Position": {
"OSD Position": "OSD 位置" "OSD Position": "OSD 位置"
}, },
"Occupied Color": {
"Occupied Color": ""
},
"Off": { "Off": {
"Off": "關閉" "Off": "關閉"
}, },
@@ -2994,9 +2771,6 @@
"Percentage": { "Percentage": {
"Percentage": "百分比" "Percentage": "百分比"
}, },
"Performance": {
"Performance": ""
},
"Permission denied to set profile image.": { "Permission denied to set profile image.": {
"Permission denied to set profile image.": "權限不足,無法設定個人資料圖片。" "Permission denied to set profile image.": "權限不足,無法設定個人資料圖片。"
}, },
@@ -3096,9 +2870,6 @@
"Power Profile Degradation": { "Power Profile Degradation": {
"Power Profile Degradation": "電源配置降級" "Power Profile Degradation": "電源配置降級"
}, },
"Power off monitors on lock": {
"Power off monitors on lock": ""
},
"Power profile management available": { "Power profile management available": {
"Power profile management available": "電源設定檔管理功能可用" "Power profile management available": "電源設定檔管理功能可用"
}, },
@@ -3168,9 +2939,6 @@
"Process Count": { "Process Count": {
"Process Count": "程序數量" "Process Count": "程序數量"
}, },
"Processes": {
"Processes": ""
},
"Processing": { "Processing": {
"Processing": "正在處理" "Processing": "正在處理"
}, },
@@ -3369,9 +3137,6 @@
"Saved Configurations": { "Saved Configurations": {
"Saved Configurations": "已儲存的設定" "Saved Configurations": "已儲存的設定"
}, },
"Saved item deleted": {
"Saved item deleted": ""
},
"Scale": { "Scale": {
"Scale": "縮放" "Scale": "縮放"
}, },
@@ -3393,9 +3158,6 @@
"Science": { "Science": {
"Science": "科學" "Science": "科學"
}, },
"Screen Sharing": {
"Screen Sharing": ""
},
"Screen sharing": { "Screen sharing": {
"Screen sharing": "螢幕分享" "Screen sharing": "螢幕分享"
}, },
@@ -3675,9 +3437,6 @@
"Show darkened overlay behind modal dialogs": { "Show darkened overlay behind modal dialogs": {
"Show darkened overlay behind modal dialogs": "在模態對話框後顯示暗化覆蓋層" "Show darkened overlay behind modal dialogs": "在模態對話框後顯示暗化覆蓋層"
}, },
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": ""
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": { "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "在 Niri 總覽中輸入時顯示啟動器疊加。停用以使用其他啟動器。" "Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "在 Niri 總覽中輸入時顯示啟動器疊加。停用以使用其他啟動器。"
}, },
@@ -3993,15 +3752,9 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": { "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": {
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "此部件可防止 GPU 電源關閉,這會嚴重影響筆記型電腦的電池續航時間。不建議在配備混合顯示卡的筆記型電腦上使用此功能。" "This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "此部件可防止 GPU 電源關閉,這會嚴重影響筆記型電腦的電池續航時間。不建議在配備混合顯示卡的筆記型電腦上使用此功能。"
}, },
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": ""
},
"This will permanently delete all clipboard history.": { "This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "這將永久刪除所有剪貼簿歷史記錄。" "This will permanently delete all clipboard history.": "這將永久刪除所有剪貼簿歷史記錄。"
}, },
"This will permanently remove this saved clipboard item. This action cannot be undone.": {
"This will permanently remove this saved clipboard item. This action cannot be undone.": ""
},
"Tiling": { "Tiling": {
"Tiling": "平鋪" "Tiling": "平鋪"
}, },
@@ -4101,9 +3854,6 @@
"Trigger Prefix": { "Trigger Prefix": {
"Trigger Prefix": "觸發前綴" "Trigger Prefix": "觸發前綴"
}, },
"Turn off all displays immediately when the lock screen activates": {
"Turn off all displays immediately when the lock screen activates": ""
},
"Turn off monitors after": { "Turn off monitors after": {
"Turn off monitors after": "指定時間後關閉螢幕" "Turn off monitors after": "指定時間後關閉螢幕"
}, },
@@ -4170,9 +3920,6 @@
"Update Plugin": { "Update Plugin": {
"Update Plugin": "更新插件" "Update Plugin": "更新插件"
}, },
"Uptime": {
"Uptime": ""
},
"Urgent Color": { "Urgent Color": {
"Urgent Color": "" "Urgent Color": ""
}, },
@@ -4556,18 +4303,6 @@
"dgop not available": { "dgop not available": {
"dgop not available": "dgop 無法使用" "dgop not available": "dgop 無法使用"
}, },
"dgop unavailable error message": {
"The 'dgop' tool is required for system monitoring.\\nPlease install dgop to use this feature.": ""
},
"disk io header in system monitor": {
"Disk I/O": ""
},
"disk read label": {
"Read:": ""
},
"disk write label": {
"Write:": ""
},
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": { "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
"dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl 存在但未包含在 config.kdl 中。此問題解決前,自訂按鍵綁定將無法運作。" "dms/binds.kdl exists but is not included in config.kdl. Custom keybinds will not work until this is fixed.": "dms/binds.kdl 存在但未包含在 config.kdl 中。此問題解決前,自訂按鍵綁定將無法運作。"
}, },
@@ -4601,33 +4336,18 @@
"empty plugin list": { "empty plugin list": {
"No plugins found": "找不到任何外掛" "No plugins found": "找不到任何外掛"
}, },
"empty state in disk mounts list": {
"No mount points found": ""
},
"empty state in gpu list": {
"No GPUs detected": ""
},
"empty state in process list": {
"No matching processes": ""
},
"empty theme list": { "empty theme list": {
"No themes found": "找不到任何主題" "No themes found": "找不到任何主題"
}, },
"events": { "events": {
"events": "活動" "events": "活動"
}, },
"fallback gpu name": {
"Unknown GPU": ""
},
"files": { "files": {
"files": "檔案" "files": "檔案"
}, },
"generic theme description": { "generic theme description": {
"Material Design inspired color themes": "受 Material Design 啟發的色彩主題" "Material Design inspired color themes": "受 Material Design 啟發的色彩主題"
}, },
"gpu section header in system monitor": {
"GPU Monitoring": ""
},
"greeter back button": { "greeter back button": {
"Back": "返回" "Back": "返回"
}, },
@@ -4820,9 +4540,6 @@
"minutes": { "minutes": {
"minutes": "分鐘" "minutes": "分鐘"
}, },
"mount points header in system monitor": {
"Mount Points": ""
},
"ms": { "ms": {
"ms": "毫秒" "ms": "毫秒"
}, },
@@ -4897,15 +4614,6 @@
"plugin search placeholder": { "plugin search placeholder": {
"Search plugins...": "搜尋外掛..." "Search plugins...": "搜尋外掛..."
}, },
"process count label in footer": {
"Processes:": ""
},
"process detail label": {
"Full Command:": ""
},
"process search placeholder": {
"Search processes...": ""
},
"profile image file browser title": { "profile image file browser title": {
"Select Profile Image": "選擇個人資料圖片" "Select Profile Image": "選擇個人資料圖片"
}, },
@@ -4931,25 +4639,12 @@
"shadow intensity slider": { "shadow intensity slider": {
"Intensity": "強度" "Intensity": "強度"
}, },
"short for processes": {
"procs": ""
},
"source code link": { "source code link": {
"source": "來源" "source": "來源"
}, },
"sysmon window title": { "sysmon window title": {
"System Monitor": "系統監視器" "System Monitor": "系統監視器"
}, },
"system info header in system monitor": {
"System Information": ""
},
"system info label": {
"Architecture": "",
"Distribution": "",
"Hostname": "",
"Kernel": "",
"Load Average": ""
},
"theme browser description": { "theme browser description": {
"Install color themes from the DMS theme registry": "從 DMS 主題登錄檔安裝色彩主題" "Install color themes from the DMS theme registry": "從 DMS 主題登錄檔安裝色彩主題"
}, },
@@ -4980,9 +4675,6 @@
"update dms for NM integration.": { "update dms for NM integration.": {
"update dms for NM integration.": "更新 dms 以進行 NM 整合。" "update dms for NM integration.": "更新 dms 以進行 NM 整合。"
}, },
"uptime label in footer": {
"Uptime:": ""
},
"version requirement": { "version requirement": {
"Requires %1": "需要 %1" "Requires %1": "需要 %1"
}, },

File diff suppressed because it is too large Load Diff