mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
Compare commits
110 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c12eafa1db | ||
|
|
9e26d8755c | ||
|
|
90bd30e351 | ||
|
|
3fb5d5c4f3 | ||
|
|
9f3685e4d5 | ||
|
|
6565988952 | ||
|
|
10b7a0875b | ||
|
|
bb4b9f1a58 | ||
|
|
981e527560 | ||
|
|
80b2ee719c | ||
|
|
6103d6196f | ||
|
|
ed1a5bfded | ||
|
|
3909ce3350 | ||
|
|
d64cd0b8a4 | ||
|
|
676aa9f93f | ||
|
|
ebd48e2556 | ||
|
|
ad5871aae4 | ||
|
|
e327b1ca5b | ||
|
|
ad43ca11eb | ||
|
|
41ba76e2e2 | ||
|
|
15e773434e | ||
|
|
ed118f4e7a | ||
|
|
3c420f2e30 | ||
|
|
4e271d4f0e | ||
|
|
27f9b3cd0b | ||
|
|
1ed4abd347 | ||
|
|
f71dd1ed54 | ||
|
|
19828d3b06 | ||
|
|
d242e729f0 | ||
|
|
8cd0d5faa5 | ||
|
|
a741d892a9 | ||
|
|
9add3361e0 | ||
|
|
4aac70ab5f | ||
|
|
980aec714a | ||
|
|
af8ee5af0f | ||
|
|
32d9aa0cf2 | ||
|
|
7e49631912 | ||
|
|
43970d34aa | ||
|
|
abb3c40697 | ||
|
|
2757a41102 | ||
|
|
1f8bddaa5e | ||
|
|
4c3b7ca60f | ||
|
|
d9d83e5767 | ||
|
|
b4ebde47be | ||
|
|
ef9f76190d | ||
|
|
71b96efca0 | ||
|
|
7158e09b0e | ||
|
|
8ef125bed2 | ||
|
|
0b11fb2fd5 | ||
|
|
3871f3cf3d | ||
|
|
7c5d1ec0f6 | ||
|
|
b507b08e34 | ||
|
|
1b06090f72 | ||
|
|
5460c20ac3 | ||
|
|
2ccec607a0 | ||
|
|
8a99fcf188 | ||
|
|
1e2489ca76 | ||
|
|
89793d2d62 | ||
|
|
11a1af89f4 | ||
|
|
e24ddb804d | ||
|
|
3524d365be | ||
|
|
2b3b9d037c | ||
|
|
5140cd9d7f | ||
|
|
2df9437b39 | ||
|
|
db440b8a14 | ||
|
|
c3dd70bc99 | ||
|
|
223e783bbc | ||
|
|
ca086dbf16 | ||
|
|
523422cf6c | ||
|
|
2dc310dcbc | ||
|
|
c092cd2921 | ||
|
|
2b14ef76c9 | ||
|
|
fbbf10078f | ||
|
|
2315d423c4 | ||
|
|
9a43465ebf | ||
|
|
fc1444763d | ||
|
|
804bf879ed | ||
|
|
ad44f09421 | ||
|
|
df2469468b | ||
|
|
f8f4fe11eb | ||
|
|
039a370add | ||
|
|
6feebc086d | ||
|
|
bc335c7d72 | ||
|
|
a6dd7254b2 | ||
|
|
7b1026c624 | ||
|
|
4758393cc1 | ||
|
|
52373a3a7d | ||
|
|
c30f9a2841 | ||
|
|
44d6f8f15c | ||
|
|
5ada12f989 | ||
|
|
d213045168 | ||
|
|
d83478239e | ||
|
|
3869955357 | ||
|
|
345d37edf8 | ||
|
|
2788ef28cf | ||
|
|
0d5c1bb3df | ||
|
|
c3d505cdad | ||
|
|
90854e1dd4 | ||
|
|
f96e3b04be | ||
|
|
44449e26a0 | ||
|
|
ddc88fd360 | ||
|
|
fedec450cb | ||
|
|
04ea742830 | ||
|
|
5a5c860cef | ||
|
|
55d06a43f8 | ||
|
|
71eecd6e7b | ||
|
|
6f3019f84b | ||
|
|
e95d3126b2 | ||
|
|
5da265bf0b | ||
|
|
2ce9c43b8c |
90
.github/workflows/release.yml
vendored
90
.github/workflows/release.yml
vendored
@@ -1,59 +1,97 @@
|
|||||||
name: Create Release
|
# Release from a dispatch event from the danklinux repo
|
||||||
|
name: Create Release from DMS
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
repository_dispatch:
|
||||||
tags:
|
types: [dms_release]
|
||||||
- 'v*'
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: release-${{ github.ref_name }}
|
group: release-${{ github.event.client_payload.tag }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
create_release:
|
create_release_from_dms:
|
||||||
name: 📦 Create GitHub Release
|
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
env:
|
||||||
|
TAG: ${{ github.event.client_payload.tag }}
|
||||||
|
DMS_REPO: ${{ github.event.client_payload.dms_repo }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Fetch full history for changelog generation
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Ensure VERSION and tag
|
||||||
|
run: |
|
||||||
|
set -euxo pipefail
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
|
# create/update VERSION file to match incoming tag
|
||||||
|
echo "${TAG}" > VERSION
|
||||||
|
if ! git diff --quiet -- VERSION; then
|
||||||
|
git add VERSION
|
||||||
|
git commit -m "Add VERSION file for ${TAG} (from DMS)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If tag doesn't exist (or differs), (re)create it
|
||||||
|
if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
|
||||||
|
echo "Tag ${TAG} already exists"
|
||||||
|
else
|
||||||
|
git tag "${TAG}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Push commit (if any) and tag
|
||||||
|
git push --follow-tags origin HEAD
|
||||||
|
|
||||||
# Generate changelog
|
|
||||||
- name: Generate Changelog
|
- name: Generate Changelog
|
||||||
id: changelog
|
id: changelog
|
||||||
run: |
|
run: |
|
||||||
# Get the previous tag
|
set -e
|
||||||
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
|
PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || echo "")
|
||||||
|
|
||||||
if [ -z "$PREVIOUS_TAG" ]; then
|
if [ -z "$PREVIOUS_TAG" ]; then
|
||||||
echo "No previous tag found, using all commits"
|
|
||||||
CHANGELOG=$(git log --oneline --pretty=format:"- %s (%h)" | head -50)
|
CHANGELOG=$(git log --oneline --pretty=format:"- %s (%h)" | head -50)
|
||||||
else
|
else
|
||||||
echo "Generating changelog from $PREVIOUS_TAG to HEAD"
|
CHANGELOG=$(git log --oneline --pretty=format:"- %s (%h)" "${PREVIOUS_TAG}..${TAG}")
|
||||||
CHANGELOG=$(git log --oneline --pretty=format:"- %s (%h)" $PREVIOUS_TAG..HEAD)
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create the changelog with proper formatting
|
|
||||||
cat > CHANGELOG.md << EOF
|
cat > CHANGELOG.md << EOF
|
||||||
## What's Changed
|
## What's Changed
|
||||||
|
|
||||||
$CHANGELOG
|
$CHANGELOG
|
||||||
|
|
||||||
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREVIOUS_TAG}...${{ github.ref_name }}
|
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREVIOUS_TAG}...${TAG}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Set output for use in release step
|
|
||||||
echo "changelog<<EOF" >> $GITHUB_OUTPUT
|
echo "changelog<<EOF" >> $GITHUB_OUTPUT
|
||||||
cat CHANGELOG.md >> $GITHUB_OUTPUT
|
cat CHANGELOG.md >> $GITHUB_OUTPUT
|
||||||
echo "EOF" >> $GITHUB_OUTPUT
|
echo "EOF" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# Create GitHub Release
|
- name: Create/Update DankMaterialShell Release
|
||||||
- name: Create GitHub Release
|
uses: softprops/action-gh-release@v2
|
||||||
uses: comnoco/create-release-action@v2.0.5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ github.ref_name }}
|
tag_name: ${{ env.TAG }}
|
||||||
release_name: Release ${{ github.ref_name }}
|
name: Release ${{ env.TAG }}
|
||||||
body: ${{ steps.changelog.outputs.changelog }}
|
body: ${{ steps.changelog.outputs.changelog }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: ${{ contains(github.ref_name, '-') }}
|
prerelease: ${{ contains(env.TAG, '-') }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Download DMS release assets
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euxo pipefail
|
||||||
|
# gh is preinstalled on ubuntu-24.04; auth via GH_TOKEN env
|
||||||
|
gh release download "${TAG}" -R "${DMS_REPO}" --dir ./_dms_assets
|
||||||
|
|
||||||
|
- name: Attach DMS assets to DankMaterialShell release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
tag_name: ${{ env.TAG }}
|
||||||
|
files: _dms_assets/**
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
68
CLAUDE.md
68
CLAUDE.md
@@ -448,7 +448,13 @@ When modifying the shell:
|
|||||||
|
|
||||||
### Creating Plugins
|
### Creating Plugins
|
||||||
|
|
||||||
Plugins are external, dynamically-loaded components that extend DankBar functionality. Plugins are stored in `~/.config/DankMaterialShell/plugins/` and have their settings isolated from core DMS settings.
|
Plugins are external, dynamically-loaded components that extend DankMaterialShell functionality. Plugins are stored in `~/.config/DankMaterialShell/plugins/` and have their settings isolated from core DMS settings.
|
||||||
|
|
||||||
|
**Plugin Types:**
|
||||||
|
- **Widget plugins** (`"type": "widget"` or omit type field): Display UI components in DankBar
|
||||||
|
- **Daemon plugins** (`"type": "daemon"`): Run invisibly in the background without UI
|
||||||
|
|
||||||
|
#### Widget Plugins
|
||||||
|
|
||||||
1. **Create plugin directory**:
|
1. **Create plugin directory**:
|
||||||
```bash
|
```bash
|
||||||
@@ -464,6 +470,7 @@ Plugins are external, dynamically-loaded components that extend DankBar function
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Your Name",
|
"author": "Your Name",
|
||||||
"icon": "extension",
|
"icon": "extension",
|
||||||
|
"type": "widget",
|
||||||
"component": "./YourWidget.qml",
|
"component": "./YourWidget.qml",
|
||||||
"settings": "./YourSettings.qml",
|
"settings": "./YourSettings.qml",
|
||||||
"permissions": ["settings_read", "settings_write"]
|
"permissions": ["settings_read", "settings_write"]
|
||||||
@@ -545,6 +552,65 @@ Plugins are external, dynamically-loaded components that extend DankBar function
|
|||||||
- Toggle plugin to enable
|
- Toggle plugin to enable
|
||||||
- Add plugin ID to DankBar widget list
|
- Add plugin ID to DankBar widget list
|
||||||
|
|
||||||
|
#### Daemon Plugins
|
||||||
|
|
||||||
|
Daemon plugins run invisibly in the background without any UI components. They're useful for monitoring system events, background tasks, or data synchronization.
|
||||||
|
|
||||||
|
1. **Create plugin directory**:
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/.config/DankMaterialShell/plugins/YourDaemon
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Create manifest** (`plugin.json`):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "yourDaemon",
|
||||||
|
"name": "Your Daemon",
|
||||||
|
"description": "Background daemon description",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Your Name",
|
||||||
|
"icon": "settings_applications",
|
||||||
|
"type": "daemon",
|
||||||
|
"component": "./YourDaemon.qml",
|
||||||
|
"permissions": ["settings_read", "settings_write"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Create daemon component** (`YourDaemon.qml`):
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var pluginService: null
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SessionData
|
||||||
|
function onWallpaperPathChanged() {
|
||||||
|
console.log("Wallpaper changed:", SessionData.wallpaperPath)
|
||||||
|
if (pluginService) {
|
||||||
|
pluginService.savePluginData("yourDaemon", "lastEvent", Date.now())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
console.log("Daemon started")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Enable daemon**:
|
||||||
|
- Open Settings → Plugins
|
||||||
|
- Click "Scan for Plugins"
|
||||||
|
- Toggle daemon to enable
|
||||||
|
- Daemon runs automatically in background
|
||||||
|
|
||||||
|
**Example**: See `PLUGINS/WallpaperWatcherDaemon/` for a complete daemon plugin that monitors wallpaper changes
|
||||||
|
|
||||||
**Plugin Directory Structure:**
|
**Plugin Directory Structure:**
|
||||||
```
|
```
|
||||||
~/.config/DankMaterialShell/
|
~/.config/DankMaterialShell/
|
||||||
|
|||||||
@@ -72,10 +72,6 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAppUsageRanking() {
|
|
||||||
return appUsageRanking
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRankedApps() {
|
function getRankedApps() {
|
||||||
var apps = []
|
var apps = []
|
||||||
for (var appId in appUsageRanking) {
|
for (var appId in appUsageRanking) {
|
||||||
|
|||||||
62
Common/DankSocket.qml
Normal file
62
Common/DankSocket.qml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property alias path: socket.path
|
||||||
|
property alias parser: socket.parser
|
||||||
|
property bool connected: false
|
||||||
|
|
||||||
|
property int reconnectBaseMs: 400
|
||||||
|
property int reconnectMaxMs: 15000
|
||||||
|
|
||||||
|
property int _reconnectAttempt: 0
|
||||||
|
|
||||||
|
signal connectionStateChanged()
|
||||||
|
|
||||||
|
onConnectedChanged: {
|
||||||
|
socket.connected = connected
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket {
|
||||||
|
id: socket
|
||||||
|
|
||||||
|
onConnectionStateChanged: {
|
||||||
|
root.connectionStateChanged()
|
||||||
|
if (connected) {
|
||||||
|
root._reconnectAttempt = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (root.connected) {
|
||||||
|
root._scheduleReconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: reconnectTimer
|
||||||
|
interval: 0
|
||||||
|
repeat: false
|
||||||
|
onTriggered: {
|
||||||
|
socket.connected = false
|
||||||
|
Qt.callLater(() => socket.connected = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function send(data) {
|
||||||
|
const json = typeof data === "string" ? data : JSON.stringify(data)
|
||||||
|
const message = json.endsWith("\n") ? json : json + "\n"
|
||||||
|
socket.write(message)
|
||||||
|
socket.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
function _scheduleReconnect() {
|
||||||
|
const pow = Math.min(_reconnectAttempt, 10)
|
||||||
|
const base = Math.min(reconnectBaseMs * Math.pow(2, pow), reconnectMaxMs)
|
||||||
|
const jitter = Math.floor(Math.random() * Math.floor(base / 4))
|
||||||
|
reconnectTimer.interval = base + jitter
|
||||||
|
reconnectTimer.restart()
|
||||||
|
_reconnectAttempt++
|
||||||
|
}
|
||||||
|
}
|
||||||
66
Common/I18n.qml
Normal file
66
Common/I18n.qml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
pragma Singleton
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string currentLocale: Qt.locale().name.substring(0, 2)
|
||||||
|
property var translations: ({})
|
||||||
|
property bool translationsLoaded: false
|
||||||
|
|
||||||
|
FileView {
|
||||||
|
id: translationLoader
|
||||||
|
path: root.currentLocale === "en" ? "" : Qt.resolvedUrl(`../translations/${root.currentLocale}.json`)
|
||||||
|
|
||||||
|
onLoaded: {
|
||||||
|
try {
|
||||||
|
root.translations = JSON.parse(text())
|
||||||
|
root.translationsLoaded = true
|
||||||
|
console.log(`I18n: Loaded translations for locale '${root.currentLocale}' (${Object.keys(root.translations).length} contexts)`)
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`I18n: Error parsing translations for locale '${root.currentLocale}':`, e, "- falling back to English")
|
||||||
|
root.translationsLoaded = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoadFailed: (error) => {
|
||||||
|
console.warn(`I18n: Failed to load translations for locale '${root.currentLocale}' (${error}), falling back to English`)
|
||||||
|
root.translationsLoaded = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tr(term, context) {
|
||||||
|
if (!translationsLoaded || !translations) {
|
||||||
|
return term
|
||||||
|
}
|
||||||
|
|
||||||
|
const actualContext = context || term
|
||||||
|
|
||||||
|
if (translations[actualContext] && translations[actualContext][term]) {
|
||||||
|
return translations[actualContext][term]
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ctx in translations) {
|
||||||
|
if (translations[ctx][term]) {
|
||||||
|
return translations[ctx][term]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return term
|
||||||
|
}
|
||||||
|
|
||||||
|
function trContext(context, term) {
|
||||||
|
if (!translationsLoaded || !translations) {
|
||||||
|
return term
|
||||||
|
}
|
||||||
|
|
||||||
|
if (translations[context] && translations[context][term]) {
|
||||||
|
return translations[context][term]
|
||||||
|
}
|
||||||
|
|
||||||
|
return term
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,6 +70,8 @@ Singleton {
|
|||||||
property int batteryHibernateTimeout: 0 // Never
|
property int batteryHibernateTimeout: 0 // Never
|
||||||
|
|
||||||
property bool lockBeforeSuspend: false
|
property bool lockBeforeSuspend: false
|
||||||
|
property var recentColors: []
|
||||||
|
property bool showThirdPartyPlugins: false
|
||||||
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -150,6 +152,8 @@ Singleton {
|
|||||||
batterySuspendTimeout = settings.batterySuspendTimeout !== undefined ? settings.batterySuspendTimeout : 0
|
batterySuspendTimeout = settings.batterySuspendTimeout !== undefined ? settings.batterySuspendTimeout : 0
|
||||||
batteryHibernateTimeout = settings.batteryHibernateTimeout !== undefined ? settings.batteryHibernateTimeout : 0
|
batteryHibernateTimeout = settings.batteryHibernateTimeout !== undefined ? settings.batteryHibernateTimeout : 0
|
||||||
lockBeforeSuspend = settings.lockBeforeSuspend !== undefined ? settings.lockBeforeSuspend : false
|
lockBeforeSuspend = settings.lockBeforeSuspend !== undefined ? settings.lockBeforeSuspend : false
|
||||||
|
recentColors = settings.recentColors !== undefined ? settings.recentColors : []
|
||||||
|
showThirdPartyPlugins = settings.showThirdPartyPlugins !== undefined ? settings.showThirdPartyPlugins : false
|
||||||
|
|
||||||
if (!isGreeterMode) {
|
if (!isGreeterMode) {
|
||||||
if (typeof Theme !== "undefined") {
|
if (typeof Theme !== "undefined") {
|
||||||
@@ -210,7 +214,9 @@ Singleton {
|
|||||||
"batteryLockTimeout": batteryLockTimeout,
|
"batteryLockTimeout": batteryLockTimeout,
|
||||||
"batterySuspendTimeout": batterySuspendTimeout,
|
"batterySuspendTimeout": batterySuspendTimeout,
|
||||||
"batteryHibernateTimeout": batteryHibernateTimeout,
|
"batteryHibernateTimeout": batteryHibernateTimeout,
|
||||||
"lockBeforeSuspend": lockBeforeSuspend
|
"lockBeforeSuspend": lockBeforeSuspend,
|
||||||
|
"recentColors": recentColors,
|
||||||
|
"showThirdPartyPlugins": showThirdPartyPlugins
|
||||||
}, null, 2))
|
}, null, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,6 +365,16 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addRecentColor(color) {
|
||||||
|
const colorStr = color.toString()
|
||||||
|
let recent = recentColors.slice()
|
||||||
|
recent = recent.filter(c => c !== colorStr)
|
||||||
|
recent.unshift(colorStr)
|
||||||
|
if (recent.length > 5) recent = recent.slice(0, 5)
|
||||||
|
recentColors = recent
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
function addPinnedApp(appId) {
|
function addPinnedApp(appId) {
|
||||||
if (!appId)
|
if (!appId)
|
||||||
return
|
return
|
||||||
@@ -627,6 +643,11 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setShowThirdPartyPlugins(enabled) {
|
||||||
|
showThirdPartyPlugins = enabled
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
FileView {
|
FileView {
|
||||||
id: settingsFile
|
id: settingsFile
|
||||||
|
|
||||||
@@ -641,8 +662,8 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onLoadFailed: error => {
|
onLoadFailed: error => {
|
||||||
if (!isGreeterMode && !hasTriedDefaultSettings) {
|
if (!isGreeterMode && !hasTriedDefaultSession) {
|
||||||
hasTriedDefaultSettings = true
|
hasTriedDefaultSession = true
|
||||||
defaultSessionCheckProcess.running = true
|
defaultSessionCheckProcess.running = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -671,7 +692,7 @@ Singleton {
|
|||||||
id: defaultSessionCheckProcess
|
id: defaultSessionCheckProcess
|
||||||
|
|
||||||
command: ["sh", "-c", "CONFIG_DIR=\"" + _stateDir
|
command: ["sh", "-c", "CONFIG_DIR=\"" + _stateDir
|
||||||
+ "/DankMaterialShell\"; if [ -f \"$CONFIG_DIR/default-session.json\" ] && [ ! -f \"$CONFIG_DIR/session.json\" ]; then cp \"$CONFIG_DIR/default-session.json\" \"$CONFIG_DIR/session.json\" && echo 'copied'; else echo 'not_found'; fi"]
|
+ "/DankMaterialShell\"; if [ -f \"$CONFIG_DIR/default-session.json\" ] && [ ! -f \"$CONFIG_DIR/session.json\" ]; then cp --no-preserve=mode \"$CONFIG_DIR/default-session.json\" \"$CONFIG_DIR/session.json\" && echo 'copied'; else echo 'not_found'; fi"]
|
||||||
running: false
|
running: false
|
||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
@@ -817,4 +838,4 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,15 +103,19 @@ Singleton {
|
|||||||
property bool qt5ctAvailable: false
|
property bool qt5ctAvailable: false
|
||||||
property bool qt6ctAvailable: false
|
property bool qt6ctAvailable: false
|
||||||
property bool gtkAvailable: false
|
property bool gtkAvailable: false
|
||||||
property bool useOSLogo: false
|
property string launcherLogoMode: "apps"
|
||||||
property string osLogoColorOverride: ""
|
property string launcherLogoCustomPath: ""
|
||||||
property real osLogoBrightness: 0.5
|
property string launcherLogoColorOverride: ""
|
||||||
property real osLogoContrast: 1
|
property bool launcherLogoColorInvertOnMode: false
|
||||||
|
property real launcherLogoBrightness: 0.5
|
||||||
|
property real launcherLogoContrast: 1
|
||||||
|
property int launcherLogoSizeOffset: 0
|
||||||
property bool weatherEnabled: true
|
property bool weatherEnabled: true
|
||||||
property string fontFamily: "Inter Variable"
|
property string fontFamily: "Inter Variable"
|
||||||
property string monoFontFamily: "Fira Code"
|
property string monoFontFamily: "Fira Code"
|
||||||
property int fontWeight: Font.Normal
|
property int fontWeight: Font.Normal
|
||||||
property real fontScale: 1.0
|
property real fontScale: 1.0
|
||||||
|
property real dankBarFontScale: 1.0
|
||||||
property bool notepadUseMonospace: true
|
property bool notepadUseMonospace: true
|
||||||
property string notepadFontFamily: ""
|
property string notepadFontFamily: ""
|
||||||
property real notepadFontSize: 14
|
property real notepadFontSize: 14
|
||||||
@@ -150,6 +154,7 @@ Singleton {
|
|||||||
property bool dankBarSquareCorners: false
|
property bool dankBarSquareCorners: false
|
||||||
property bool dankBarNoBackground: false
|
property bool dankBarNoBackground: false
|
||||||
property bool dankBarGothCornersEnabled: false
|
property bool dankBarGothCornersEnabled: false
|
||||||
|
property bool dankBarBorderEnabled: false
|
||||||
property int dankBarPosition: SettingsData.Position.Top
|
property int dankBarPosition: SettingsData.Position.Top
|
||||||
property bool dankBarIsVertical: dankBarPosition === SettingsData.Position.Left || dankBarPosition === SettingsData.Position.Right
|
property bool dankBarIsVertical: dankBarPosition === SettingsData.Position.Left || dankBarPosition === SettingsData.Position.Right
|
||||||
property bool lockScreenShowPowerActions: true
|
property bool lockScreenShowPowerActions: true
|
||||||
@@ -160,6 +165,7 @@ Singleton {
|
|||||||
property int notificationTimeoutNormal: 5000
|
property int notificationTimeoutNormal: 5000
|
||||||
property int notificationTimeoutCritical: 0
|
property int notificationTimeoutCritical: 0
|
||||||
property int notificationPopupPosition: SettingsData.Position.Top
|
property int notificationPopupPosition: SettingsData.Position.Top
|
||||||
|
property bool osdAlwaysShowValue: false
|
||||||
property var screenPreferences: ({})
|
property var screenPreferences: ({})
|
||||||
property int animationSpeed: SettingsData.AnimationSpeed.Short
|
property int animationSpeed: SettingsData.AnimationSpeed.Short
|
||||||
readonly property string defaultFontFamily: "Inter Variable"
|
readonly property string defaultFontFamily: "Inter Variable"
|
||||||
@@ -167,6 +173,7 @@ Singleton {
|
|||||||
readonly property string _homeUrl: StandardPaths.writableLocation(StandardPaths.HomeLocation)
|
readonly property string _homeUrl: StandardPaths.writableLocation(StandardPaths.HomeLocation)
|
||||||
readonly property string _configUrl: StandardPaths.writableLocation(StandardPaths.ConfigLocation)
|
readonly property string _configUrl: StandardPaths.writableLocation(StandardPaths.ConfigLocation)
|
||||||
readonly property string _configDir: Paths.strip(_configUrl)
|
readonly property string _configDir: Paths.strip(_configUrl)
|
||||||
|
readonly property string pluginSettingsPath: _configDir + "/DankMaterialShell/plugin_settings.json"
|
||||||
|
|
||||||
signal forceDankBarLayoutRefresh
|
signal forceDankBarLayoutRefresh
|
||||||
signal forceDockLayoutRefresh
|
signal forceDockLayoutRefresh
|
||||||
@@ -174,6 +181,7 @@ Singleton {
|
|||||||
signal workspaceIconsUpdated
|
signal workspaceIconsUpdated
|
||||||
|
|
||||||
property bool _loading: false
|
property bool _loading: false
|
||||||
|
property bool _pluginSettingsLoading: false
|
||||||
|
|
||||||
property var pluginSettings: ({})
|
property var pluginSettings: ({})
|
||||||
|
|
||||||
@@ -202,7 +210,8 @@ Singleton {
|
|||||||
"size": 20,
|
"size": 20,
|
||||||
"selectedGpuIndex": 0,
|
"selectedGpuIndex": 0,
|
||||||
"pciId": "",
|
"pciId": "",
|
||||||
"mountPath": "/"
|
"mountPath": "/",
|
||||||
|
"minimumWidth": true
|
||||||
}
|
}
|
||||||
leftWidgetsModel.append(dummyItem)
|
leftWidgetsModel.append(dummyItem)
|
||||||
centerWidgetsModel.append(dummyItem)
|
centerWidgetsModel.append(dummyItem)
|
||||||
@@ -217,13 +226,41 @@ Singleton {
|
|||||||
_loading = true
|
_loading = true
|
||||||
parseSettings(settingsFile.text())
|
parseSettings(settingsFile.text())
|
||||||
_loading = false
|
_loading = false
|
||||||
|
loadPluginSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadPluginSettings() {
|
||||||
|
_pluginSettingsLoading = true
|
||||||
|
parsePluginSettings(pluginSettingsFile.text())
|
||||||
|
_pluginSettingsLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePluginSettings(content) {
|
||||||
|
_pluginSettingsLoading = true
|
||||||
|
try {
|
||||||
|
if (content && content.trim()) {
|
||||||
|
pluginSettings = JSON.parse(content)
|
||||||
|
} else {
|
||||||
|
pluginSettings = {}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("SettingsData: Failed to parse plugin settings:", e.message)
|
||||||
|
pluginSettings = {}
|
||||||
|
} finally {
|
||||||
|
_pluginSettingsLoading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSettings(content) {
|
function parseSettings(content) {
|
||||||
_loading = true
|
_loading = true
|
||||||
|
var shouldMigrate = false
|
||||||
try {
|
try {
|
||||||
if (content && content.trim()) {
|
if (content && content.trim()) {
|
||||||
var settings = JSON.parse(content)
|
var settings = JSON.parse(content)
|
||||||
|
if (settings.pluginSettings !== undefined) {
|
||||||
|
pluginSettings = settings.pluginSettings
|
||||||
|
shouldMigrate = true
|
||||||
|
}
|
||||||
// Auto-migrate from old theme system
|
// Auto-migrate from old theme system
|
||||||
if (settings.themeIndex !== undefined || settings.themeIsDynamic !== undefined) {
|
if (settings.themeIndex !== undefined || settings.themeIsDynamic !== undefined) {
|
||||||
const themeNames = ["blue", "deepBlue", "purple", "green", "orange", "red", "cyan", "pink", "amber", "coral"]
|
const themeNames = ["blue", "deepBlue", "purple", "green", "orange", "red", "cyan", "pink", "amber", "coral"]
|
||||||
@@ -319,14 +356,25 @@ Singleton {
|
|||||||
spotlightModalViewMode = settings.spotlightModalViewMode !== undefined ? settings.spotlightModalViewMode : "list"
|
spotlightModalViewMode = settings.spotlightModalViewMode !== undefined ? settings.spotlightModalViewMode : "list"
|
||||||
networkPreference = settings.networkPreference !== undefined ? settings.networkPreference : "auto"
|
networkPreference = settings.networkPreference !== undefined ? settings.networkPreference : "auto"
|
||||||
iconTheme = settings.iconTheme !== undefined ? settings.iconTheme : "System Default"
|
iconTheme = settings.iconTheme !== undefined ? settings.iconTheme : "System Default"
|
||||||
useOSLogo = settings.useOSLogo !== undefined ? settings.useOSLogo : false
|
if (settings.useOSLogo !== undefined) {
|
||||||
osLogoColorOverride = settings.osLogoColorOverride !== undefined ? settings.osLogoColorOverride : ""
|
launcherLogoMode = settings.useOSLogo ? "os" : "apps"
|
||||||
osLogoBrightness = settings.osLogoBrightness !== undefined ? settings.osLogoBrightness : 0.5
|
launcherLogoColorOverride = settings.osLogoColorOverride !== undefined ? settings.osLogoColorOverride : ""
|
||||||
osLogoContrast = settings.osLogoContrast !== undefined ? settings.osLogoContrast : 1
|
launcherLogoBrightness = settings.osLogoBrightness !== undefined ? settings.osLogoBrightness : 0.5
|
||||||
|
launcherLogoContrast = settings.osLogoContrast !== undefined ? settings.osLogoContrast : 1
|
||||||
|
} else {
|
||||||
|
launcherLogoMode = settings.launcherLogoMode !== undefined ? settings.launcherLogoMode : "apps"
|
||||||
|
launcherLogoCustomPath = settings.launcherLogoCustomPath !== undefined ? settings.launcherLogoCustomPath : ""
|
||||||
|
launcherLogoColorOverride = settings.launcherLogoColorOverride !== undefined ? settings.launcherLogoColorOverride : ""
|
||||||
|
launcherLogoColorInvertOnMode = settings.launcherLogoColorInvertOnMode !== undefined ? settings.launcherLogoColorInvertOnMode : false
|
||||||
|
launcherLogoBrightness = settings.launcherLogoBrightness !== undefined ? settings.launcherLogoBrightness : 0.5
|
||||||
|
launcherLogoContrast = settings.launcherLogoContrast !== undefined ? settings.launcherLogoContrast : 1
|
||||||
|
launcherLogoSizeOffset = settings.launcherLogoSizeOffset !== undefined ? settings.launcherLogoSizeOffset : 0
|
||||||
|
}
|
||||||
fontFamily = settings.fontFamily !== undefined ? settings.fontFamily : defaultFontFamily
|
fontFamily = settings.fontFamily !== undefined ? settings.fontFamily : defaultFontFamily
|
||||||
monoFontFamily = settings.monoFontFamily !== undefined ? settings.monoFontFamily : defaultMonoFontFamily
|
monoFontFamily = settings.monoFontFamily !== undefined ? settings.monoFontFamily : defaultMonoFontFamily
|
||||||
fontWeight = settings.fontWeight !== undefined ? settings.fontWeight : Font.Normal
|
fontWeight = settings.fontWeight !== undefined ? settings.fontWeight : Font.Normal
|
||||||
fontScale = settings.fontScale !== undefined ? settings.fontScale : 1.0
|
fontScale = settings.fontScale !== undefined ? settings.fontScale : 1.0
|
||||||
|
dankBarFontScale = settings.dankBarFontScale !== undefined ? settings.dankBarFontScale : 1.0
|
||||||
notepadUseMonospace = settings.notepadUseMonospace !== undefined ? settings.notepadUseMonospace : true
|
notepadUseMonospace = settings.notepadUseMonospace !== undefined ? settings.notepadUseMonospace : true
|
||||||
notepadFontFamily = settings.notepadFontFamily !== undefined ? settings.notepadFontFamily : ""
|
notepadFontFamily = settings.notepadFontFamily !== undefined ? settings.notepadFontFamily : ""
|
||||||
notepadFontSize = settings.notepadFontSize !== undefined ? settings.notepadFontSize : 14
|
notepadFontSize = settings.notepadFontSize !== undefined ? settings.notepadFontSize : 14
|
||||||
@@ -351,19 +399,20 @@ Singleton {
|
|||||||
notificationTimeoutNormal = settings.notificationTimeoutNormal !== undefined ? settings.notificationTimeoutNormal : 5000
|
notificationTimeoutNormal = settings.notificationTimeoutNormal !== undefined ? settings.notificationTimeoutNormal : 5000
|
||||||
notificationTimeoutCritical = settings.notificationTimeoutCritical !== undefined ? settings.notificationTimeoutCritical : 0
|
notificationTimeoutCritical = settings.notificationTimeoutCritical !== undefined ? settings.notificationTimeoutCritical : 0
|
||||||
notificationPopupPosition = settings.notificationPopupPosition !== undefined ? settings.notificationPopupPosition : SettingsData.Position.Top
|
notificationPopupPosition = settings.notificationPopupPosition !== undefined ? settings.notificationPopupPosition : SettingsData.Position.Top
|
||||||
|
osdAlwaysShowValue = settings.osdAlwaysShowValue !== undefined ? settings.osdAlwaysShowValue : false
|
||||||
dankBarSpacing = settings.dankBarSpacing !== undefined ? settings.dankBarSpacing : (settings.topBarSpacing !== undefined ? settings.topBarSpacing : 4)
|
dankBarSpacing = settings.dankBarSpacing !== undefined ? settings.dankBarSpacing : (settings.topBarSpacing !== undefined ? settings.topBarSpacing : 4)
|
||||||
dankBarBottomGap = settings.dankBarBottomGap !== undefined ? settings.dankBarBottomGap : (settings.topBarBottomGap !== undefined ? settings.topBarBottomGap : 0)
|
dankBarBottomGap = settings.dankBarBottomGap !== undefined ? settings.dankBarBottomGap : (settings.topBarBottomGap !== undefined ? settings.topBarBottomGap : 0)
|
||||||
dankBarInnerPadding = settings.dankBarInnerPadding !== undefined ? settings.dankBarInnerPadding : (settings.topBarInnerPadding !== undefined ? settings.topBarInnerPadding : 4)
|
dankBarInnerPadding = settings.dankBarInnerPadding !== undefined ? settings.dankBarInnerPadding : (settings.topBarInnerPadding !== undefined ? settings.topBarInnerPadding : 4)
|
||||||
dankBarSquareCorners = settings.dankBarSquareCorners !== undefined ? settings.dankBarSquareCorners : (settings.topBarSquareCorners !== undefined ? settings.topBarSquareCorners : false)
|
dankBarSquareCorners = settings.dankBarSquareCorners !== undefined ? settings.dankBarSquareCorners : (settings.topBarSquareCorners !== undefined ? settings.topBarSquareCorners : false)
|
||||||
dankBarNoBackground = settings.dankBarNoBackground !== undefined ? settings.dankBarNoBackground : (settings.topBarNoBackground !== undefined ? settings.topBarNoBackground : false)
|
dankBarNoBackground = settings.dankBarNoBackground !== undefined ? settings.dankBarNoBackground : (settings.topBarNoBackground !== undefined ? settings.topBarNoBackground : false)
|
||||||
dankBarGothCornersEnabled = settings.dankBarGothCornersEnabled !== undefined ? settings.dankBarGothCornersEnabled : (settings.topBarGothCornersEnabled !== undefined ? settings.topBarGothCornersEnabled : false)
|
dankBarGothCornersEnabled = settings.dankBarGothCornersEnabled !== undefined ? settings.dankBarGothCornersEnabled : (settings.topBarGothCornersEnabled !== undefined ? settings.topBarGothCornersEnabled : false)
|
||||||
|
dankBarBorderEnabled = settings.dankBarBorderEnabled !== undefined ? settings.dankBarBorderEnabled : false
|
||||||
dankBarPosition = settings.dankBarPosition !== undefined ? settings.dankBarPosition : (settings.dankBarAtBottom !== undefined ? (settings.dankBarAtBottom ? SettingsData.Position.Bottom : SettingsData.Position.Top) : (settings.topBarAtBottom !== undefined ? (settings.topBarAtBottom ? SettingsData.Position.Bottom : SettingsData.Position.Top) : SettingsData.Position.Top))
|
dankBarPosition = settings.dankBarPosition !== undefined ? settings.dankBarPosition : (settings.dankBarAtBottom !== undefined ? (settings.dankBarAtBottom ? SettingsData.Position.Bottom : SettingsData.Position.Top) : (settings.topBarAtBottom !== undefined ? (settings.topBarAtBottom ? SettingsData.Position.Bottom : SettingsData.Position.Top) : SettingsData.Position.Top))
|
||||||
lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true
|
lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true
|
||||||
hideBrightnessSlider = settings.hideBrightnessSlider !== undefined ? settings.hideBrightnessSlider : false
|
hideBrightnessSlider = settings.hideBrightnessSlider !== undefined ? settings.hideBrightnessSlider : false
|
||||||
widgetBackgroundColor = settings.widgetBackgroundColor !== undefined ? settings.widgetBackgroundColor : "sch"
|
widgetBackgroundColor = settings.widgetBackgroundColor !== undefined ? settings.widgetBackgroundColor : "sch"
|
||||||
surfaceBase = settings.surfaceBase !== undefined ? settings.surfaceBase : "s"
|
surfaceBase = settings.surfaceBase !== undefined ? settings.surfaceBase : "s"
|
||||||
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({})
|
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({})
|
||||||
pluginSettings = settings.pluginSettings !== undefined ? settings.pluginSettings : ({})
|
|
||||||
animationSpeed = settings.animationSpeed !== undefined ? settings.animationSpeed : SettingsData.AnimationSpeed.Short
|
animationSpeed = settings.animationSpeed !== undefined ? settings.animationSpeed : SettingsData.AnimationSpeed.Short
|
||||||
applyStoredTheme()
|
applyStoredTheme()
|
||||||
detectAvailableIconThemes()
|
detectAvailableIconThemes()
|
||||||
@@ -378,6 +427,11 @@ Singleton {
|
|||||||
} finally {
|
} finally {
|
||||||
_loading = false
|
_loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shouldMigrate) {
|
||||||
|
savePluginSettings()
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
@@ -440,14 +494,18 @@ Singleton {
|
|||||||
"spotlightModalViewMode": spotlightModalViewMode,
|
"spotlightModalViewMode": spotlightModalViewMode,
|
||||||
"networkPreference": networkPreference,
|
"networkPreference": networkPreference,
|
||||||
"iconTheme": iconTheme,
|
"iconTheme": iconTheme,
|
||||||
"useOSLogo": useOSLogo,
|
"launcherLogoMode": launcherLogoMode,
|
||||||
"osLogoColorOverride": osLogoColorOverride,
|
"launcherLogoCustomPath": launcherLogoCustomPath,
|
||||||
"osLogoBrightness": osLogoBrightness,
|
"launcherLogoColorOverride": launcherLogoColorOverride,
|
||||||
"osLogoContrast": osLogoContrast,
|
"launcherLogoColorInvertOnMode": launcherLogoColorInvertOnMode,
|
||||||
|
"launcherLogoBrightness": launcherLogoBrightness,
|
||||||
|
"launcherLogoContrast": launcherLogoContrast,
|
||||||
|
"launcherLogoSizeOffset": launcherLogoSizeOffset,
|
||||||
"fontFamily": fontFamily,
|
"fontFamily": fontFamily,
|
||||||
"monoFontFamily": monoFontFamily,
|
"monoFontFamily": monoFontFamily,
|
||||||
"fontWeight": fontWeight,
|
"fontWeight": fontWeight,
|
||||||
"fontScale": fontScale,
|
"fontScale": fontScale,
|
||||||
|
"dankBarFontScale": dankBarFontScale,
|
||||||
"notepadUseMonospace": notepadUseMonospace,
|
"notepadUseMonospace": notepadUseMonospace,
|
||||||
"notepadFontFamily": notepadFontFamily,
|
"notepadFontFamily": notepadFontFamily,
|
||||||
"notepadFontSize": notepadFontSize,
|
"notepadFontSize": notepadFontSize,
|
||||||
@@ -474,6 +532,7 @@ Singleton {
|
|||||||
"dankBarSquareCorners": dankBarSquareCorners,
|
"dankBarSquareCorners": dankBarSquareCorners,
|
||||||
"dankBarNoBackground": dankBarNoBackground,
|
"dankBarNoBackground": dankBarNoBackground,
|
||||||
"dankBarGothCornersEnabled": dankBarGothCornersEnabled,
|
"dankBarGothCornersEnabled": dankBarGothCornersEnabled,
|
||||||
|
"dankBarBorderEnabled": dankBarBorderEnabled,
|
||||||
"dankBarPosition": dankBarPosition,
|
"dankBarPosition": dankBarPosition,
|
||||||
"lockScreenShowPowerActions": lockScreenShowPowerActions,
|
"lockScreenShowPowerActions": lockScreenShowPowerActions,
|
||||||
"hideBrightnessSlider": hideBrightnessSlider,
|
"hideBrightnessSlider": hideBrightnessSlider,
|
||||||
@@ -483,12 +542,18 @@ Singleton {
|
|||||||
"notificationTimeoutNormal": notificationTimeoutNormal,
|
"notificationTimeoutNormal": notificationTimeoutNormal,
|
||||||
"notificationTimeoutCritical": notificationTimeoutCritical,
|
"notificationTimeoutCritical": notificationTimeoutCritical,
|
||||||
"notificationPopupPosition": notificationPopupPosition,
|
"notificationPopupPosition": notificationPopupPosition,
|
||||||
|
"osdAlwaysShowValue": osdAlwaysShowValue,
|
||||||
"screenPreferences": screenPreferences,
|
"screenPreferences": screenPreferences,
|
||||||
"pluginSettings": pluginSettings,
|
|
||||||
"animationSpeed": animationSpeed
|
"animationSpeed": animationSpeed
|
||||||
}, null, 2))
|
}, null, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function savePluginSettings() {
|
||||||
|
if (_pluginSettingsLoading)
|
||||||
|
return
|
||||||
|
pluginSettingsFile.setText(JSON.stringify(pluginSettings, null, 2))
|
||||||
|
}
|
||||||
|
|
||||||
function setShowWorkspaceIndex(enabled) {
|
function setShowWorkspaceIndex(enabled) {
|
||||||
showWorkspaceIndex = enabled
|
showWorkspaceIndex = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
@@ -805,6 +870,7 @@ Singleton {
|
|||||||
var selectedGpuIndex = typeof order[i] === "string" ? undefined : order[i].selectedGpuIndex
|
var selectedGpuIndex = typeof order[i] === "string" ? undefined : order[i].selectedGpuIndex
|
||||||
var pciId = typeof order[i] === "string" ? undefined : order[i].pciId
|
var pciId = typeof order[i] === "string" ? undefined : order[i].pciId
|
||||||
var mountPath = typeof order[i] === "string" ? undefined : order[i].mountPath
|
var mountPath = typeof order[i] === "string" ? undefined : order[i].mountPath
|
||||||
|
var minimumWidth = typeof order[i] === "string" ? undefined : order[i].minimumWidth
|
||||||
var item = {
|
var item = {
|
||||||
"widgetId": widgetId,
|
"widgetId": widgetId,
|
||||||
"enabled": enabled
|
"enabled": enabled
|
||||||
@@ -817,6 +883,8 @@ Singleton {
|
|||||||
item.pciId = pciId
|
item.pciId = pciId
|
||||||
if (mountPath !== undefined)
|
if (mountPath !== undefined)
|
||||||
item.mountPath = mountPath
|
item.mountPath = mountPath
|
||||||
|
if (minimumWidth !== undefined)
|
||||||
|
item.minimumWidth = minimumWidth
|
||||||
|
|
||||||
listModel.append(item)
|
listModel.append(item)
|
||||||
}
|
}
|
||||||
@@ -939,23 +1007,38 @@ Singleton {
|
|||||||
updateQtIconTheme(iconTheme)
|
updateQtIconTheme(iconTheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setUseOSLogo(enabled) {
|
function setLauncherLogoMode(mode) {
|
||||||
useOSLogo = enabled
|
launcherLogoMode = mode
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setOSLogoColorOverride(color) {
|
function setLauncherLogoCustomPath(path) {
|
||||||
osLogoColorOverride = color
|
launcherLogoCustomPath = path
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setOSLogoBrightness(brightness) {
|
function setLauncherLogoColorOverride(color) {
|
||||||
osLogoBrightness = brightness
|
launcherLogoColorOverride = color
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setOSLogoContrast(contrast) {
|
function setLauncherLogoColorInvertOnMode(invert) {
|
||||||
osLogoContrast = contrast
|
launcherLogoColorInvertOnMode = invert
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLauncherLogoBrightness(brightness) {
|
||||||
|
launcherLogoBrightness = brightness
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLauncherLogoContrast(contrast) {
|
||||||
|
launcherLogoContrast = contrast
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLauncherLogoSizeOffset(offset) {
|
||||||
|
launcherLogoSizeOffset = offset
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,6 +1062,11 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setDankBarFontScale(scale) {
|
||||||
|
dankBarFontScale = scale
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
function setGtkThemingEnabled(enabled) {
|
function setGtkThemingEnabled(enabled) {
|
||||||
gtkThemingEnabled = enabled
|
gtkThemingEnabled = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
@@ -1083,6 +1171,11 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setOsdAlwaysShowValue(enabled) {
|
||||||
|
osdAlwaysShowValue = enabled
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
function sendTestNotifications() {
|
function sendTestNotifications() {
|
||||||
sendTestNotification(0)
|
sendTestNotification(0)
|
||||||
testNotifTimer1.start()
|
testNotifTimer1.start()
|
||||||
@@ -1091,9 +1184,9 @@ Singleton {
|
|||||||
|
|
||||||
function sendTestNotification(index) {
|
function sendTestNotification(index) {
|
||||||
const notifications = [
|
const notifications = [
|
||||||
["Notification Position Test", "DMS test notification 1 of 3 ~ Hi there!", "dialog-information"],
|
["Notification Position Test", "DMS test notification 1 of 3 ~ Hi there!", "preferences-system"],
|
||||||
["Second Test", "DMS Notification 2 of 3 ~ Check it out!", "emblem-default"],
|
["Second Test", "DMS Notification 2 of 3 ~ Check it out!", "applications-graphics"],
|
||||||
["Third Test", "DMS notification 3 of 3 ~ Enjoy!", "emblem-favorite"]
|
["Third Test", "DMS notification 3 of 3 ~ Enjoy!", "face-smile"]
|
||||||
]
|
]
|
||||||
|
|
||||||
if (index < 0 || index >= notifications.length) {
|
if (index < 0 || index >= notifications.length) {
|
||||||
@@ -1158,6 +1251,11 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setDankBarBorderEnabled(enabled) {
|
||||||
|
dankBarBorderEnabled = enabled
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
function setDankBarPosition(position) {
|
function setDankBarPosition(position) {
|
||||||
dankBarPosition = position
|
dankBarPosition = position
|
||||||
if (position === SettingsData.Position.Bottom && dockPosition === SettingsData.Position.Bottom && showDock) {
|
if (position === SettingsData.Position.Bottom && dockPosition === SettingsData.Position.Bottom && showDock) {
|
||||||
@@ -1283,13 +1381,13 @@ Singleton {
|
|||||||
pluginSettings[pluginId] = {}
|
pluginSettings[pluginId] = {}
|
||||||
}
|
}
|
||||||
pluginSettings[pluginId][key] = value
|
pluginSettings[pluginId][key] = value
|
||||||
saveSettings()
|
savePluginSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function removePluginSettings(pluginId) {
|
function removePluginSettings(pluginId) {
|
||||||
if (pluginSettings[pluginId]) {
|
if (pluginSettings[pluginId]) {
|
||||||
delete pluginSettings[pluginId]
|
delete pluginSettings[pluginId]
|
||||||
saveSettings()
|
savePluginSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1373,6 +1471,26 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileView {
|
||||||
|
id: pluginSettingsFile
|
||||||
|
|
||||||
|
path: isGreeterMode ? "" : pluginSettingsPath
|
||||||
|
blockLoading: true
|
||||||
|
blockWrites: true
|
||||||
|
atomicWrites: true
|
||||||
|
watchChanges: !isGreeterMode
|
||||||
|
onLoaded: {
|
||||||
|
if (!isGreeterMode) {
|
||||||
|
parsePluginSettings(pluginSettingsFile.text())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onLoadFailed: error => {
|
||||||
|
if (!isGreeterMode) {
|
||||||
|
pluginSettings = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: systemDefaultDetectionProcess
|
id: systemDefaultDetectionProcess
|
||||||
|
|
||||||
@@ -1437,7 +1555,7 @@ Singleton {
|
|||||||
id: defaultSettingsCheckProcess
|
id: defaultSettingsCheckProcess
|
||||||
|
|
||||||
command: ["sh", "-c", "CONFIG_DIR=\"" + _configDir
|
command: ["sh", "-c", "CONFIG_DIR=\"" + _configDir
|
||||||
+ "/DankMaterialShell\"; if [ -f \"$CONFIG_DIR/default-settings.json\" ] && [ ! -f \"$CONFIG_DIR/settings.json\" ]; then cp \"$CONFIG_DIR/default-settings.json\" \"$CONFIG_DIR/settings.json\" && echo 'copied'; else echo 'not_found'; fi"]
|
+ "/DankMaterialShell\"; if [ -f \"$CONFIG_DIR/default-settings.json\" ] && [ ! -f \"$CONFIG_DIR/settings.json\" ]; then cp --no-preserve=mode \"$CONFIG_DIR/default-settings.json\" \"$CONFIG_DIR/settings.json\" && echo 'copied'; else echo 'not_found'; fi"]
|
||||||
running: false
|
running: false
|
||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
|
|||||||
@@ -473,6 +473,19 @@ Singleton {
|
|||||||
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5
|
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function barIconSize(barThickness, offset) {
|
||||||
|
const defaultOffset = offset !== undefined ? offset : -6
|
||||||
|
return Math.round((barThickness / 48) * (iconSize + defaultOffset))
|
||||||
|
}
|
||||||
|
|
||||||
|
function barTextSize(barThickness) {
|
||||||
|
const scale = barThickness / 48
|
||||||
|
const dankBarScale = (typeof SettingsData !== "undefined" ? SettingsData.dankBarFontScale : 1.0)
|
||||||
|
if (scale <= 0.75) return fontSizeSmall * 0.9 * dankBarScale
|
||||||
|
if (scale >= 1.25) return fontSizeMedium * dankBarScale
|
||||||
|
return fontSizeSmall * dankBarScale
|
||||||
|
}
|
||||||
|
|
||||||
function getBatteryIcon(level, isCharging, batteryAvailable) {
|
function getBatteryIcon(level, isCharging, batteryAvailable) {
|
||||||
if (!batteryAvailable)
|
if (!batteryAvailable)
|
||||||
return _getBatteryPowerProfileIcon()
|
return _getBatteryPowerProfileIcon()
|
||||||
@@ -602,10 +615,10 @@ Singleton {
|
|||||||
console.log("calling matugen worker")
|
console.log("calling matugen worker")
|
||||||
systemThemeGenerator.command = [
|
systemThemeGenerator.command = [
|
||||||
"sh", "-c",
|
"sh", "-c",
|
||||||
`sleep 1 && ${shellDir}/scripts/matugen-worker.sh '${stateDir}' '${shellDir}' --run`
|
`sleep 1 && ${shellDir}/scripts/matugen-worker.sh '${stateDir}' '${shellDir}' '${configDir}' --run`
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
systemThemeGenerator.command = [shellDir + "/scripts/matugen-worker.sh", stateDir, shellDir, "--run"]
|
systemThemeGenerator.command = [shellDir + "/scripts/matugen-worker.sh", stateDir, shellDir, configDir, "--run"]
|
||||||
}
|
}
|
||||||
systemThemeGenerator.running = true
|
systemThemeGenerator.running = true
|
||||||
}
|
}
|
||||||
@@ -678,6 +691,59 @@ Singleton {
|
|||||||
|
|
||||||
function withAlpha(c, a) { return Qt.rgba(c.r, c.g, c.b, a); }
|
function withAlpha(c, a) { return Qt.rgba(c.r, c.g, c.b, a); }
|
||||||
|
|
||||||
|
function snap(value, dpr) {
|
||||||
|
return Math.round(value * dpr) / dpr
|
||||||
|
}
|
||||||
|
|
||||||
|
function invertHex(hex) {
|
||||||
|
hex = hex.replace('#', '');
|
||||||
|
|
||||||
|
if (!/^[0-9A-Fa-f]{6}$/.test(hex)) {
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
const r = parseInt(hex.substr(0, 2), 16);
|
||||||
|
const g = parseInt(hex.substr(2, 2), 16);
|
||||||
|
const b = parseInt(hex.substr(4, 2), 16);
|
||||||
|
|
||||||
|
const invR = (255 - r).toString(16).padStart(2, '0');
|
||||||
|
const invG = (255 - g).toString(16).padStart(2, '0');
|
||||||
|
const invB = (255 - b).toString(16).padStart(2, '0');
|
||||||
|
|
||||||
|
return `#${invR}${invG}${invB}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
property string baseLogoColor: {
|
||||||
|
if (typeof SettingsData === "undefined") return ""
|
||||||
|
const colorOverride = SettingsData.launcherLogoColorOverride
|
||||||
|
if (!colorOverride || colorOverride === "") return ""
|
||||||
|
if (colorOverride === "primary") return primary
|
||||||
|
if (colorOverride === "surface") return surfaceText
|
||||||
|
return colorOverride
|
||||||
|
}
|
||||||
|
|
||||||
|
property string effectiveLogoColor: {
|
||||||
|
if (typeof SettingsData === "undefined") return ""
|
||||||
|
|
||||||
|
const colorOverride = SettingsData.launcherLogoColorOverride
|
||||||
|
if (!colorOverride || colorOverride === "") return ""
|
||||||
|
|
||||||
|
if (colorOverride === "primary") return primary
|
||||||
|
if (colorOverride === "surface") return surfaceText
|
||||||
|
|
||||||
|
if (!SettingsData.launcherLogoColorInvertOnMode) {
|
||||||
|
return colorOverride
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLightMode) {
|
||||||
|
return invertHex(colorOverride)
|
||||||
|
}
|
||||||
|
|
||||||
|
return colorOverride
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: matugenCheck
|
id: matugenCheck
|
||||||
command: ["which", "matugen"]
|
command: ["which", "matugen"]
|
||||||
@@ -877,7 +943,7 @@ Singleton {
|
|||||||
|
|
||||||
function toggle(): string {
|
function toggle(): string {
|
||||||
root.toggleLightMode()
|
root.toggleLightMode()
|
||||||
return root.isLightMode ? "light" : "dark"
|
return root.isLightMode ? "dark" : "light"
|
||||||
}
|
}
|
||||||
|
|
||||||
function light(): string {
|
function light(): string {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Quickshell.Services.Greetd
|
|||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Modules.Greetd
|
import qs.Modules.Greetd
|
||||||
|
|
||||||
ShellRoot {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
WlSessionLock {
|
WlSessionLock {
|
||||||
|
|||||||
396
DMSShell.qml
396
DMSShell.qml
@@ -1,6 +1,3 @@
|
|||||||
//@ pragma Env QSG_RENDER_LOOP=threaded
|
|
||||||
//@ pragma UseQApplication
|
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
@@ -29,25 +26,54 @@ import qs.Modules.Plugins
|
|||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
|
|
||||||
ShellRoot {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
Component.onCompleted: {
|
Instantiator {
|
||||||
PortalService.init()
|
id: daemonPluginInstantiator
|
||||||
// Initialize DisplayService night mode functionality
|
asynchronous: true
|
||||||
DisplayService.nightModeEnabled
|
model: Object.keys(PluginService.pluginDaemonComponents)
|
||||||
// Initialize WallpaperCyclingService
|
|
||||||
WallpaperCyclingService.cyclingActive
|
delegate: Loader {
|
||||||
// Initialize PluginService by accessing its properties
|
id: daemonLoader
|
||||||
PluginService.pluginDirectory
|
property string pluginId: modelData
|
||||||
|
sourceComponent: PluginService.pluginDaemonComponents[pluginId]
|
||||||
|
|
||||||
|
onLoaded: {
|
||||||
|
if (item) {
|
||||||
|
item.pluginService = PluginService
|
||||||
|
if (item.popoutService !== undefined) {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
|
item.pluginId = pluginId
|
||||||
|
console.log("Daemon plugin loaded:", pluginId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WallpaperBackground {}
|
WallpaperBackground {}
|
||||||
|
|
||||||
Lock {
|
LazyLoader {
|
||||||
id: lock
|
id: lockLoader
|
||||||
|
active: false
|
||||||
|
|
||||||
anchors.fill: parent
|
Lock {
|
||||||
|
id: lock
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
IdleService.lockComponent = lock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: lockInitTimer
|
||||||
|
interval: 100
|
||||||
|
running: true
|
||||||
|
repeat: false
|
||||||
|
onTriggered: lockLoader.active = true
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
@@ -55,17 +81,22 @@ ShellRoot {
|
|||||||
asynchronous: false
|
asynchronous: false
|
||||||
|
|
||||||
property var currentPosition: SettingsData.dankBarPosition
|
property var currentPosition: SettingsData.dankBarPosition
|
||||||
|
property bool initialized: false
|
||||||
|
|
||||||
sourceComponent: DankBar {
|
sourceComponent: DankBar {
|
||||||
onColorPickerRequested: colorPickerModal.show()
|
onColorPickerRequested: colorPickerModal.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
initialized = true
|
||||||
|
}
|
||||||
|
|
||||||
onCurrentPositionChanged: {
|
onCurrentPositionChanged: {
|
||||||
|
if (!initialized) return
|
||||||
|
|
||||||
const component = sourceComponent
|
const component = sourceComponent
|
||||||
sourceComponent = null
|
sourceComponent = null
|
||||||
Qt.callLater(() => {
|
sourceComponent = component
|
||||||
sourceComponent = component
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +106,7 @@ ShellRoot {
|
|||||||
asynchronous: false
|
asynchronous: false
|
||||||
|
|
||||||
property var currentPosition: SettingsData.dockPosition
|
property var currentPosition: SettingsData.dockPosition
|
||||||
|
property bool initialized: false
|
||||||
|
|
||||||
sourceComponent: Dock {
|
sourceComponent: Dock {
|
||||||
contextMenu: dockContextMenuLoader.item ? dockContextMenuLoader.item : null
|
contextMenu: dockContextMenuLoader.item ? dockContextMenuLoader.item : null
|
||||||
@@ -86,13 +118,17 @@ ShellRoot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
initialized = true
|
||||||
|
}
|
||||||
|
|
||||||
onCurrentPositionChanged: {
|
onCurrentPositionChanged: {
|
||||||
|
if (!initialized) return
|
||||||
|
|
||||||
console.log("DEBUG: Dock position changed to:", currentPosition, "- recreating dock")
|
console.log("DEBUG: Dock position changed to:", currentPosition, "- recreating dock")
|
||||||
const comp = sourceComponent
|
const comp = sourceComponent
|
||||||
sourceComponent = null
|
sourceComponent = null
|
||||||
Qt.callLater(() => {
|
sourceComponent = comp
|
||||||
sourceComponent = comp
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,6 +141,10 @@ ShellRoot {
|
|||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
DankDashPopout {
|
DankDashPopout {
|
||||||
id: dankDashPopout
|
id: dankDashPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.dankDashPopout = dankDashPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,6 +166,10 @@ ShellRoot {
|
|||||||
|
|
||||||
NotificationCenterPopout {
|
NotificationCenterPopout {
|
||||||
id: notificationCenter
|
id: notificationCenter
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.notificationCenterPopout = notificationCenter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,38 +187,19 @@ ShellRoot {
|
|||||||
active: false
|
active: false
|
||||||
|
|
||||||
property var modalRef: colorPickerModal
|
property var modalRef: colorPickerModal
|
||||||
|
property LazyLoader powerModalLoaderRef: powerMenuModalLoader
|
||||||
|
|
||||||
ControlCenterPopout {
|
ControlCenterPopout {
|
||||||
id: controlCenterPopout
|
id: controlCenterPopout
|
||||||
colorPickerModal: controlCenterLoader.modalRef
|
colorPickerModal: controlCenterLoader.modalRef
|
||||||
|
powerMenuModalLoader: controlCenterLoader.powerModalLoaderRef
|
||||||
|
|
||||||
onPowerActionRequested: (action, title, message) => {
|
|
||||||
powerConfirmModalLoader.active = true
|
|
||||||
if (powerConfirmModalLoader.item) {
|
|
||||||
powerConfirmModalLoader.item.confirmButtonColor = action === "poweroff" ? Theme.error : action === "reboot" ? Theme.warning : Theme.primary
|
|
||||||
powerConfirmModalLoader.item.show(title, message, function () {
|
|
||||||
switch (action) {
|
|
||||||
case "logout":
|
|
||||||
SessionService.logout()
|
|
||||||
break
|
|
||||||
case "suspend":
|
|
||||||
SessionService.suspend()
|
|
||||||
break
|
|
||||||
case "hibernate":
|
|
||||||
SessionService.hibernate()
|
|
||||||
break
|
|
||||||
case "reboot":
|
|
||||||
SessionService.reboot()
|
|
||||||
break
|
|
||||||
case "poweroff":
|
|
||||||
SessionService.poweroff()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}, function () {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onLockRequested: {
|
onLockRequested: {
|
||||||
lock.activate()
|
lockLoader.item.activate()
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.controlCenterPopout = controlCenterPopout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,6 +211,10 @@ ShellRoot {
|
|||||||
|
|
||||||
WifiPasswordModal {
|
WifiPasswordModal {
|
||||||
id: wifiPasswordModal
|
id: wifiPasswordModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.wifiPasswordModal = wifiPasswordModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,6 +225,10 @@ ShellRoot {
|
|||||||
|
|
||||||
NetworkInfoModal {
|
NetworkInfoModal {
|
||||||
id: networkInfoModal
|
id: networkInfoModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.networkInfoModal = networkInfoModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +239,10 @@ ShellRoot {
|
|||||||
|
|
||||||
BatteryPopout {
|
BatteryPopout {
|
||||||
id: batteryPopout
|
id: batteryPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.batteryPopout = batteryPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,6 +253,10 @@ ShellRoot {
|
|||||||
|
|
||||||
VpnPopout {
|
VpnPopout {
|
||||||
id: vpnPopout
|
id: vpnPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.vpnPopout = vpnPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,11 +313,19 @@ ShellRoot {
|
|||||||
|
|
||||||
ProcessListPopout {
|
ProcessListPopout {
|
||||||
id: processListPopout
|
id: processListPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.processListPopout = processListPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsModal {
|
SettingsModal {
|
||||||
id: settingsModal
|
id: settingsModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.settingsModal = settingsModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
@@ -286,22 +335,43 @@ ShellRoot {
|
|||||||
|
|
||||||
AppDrawerPopout {
|
AppDrawerPopout {
|
||||||
id: appDrawerPopout
|
id: appDrawerPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.appDrawerPopout = appDrawerPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpotlightModal {
|
SpotlightModal {
|
||||||
id: spotlightModal
|
id: spotlightModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.spotlightModal = spotlightModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipboardHistoryModal {
|
ClipboardHistoryModal {
|
||||||
id: clipboardHistoryModalPopup
|
id: clipboardHistoryModalPopup
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.clipboardHistoryModal = clipboardHistoryModalPopup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationModal {
|
NotificationModal {
|
||||||
id: notificationModal
|
id: notificationModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.notificationModal = notificationModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ColorPickerModal {
|
|
||||||
|
DankColorPickerModal {
|
||||||
id: colorPickerModal
|
id: colorPickerModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.colorPickerModal = colorPickerModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
@@ -311,6 +381,10 @@ ShellRoot {
|
|||||||
|
|
||||||
ProcessListModal {
|
ProcessListModal {
|
||||||
id: processListModal
|
id: processListModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.processListModal = processListModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,6 +395,10 @@ ShellRoot {
|
|||||||
|
|
||||||
SystemUpdatePopout {
|
SystemUpdatePopout {
|
||||||
id: systemUpdatePopout
|
id: systemUpdatePopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.systemUpdatePopout = systemUpdatePopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +409,7 @@ ShellRoot {
|
|||||||
delegate: DankSlideout {
|
delegate: DankSlideout {
|
||||||
id: notepadSlideout
|
id: notepadSlideout
|
||||||
modelData: item
|
modelData: item
|
||||||
title: qsTr("Notepad")
|
title: I18n.tr("Notepad")
|
||||||
slideoutWidth: 480
|
slideoutWidth: 480
|
||||||
expandable: true
|
expandable: true
|
||||||
expandedWidthValue: 960
|
expandedWidthValue: 960
|
||||||
@@ -388,219 +466,19 @@ ShellRoot {
|
|||||||
}, function () {})
|
}, function () {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.powerMenuModal = powerMenuModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcHandler {
|
DMSShellIPC {
|
||||||
function open() {
|
powerMenuModalLoader: powerMenuModalLoader
|
||||||
powerMenuModalLoader.active = true
|
processListModalLoader: processListModalLoader
|
||||||
if (powerMenuModalLoader.item)
|
controlCenterLoader: controlCenterLoader
|
||||||
powerMenuModalLoader.item.open()
|
dankDashPopoutLoader: dankDashPopoutLoader
|
||||||
|
notepadSlideoutVariants: notepadSlideoutVariants
|
||||||
return "POWERMENU_OPEN_SUCCESS"
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
if (powerMenuModalLoader.item)
|
|
||||||
powerMenuModalLoader.item.close()
|
|
||||||
|
|
||||||
return "POWERMENU_CLOSE_SUCCESS"
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggle() {
|
|
||||||
powerMenuModalLoader.active = true
|
|
||||||
if (powerMenuModalLoader.item)
|
|
||||||
powerMenuModalLoader.item.toggle()
|
|
||||||
|
|
||||||
return "POWERMENU_TOGGLE_SUCCESS"
|
|
||||||
}
|
|
||||||
|
|
||||||
target: "powermenu"
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcHandler {
|
|
||||||
function open(): string {
|
|
||||||
processListModalLoader.active = true
|
|
||||||
if (processListModalLoader.item)
|
|
||||||
processListModalLoader.item.show()
|
|
||||||
|
|
||||||
return "PROCESSLIST_OPEN_SUCCESS"
|
|
||||||
}
|
|
||||||
|
|
||||||
function close(): string {
|
|
||||||
if (processListModalLoader.item)
|
|
||||||
processListModalLoader.item.hide()
|
|
||||||
|
|
||||||
return "PROCESSLIST_CLOSE_SUCCESS"
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggle(): string {
|
|
||||||
processListModalLoader.active = true
|
|
||||||
if (processListModalLoader.item)
|
|
||||||
processListModalLoader.item.toggle()
|
|
||||||
|
|
||||||
return "PROCESSLIST_TOGGLE_SUCCESS"
|
|
||||||
}
|
|
||||||
|
|
||||||
target: "processlist"
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcHandler {
|
|
||||||
function open(): string {
|
|
||||||
controlCenterLoader.active = true
|
|
||||||
if (controlCenterLoader.item) {
|
|
||||||
controlCenterLoader.item.open()
|
|
||||||
return "CONTROL_CENTER_OPEN_SUCCESS"
|
|
||||||
}
|
|
||||||
return "CONTROL_CENTER_OPEN_FAILED"
|
|
||||||
}
|
|
||||||
|
|
||||||
function close(): string {
|
|
||||||
if (controlCenterLoader.item) {
|
|
||||||
controlCenterLoader.item.close()
|
|
||||||
return "CONTROL_CENTER_CLOSE_SUCCESS"
|
|
||||||
}
|
|
||||||
return "CONTROL_CENTER_CLOSE_FAILED"
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggle(): string {
|
|
||||||
controlCenterLoader.active = true
|
|
||||||
if (controlCenterLoader.item) {
|
|
||||||
controlCenterLoader.item.toggle()
|
|
||||||
return "CONTROL_CENTER_TOGGLE_SUCCESS"
|
|
||||||
}
|
|
||||||
return "CONTROL_CENTER_TOGGLE_FAILED"
|
|
||||||
}
|
|
||||||
|
|
||||||
target: "control-center"
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcHandler {
|
|
||||||
function open(tab: string): string {
|
|
||||||
dankDashPopoutLoader.active = true
|
|
||||||
if (dankDashPopoutLoader.item) {
|
|
||||||
switch (tab.toLowerCase()) {
|
|
||||||
case "media":
|
|
||||||
dankDashPopoutLoader.item.currentTabIndex = 1
|
|
||||||
break
|
|
||||||
case "weather":
|
|
||||||
dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 2 : 0
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
dankDashPopoutLoader.item.currentTabIndex = 0
|
|
||||||
break
|
|
||||||
}
|
|
||||||
dankDashPopoutLoader.item.setTriggerPosition(Screen.width / 2, Theme.barHeight + Theme.spacingS, 100, "center", Screen)
|
|
||||||
dankDashPopoutLoader.item.dashVisible = true
|
|
||||||
return "DASH_OPEN_SUCCESS"
|
|
||||||
}
|
|
||||||
return "DASH_OPEN_FAILED"
|
|
||||||
}
|
|
||||||
|
|
||||||
function close(): string {
|
|
||||||
if (dankDashPopoutLoader.item) {
|
|
||||||
dankDashPopoutLoader.item.dashVisible = false
|
|
||||||
return "DASH_CLOSE_SUCCESS"
|
|
||||||
}
|
|
||||||
return "DASH_CLOSE_FAILED"
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggle(tab: string): string {
|
|
||||||
dankDashPopoutLoader.active = true
|
|
||||||
if (dankDashPopoutLoader.item) {
|
|
||||||
if (dankDashPopoutLoader.item.dashVisible) {
|
|
||||||
dankDashPopoutLoader.item.dashVisible = false
|
|
||||||
} else {
|
|
||||||
switch (tab.toLowerCase()) {
|
|
||||||
case "media":
|
|
||||||
dankDashPopoutLoader.item.currentTabIndex = 1
|
|
||||||
break
|
|
||||||
case "weather":
|
|
||||||
dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 2 : 0
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
dankDashPopoutLoader.item.currentTabIndex = 0
|
|
||||||
break
|
|
||||||
}
|
|
||||||
dankDashPopoutLoader.item.setTriggerPosition(Screen.width / 2, Theme.barHeight + Theme.spacingS, 100, "center", Screen)
|
|
||||||
dankDashPopoutLoader.item.dashVisible = true
|
|
||||||
}
|
|
||||||
return "DASH_TOGGLE_SUCCESS"
|
|
||||||
}
|
|
||||||
return "DASH_TOGGLE_FAILED"
|
|
||||||
}
|
|
||||||
|
|
||||||
target: "dash"
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcHandler {
|
|
||||||
function getFocusedScreenName() {
|
|
||||||
if (CompositorService.isHyprland && Hyprland.focusedWorkspace && Hyprland.focusedWorkspace.monitor) {
|
|
||||||
return Hyprland.focusedWorkspace.monitor.name
|
|
||||||
}
|
|
||||||
if (CompositorService.isNiri && NiriService.currentOutput) {
|
|
||||||
return NiriService.currentOutput
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
function getActiveNotepadInstance() {
|
|
||||||
if (notepadSlideoutVariants.instances.length === 0) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notepadSlideoutVariants.instances.length === 1) {
|
|
||||||
return notepadSlideoutVariants.instances[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
var focusedScreen = getFocusedScreenName()
|
|
||||||
if (focusedScreen && notepadSlideoutVariants.instances.length > 0) {
|
|
||||||
for (var i = 0; i < notepadSlideoutVariants.instances.length; i++) {
|
|
||||||
var slideout = notepadSlideoutVariants.instances[i]
|
|
||||||
if (slideout.modelData && slideout.modelData.name === focusedScreen) {
|
|
||||||
return slideout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < notepadSlideoutVariants.instances.length; i++) {
|
|
||||||
var slideout = notepadSlideoutVariants.instances[i]
|
|
||||||
if (slideout.isVisible) {
|
|
||||||
return slideout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return notepadSlideoutVariants.instances[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
function open(): string {
|
|
||||||
var instance = getActiveNotepadInstance()
|
|
||||||
if (instance) {
|
|
||||||
instance.show()
|
|
||||||
return "NOTEPAD_OPEN_SUCCESS"
|
|
||||||
}
|
|
||||||
return "NOTEPAD_OPEN_FAILED"
|
|
||||||
}
|
|
||||||
|
|
||||||
function close(): string {
|
|
||||||
var instance = getActiveNotepadInstance()
|
|
||||||
if (instance) {
|
|
||||||
instance.hide()
|
|
||||||
return "NOTEPAD_CLOSE_SUCCESS"
|
|
||||||
}
|
|
||||||
return "NOTEPAD_CLOSE_FAILED"
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggle(): string {
|
|
||||||
var instance = getActiveNotepadInstance()
|
|
||||||
if (instance) {
|
|
||||||
instance.toggle()
|
|
||||||
return "NOTEPAD_TOGGLE_SUCCESS"
|
|
||||||
}
|
|
||||||
return "NOTEPAD_TOGGLE_FAILED"
|
|
||||||
}
|
|
||||||
|
|
||||||
target: "notepad"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
|
|||||||
265
DMSShellIPC.qml
Normal file
265
DMSShellIPC.qml
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var powerMenuModalLoader
|
||||||
|
required property var processListModalLoader
|
||||||
|
required property var controlCenterLoader
|
||||||
|
required property var dankDashPopoutLoader
|
||||||
|
required property var notepadSlideoutVariants
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
function open() {
|
||||||
|
root.powerMenuModalLoader.active = true
|
||||||
|
if (root.powerMenuModalLoader.item)
|
||||||
|
root.powerMenuModalLoader.item.openCentered()
|
||||||
|
|
||||||
|
return "POWERMENU_OPEN_SUCCESS"
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
if (root.powerMenuModalLoader.item)
|
||||||
|
root.powerMenuModalLoader.item.close()
|
||||||
|
|
||||||
|
return "POWERMENU_CLOSE_SUCCESS"
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle() {
|
||||||
|
root.powerMenuModalLoader.active = true
|
||||||
|
if (root.powerMenuModalLoader.item) {
|
||||||
|
if (root.powerMenuModalLoader.item.shouldBeVisible) {
|
||||||
|
root.powerMenuModalLoader.item.close()
|
||||||
|
} else {
|
||||||
|
root.powerMenuModalLoader.item.openCentered()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "POWERMENU_TOGGLE_SUCCESS"
|
||||||
|
}
|
||||||
|
|
||||||
|
target: "powermenu"
|
||||||
|
}
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
function open(): string {
|
||||||
|
root.processListModalLoader.active = true
|
||||||
|
if (root.processListModalLoader.item)
|
||||||
|
root.processListModalLoader.item.show()
|
||||||
|
|
||||||
|
return "PROCESSLIST_OPEN_SUCCESS"
|
||||||
|
}
|
||||||
|
|
||||||
|
function close(): string {
|
||||||
|
if (root.processListModalLoader.item)
|
||||||
|
root.processListModalLoader.item.hide()
|
||||||
|
|
||||||
|
return "PROCESSLIST_CLOSE_SUCCESS"
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle(): string {
|
||||||
|
root.processListModalLoader.active = true
|
||||||
|
if (root.processListModalLoader.item)
|
||||||
|
root.processListModalLoader.item.toggle()
|
||||||
|
|
||||||
|
return "PROCESSLIST_TOGGLE_SUCCESS"
|
||||||
|
}
|
||||||
|
|
||||||
|
target: "processlist"
|
||||||
|
}
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
function open(): string {
|
||||||
|
root.controlCenterLoader.active = true
|
||||||
|
if (root.controlCenterLoader.item) {
|
||||||
|
root.controlCenterLoader.item.open()
|
||||||
|
return "CONTROL_CENTER_OPEN_SUCCESS"
|
||||||
|
}
|
||||||
|
return "CONTROL_CENTER_OPEN_FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
|
function close(): string {
|
||||||
|
if (root.controlCenterLoader.item) {
|
||||||
|
root.controlCenterLoader.item.close()
|
||||||
|
return "CONTROL_CENTER_CLOSE_SUCCESS"
|
||||||
|
}
|
||||||
|
return "CONTROL_CENTER_CLOSE_FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle(): string {
|
||||||
|
root.controlCenterLoader.active = true
|
||||||
|
if (root.controlCenterLoader.item) {
|
||||||
|
root.controlCenterLoader.item.toggle()
|
||||||
|
return "CONTROL_CENTER_TOGGLE_SUCCESS"
|
||||||
|
}
|
||||||
|
return "CONTROL_CENTER_TOGGLE_FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
|
target: "control-center"
|
||||||
|
}
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
function open(tab: string): string {
|
||||||
|
root.dankDashPopoutLoader.active = true
|
||||||
|
if (root.dankDashPopoutLoader.item) {
|
||||||
|
switch (tab.toLowerCase()) {
|
||||||
|
case "media":
|
||||||
|
root.dankDashPopoutLoader.item.currentTabIndex = 1
|
||||||
|
break
|
||||||
|
case "weather":
|
||||||
|
root.dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 2 : 0
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
root.dankDashPopoutLoader.item.currentTabIndex = 0
|
||||||
|
break
|
||||||
|
}
|
||||||
|
root.dankDashPopoutLoader.item.setTriggerPosition(Screen.width / 2, Theme.barHeight + Theme.spacingS, 100, "center", Screen)
|
||||||
|
root.dankDashPopoutLoader.item.dashVisible = true
|
||||||
|
return "DASH_OPEN_SUCCESS"
|
||||||
|
}
|
||||||
|
return "DASH_OPEN_FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
|
function close(): string {
|
||||||
|
if (root.dankDashPopoutLoader.item) {
|
||||||
|
root.dankDashPopoutLoader.item.dashVisible = false
|
||||||
|
return "DASH_CLOSE_SUCCESS"
|
||||||
|
}
|
||||||
|
return "DASH_CLOSE_FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle(tab: string): string {
|
||||||
|
root.dankDashPopoutLoader.active = true
|
||||||
|
if (root.dankDashPopoutLoader.item) {
|
||||||
|
if (root.dankDashPopoutLoader.item.dashVisible) {
|
||||||
|
root.dankDashPopoutLoader.item.dashVisible = false
|
||||||
|
} else {
|
||||||
|
switch (tab.toLowerCase()) {
|
||||||
|
case "media":
|
||||||
|
root.dankDashPopoutLoader.item.currentTabIndex = 1
|
||||||
|
break
|
||||||
|
case "weather":
|
||||||
|
root.dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 2 : 0
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
root.dankDashPopoutLoader.item.currentTabIndex = 0
|
||||||
|
break
|
||||||
|
}
|
||||||
|
root.dankDashPopoutLoader.item.setTriggerPosition(Screen.width / 2, Theme.barHeight + Theme.spacingS, 100, "center", Screen)
|
||||||
|
root.dankDashPopoutLoader.item.dashVisible = true
|
||||||
|
}
|
||||||
|
return "DASH_TOGGLE_SUCCESS"
|
||||||
|
}
|
||||||
|
return "DASH_TOGGLE_FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
|
target: "dash"
|
||||||
|
}
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
function getFocusedScreenName() {
|
||||||
|
if (CompositorService.isHyprland && Hyprland.focusedWorkspace && Hyprland.focusedWorkspace.monitor) {
|
||||||
|
return Hyprland.focusedWorkspace.monitor.name
|
||||||
|
}
|
||||||
|
if (CompositorService.isNiri && NiriService.currentOutput) {
|
||||||
|
return NiriService.currentOutput
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function getActiveNotepadInstance() {
|
||||||
|
if (root.notepadSlideoutVariants.instances.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.notepadSlideoutVariants.instances.length === 1) {
|
||||||
|
return root.notepadSlideoutVariants.instances[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
var focusedScreen = getFocusedScreenName()
|
||||||
|
if (focusedScreen && root.notepadSlideoutVariants.instances.length > 0) {
|
||||||
|
for (var i = 0; i < root.notepadSlideoutVariants.instances.length; i++) {
|
||||||
|
var slideout = root.notepadSlideoutVariants.instances[i]
|
||||||
|
if (slideout.modelData && slideout.modelData.name === focusedScreen) {
|
||||||
|
return slideout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < root.notepadSlideoutVariants.instances.length; i++) {
|
||||||
|
var slideout = root.notepadSlideoutVariants.instances[i]
|
||||||
|
if (slideout.isVisible) {
|
||||||
|
return slideout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.notepadSlideoutVariants.instances[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
function open(): string {
|
||||||
|
var instance = getActiveNotepadInstance()
|
||||||
|
if (instance) {
|
||||||
|
instance.show()
|
||||||
|
return "NOTEPAD_OPEN_SUCCESS"
|
||||||
|
}
|
||||||
|
return "NOTEPAD_OPEN_FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
|
function close(): string {
|
||||||
|
var instance = getActiveNotepadInstance()
|
||||||
|
if (instance) {
|
||||||
|
instance.hide()
|
||||||
|
return "NOTEPAD_CLOSE_SUCCESS"
|
||||||
|
}
|
||||||
|
return "NOTEPAD_CLOSE_FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle(): string {
|
||||||
|
var instance = getActiveNotepadInstance()
|
||||||
|
if (instance) {
|
||||||
|
instance.toggle()
|
||||||
|
return "NOTEPAD_TOGGLE_SUCCESS"
|
||||||
|
}
|
||||||
|
return "NOTEPAD_TOGGLE_FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
|
target: "notepad"
|
||||||
|
}
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
function toggle(): string {
|
||||||
|
SessionService.toggleIdleInhibit()
|
||||||
|
return SessionService.idleInhibited ? "Idle inhibit enabled" : "Idle inhibit disabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable(): string {
|
||||||
|
SessionService.enableIdleInhibit()
|
||||||
|
return "Idle inhibit enabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
function disable(): string {
|
||||||
|
SessionService.disableIdleInhibit()
|
||||||
|
return "Idle inhibit disabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
function status(): string {
|
||||||
|
return SessionService.idleInhibited ? "Idle inhibit is enabled" : "Idle inhibit is disabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
function reason(newReason: string): string {
|
||||||
|
if (!newReason) {
|
||||||
|
return `Current reason: ${SessionService.inhibitReason}`
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionService.setInhibitReason(newReason)
|
||||||
|
return `Inhibit reason set to: ${newReason}`
|
||||||
|
}
|
||||||
|
|
||||||
|
target: "inhibit"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,7 +30,7 @@ Item {
|
|||||||
showKeyboardHints: modal.showKeyboardHints
|
showKeyboardHints: modal.showKeyboardHints
|
||||||
onKeyboardHintsToggled: modal.showKeyboardHints = !modal.showKeyboardHints
|
onKeyboardHintsToggled: modal.showKeyboardHints = !modal.showKeyboardHints
|
||||||
onClearAllClicked: {
|
onClearAllClicked: {
|
||||||
clearConfirmDialog.show("Clear All History?", "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()
|
||||||
modal.hide()
|
modal.hide()
|
||||||
}, function () {})
|
}, function () {})
|
||||||
@@ -46,7 +46,6 @@ Item {
|
|||||||
leftIconName: "search"
|
leftIconName: "search"
|
||||||
showClearButton: true
|
showClearButton: true
|
||||||
focus: true
|
focus: true
|
||||||
ignoreLeftRightKeys: true
|
|
||||||
keyForwardTargets: [modal.modalFocusScope]
|
keyForwardTargets: [modal.modalFocusScope]
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
modal.searchText = text
|
modal.searchText = text
|
||||||
@@ -116,7 +115,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "No 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
|
||||||
|
|||||||
@@ -80,11 +80,11 @@ Rectangle {
|
|||||||
text: {
|
text: {
|
||||||
switch (entryType) {
|
switch (entryType) {
|
||||||
case "image":
|
case "image":
|
||||||
return "Image • " + entryPreview
|
return I18n.tr("Image") + " • " + entryPreview
|
||||||
case "long_text":
|
case "long_text":
|
||||||
return "Long Text"
|
return I18n.tr("Long Text")
|
||||||
default:
|
default:
|
||||||
return "Text"
|
return I18n.tr("Text")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: `Clipboard History (${totalCount})`
|
text: I18n.tr("Clipboard History") + ` (${totalCount})`
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ DankModal {
|
|||||||
function copyEntry(entry) {
|
function copyEntry(entry) {
|
||||||
const entryId = entry.split('\t')[0]
|
const entryId = entry.split('\t')[0]
|
||||||
Quickshell.execDetached(["sh", "-c", `cliphist decode ${entryId} | wl-copy`])
|
Quickshell.execDetached(["sh", "-c", `cliphist decode ${entryId} | wl-copy`])
|
||||||
ToastService.showInfo("Copied to clipboard")
|
ToastService.showInfo(I18n.tr("Copied to clipboard"))
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ DankModal {
|
|||||||
|
|
||||||
ConfirmModal {
|
ConfirmModal {
|
||||||
id: clearConfirmDialog
|
id: clearConfirmDialog
|
||||||
confirmButtonText: "Clear All"
|
confirmButtonText: I18n.tr("Clear All")
|
||||||
confirmButtonColor: Theme.primary
|
confirmButtonColor: Theme.primary
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import qs.Modals.Clipboard
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: keyboardHints
|
id: keyboardHints
|
||||||
|
|
||||||
|
readonly property string hintsText: I18n.tr("Shift+Del: Clear All • Esc: Close")
|
||||||
|
|
||||||
height: ClipboardConstants.keyboardHintsHeight
|
height: ClipboardConstants.keyboardHintsHeight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
|
||||||
@@ -26,7 +28,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Shift+Del: Clear All • Esc: Close"
|
text: keyboardHints.hintsText
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Qt.labs.platform
|
|
||||||
import Quickshell
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: colorPickerModal
|
|
||||||
|
|
||||||
signal colorSelected(color selectedColor)
|
|
||||||
|
|
||||||
function show() {
|
|
||||||
colorDialog.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
function hide() {
|
|
||||||
colorDialog.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyColorToClipboard(colorValue) {
|
|
||||||
Quickshell.execDetached(["sh", "-c", `echo "${colorValue}" | wl-copy`])
|
|
||||||
ToastService.showInfo(`Color ${colorValue} copied to clipboard`)
|
|
||||||
console.log("Copied color to clipboard:", colorValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorDialog {
|
|
||||||
id: colorDialog
|
|
||||||
title: "Color Picker - Select and copy color"
|
|
||||||
color: Theme.primary
|
|
||||||
|
|
||||||
onAccepted: {
|
|
||||||
const colorString = color.toString()
|
|
||||||
copyColorToClipboard(colorString)
|
|
||||||
colorSelected(color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -15,6 +14,15 @@ PanelWindow {
|
|||||||
property real height: 300
|
property real height: 300
|
||||||
readonly property real screenWidth: screen ? screen.width : 1920
|
readonly property real screenWidth: screen ? screen.width : 1920
|
||||||
readonly property real screenHeight: screen ? screen.height : 1080
|
readonly property real screenHeight: screen ? screen.height : 1080
|
||||||
|
readonly property real dpr: (screen && screen.devicePixelRatio) || 1
|
||||||
|
|
||||||
|
function snap(v) {
|
||||||
|
return Math.round(v * dpr) / dpr
|
||||||
|
}
|
||||||
|
|
||||||
|
function px(v) {
|
||||||
|
return Math.round(v)
|
||||||
|
}
|
||||||
property bool showBackground: true
|
property bool showBackground: true
|
||||||
property real backgroundOpacity: 0.5
|
property real backgroundOpacity: 0.5
|
||||||
property string positioning: "center"
|
property string positioning: "center"
|
||||||
@@ -134,22 +142,26 @@ PanelWindow {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: contentContainer
|
id: contentContainer
|
||||||
|
|
||||||
width: root.width
|
width: px(root.width)
|
||||||
height: root.height
|
height: px(root.height)
|
||||||
anchors.centerIn: positioning === "center" ? parent : undefined
|
anchors.centerIn: undefined
|
||||||
x: {
|
x: {
|
||||||
if (positioning === "top-right") {
|
if (positioning === "center") {
|
||||||
return Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL)
|
return snap((root.screenWidth - width) / 2)
|
||||||
|
} else if (positioning === "top-right") {
|
||||||
|
return px(Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL))
|
||||||
} else if (positioning === "custom") {
|
} else if (positioning === "custom") {
|
||||||
return root.customPosition.x
|
return snap(root.customPosition.x)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
y: {
|
y: {
|
||||||
if (positioning === "top-right") {
|
if (positioning === "center") {
|
||||||
return Theme.barHeight + Theme.spacingXS
|
return snap((root.screenHeight - height) / 2)
|
||||||
|
} else if (positioning === "top-right") {
|
||||||
|
return px(Theme.barHeight + Theme.spacingXS)
|
||||||
} else if (positioning === "custom") {
|
} else if (positioning === "custom") {
|
||||||
return root.customPosition.y
|
return snap(root.customPosition.y)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -157,39 +169,47 @@ PanelWindow {
|
|||||||
radius: root.cornerRadius
|
radius: root.cornerRadius
|
||||||
border.color: root.borderColor
|
border.color: root.borderColor
|
||||||
border.width: root.borderWidth
|
border.width: root.borderWidth
|
||||||
layer.enabled: root.enableShadow
|
clip: false
|
||||||
opacity: root.shouldBeVisible ? 1 : 0
|
opacity: root.shouldBeVisible ? 1 : 0
|
||||||
transform: root.animationType === "slide" ? slideTransform : null
|
transform: root.animationType === "slide" ? slideTransform : null
|
||||||
|
|
||||||
Translate {
|
Translate {
|
||||||
id: slideTransform
|
id: slideTransform
|
||||||
|
|
||||||
x: root.shouldBeVisible ? 0 : 15
|
readonly property real rawX: root.shouldBeVisible ? 0 : 15
|
||||||
y: root.shouldBeVisible ? 0 : -30
|
readonly property real rawY: root.shouldBeVisible ? 0 : -30
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
x: snap(rawX)
|
||||||
id: contentLoader
|
y: snap(rawY)
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
active: root.keepContentLoaded || root.shouldBeVisible || root.visible
|
|
||||||
asynchronous: false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: root.animationDuration
|
duration: animationDuration
|
||||||
easing.type: root.animationEasing
|
easing.type: animationEasing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.effect: MultiEffect {
|
FocusScope {
|
||||||
shadowEnabled: true
|
anchors.fill: parent
|
||||||
shadowHorizontalOffset: 0
|
focus: root.shouldBeVisible
|
||||||
shadowVerticalOffset: 8
|
clip: false
|
||||||
shadowBlur: 1
|
|
||||||
shadowColor: Theme.shadowStrong
|
Loader {
|
||||||
shadowOpacity: 0.3
|
id: contentLoader
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
active: root.keepContentLoaded || root.shouldBeVisible || root.visible
|
||||||
|
asynchronous: false
|
||||||
|
focus: true
|
||||||
|
clip: false
|
||||||
|
|
||||||
|
onLoaded: {
|
||||||
|
if (item) {
|
||||||
|
Qt.callLater(() => item.forceActiveFocus())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
580
Modals/DankColorPickerModal.qml
Normal file
580
Modals/DankColorPickerModal.qml
Normal file
@@ -0,0 +1,580 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
PanelWindow {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string pickerTitle: "Choose Color"
|
||||||
|
property color selectedColor: Theme.primary
|
||||||
|
property bool shouldBeVisible: false
|
||||||
|
property var onColorSelectedCallback: null
|
||||||
|
|
||||||
|
signal colorSelected(color selectedColor)
|
||||||
|
|
||||||
|
property color currentColor: Theme.primary
|
||||||
|
property real hue: 0
|
||||||
|
property real saturation: 1
|
||||||
|
property real value: 1
|
||||||
|
property real alpha: 1
|
||||||
|
property real gradientX: 0
|
||||||
|
property real gradientY: 0
|
||||||
|
|
||||||
|
function open() {
|
||||||
|
currentColor = selectedColor
|
||||||
|
updateFromColor(currentColor)
|
||||||
|
shouldBeVisible = true
|
||||||
|
Qt.callLater(() => colorContent.forceActiveFocus())
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
shouldBeVisible = false
|
||||||
|
onColorSelectedCallback = null
|
||||||
|
}
|
||||||
|
|
||||||
|
function show() {
|
||||||
|
open()
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide() {
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
onColorSelected: (color) => {
|
||||||
|
if (onColorSelectedCallback) {
|
||||||
|
onColorSelectedCallback(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyColorToClipboard(colorValue) {
|
||||||
|
Quickshell.execDetached(["sh", "-c", `echo "${colorValue}" | wl-copy`])
|
||||||
|
ToastService.showInfo(`Color ${colorValue} copied`)
|
||||||
|
SessionData.addRecentColor(currentColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFromColor(color) {
|
||||||
|
hue = color.hsvHue
|
||||||
|
saturation = color.hsvSaturation
|
||||||
|
value = color.hsvValue
|
||||||
|
alpha = color.a
|
||||||
|
gradientX = saturation
|
||||||
|
gradientY = 1 - value
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateColor() {
|
||||||
|
currentColor = Qt.hsva(hue, saturation, value, alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateColorFromGradient(x, y) {
|
||||||
|
saturation = Math.max(0, Math.min(1, x))
|
||||||
|
value = Math.max(0, Math.min(1, 1 - y))
|
||||||
|
updateColor()
|
||||||
|
}
|
||||||
|
|
||||||
|
function pickColorFromScreen() {
|
||||||
|
close()
|
||||||
|
hyprpickerProcess.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: hyprpickerProcess
|
||||||
|
running: false
|
||||||
|
command: ["hyprpicker", "--format=hex"]
|
||||||
|
|
||||||
|
stdout: SplitParser {
|
||||||
|
onRead: data => {
|
||||||
|
const colorStr = data.trim()
|
||||||
|
if (colorStr.length >= 7 && colorStr.startsWith('#')) {
|
||||||
|
root.currentColor = colorStr
|
||||||
|
root.updateFromColor(root.currentColor)
|
||||||
|
hexInput.text = root.currentColor.toString()
|
||||||
|
copyColorToClipboard(colorStr)
|
||||||
|
root.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: (exitCode, exitStatus) => {
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
console.warn("hyprpicker exited with code:", exitCode)
|
||||||
|
}
|
||||||
|
root.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property var standardColors: [
|
||||||
|
"#f44336", "#e91e63", "#9c27b0", "#673ab7", "#3f51b5", "#2196f3", "#03a9f4", "#00bcd4",
|
||||||
|
"#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b", "#ffc107", "#ff9800", "#ff5722",
|
||||||
|
"#d32f2f", "#c2185b", "#7b1fa2", "#512da8", "#303f9f", "#1976d2", "#0288d1", "#0097a7",
|
||||||
|
"#00796b", "#388e3c", "#689f38", "#afb42b", "#fbc02d", "#ffa000", "#f57c00", "#e64a19",
|
||||||
|
"#c62828", "#ad1457", "#6a1b9a", "#4527a0", "#283593", "#1565c0", "#0277bd", "#00838f",
|
||||||
|
"#00695c", "#2e7d32", "#558b2f", "#9e9d24", "#f9a825", "#ff8f00", "#ef6c00", "#d84315",
|
||||||
|
"#ffffff", "#9e9e9e", "#212121"
|
||||||
|
]
|
||||||
|
|
||||||
|
visible: shouldBeVisible
|
||||||
|
|
||||||
|
WlrLayershell.namespace: "quickshell:color-picker"
|
||||||
|
WlrLayershell.layer: WlrLayer.Overlay
|
||||||
|
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
top: true
|
||||||
|
left: true
|
||||||
|
right: true
|
||||||
|
bottom: true
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: root.close()
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: "#80000000"
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 680
|
||||||
|
height: 680
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Theme.surfaceContainer
|
||||||
|
border.color: Theme.outlineMedium
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {} // Prevent clicks from propagating to background
|
||||||
|
}
|
||||||
|
|
||||||
|
FocusScope {
|
||||||
|
id: colorContent
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
focus: root.shouldBeVisible
|
||||||
|
|
||||||
|
Keys.onEscapePressed: event => {
|
||||||
|
root.close()
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingM
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width - 90
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: root.pickerTitle
|
||||||
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Select a color from the palette or use custom sliders")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
iconName: "colorize"
|
||||||
|
iconSize: Theme.iconSize - 4
|
||||||
|
iconColor: Theme.surfaceText
|
||||||
|
onClicked: () => {
|
||||||
|
pickColorFromScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
iconName: "close"
|
||||||
|
iconSize: Theme.iconSize - 4
|
||||||
|
iconColor: Theme.surfaceText
|
||||||
|
onClicked: () => {
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: gradientPicker
|
||||||
|
width: parent.width - 70
|
||||||
|
height: 280
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
border.color: Theme.outlineStrong
|
||||||
|
border.width: 1
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Qt.hsva(root.hue, 1, 1, 1)
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
gradient: Gradient {
|
||||||
|
orientation: Gradient.Horizontal
|
||||||
|
GradientStop { position: 0.0; color: "#ffffff" }
|
||||||
|
GradientStop { position: 1.0; color: "transparent" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
gradient: Gradient {
|
||||||
|
orientation: Gradient.Vertical
|
||||||
|
GradientStop { position: 0.0; color: "transparent" }
|
||||||
|
GradientStop { position: 1.0; color: "#000000" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: pickerCircle
|
||||||
|
width: 16
|
||||||
|
height: 16
|
||||||
|
radius: 8
|
||||||
|
border.color: "white"
|
||||||
|
border.width: 2
|
||||||
|
color: "transparent"
|
||||||
|
x: root.gradientX * parent.width - width / 2
|
||||||
|
y: root.gradientY * parent.height - height / 2
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - 4
|
||||||
|
height: parent.height - 4
|
||||||
|
radius: width / 2
|
||||||
|
border.color: "black"
|
||||||
|
border.width: 1
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.CrossCursor
|
||||||
|
onPressed: mouse => {
|
||||||
|
const x = Math.max(0, Math.min(1, mouse.x / width))
|
||||||
|
const y = Math.max(0, Math.min(1, mouse.y / height))
|
||||||
|
root.gradientX = x
|
||||||
|
root.gradientY = y
|
||||||
|
root.updateColorFromGradient(x, y)
|
||||||
|
}
|
||||||
|
onPositionChanged: mouse => {
|
||||||
|
if (pressed) {
|
||||||
|
const x = Math.max(0, Math.min(1, mouse.x / width))
|
||||||
|
const y = Math.max(0, Math.min(1, mouse.y / height))
|
||||||
|
root.gradientX = x
|
||||||
|
root.gradientY = y
|
||||||
|
root.updateColorFromGradient(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: hueSlider
|
||||||
|
width: 50
|
||||||
|
height: 280
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
border.color: Theme.outlineStrong
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
orientation: Gradient.Vertical
|
||||||
|
GradientStop { position: 0.00; color: "#ff0000" }
|
||||||
|
GradientStop { position: 0.17; color: "#ffff00" }
|
||||||
|
GradientStop { position: 0.33; color: "#00ff00" }
|
||||||
|
GradientStop { position: 0.50; color: "#00ffff" }
|
||||||
|
GradientStop { position: 0.67; color: "#0000ff" }
|
||||||
|
GradientStop { position: 0.83; color: "#ff00ff" }
|
||||||
|
GradientStop { position: 1.00; color: "#ff0000" }
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: hueIndicator
|
||||||
|
width: parent.width
|
||||||
|
height: 4
|
||||||
|
color: "white"
|
||||||
|
border.color: "black"
|
||||||
|
border.width: 1
|
||||||
|
y: root.hue * parent.height - height / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.SizeVerCursor
|
||||||
|
onPressed: mouse => {
|
||||||
|
const h = Math.max(0, Math.min(1, mouse.y / height))
|
||||||
|
root.hue = h
|
||||||
|
root.updateColor()
|
||||||
|
}
|
||||||
|
onPositionChanged: mouse => {
|
||||||
|
if (pressed) {
|
||||||
|
const h = Math.max(0, Math.min(1, mouse.y / height))
|
||||||
|
root.hue = h
|
||||||
|
root.updateColor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Material Colors")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
width: parent.width
|
||||||
|
height: 140
|
||||||
|
cellWidth: 38
|
||||||
|
cellHeight: 38
|
||||||
|
clip: true
|
||||||
|
interactive: false
|
||||||
|
model: root.standardColors
|
||||||
|
|
||||||
|
delegate: Rectangle {
|
||||||
|
width: 36
|
||||||
|
height: 36
|
||||||
|
color: modelData
|
||||||
|
radius: 4
|
||||||
|
border.color: Theme.outlineStrong
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: () => {
|
||||||
|
root.currentColor = modelData
|
||||||
|
root.updateFromColor(root.currentColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: 210
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Recent Colors")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: 5
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 36
|
||||||
|
height: 36
|
||||||
|
radius: 4
|
||||||
|
border.color: Theme.outlineStrong
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
color: {
|
||||||
|
if (index < SessionData.recentColors.length) {
|
||||||
|
return SessionData.recentColors[index]
|
||||||
|
}
|
||||||
|
return Theme.surfaceContainerHigh
|
||||||
|
}
|
||||||
|
|
||||||
|
opacity: index < SessionData.recentColors.length ? 1.0 : 0.3
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: index < SessionData.recentColors.length ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
|
enabled: index < SessionData.recentColors.length
|
||||||
|
onClicked: () => {
|
||||||
|
if (index < SessionData.recentColors.length) {
|
||||||
|
root.currentColor = SessionData.recentColors[index]
|
||||||
|
root.updateFromColor(root.currentColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width - 330
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Opacity")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
DankSlider {
|
||||||
|
width: parent.width
|
||||||
|
value: Math.round(root.alpha * 100)
|
||||||
|
minimum: 0
|
||||||
|
maximum: 100
|
||||||
|
showValue: false
|
||||||
|
onSliderValueChanged: (newValue) => {
|
||||||
|
root.alpha = newValue / 100
|
||||||
|
root.updateColor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 100
|
||||||
|
height: 50
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: root.currentColor
|
||||||
|
border.color: Theme.outlineStrong
|
||||||
|
border.width: 2
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Hex:")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: hexInput
|
||||||
|
width: 120
|
||||||
|
height: 38
|
||||||
|
text: root.currentColor.toString()
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
textColor: {
|
||||||
|
if (text.length === 0) return Theme.surfaceText
|
||||||
|
const hexPattern = /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/
|
||||||
|
return hexPattern.test(text) ? Theme.surfaceText : Theme.error
|
||||||
|
}
|
||||||
|
placeholderText: "#000000"
|
||||||
|
backgroundColor: Theme.surfaceHover
|
||||||
|
borderWidth: 1
|
||||||
|
focusedBorderWidth: 2
|
||||||
|
topPadding: Theme.spacingS
|
||||||
|
bottomPadding: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onAccepted: () => {
|
||||||
|
const hexPattern = /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/
|
||||||
|
if (!hexPattern.test(text)) return
|
||||||
|
const color = Qt.color(text)
|
||||||
|
if (color) {
|
||||||
|
root.currentColor = color
|
||||||
|
root.updateFromColor(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankButton {
|
||||||
|
width: 80
|
||||||
|
buttonHeight: 36
|
||||||
|
text: I18n.tr("Apply")
|
||||||
|
backgroundColor: Theme.primary
|
||||||
|
textColor: Theme.background
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
const hexPattern = /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/
|
||||||
|
if (!hexPattern.test(hexInput.text)) return
|
||||||
|
const color = Qt.color(hexInput.text)
|
||||||
|
if (color) {
|
||||||
|
root.currentColor = color
|
||||||
|
root.updateFromColor(color)
|
||||||
|
root.selectedColor = root.currentColor
|
||||||
|
colorSelected(root.currentColor)
|
||||||
|
SessionData.addRecentColor(root.currentColor)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width - 460
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
DankButton {
|
||||||
|
width: 70
|
||||||
|
buttonHeight: 36
|
||||||
|
text: I18n.tr("Cancel")
|
||||||
|
backgroundColor: "transparent"
|
||||||
|
textColor: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: root.close()
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: "transparent"
|
||||||
|
border.color: Theme.surfaceVariantAlpha
|
||||||
|
border.width: 1
|
||||||
|
z: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankButton {
|
||||||
|
width: 70
|
||||||
|
buttonHeight: 36
|
||||||
|
text: I18n.tr("Copy")
|
||||||
|
backgroundColor: Theme.primary
|
||||||
|
textColor: Theme.background
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
const colorString = root.currentColor.toString()
|
||||||
|
copyColorToClipboard(colorString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ DankModal {
|
|||||||
property bool weAvailable: false
|
property bool weAvailable: false
|
||||||
property string wePath: ""
|
property string wePath: ""
|
||||||
property bool weMode: false
|
property bool weMode: false
|
||||||
|
property var parentModal: null
|
||||||
|
|
||||||
signal fileSelected(string path)
|
signal fileSelected(string path)
|
||||||
|
|
||||||
@@ -131,6 +132,8 @@ DankModal {
|
|||||||
|
|
||||||
objectName: "fileBrowserModal"
|
objectName: "fileBrowserModal"
|
||||||
allowStacking: true
|
allowStacking: true
|
||||||
|
closeOnEscapeKey: false
|
||||||
|
shouldHaveFocus: shouldBeVisible
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
currentPath = getLastPath()
|
currentPath = getLastPath()
|
||||||
}
|
}
|
||||||
@@ -165,10 +168,23 @@ DankModal {
|
|||||||
visible: false
|
visible: false
|
||||||
onBackgroundClicked: close()
|
onBackgroundClicked: close()
|
||||||
onOpened: {
|
onOpened: {
|
||||||
modalFocusScope.forceActiveFocus()
|
if (parentModal) {
|
||||||
|
parentModal.shouldHaveFocus = false
|
||||||
|
parentModal.allowFocusOverride = true
|
||||||
|
}
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (contentLoader && contentLoader.item) {
|
||||||
|
contentLoader.item.forceActiveFocus()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
modalFocusScope.Keys.onPressed: function (event) {
|
onDialogClosed: {
|
||||||
keyboardController.handleKey(event)
|
if (parentModal) {
|
||||||
|
parentModal.allowFocusOverride = false
|
||||||
|
parentModal.shouldHaveFocus = Qt.binding(() => {
|
||||||
|
return parentModal.shouldBeVisible
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
@@ -455,6 +471,16 @@ DankModal {
|
|||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Keys.onPressed: event => {
|
||||||
|
keyboardController.handleKey(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible) {
|
||||||
|
forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.spacingM
|
anchors.margins: Theme.spacingM
|
||||||
@@ -755,7 +781,7 @@ DankModal {
|
|||||||
width: parent.width - saveButton.width - Theme.spacingM
|
width: parent.width - saveButton.width - Theme.spacingM
|
||||||
height: 40
|
height: 40
|
||||||
text: defaultFileName
|
text: defaultFileName
|
||||||
placeholderText: "Enter filename..."
|
placeholderText: I18n.tr("Enter filename...")
|
||||||
ignoreLeftRightKeys: false
|
ignoreLeftRightKeys: false
|
||||||
focus: saveMode
|
focus: saveMode
|
||||||
topPadding: Theme.spacingS
|
topPadding: Theme.spacingS
|
||||||
@@ -788,7 +814,7 @@ DankModal {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Save"
|
text: I18n.tr("Save")
|
||||||
color: fileNameInput.text.trim() !== "" ? Theme.primaryText : Theme.surfaceVariantText
|
color: fileNameInput.text.trim() !== "" ? Theme.primaryText : Theme.surfaceVariantText
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
}
|
}
|
||||||
@@ -892,7 +918,7 @@ DankModal {
|
|||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: qsTr("File Already Exists")
|
text: I18n.tr("File Already Exists")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
@@ -900,7 +926,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: qsTr("A file with this name already exists. Do you want to overwrite it?")
|
text: I18n.tr("A file with this name already exists. Do you want to overwrite it?")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceTextMedium
|
color: Theme.surfaceTextMedium
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -922,7 +948,7 @@ DankModal {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: qsTr("Cancel")
|
text: I18n.tr("Cancel")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -948,7 +974,7 @@ DankModal {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: qsTr("Overwrite")
|
text: I18n.tr("Overwrite")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.background
|
color: Theme.background
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "File Information"
|
text: I18n.tr("File Information")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -197,7 +197,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "F1/I: Toggle • F10: Help"
|
text: I18n.tr("F1/I: Toggle • F10: Help")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceTextMedium
|
color: Theme.surfaceTextMedium
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ Rectangle {
|
|||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Tab/Shift+Tab: Nav • ←→↑↓: Grid Nav • Enter/Space: Select"
|
text: I18n.tr("Tab/Shift+Tab: Nav • ←→↑↓: Grid Nav • Enter/Space: Select")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -32,7 +32,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Alt+←/Backspace: Back • F1/I: File Info • F10: Help • Esc: Close"
|
text: I18n.tr("Alt+←/Backspace: Back • F1/I: File Info • F10: Help • Esc: Close")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ DankModal {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Network Information"
|
text: I18n.tr("Network Information")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -126,7 +126,7 @@ DankModal {
|
|||||||
id: closeText
|
id: closeText
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Close"
|
text: I18n.tr("Close")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.background
|
color: Theme.background
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -9,31 +9,47 @@ DankModal {
|
|||||||
|
|
||||||
property int selectedIndex: 0
|
property int selectedIndex: 0
|
||||||
property int optionCount: SessionService.hibernateSupported ? 5 : 4
|
property int optionCount: SessionService.hibernateSupported ? 5 : 4
|
||||||
|
property rect parentBounds: Qt.rect(0, 0, 0, 0)
|
||||||
|
property var parentScreen: null
|
||||||
|
|
||||||
signal powerActionRequested(string action, string title, string message)
|
signal powerActionRequested(string action, string title, string message)
|
||||||
|
|
||||||
|
function openCentered() {
|
||||||
|
parentBounds = Qt.rect(0, 0, 0, 0)
|
||||||
|
parentScreen = null
|
||||||
|
backgroundOpacity = 0.5
|
||||||
|
open()
|
||||||
|
}
|
||||||
|
|
||||||
|
function openFromControlCenter(bounds, targetScreen) {
|
||||||
|
parentBounds = bounds
|
||||||
|
parentScreen = targetScreen
|
||||||
|
backgroundOpacity = 0
|
||||||
|
open()
|
||||||
|
}
|
||||||
|
|
||||||
function selectOption(action) {
|
function selectOption(action) {
|
||||||
close();
|
close();
|
||||||
const actions = {
|
const actions = {
|
||||||
"logout": {
|
"logout": {
|
||||||
"title": "Log Out",
|
"title": I18n.tr("Log Out"),
|
||||||
"message": "Are you sure you want to log out?"
|
"message": I18n.tr("Are you sure you want to log out?")
|
||||||
},
|
},
|
||||||
"suspend": {
|
"suspend": {
|
||||||
"title": "Suspend",
|
"title": I18n.tr("Suspend"),
|
||||||
"message": "Are you sure you want to suspend the system?"
|
"message": I18n.tr("Are you sure you want to suspend the system?")
|
||||||
},
|
},
|
||||||
"hibernate": {
|
"hibernate": {
|
||||||
"title": "Hibernate",
|
"title": I18n.tr("Hibernate"),
|
||||||
"message": "Are you sure you want to hibernate the system?"
|
"message": I18n.tr("Are you sure you want to hibernate the system?")
|
||||||
},
|
},
|
||||||
"reboot": {
|
"reboot": {
|
||||||
"title": "Reboot",
|
"title": I18n.tr("Reboot"),
|
||||||
"message": "Are you sure you want to reboot the system?"
|
"message": I18n.tr("Are you sure you want to reboot the system?")
|
||||||
},
|
},
|
||||||
"poweroff": {
|
"poweroff": {
|
||||||
"title": "Power Off",
|
"title": I18n.tr("Power Off"),
|
||||||
"message": "Are you sure you want to power off the system?"
|
"message": I18n.tr("Are you sure you want to power off the system?")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const selected = actions[action]
|
const selected = actions[action]
|
||||||
@@ -47,6 +63,16 @@ DankModal {
|
|||||||
width: 320
|
width: 320
|
||||||
height: contentLoader.item ? contentLoader.item.implicitHeight : 300
|
height: contentLoader.item ? contentLoader.item.implicitHeight : 300
|
||||||
enableShadow: true
|
enableShadow: true
|
||||||
|
screen: parentScreen
|
||||||
|
positioning: parentBounds.width > 0 ? "custom" : "center"
|
||||||
|
customPosition: {
|
||||||
|
if (parentBounds.width > 0) {
|
||||||
|
const centerX = parentBounds.x + (parentBounds.width - width) / 2
|
||||||
|
const centerY = parentBounds.y + (parentBounds.height - height) / 2
|
||||||
|
return Qt.point(centerX, centerY)
|
||||||
|
}
|
||||||
|
return Qt.point(0, 0)
|
||||||
|
}
|
||||||
onBackgroundClicked: () => {
|
onBackgroundClicked: () => {
|
||||||
return close();
|
return close();
|
||||||
}
|
}
|
||||||
@@ -118,7 +144,7 @@ DankModal {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Power Options"
|
text: I18n.tr("Power Options")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -175,7 +201,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Log Out"
|
text: I18n.tr("Log Out")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -228,7 +254,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Suspend"
|
text: I18n.tr("Suspend")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -282,7 +308,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Hibernate"
|
text: I18n.tr("Hibernate")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -336,7 +362,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Reboot"
|
text: I18n.tr("Reboot")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: rebootArea.containsMouse ? Theme.warning : Theme.surfaceText
|
color: rebootArea.containsMouse ? Theme.warning : Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -390,7 +416,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Power Off"
|
text: I18n.tr("Power Off")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: powerOffArea.containsMouse ? Theme.error : Theme.surfaceText
|
color: powerOffArea.containsMouse ? Theme.error : Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "System Monitor Unavailable"
|
text: I18n.tr("System Monitor Unavailable")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
@@ -131,7 +131,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "The 'dgop' tool is required for system monitoring.\nPlease install dgop to use this feature."
|
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
|
||||||
@@ -154,7 +154,7 @@ DankModal {
|
|||||||
height: 40
|
height: 40
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "System Monitor"
|
text: I18n.tr("System Monitor")
|
||||||
font.pixelSize: Theme.fontSizeLarge + 4
|
font.pixelSize: Theme.fontSizeLarge + 4
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Item {
|
|||||||
spacing: Theme.spacingXL
|
spacing: Theme.spacingXL
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Battery not detected - only AC power settings available"
|
text: I18n.tr("Battery not detected - only AC power settings available")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
visible: !BatteryService.batteryAvailable
|
visible: !BatteryService.batteryAvailable
|
||||||
@@ -51,7 +51,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Idle Settings"
|
text: I18n.tr("Idle Settings")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
@@ -79,7 +79,7 @@ Item {
|
|||||||
property var timeoutOptions: ["Never", "1 minute", "2 minutes", "3 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes", "30 minutes", "1 hour", "1 hour 30 minutes", "2 hours", "3 hours"]
|
property var timeoutOptions: ["Never", "1 minute", "2 minutes", "3 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes", "30 minutes", "1 hour", "1 hour 30 minutes", "2 hours", "3 hours"]
|
||||||
property var timeoutValues: [0, 60, 120, 180, 300, 600, 900, 1200, 1800, 3600, 5400, 7200, 10800]
|
property var timeoutValues: [0, 60, 120, 180, 300, 600, 900, 1200, 1800, 3600, 5400, 7200, 10800]
|
||||||
|
|
||||||
text: "Automatically lock after"
|
text: I18n.tr("Automatically lock after")
|
||||||
options: timeoutOptions
|
options: timeoutOptions
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -115,7 +115,7 @@ Item {
|
|||||||
property var timeoutOptions: ["Never", "1 minute", "2 minutes", "3 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes", "30 minutes", "1 hour", "1 hour 30 minutes", "2 hours", "3 hours"]
|
property var timeoutOptions: ["Never", "1 minute", "2 minutes", "3 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes", "30 minutes", "1 hour", "1 hour 30 minutes", "2 hours", "3 hours"]
|
||||||
property var timeoutValues: [0, 60, 120, 180, 300, 600, 900, 1200, 1800, 3600, 5400, 7200, 10800]
|
property var timeoutValues: [0, 60, 120, 180, 300, 600, 900, 1200, 1800, 3600, 5400, 7200, 10800]
|
||||||
|
|
||||||
text: "Turn off monitors after"
|
text: I18n.tr("Turn off monitors after")
|
||||||
options: timeoutOptions
|
options: timeoutOptions
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -151,7 +151,7 @@ Item {
|
|||||||
property var timeoutOptions: ["Never", "1 minute", "2 minutes", "3 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes", "30 minutes", "1 hour", "1 hour 30 minutes", "2 hours", "3 hours"]
|
property var timeoutOptions: ["Never", "1 minute", "2 minutes", "3 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes", "30 minutes", "1 hour", "1 hour 30 minutes", "2 hours", "3 hours"]
|
||||||
property var timeoutValues: [0, 60, 120, 180, 300, 600, 900, 1200, 1800, 3600, 5400, 7200, 10800]
|
property var timeoutValues: [0, 60, 120, 180, 300, 600, 900, 1200, 1800, 3600, 5400, 7200, 10800]
|
||||||
|
|
||||||
text: "Suspend system after"
|
text: I18n.tr("Suspend system after")
|
||||||
options: timeoutOptions
|
options: timeoutOptions
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -187,7 +187,7 @@ Item {
|
|||||||
property var timeoutOptions: ["Never", "1 minute", "2 minutes", "3 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes", "30 minutes", "1 hour", "1 hour 30 minutes", "2 hours", "3 hours"]
|
property var timeoutOptions: ["Never", "1 minute", "2 minutes", "3 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes", "30 minutes", "1 hour", "1 hour 30 minutes", "2 hours", "3 hours"]
|
||||||
property var timeoutValues: [0, 60, 120, 180, 300, 600, 900, 1200, 1800, 3600, 5400, 7200, 10800]
|
property var timeoutValues: [0, 60, 120, 180, 300, 600, 900, 1200, 1800, 3600, 5400, 7200, 10800]
|
||||||
|
|
||||||
text: "Hibernate system after"
|
text: I18n.tr("Hibernate system after")
|
||||||
options: timeoutOptions
|
options: timeoutOptions
|
||||||
visible: SessionService.hibernateSupported
|
visible: SessionService.hibernateSupported
|
||||||
|
|
||||||
@@ -221,14 +221,14 @@ Item {
|
|||||||
|
|
||||||
DankToggle {
|
DankToggle {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
text: "Lock before suspend"
|
text: I18n.tr("Lock before suspend")
|
||||||
description: "Automatically lock the screen when the system prepares to suspend"
|
description: "Automatically lock the screen when the system prepares to suspend"
|
||||||
checked: SessionData.lockBeforeSuspend
|
checked: SessionData.lockBeforeSuspend
|
||||||
onToggled: checked => SessionData.setLockBeforeSuspend(checked)
|
onToggled: checked => SessionData.setLockBeforeSuspend(checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Idle monitoring not supported - requires newer Quickshell version"
|
text: I18n.tr("Idle monitoring not supported - requires newer Quickshell version")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import QtQuick
|
|||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Modules.Settings
|
import qs.Modules.Settings
|
||||||
|
|
||||||
Item {
|
FocusScope {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int currentIndex: 0
|
property int currentIndex: 0
|
||||||
property var parentModal: null
|
property var parentModal: null
|
||||||
|
focus: true
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -68,6 +69,7 @@ Item {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
|
||||||
sourceComponent: DankBarTab {
|
sourceComponent: DankBarTab {
|
||||||
|
parentModal: root.parentModal
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -162,6 +164,7 @@ Item {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
|
||||||
sourceComponent: PluginsTab {
|
sourceComponent: PluginsTab {
|
||||||
|
parentModal: root.parentModal
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ DankModal {
|
|||||||
id: profileBrowser
|
id: profileBrowser
|
||||||
|
|
||||||
allowStacking: true
|
allowStacking: true
|
||||||
|
parentModal: settingsModal
|
||||||
browserTitle: "Select Profile Image"
|
browserTitle: "Select Profile Image"
|
||||||
browserIcon: "person"
|
browserIcon: "person"
|
||||||
browserType: "profile"
|
browserType: "profile"
|
||||||
@@ -87,12 +88,6 @@ DankModal {
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
onDialogClosed: () => {
|
onDialogClosed: () => {
|
||||||
if (settingsModal) {
|
|
||||||
settingsModal.allowFocusOverride = false;
|
|
||||||
settingsModal.shouldHaveFocus = Qt.binding(() => {
|
|
||||||
return settingsModal.shouldBeVisible;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
allowStacking = true;
|
allowStacking = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,6 +96,7 @@ DankModal {
|
|||||||
id: wallpaperBrowser
|
id: wallpaperBrowser
|
||||||
|
|
||||||
allowStacking: true
|
allowStacking: true
|
||||||
|
parentModal: settingsModal
|
||||||
browserTitle: "Select Wallpaper"
|
browserTitle: "Select Wallpaper"
|
||||||
browserIcon: "wallpaper"
|
browserIcon: "wallpaper"
|
||||||
browserType: "wallpaper"
|
browserType: "wallpaper"
|
||||||
@@ -115,7 +111,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
settingsContent: Component {
|
settingsContent: Component {
|
||||||
Item {
|
FocusScope {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
focus: true
|
focus: true
|
||||||
|
|
||||||
@@ -144,7 +140,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Settings"
|
text: I18n.tr("Settings")
|
||||||
font.pixelSize: Theme.fontSizeXLarge
|
font.pixelSize: Theme.fontSizeXLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -9,40 +9,40 @@ Rectangle {
|
|||||||
property int currentIndex: 0
|
property int currentIndex: 0
|
||||||
property var parentModal: null
|
property var parentModal: null
|
||||||
readonly property var sidebarItems: [{
|
readonly property var sidebarItems: [{
|
||||||
"text": "Personalization",
|
"text": I18n.tr("Personalization"),
|
||||||
"icon": "person"
|
"icon": "person"
|
||||||
}, {
|
}, {
|
||||||
"text": "Time & Date",
|
"text": I18n.tr("Time & Date"),
|
||||||
"icon": "schedule"
|
"icon": "schedule"
|
||||||
}, {
|
}, {
|
||||||
"text": "Weather",
|
"text": I18n.tr("Weather"),
|
||||||
"icon": "cloud"
|
"icon": "cloud"
|
||||||
}, {
|
}, {
|
||||||
"text": "Dank Bar",
|
"text": I18n.tr("Dank Bar"),
|
||||||
"icon": "toolbar"
|
"icon": "toolbar"
|
||||||
}, {
|
}, {
|
||||||
"text": "Widgets",
|
"text": I18n.tr("Widgets"),
|
||||||
"icon": "widgets"
|
"icon": "widgets"
|
||||||
}, {
|
}, {
|
||||||
"text": "Dock",
|
"text": I18n.tr("Dock"),
|
||||||
"icon": "dock_to_bottom"
|
"icon": "dock_to_bottom"
|
||||||
}, {
|
}, {
|
||||||
"text": "Displays",
|
"text": I18n.tr("Displays"),
|
||||||
"icon": "monitor"
|
"icon": "monitor"
|
||||||
}, {
|
}, {
|
||||||
"text": "Launcher",
|
"text": I18n.tr("Launcher"),
|
||||||
"icon": "apps"
|
"icon": "apps"
|
||||||
}, {
|
}, {
|
||||||
"text": "Theme & Colors",
|
"text": I18n.tr("Theme & Colors"),
|
||||||
"icon": "palette"
|
"icon": "palette"
|
||||||
}, {
|
}, {
|
||||||
"text": "Power",
|
"text": I18n.tr("Power"),
|
||||||
"icon": "power_settings_new"
|
"icon": "power_settings_new"
|
||||||
}, {
|
}, {
|
||||||
"text": "Plugins",
|
"text": I18n.tr("Plugins"),
|
||||||
"icon": "extension"
|
"icon": "extension"
|
||||||
}, {
|
}, {
|
||||||
"text": "About",
|
"text": I18n.tr("About"),
|
||||||
"icon": "info"
|
"icon": "info"
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,13 @@ Item {
|
|||||||
property alias searchField: searchField
|
property alias searchField: searchField
|
||||||
property var parentModal: null
|
property var parentModal: null
|
||||||
|
|
||||||
|
function resetScroll() {
|
||||||
|
resultsView.resetScroll()
|
||||||
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
focus: true
|
focus: true
|
||||||
|
clip: false
|
||||||
Keys.onPressed: event => {
|
Keys.onPressed: event => {
|
||||||
if (event.key === Qt.Key_Escape) {
|
if (event.key === Qt.Key_Escape) {
|
||||||
if (parentModal)
|
if (parentModal)
|
||||||
@@ -76,10 +81,6 @@ Item {
|
|||||||
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
||||||
appLauncher.launchSelected()
|
appLauncher.launchSelected()
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
} else if (!searchField.activeFocus && event.text && event.text.length > 0 && event.text.match(/[a-zA-Z0-9\\s]/)) {
|
|
||||||
searchField.forceActiveFocus()
|
|
||||||
searchField.insertText(event.text)
|
|
||||||
event.accepted = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,27 +102,7 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.spacingM
|
anchors.margins: Theme.spacingM
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
|
clip: false
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: categorySelector.height + Theme.spacingS * 2
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: "transparent"
|
|
||||||
visible: appLauncher.categories.length > 1 || appLauncher.model.count > 0
|
|
||||||
|
|
||||||
CategorySelector {
|
|
||||||
id: categorySelector
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: parent.width - Theme.spacingS * 2
|
|
||||||
categories: appLauncher.categories
|
|
||||||
selectedCategory: appLauncher.selectedCategory
|
|
||||||
compact: false
|
|
||||||
onCategorySelected: category => {
|
|
||||||
appLauncher.setCategory(category)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -146,7 +127,7 @@ Item {
|
|||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
enabled: parentModal ? parentModal.spotlightOpen : true
|
enabled: parentModal ? parentModal.spotlightOpen : true
|
||||||
placeholderText: ""
|
placeholderText: ""
|
||||||
ignoreLeftRightKeys: true
|
ignoreLeftRightKeys: appLauncher.viewMode !== "list"
|
||||||
keyForwardTargets: [spotlightKeyHandler]
|
keyForwardTargets: [spotlightKeyHandler]
|
||||||
text: appLauncher.searchQuery
|
text: appLauncher.searchQuery
|
||||||
onTextEdited: () => {
|
onTextEdited: () => {
|
||||||
@@ -228,6 +209,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SpotlightResults {
|
SpotlightResults {
|
||||||
|
id: resultsView
|
||||||
appLauncher: spotlightKeyHandler.appLauncher
|
appLauncher: spotlightKeyHandler.appLauncher
|
||||||
contextMenu: contextMenu
|
contextMenu: contextMenu
|
||||||
}
|
}
|
||||||
@@ -245,7 +227,7 @@ Item {
|
|||||||
visible: contextMenu.visible
|
visible: contextMenu.visible
|
||||||
z: 999
|
z: 999
|
||||||
onClicked: () => {
|
onClicked: () => {
|
||||||
contextMenu.close()
|
contextMenu.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -1,65 +1,72 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
Rectangle {
|
Popup {
|
||||||
id: contextMenu
|
id: contextMenu
|
||||||
|
|
||||||
property var currentApp: null
|
property var currentApp: null
|
||||||
property bool menuVisible: false
|
|
||||||
property var appLauncher: null
|
property var appLauncher: null
|
||||||
property var parentHandler: null
|
property var parentHandler: null
|
||||||
|
|
||||||
function show(x, y, app) {
|
function show(x, y, app) {
|
||||||
currentApp = app
|
currentApp = app
|
||||||
const menuWidth = 180
|
contextMenu.x = x + 4
|
||||||
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
|
contextMenu.y = y + 4
|
||||||
let finalX = x + 8
|
contextMenu.open()
|
||||||
let finalY = y + 8
|
|
||||||
if (parentHandler) {
|
|
||||||
if (finalX + menuWidth > parentHandler.width)
|
|
||||||
finalX = x - menuWidth - 8
|
|
||||||
|
|
||||||
if (finalY + menuHeight > parentHandler.height)
|
|
||||||
finalY = y - menuHeight - 8
|
|
||||||
|
|
||||||
finalX = Math.max(8, Math.min(finalX, parentHandler.width - menuWidth - 8))
|
|
||||||
finalY = Math.max(8, Math.min(finalY, parentHandler.height - menuHeight - 8))
|
|
||||||
}
|
|
||||||
contextMenu.x = finalX
|
|
||||||
contextMenu.y = finalY
|
|
||||||
contextMenu.visible = true
|
|
||||||
contextMenu.menuVisible = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function hide() {
|
||||||
contextMenu.menuVisible = false
|
contextMenu.close()
|
||||||
Qt.callLater(() => {
|
|
||||||
contextMenu.visible = false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visible: false
|
width: Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2)
|
||||||
width: 180
|
|
||||||
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
||||||
radius: Theme.cornerRadius
|
padding: 0
|
||||||
color: Theme.popupBackground()
|
closePolicy: Popup.CloseOnPressOutside
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
modal: false
|
||||||
border.width: 1
|
dim: false
|
||||||
z: 1000
|
|
||||||
opacity: menuVisible ? 1 : 0
|
|
||||||
scale: menuVisible ? 1 : 0.85
|
|
||||||
|
|
||||||
Rectangle {
|
background: Rectangle {
|
||||||
anchors.fill: parent
|
radius: Theme.cornerRadius
|
||||||
anchors.topMargin: 4
|
color: Theme.popupBackground()
|
||||||
anchors.leftMargin: 2
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
anchors.rightMargin: -2
|
border.width: 1
|
||||||
anchors.bottomMargin: -4
|
|
||||||
radius: parent.radius
|
Rectangle {
|
||||||
color: Qt.rgba(0, 0, 0, 0.15)
|
anchors.fill: parent
|
||||||
z: parent.z - 1
|
anchors.topMargin: 4
|
||||||
|
anchors.leftMargin: 2
|
||||||
|
anchors.rightMargin: -2
|
||||||
|
anchors.bottomMargin: -4
|
||||||
|
radius: parent.radius
|
||||||
|
color: Qt.rgba(0, 0, 0, 0.15)
|
||||||
|
z: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enter: Transition {
|
||||||
|
NumberAnimation {
|
||||||
|
property: "opacity"
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.emphasizedEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit: Transition {
|
||||||
|
NumberAnimation {
|
||||||
|
property: "opacity"
|
||||||
|
from: 1
|
||||||
|
to: 0
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.emphasizedEasing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -98,10 +105,10 @@ Rectangle {
|
|||||||
StyledText {
|
StyledText {
|
||||||
text: {
|
text: {
|
||||||
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
|
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
|
||||||
return "Pin to Dock"
|
return I18n.tr("Pin to Dock")
|
||||||
|
|
||||||
const appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""
|
const appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""
|
||||||
return SessionData.isPinnedApp(appId) ? "Unpin from Dock" : "Pin to Dock"
|
return SessionData.isPinnedApp(appId) ? I18n.tr("Unpin from Dock") : I18n.tr("Pin to Dock")
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
@@ -125,7 +132,7 @@ Rectangle {
|
|||||||
SessionData.removePinnedApp(appId)
|
SessionData.removePinnedApp(appId)
|
||||||
else
|
else
|
||||||
SessionData.addPinnedApp(appId)
|
SessionData.addPinnedApp(appId)
|
||||||
contextMenu.close()
|
contextMenu.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,6 +151,82 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: contextMenu.currentApp && contextMenu.currentApp.desktopEntry && contextMenu.currentApp.desktopEntry.actions ? contextMenu.currentApp.desktopEntry.actions : []
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 32
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: actionMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: Theme.iconSize - 2
|
||||||
|
height: Theme.iconSize - 2
|
||||||
|
visible: modelData.icon && modelData.icon !== ""
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: modelData.icon ? Quickshell.iconPath(modelData.icon, true) : ""
|
||||||
|
smooth: true
|
||||||
|
asynchronous: true
|
||||||
|
visible: status === Image.Ready
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: modelData.name || ""
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Normal
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width - (modelData.icon && modelData.icon !== "" ? (Theme.iconSize - 2 + Theme.spacingS) : 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: actionMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
if (modelData && contextMenu.currentApp && contextMenu.currentApp.desktopEntry) {
|
||||||
|
SessionService.launchDesktopAction(contextMenu.currentApp.desktopEntry, modelData)
|
||||||
|
if (appLauncher) {
|
||||||
|
appLauncher.appLaunched(contextMenu.currentApp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contextMenu.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: contextMenu.currentApp && contextMenu.currentApp.desktopEntry && contextMenu.currentApp.desktopEntry.actions && contextMenu.currentApp.desktopEntry.actions.length > 0
|
||||||
|
width: parent.width - Theme.spacingS * 2
|
||||||
|
height: 5
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 32
|
height: 32
|
||||||
@@ -165,7 +248,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Launch"
|
text: I18n.tr("Launch")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
@@ -183,23 +266,72 @@ Rectangle {
|
|||||||
if (contextMenu.currentApp && appLauncher)
|
if (contextMenu.currentApp && appLauncher)
|
||||||
appLauncher.launchApp(contextMenu.currentApp)
|
appLauncher.launchApp(contextMenu.currentApp)
|
||||||
|
|
||||||
contextMenu.close()
|
contextMenu.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: SessionService.hasPrimeRun
|
||||||
|
width: parent.width - Theme.spacingS * 2
|
||||||
|
height: 5
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: SessionService.hasPrimeRun
|
||||||
|
width: parent.width
|
||||||
|
height: 32
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: primeRunMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "memory"
|
||||||
|
size: Theme.iconSize - 2
|
||||||
|
color: Theme.surfaceText
|
||||||
|
opacity: 0.7
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Launch on dGPU")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Normal
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: primeRunMouseArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: () => {
|
||||||
|
if (contextMenu.currentApp && contextMenu.currentApp.desktopEntry) {
|
||||||
|
SessionService.launchDesktopEntry(contextMenu.currentApp.desktopEntry, true)
|
||||||
|
if (appLauncher) {
|
||||||
|
appLauncher.appLaunched(contextMenu.currentApp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contextMenu.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.mediumDuration
|
|
||||||
easing.type: Theme.emphasizedEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on scale {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.mediumDuration
|
|
||||||
easing.type: Theme.emphasizedEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,21 +18,33 @@ DankModal {
|
|||||||
function show() {
|
function show() {
|
||||||
spotlightOpen = true
|
spotlightOpen = true
|
||||||
open()
|
open()
|
||||||
if (contentLoader.item && contentLoader.item.appLauncher) {
|
|
||||||
contentLoader.item.appLauncher.searchQuery = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (contentLoader.item && contentLoader.item.searchField) {
|
if (contentLoader.item && contentLoader.item.searchField) {
|
||||||
contentLoader.item.searchField.forceActiveFocus()
|
contentLoader.item.searchField.forceActiveFocus()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide() {
|
function hide() {
|
||||||
spotlightOpen = false
|
spotlightOpen = false
|
||||||
close()
|
close()
|
||||||
cleanupTimer.restart()
|
}
|
||||||
|
|
||||||
|
onDialogClosed: {
|
||||||
|
if (contentLoader.item) {
|
||||||
|
if (contentLoader.item.appLauncher) {
|
||||||
|
contentLoader.item.appLauncher.searchQuery = ""
|
||||||
|
contentLoader.item.appLauncher.selectedIndex = 0
|
||||||
|
contentLoader.item.appLauncher.setCategory(I18n.tr("All"))
|
||||||
|
}
|
||||||
|
if (contentLoader.item.resetScroll) {
|
||||||
|
contentLoader.item.resetScroll()
|
||||||
|
}
|
||||||
|
if (contentLoader.item.searchField) {
|
||||||
|
contentLoader.item.searchField.text = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
@@ -45,7 +57,7 @@ DankModal {
|
|||||||
|
|
||||||
shouldBeVisible: spotlightOpen
|
shouldBeVisible: spotlightOpen
|
||||||
width: 550
|
width: 550
|
||||||
height: 600
|
height: 700
|
||||||
backgroundColor: Theme.popupBackground()
|
backgroundColor: Theme.popupBackground()
|
||||||
cornerRadius: Theme.cornerRadius
|
cornerRadius: Theme.cornerRadius
|
||||||
borderColor: Theme.outlineMedium
|
borderColor: Theme.outlineMedium
|
||||||
@@ -69,19 +81,6 @@ DankModal {
|
|||||||
}
|
}
|
||||||
content: spotlightContent
|
content: spotlightContent
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: cleanupTimer
|
|
||||||
|
|
||||||
interval: animationDuration + 50
|
|
||||||
onTriggered: {
|
|
||||||
if (contentLoader.item && contentLoader.item.appLauncher) {
|
|
||||||
contentLoader.item.appLauncher.searchQuery = ""
|
|
||||||
contentLoader.item.appLauncher.selectedIndex = 0
|
|
||||||
contentLoader.item.appLauncher.setCategory("All")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onCloseAllModalsExcept(excludedModal) {
|
function onCloseAllModalsExcept(excludedModal) {
|
||||||
if (excludedModal !== spotlightModal && !allowStacking && spotlightOpen) {
|
if (excludedModal !== spotlightModal && !allowStacking && spotlightOpen) {
|
||||||
|
|||||||
@@ -10,10 +10,16 @@ Rectangle {
|
|||||||
property var appLauncher: null
|
property var appLauncher: null
|
||||||
property var contextMenu: null
|
property var contextMenu: null
|
||||||
|
|
||||||
|
function resetScroll() {
|
||||||
|
resultsList.contentY = 0
|
||||||
|
resultsGrid.contentY = 0
|
||||||
|
}
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height - y
|
height: parent.height - y
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
clip: true
|
||||||
|
|
||||||
DankListView {
|
DankListView {
|
||||||
id: resultsList
|
id: resultsList
|
||||||
@@ -157,7 +163,8 @@ Rectangle {
|
|||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
resultsList.itemClicked(index, model)
|
resultsList.itemClicked(index, model)
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
const modalPos = mapToItem(resultsContainer.parent, mouse.x, mouse.y)
|
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
||||||
|
const modalPos = resultsContainer.parent.mapFromItem(null, globalPos.x, globalPos.y)
|
||||||
resultsList.itemRightClicked(index, model, modalPos.x, modalPos.y)
|
resultsList.itemRightClicked(index, model, modalPos.x, modalPos.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,7 +315,8 @@ Rectangle {
|
|||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
resultsGrid.itemClicked(index, model)
|
resultsGrid.itemClicked(index, model)
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
const modalPos = mapToItem(resultsContainer.parent, mouse.x, mouse.y)
|
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
||||||
|
const modalPos = resultsContainer.parent.mapFromItem(null, globalPos.x, globalPos.y)
|
||||||
resultsGrid.itemRightClicked(index, model, modalPos.x, modalPos.y)
|
resultsGrid.itemRightClicked(index, model, modalPos.x, modalPos.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,33 +9,53 @@ DankModal {
|
|||||||
|
|
||||||
property string wifiPasswordSSID: ""
|
property string wifiPasswordSSID: ""
|
||||||
property string wifiPasswordInput: ""
|
property string wifiPasswordInput: ""
|
||||||
|
property string wifiUsernameInput: ""
|
||||||
|
property bool requiresEnterprise: false
|
||||||
|
|
||||||
function show(ssid) {
|
function show(ssid) {
|
||||||
wifiPasswordSSID = ssid
|
wifiPasswordSSID = ssid
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
|
wifiUsernameInput = ""
|
||||||
|
|
||||||
|
const network = NetworkService.wifiNetworks.find(n => n.ssid === ssid)
|
||||||
|
requiresEnterprise = network?.enterprise || false
|
||||||
|
|
||||||
open()
|
open()
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (contentLoader.item && contentLoader.item.passwordInput)
|
if (contentLoader.item) {
|
||||||
contentLoader.item.passwordInput.forceActiveFocus()
|
if (requiresEnterprise && contentLoader.item.usernameInput) {
|
||||||
|
contentLoader.item.usernameInput.forceActiveFocus()
|
||||||
|
} else if (contentLoader.item.passwordInput) {
|
||||||
|
contentLoader.item.passwordInput.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldBeVisible: false
|
shouldBeVisible: false
|
||||||
width: 420
|
width: 420
|
||||||
height: 230
|
height: requiresEnterprise ? 310 : 230
|
||||||
onShouldBeVisibleChanged: () => {
|
onShouldBeVisibleChanged: () => {
|
||||||
if (!shouldBeVisible)
|
if (!shouldBeVisible) {
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
|
wifiUsernameInput = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onOpened: {
|
onOpened: {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (contentLoader.item && contentLoader.item.passwordInput)
|
if (contentLoader.item) {
|
||||||
contentLoader.item.passwordInput.forceActiveFocus()
|
if (requiresEnterprise && contentLoader.item.usernameInput) {
|
||||||
|
contentLoader.item.usernameInput.forceActiveFocus()
|
||||||
|
} else if (contentLoader.item.passwordInput) {
|
||||||
|
contentLoader.item.passwordInput.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onBackgroundClicked: () => {
|
onBackgroundClicked: () => {
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
|
wifiUsernameInput = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -55,6 +75,7 @@ DankModal {
|
|||||||
FocusScope {
|
FocusScope {
|
||||||
id: wifiContent
|
id: wifiContent
|
||||||
|
|
||||||
|
property alias usernameInput: usernameInput
|
||||||
property alias passwordInput: passwordInput
|
property alias passwordInput: passwordInput
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -62,6 +83,7 @@ DankModal {
|
|||||||
Keys.onEscapePressed: event => {
|
Keys.onEscapePressed: event => {
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
|
wifiUsernameInput = ""
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,14 +100,14 @@ DankModal {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Connect to Wi-Fi"
|
text: I18n.tr("Connect to Wi-Fi")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: `Enter password for "${wifiPasswordSSID}"`
|
text: requiresEnterprise ? `Enter credentials for "${wifiPasswordSSID}"` : `Enter password for "${wifiPasswordSSID}"`
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceTextMedium
|
color: Theme.surfaceTextMedium
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -100,10 +122,48 @@ DankModal {
|
|||||||
onClicked: () => {
|
onClicked: () => {
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
|
wifiUsernameInput = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 50
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Theme.surfaceHover
|
||||||
|
border.color: usernameInput.activeFocus ? Theme.primary : Theme.outlineStrong
|
||||||
|
border.width: usernameInput.activeFocus ? 2 : 1
|
||||||
|
visible: requiresEnterprise
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: () => {
|
||||||
|
usernameInput.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: usernameInput
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
textColor: Theme.surfaceText
|
||||||
|
text: wifiUsernameInput
|
||||||
|
placeholderText: "Username"
|
||||||
|
backgroundColor: "transparent"
|
||||||
|
enabled: root.shouldBeVisible
|
||||||
|
onTextEdited: () => {
|
||||||
|
wifiUsernameInput = text
|
||||||
|
}
|
||||||
|
onAccepted: () => {
|
||||||
|
if (passwordInput) {
|
||||||
|
passwordInput.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
@@ -127,21 +187,24 @@ DankModal {
|
|||||||
textColor: Theme.surfaceText
|
textColor: Theme.surfaceText
|
||||||
text: wifiPasswordInput
|
text: wifiPasswordInput
|
||||||
echoMode: showPasswordCheckbox.checked ? TextInput.Normal : TextInput.Password
|
echoMode: showPasswordCheckbox.checked ? TextInput.Normal : TextInput.Password
|
||||||
placeholderText: ""
|
placeholderText: requiresEnterprise ? "Password" : ""
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
focus: true
|
focus: !requiresEnterprise
|
||||||
enabled: root.shouldBeVisible
|
enabled: root.shouldBeVisible
|
||||||
onTextEdited: () => {
|
onTextEdited: () => {
|
||||||
wifiPasswordInput = text
|
wifiPasswordInput = text
|
||||||
}
|
}
|
||||||
onAccepted: () => {
|
onAccepted: () => {
|
||||||
NetworkService.connectToWifi(wifiPasswordSSID, passwordInput.text)
|
const username = requiresEnterprise ? usernameInput.text : ""
|
||||||
|
NetworkService.connectToWifi(wifiPasswordSSID, passwordInput.text, username)
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
|
wifiUsernameInput = ""
|
||||||
passwordInput.text = ""
|
passwordInput.text = ""
|
||||||
|
if (requiresEnterprise) usernameInput.text = ""
|
||||||
}
|
}
|
||||||
Component.onCompleted: () => {
|
Component.onCompleted: () => {
|
||||||
if (root.shouldBeVisible)
|
if (root.shouldBeVisible && !requiresEnterprise)
|
||||||
focusDelayTimer.start()
|
focusDelayTimer.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,8 +214,13 @@ DankModal {
|
|||||||
interval: 100
|
interval: 100
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: () => {
|
onTriggered: () => {
|
||||||
if (root.shouldBeVisible)
|
if (root.shouldBeVisible) {
|
||||||
passwordInput.forceActiveFocus()
|
if (requiresEnterprise && usernameInput) {
|
||||||
|
usernameInput.forceActiveFocus()
|
||||||
|
} else {
|
||||||
|
passwordInput.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +269,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Show password"
|
text: I18n.tr("Show password")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -229,7 +297,7 @@ DankModal {
|
|||||||
id: cancelText
|
id: cancelText
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Cancel"
|
text: I18n.tr("Cancel")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -244,6 +312,7 @@ DankModal {
|
|||||||
onClicked: () => {
|
onClicked: () => {
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
|
wifiUsernameInput = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,14 +322,14 @@ DankModal {
|
|||||||
height: 36
|
height: 36
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: connectArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
|
color: connectArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
|
||||||
enabled: passwordInput.text.length > 0
|
enabled: requiresEnterprise ? (usernameInput.text.length > 0 && passwordInput.text.length > 0) : passwordInput.text.length > 0
|
||||||
opacity: enabled ? 1 : 0.5
|
opacity: enabled ? 1 : 0.5
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: connectText
|
id: connectText
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Connect"
|
text: I18n.tr("Connect")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.background
|
color: Theme.background
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -274,10 +343,13 @@ DankModal {
|
|||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
enabled: parent.enabled
|
enabled: parent.enabled
|
||||||
onClicked: () => {
|
onClicked: () => {
|
||||||
NetworkService.connectToWifi(wifiPasswordSSID, passwordInput.text)
|
const username = requiresEnterprise ? usernameInput.text : ""
|
||||||
|
NetworkService.connectToWifi(wifiPasswordSSID, passwordInput.text, username)
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
|
wifiUsernameInput = ""
|
||||||
passwordInput.text = ""
|
passwordInput.text = ""
|
||||||
|
if (requiresEnterprise) usernameInput.text = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
@@ -41,7 +42,7 @@ DankPopout {
|
|||||||
if (shouldBeVisible) {
|
if (shouldBeVisible) {
|
||||||
appLauncher.searchQuery = ""
|
appLauncher.searchQuery = ""
|
||||||
appLauncher.selectedIndex = 0
|
appLauncher.selectedIndex = 0
|
||||||
appLauncher.setCategory("All")
|
appLauncher.setCategory(I18n.tr("All"))
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (contentLoader.item && contentLoader.item.searchField) {
|
if (contentLoader.item && contentLoader.item.searchField) {
|
||||||
contentLoader.item.searchField.text = ""
|
contentLoader.item.searchField.text = ""
|
||||||
@@ -165,11 +166,6 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!searchField.activeFocus && event.text && /[a-zA-Z0-9\s]/.test(event.text)) {
|
|
||||||
searchField.forceActiveFocus()
|
|
||||||
searchField.insertText(event.text)
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -179,25 +175,23 @@ DankPopout {
|
|||||||
y: Theme.spacingS
|
y: Theme.spacingS
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
Row {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 40
|
height: 40
|
||||||
leftPadding: Theme.spacingS
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: "Applications"
|
text: I18n.tr("Applications")
|
||||||
font.pixelSize: Theme.fontSizeLarge + 4
|
font.pixelSize: Theme.fontSizeLarge + 4
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
|
||||||
width: parent.width - 200
|
|
||||||
height: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: appLauncher.model.count + " apps"
|
text: appLauncher.model.count + " apps"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
@@ -222,7 +216,7 @@ DankPopout {
|
|||||||
showClearButton: true
|
showClearButton: true
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
enabled: appDrawerPopout.shouldBeVisible
|
enabled: appDrawerPopout.shouldBeVisible
|
||||||
ignoreLeftRightKeys: true
|
ignoreLeftRightKeys: appLauncher.viewMode !== "list"
|
||||||
keyForwardTargets: [keyHandler]
|
keyForwardTargets: [keyHandler]
|
||||||
onTextEdited: {
|
onTextEdited: {
|
||||||
appLauncher.searchQuery = text
|
appLauncher.searchQuery = text
|
||||||
@@ -488,7 +482,8 @@ DankPopout {
|
|||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
appList.itemClicked(index, model)
|
appList.itemClicked(index, model)
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
var panelPos = mapToItem(contextMenu.parent, mouse.x, mouse.y)
|
var globalPos = mapToItem(null, mouse.x, mouse.y)
|
||||||
|
var panelPos = contextMenu.parent.mapFromItem(null, globalPos.x, globalPos.y)
|
||||||
appList.itemRightClicked(index, model, panelPos.x, panelPos.y)
|
appList.itemRightClicked(index, model, panelPos.x, panelPos.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -649,7 +644,8 @@ DankPopout {
|
|||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
appGrid.itemClicked(index, model)
|
appGrid.itemClicked(index, model)
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
var panelPos = mapToItem(contextMenu.parent, mouse.x, mouse.y)
|
var globalPos = mapToItem(null, mouse.x, mouse.y)
|
||||||
|
var panelPos = contextMenu.parent.mapFromItem(null, globalPos.x, globalPos.y)
|
||||||
appGrid.itemRightClicked(index, model, panelPos.x, panelPos.y)
|
appGrid.itemRightClicked(index, model, panelPos.x, panelPos.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -662,68 +658,68 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Popup {
|
||||||
id: contextMenu
|
id: contextMenu
|
||||||
|
|
||||||
property var currentApp: null
|
property var currentApp: null
|
||||||
property bool menuVisible: false
|
|
||||||
|
|
||||||
readonly property string appId: (currentApp && currentApp.desktopEntry) ? (currentApp.desktopEntry.id || currentApp.desktopEntry.execString || "") : ""
|
readonly property string appId: (currentApp && currentApp.desktopEntry) ? (currentApp.desktopEntry.id || currentApp.desktopEntry.execString || "") : ""
|
||||||
readonly property bool isPinned: appId && SessionData.isPinnedApp(appId)
|
readonly property bool isPinned: appId && SessionData.isPinnedApp(appId)
|
||||||
|
|
||||||
function show(x, y, app) {
|
function show(x, y, app) {
|
||||||
currentApp = app
|
currentApp = app
|
||||||
|
contextMenu.x = x + 4
|
||||||
const menuWidth = 180
|
contextMenu.y = y + 4
|
||||||
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
|
contextMenu.open()
|
||||||
|
|
||||||
let finalX = x + 8
|
|
||||||
let finalY = y + 8
|
|
||||||
|
|
||||||
if (finalX + menuWidth > appDrawerPopout.popupWidth) {
|
|
||||||
finalX = x - menuWidth - 8
|
|
||||||
}
|
|
||||||
|
|
||||||
if (finalY + menuHeight > appDrawerPopout.popupHeight) {
|
|
||||||
finalY = y - menuHeight - 8
|
|
||||||
}
|
|
||||||
|
|
||||||
finalX = Math.max(8, Math.min(finalX, appDrawerPopout.popupWidth - menuWidth - 8))
|
|
||||||
finalY = Math.max(8, Math.min(finalY, appDrawerPopout.popupHeight - menuHeight - 8))
|
|
||||||
|
|
||||||
contextMenu.x = finalX
|
|
||||||
contextMenu.y = finalY
|
|
||||||
contextMenu.visible = true
|
|
||||||
contextMenu.menuVisible = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function hide() {
|
||||||
contextMenu.menuVisible = false
|
contextMenu.close()
|
||||||
Qt.callLater(() => {
|
|
||||||
contextMenu.visible = false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visible: false
|
width: Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2)
|
||||||
width: 180
|
|
||||||
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
||||||
radius: Theme.cornerRadius
|
padding: 0
|
||||||
color: Theme.popupBackground()
|
closePolicy: Popup.CloseOnPressOutside
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
modal: false
|
||||||
border.width: 0
|
dim: false
|
||||||
z: 1000
|
|
||||||
opacity: menuVisible ? 1 : 0
|
|
||||||
scale: menuVisible ? 1 : 0.85
|
|
||||||
|
|
||||||
Rectangle {
|
background: Rectangle {
|
||||||
anchors.fill: parent
|
radius: Theme.cornerRadius
|
||||||
anchors.topMargin: 4
|
color: Theme.popupBackground()
|
||||||
anchors.leftMargin: 2
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
anchors.rightMargin: -2
|
border.width: 1
|
||||||
anchors.bottomMargin: -4
|
|
||||||
radius: parent.radius
|
Rectangle {
|
||||||
color: Qt.rgba(0, 0, 0, 0.15)
|
anchors.fill: parent
|
||||||
z: parent.z - 1
|
anchors.topMargin: 4
|
||||||
|
anchors.leftMargin: 2
|
||||||
|
anchors.rightMargin: -2
|
||||||
|
anchors.bottomMargin: -4
|
||||||
|
radius: parent.radius
|
||||||
|
color: Qt.rgba(0, 0, 0, 0.15)
|
||||||
|
z: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enter: Transition {
|
||||||
|
NumberAnimation {
|
||||||
|
property: "opacity"
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.emphasizedEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit: Transition {
|
||||||
|
NumberAnimation {
|
||||||
|
property: "opacity"
|
||||||
|
from: 1
|
||||||
|
to: 0
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.emphasizedEasing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -754,7 +750,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: contextMenu.isPinned ? "Unpin from Dock" : "Pin to Dock"
|
text: contextMenu.isPinned ? I18n.tr("Unpin from Dock") : I18n.tr("Pin to Dock")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
@@ -778,7 +774,7 @@ DankPopout {
|
|||||||
} else {
|
} else {
|
||||||
SessionData.addPinnedApp(contextMenu.appId)
|
SessionData.addPinnedApp(contextMenu.appId)
|
||||||
}
|
}
|
||||||
contextMenu.close()
|
contextMenu.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -797,6 +793,76 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: contextMenu.currentApp && contextMenu.currentApp.desktopEntry && contextMenu.currentApp.desktopEntry.actions ? contextMenu.currentApp.desktopEntry.actions : []
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 32
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: actionMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: Theme.iconSize - 2
|
||||||
|
height: Theme.iconSize - 2
|
||||||
|
visible: modelData.icon && modelData.icon !== ""
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: modelData.icon ? Quickshell.iconPath(modelData.icon, true) : ""
|
||||||
|
smooth: true
|
||||||
|
asynchronous: true
|
||||||
|
visible: status === Image.Ready
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: modelData.name || ""
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Normal
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: actionMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
if (modelData && contextMenu.currentApp && contextMenu.currentApp.desktopEntry) {
|
||||||
|
SessionService.launchDesktopAction(contextMenu.currentApp.desktopEntry, modelData)
|
||||||
|
appLauncher.appLaunched(contextMenu.currentApp)
|
||||||
|
}
|
||||||
|
contextMenu.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: contextMenu.currentApp && contextMenu.currentApp.desktopEntry && contextMenu.currentApp.desktopEntry.actions && contextMenu.currentApp.desktopEntry.actions.length > 0
|
||||||
|
width: parent.width - Theme.spacingS * 2
|
||||||
|
height: 5
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 32
|
height: 32
|
||||||
@@ -818,7 +884,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Launch"
|
text: I18n.tr("Launch")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
@@ -836,23 +902,70 @@ DankPopout {
|
|||||||
if (contextMenu.currentApp)
|
if (contextMenu.currentApp)
|
||||||
appLauncher.launchApp(contextMenu.currentApp)
|
appLauncher.launchApp(contextMenu.currentApp)
|
||||||
|
|
||||||
contextMenu.close()
|
contextMenu.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on opacity {
|
Rectangle {
|
||||||
NumberAnimation {
|
visible: SessionService.hasPrimeRun
|
||||||
duration: Theme.mediumDuration
|
width: parent.width - Theme.spacingS * 2
|
||||||
easing.type: Theme.emphasizedEasing
|
height: 5
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on scale {
|
Rectangle {
|
||||||
NumberAnimation {
|
visible: SessionService.hasPrimeRun
|
||||||
duration: Theme.mediumDuration
|
width: parent.width
|
||||||
easing.type: Theme.emphasizedEasing
|
height: 32
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: primeRunMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "memory"
|
||||||
|
size: Theme.iconSize - 2
|
||||||
|
color: Theme.surfaceText
|
||||||
|
opacity: 0.7
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Launch on dGPU")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Normal
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: primeRunMouseArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
if (contextMenu.currentApp && contextMenu.currentApp.desktopEntry) {
|
||||||
|
SessionService.launchDesktopEntry(contextMenu.currentApp.desktopEntry, true)
|
||||||
|
appLauncher.appLaunched(contextMenu.currentApp)
|
||||||
|
}
|
||||||
|
contextMenu.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -862,7 +975,7 @@ DankPopout {
|
|||||||
visible: contextMenu.visible
|
visible: contextMenu.visible
|
||||||
z: 999
|
z: 999
|
||||||
onClicked: {
|
onClicked: {
|
||||||
contextMenu.close()
|
contextMenu.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Item {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string searchQuery: ""
|
property string searchQuery: ""
|
||||||
property string selectedCategory: "All"
|
property string selectedCategory: I18n.tr("All")
|
||||||
property string viewMode: "list" // "list" or "grid"
|
property string viewMode: "list" // "list" or "grid"
|
||||||
property int selectedIndex: 0
|
property int selectedIndex: 0
|
||||||
property int maxResults: 50
|
property int maxResults: 50
|
||||||
@@ -20,8 +20,8 @@ Item {
|
|||||||
property bool suppressUpdatesWhileLaunching: false
|
property bool suppressUpdatesWhileLaunching: false
|
||||||
readonly property var categories: {
|
readonly property var categories: {
|
||||||
const allCategories = AppSearchService.getAllCategories().filter(cat => cat !== "Education" && cat !== "Science")
|
const allCategories = AppSearchService.getAllCategories().filter(cat => cat !== "Education" && cat !== "Science")
|
||||||
const result = ["All"]
|
const result = [I18n.tr("All")]
|
||||||
return result.concat(allCategories.filter(cat => cat !== "All"))
|
return result.concat(allCategories.filter(cat => cat !== I18n.tr("All")))
|
||||||
}
|
}
|
||||||
readonly property var categoryIcons: categories.map(category => AppSearchService.getCategoryIcon(category))
|
readonly property var categoryIcons: categories.map(category => AppSearchService.getCategoryIcon(category))
|
||||||
property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {}
|
property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {}
|
||||||
@@ -42,10 +42,11 @@ Item {
|
|||||||
keyboardNavigationActive = false
|
keyboardNavigationActive = false
|
||||||
|
|
||||||
let apps = []
|
let apps = []
|
||||||
|
const allCategory = I18n.tr("All")
|
||||||
if (searchQuery.length === 0) {
|
if (searchQuery.length === 0) {
|
||||||
apps = selectedCategory === "All" ? AppSearchService.getAppsInCategory("All") : AppSearchService.getAppsInCategory(selectedCategory).slice(0, maxResults)
|
apps = selectedCategory === allCategory ? AppSearchService.getAppsInCategory(allCategory) : AppSearchService.getAppsInCategory(selectedCategory).slice(0, maxResults)
|
||||||
} else {
|
} else {
|
||||||
if (selectedCategory === "All") {
|
if (selectedCategory === allCategory) {
|
||||||
apps = AppSearchService.searchApplications(searchQuery)
|
apps = AppSearchService.searchApplications(searchQuery)
|
||||||
} else {
|
} else {
|
||||||
const categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
|
const categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var categories: []
|
property var categories: []
|
||||||
property string selectedCategory: "All"
|
property string selectedCategory: I18n.tr("All")
|
||||||
property bool compact: false
|
property bool compact: false
|
||||||
|
|
||||||
signal categorySelected(string category)
|
signal categorySelected(string category)
|
||||||
@@ -18,7 +19,6 @@ Item {
|
|||||||
readonly property color unselectedBorderColor: "transparent"
|
readonly property color unselectedBorderColor: "transparent"
|
||||||
|
|
||||||
function handleCategoryClick(category) {
|
function handleCategoryClick(category) {
|
||||||
selectedCategory = category
|
|
||||||
categorySelected(category)
|
categorySelected(category)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
246
Modules/ControlCenter/BuiltinPlugins/VpnWidget.qml
Normal file
246
Modules/ControlCenter/BuiltinPlugins/VpnWidget.qml
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
import qs.Modules.Plugins
|
||||||
|
|
||||||
|
PluginComponent {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
Ref {
|
||||||
|
service: VpnService
|
||||||
|
}
|
||||||
|
|
||||||
|
ccWidgetIcon: VpnService.isBusy ? "sync" : (VpnService.connected ? "vpn_lock" : "vpn_key_off")
|
||||||
|
ccWidgetPrimaryText: "VPN"
|
||||||
|
ccWidgetSecondaryText: {
|
||||||
|
if (!VpnService.connected)
|
||||||
|
return "Disconnected"
|
||||||
|
const names = VpnService.activeNames || []
|
||||||
|
if (names.length <= 1)
|
||||||
|
return names[0] || "Connected"
|
||||||
|
return names[0] + " +" + (names.length - 1)
|
||||||
|
}
|
||||||
|
ccWidgetIsActive: VpnService.connected
|
||||||
|
|
||||||
|
onCcWidgetToggled: {
|
||||||
|
if (VpnService.connected) {
|
||||||
|
VpnService.disconnectAllActive()
|
||||||
|
} else if (VpnService.profiles.length > 0) {
|
||||||
|
VpnService.connect(VpnService.profiles[0].uuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ccDetailContent: Component {
|
||||||
|
Rectangle {
|
||||||
|
id: detailRoot
|
||||||
|
implicitHeight: detailColumn.implicitHeight + Theme.spacingM * 2
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Theme.surfaceContainerHigh
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: detailColumn
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingM
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: {
|
||||||
|
if (!VpnService.connected)
|
||||||
|
return "Active: None"
|
||||||
|
const names = VpnService.activeNames || []
|
||||||
|
if (names.length <= 1)
|
||||||
|
return "Active: " + (names[0] || "VPN")
|
||||||
|
return "Active: " + names[0] + " +" + (names.length - 1)
|
||||||
|
}
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
height: 28
|
||||||
|
radius: 14
|
||||||
|
color: discAllArea.containsMouse ? Theme.errorHover : Theme.surfaceLight
|
||||||
|
visible: VpnService.connected
|
||||||
|
width: 110
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "link_off"
|
||||||
|
size: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Disconnect")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: discAllArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: VpnService.disconnectAllActive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
height: 1
|
||||||
|
width: parent.width
|
||||||
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
|
}
|
||||||
|
|
||||||
|
DankFlickable {
|
||||||
|
width: parent.width
|
||||||
|
height: 160
|
||||||
|
contentHeight: listCol.height
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: listCol
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width
|
||||||
|
height: VpnService.profiles.length === 0 ? 120 : 0
|
||||||
|
visible: height > 0
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "playlist_remove"
|
||||||
|
size: 36
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("No VPN profiles found")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Add a VPN in NetworkManager")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: VpnService.profiles
|
||||||
|
|
||||||
|
delegate: Rectangle {
|
||||||
|
required property var modelData
|
||||||
|
|
||||||
|
width: parent ? parent.width : 300
|
||||||
|
height: 50
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: rowArea.containsMouse ? Theme.primaryHoverLight : (VpnService.isActiveUuid(modelData.uuid) ? Theme.primaryPressed : Theme.surfaceLight)
|
||||||
|
border.width: VpnService.isActiveUuid(modelData.uuid) ? 2 : 1
|
||||||
|
border.color: VpnService.isActiveUuid(modelData.uuid) ? Theme.primary : Theme.outlineLight
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: Theme.spacingM
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: VpnService.isActiveUuid(modelData.uuid) ? "vpn_lock" : "vpn_key_off"
|
||||||
|
size: Theme.iconSize - 4
|
||||||
|
color: VpnService.isActiveUuid(modelData.uuid) ? Theme.primary : Theme.surfaceText
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
spacing: 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: modelData.name
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: VpnService.isActiveUuid(modelData.uuid) ? Theme.primary : Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: {
|
||||||
|
if (modelData.type === "wireguard")
|
||||||
|
return "WireGuard"
|
||||||
|
const svc = modelData.serviceType || ""
|
||||||
|
if (svc.indexOf("openvpn") !== -1)
|
||||||
|
return "OpenVPN"
|
||||||
|
if (svc.indexOf("wireguard") !== -1)
|
||||||
|
return "WireGuard (plugin)"
|
||||||
|
if (svc.indexOf("openconnect") !== -1)
|
||||||
|
return "OpenConnect"
|
||||||
|
if (svc.indexOf("fortissl") !== -1 || svc.indexOf("forti") !== -1)
|
||||||
|
return "Fortinet"
|
||||||
|
if (svc.indexOf("strongswan") !== -1)
|
||||||
|
return "IPsec (strongSwan)"
|
||||||
|
if (svc.indexOf("libreswan") !== -1)
|
||||||
|
return "IPsec (Libreswan)"
|
||||||
|
if (svc.indexOf("l2tp") !== -1)
|
||||||
|
return "L2TP/IPsec"
|
||||||
|
if (svc.indexOf("pptp") !== -1)
|
||||||
|
return "PPTP"
|
||||||
|
if (svc.indexOf("vpnc") !== -1)
|
||||||
|
return "Cisco (vpnc)"
|
||||||
|
if (svc.indexOf("sstp") !== -1)
|
||||||
|
return "SSTP"
|
||||||
|
if (svc)
|
||||||
|
return svc.split('.').pop()
|
||||||
|
return "VPN"
|
||||||
|
}
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: rowArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: VpnService.toggle(modelData.uuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
import qs.Modules.ControlCenter.Details
|
import qs.Modules.ControlCenter.Details
|
||||||
|
import qs.Modules.ControlCenter.Models
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -9,31 +11,97 @@ Item {
|
|||||||
property var expandedWidgetData: null
|
property var expandedWidgetData: null
|
||||||
property var bluetoothCodecSelector: null
|
property var bluetoothCodecSelector: null
|
||||||
|
|
||||||
|
property var pluginDetailInstance: null
|
||||||
|
property var widgetModel: null
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
|
id: pluginDetailLoader
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 250
|
height: 250
|
||||||
y: Theme.spacingS
|
y: Theme.spacingS
|
||||||
active: parent.height > 0
|
active: false
|
||||||
property string sectionKey: root.expandedSection
|
sourceComponent: null
|
||||||
sourceComponent: {
|
}
|
||||||
switch (root.expandedSection) {
|
|
||||||
case "network":
|
Loader {
|
||||||
case "wifi": return networkDetailComponent
|
id: coreDetailLoader
|
||||||
case "bluetooth": return bluetoothDetailComponent
|
width: parent.width
|
||||||
case "audioOutput": return audioOutputDetailComponent
|
height: 250
|
||||||
case "audioInput": return audioInputDetailComponent
|
y: Theme.spacingS
|
||||||
case "battery": return batteryDetailComponent
|
active: false
|
||||||
default:
|
sourceComponent: null
|
||||||
if (root.expandedSection.startsWith("diskUsage_")) {
|
}
|
||||||
return diskUsageDetailComponent
|
|
||||||
|
onExpandedSectionChanged: {
|
||||||
|
if (pluginDetailInstance) {
|
||||||
|
pluginDetailInstance.destroy()
|
||||||
|
pluginDetailInstance = null
|
||||||
|
}
|
||||||
|
pluginDetailLoader.active = false
|
||||||
|
coreDetailLoader.active = false
|
||||||
|
|
||||||
|
if (!root.expandedSection) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.expandedSection.startsWith("builtin_")) {
|
||||||
|
const builtinId = root.expandedSection
|
||||||
|
let builtinInstance = null
|
||||||
|
|
||||||
|
if (builtinId === "builtin_vpn") {
|
||||||
|
if (widgetModel?.vpnLoader) {
|
||||||
|
widgetModel.vpnLoader.active = true
|
||||||
}
|
}
|
||||||
return null
|
builtinInstance = widgetModel.vpnBuiltinInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!builtinInstance || !builtinInstance.ccDetailContent) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginDetailLoader.sourceComponent = builtinInstance.ccDetailContent
|
||||||
|
pluginDetailLoader.active = parent.height > 0
|
||||||
|
return
|
||||||
}
|
}
|
||||||
onSectionKeyChanged: {
|
|
||||||
active = false
|
if (root.expandedSection.startsWith("plugin_")) {
|
||||||
active = true
|
const pluginId = root.expandedSection.replace("plugin_", "")
|
||||||
|
const pluginComponent = PluginService.pluginWidgetComponents[pluginId]
|
||||||
|
if (!pluginComponent) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginDetailInstance = pluginComponent.createObject(null)
|
||||||
|
if (!pluginDetailInstance || !pluginDetailInstance.ccDetailContent) {
|
||||||
|
if (pluginDetailInstance) {
|
||||||
|
pluginDetailInstance.destroy()
|
||||||
|
pluginDetailInstance = null
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginDetailLoader.sourceComponent = pluginDetailInstance.ccDetailContent
|
||||||
|
pluginDetailLoader.active = parent.height > 0
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root.expandedSection.startsWith("diskUsage_")) {
|
||||||
|
coreDetailLoader.sourceComponent = diskUsageDetailComponent
|
||||||
|
coreDetailLoader.active = parent.height > 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (root.expandedSection) {
|
||||||
|
case "network":
|
||||||
|
case "wifi": coreDetailLoader.sourceComponent = networkDetailComponent; break
|
||||||
|
case "bluetooth": coreDetailLoader.sourceComponent = bluetoothDetailComponent; break
|
||||||
|
case "audioOutput": coreDetailLoader.sourceComponent = audioOutputDetailComponent; break
|
||||||
|
case "audioInput": coreDetailLoader.sourceComponent = audioInputDetailComponent; break
|
||||||
|
case "battery": coreDetailLoader.sourceComponent = batteryDetailComponent; break
|
||||||
|
default: return
|
||||||
|
}
|
||||||
|
|
||||||
|
coreDetailLoader.active = parent.height > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ Column {
|
|||||||
property var rowWidgets: modelData
|
property var rowWidgets: modelData
|
||||||
property bool isSliderOnlyRow: {
|
property bool isSliderOnlyRow: {
|
||||||
const widgets = rowWidgets || []
|
const widgets = rowWidgets || []
|
||||||
if (widgets.length === 0) return false
|
if (widgets.length === 0)
|
||||||
|
return false
|
||||||
return widgets.every(w => w.id === "volumeSlider" || w.id === "brightnessSlider" || w.id === "inputVolumeSlider")
|
return widgets.every(w => w.id === "volumeSlider" || w.id === "brightnessSlider" || w.id === "inputVolumeSlider")
|
||||||
}
|
}
|
||||||
topPadding: isSliderOnlyRow ? (root.editMode ? 4 : -6) : 0
|
topPadding: isSliderOnlyRow ? (root.editMode ? 4 : -6) : 0
|
||||||
@@ -121,7 +122,11 @@ Column {
|
|||||||
|
|
||||||
widgetComponent: {
|
widgetComponent: {
|
||||||
const id = modelData.id || ""
|
const id = modelData.id || ""
|
||||||
if (id === "wifi" || id === "bluetooth" || id === "audioOutput" || id === "audioInput") {
|
if (id.startsWith("builtin_")) {
|
||||||
|
return builtinPluginWidgetComponent
|
||||||
|
} else if (id.startsWith("plugin_")) {
|
||||||
|
return pluginWidgetComponent
|
||||||
|
} else if (id === "wifi" || id === "bluetooth" || id === "audioOutput" || id === "audioInput") {
|
||||||
return compoundPillComponent
|
return compoundPillComponent
|
||||||
} else if (id === "volumeSlider") {
|
} else if (id === "volumeSlider") {
|
||||||
return audioSliderComponent
|
return audioSliderComponent
|
||||||
@@ -151,7 +156,8 @@ Column {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: active ? (250 + Theme.spacingS) : 0
|
height: active ? (250 + Theme.spacingS) : 0
|
||||||
property bool active: {
|
property bool active: {
|
||||||
if (root.expandedSection === "") return false
|
if (root.expandedSection === "")
|
||||||
|
return false
|
||||||
|
|
||||||
if (root.expandedSection.startsWith("diskUsage_") && root.expandedWidgetData) {
|
if (root.expandedSection.startsWith("diskUsage_") && root.expandedWidgetData) {
|
||||||
const expandedInstanceId = root.expandedWidgetData.instanceId
|
const expandedInstanceId = root.expandedWidgetData.instanceId
|
||||||
@@ -164,10 +170,27 @@ Column {
|
|||||||
expandedSection: root.expandedSection
|
expandedSection: root.expandedSection
|
||||||
expandedWidgetData: root.expandedWidgetData
|
expandedWidgetData: root.expandedWidgetData
|
||||||
bluetoothCodecSelector: root.bluetoothCodecSelector
|
bluetoothCodecSelector: root.bluetoothCodecSelector
|
||||||
|
widgetModel: root.model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: errorPillComponent
|
||||||
|
ErrorPill {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
width: parent.width
|
||||||
|
height: 60
|
||||||
|
primaryMessage: {
|
||||||
|
if (!DMSService.dmsAvailable) {
|
||||||
|
return I18n.tr("DMS_SOCKET not available")
|
||||||
|
}
|
||||||
|
return I18n.tr("NM not supported")
|
||||||
|
}
|
||||||
|
secondaryMessage: I18n.tr("update dms for NM integration.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: compoundPillComponent
|
id: compoundPillComponent
|
||||||
CompoundPill {
|
CompoundPill {
|
||||||
@@ -345,7 +368,8 @@ Column {
|
|||||||
}
|
}
|
||||||
enabled: widgetDef?.enabled ?? true
|
enabled: widgetDef?.enabled ?? true
|
||||||
onToggled: {
|
onToggled: {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
switch (widgetData.id || "") {
|
switch (widgetData.id || "") {
|
||||||
case "wifi":
|
case "wifi":
|
||||||
{
|
{
|
||||||
@@ -378,11 +402,13 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onExpandClicked: {
|
onExpandClicked: {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
root.expandClicked(widgetData, widgetIndex)
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
}
|
}
|
||||||
onWheelEvent: function (wheelEvent) {
|
onWheelEvent: function (wheelEvent) {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
const id = widgetData.id || ""
|
const id = widgetData.id || ""
|
||||||
if (id === "audioOutput") {
|
if (id === "audioOutput") {
|
||||||
if (!AudioService.sink || !AudioService.sink.audio)
|
if (!AudioService.sink || !AudioService.sink.audio)
|
||||||
@@ -537,9 +563,10 @@ Column {
|
|||||||
}
|
}
|
||||||
|
|
||||||
iconRotation: {
|
iconRotation: {
|
||||||
if (widgetData.id !== "darkMode") return 0
|
if (widgetData.id !== "darkMode")
|
||||||
|
return 0
|
||||||
if (darkModeTransitionPending) {
|
if (darkModeTransitionPending) {
|
||||||
return SessionData.isLightMode ? 0 : 180
|
return SessionData.isLightMode ? 180 : 0
|
||||||
}
|
}
|
||||||
return SessionData.isLightMode ? 180 : 0
|
return SessionData.isLightMode ? 180 : 0
|
||||||
}
|
}
|
||||||
@@ -549,7 +576,7 @@ Column {
|
|||||||
case "nightMode":
|
case "nightMode":
|
||||||
return DisplayService.nightModeEnabled || false
|
return DisplayService.nightModeEnabled || false
|
||||||
case "darkMode":
|
case "darkMode":
|
||||||
return !SessionData.isLightMode
|
return SessionData.isLightMode
|
||||||
case "doNotDisturb":
|
case "doNotDisturb":
|
||||||
return SessionData.doNotDisturb || false
|
return SessionData.doNotDisturb || false
|
||||||
case "idleInhibitor":
|
case "idleInhibitor":
|
||||||
@@ -559,15 +586,7 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enabled: !root.editMode
|
enabled: !root.editMode
|
||||||
|
|
||||||
onIconRotationCompleted: {
|
|
||||||
if (root.darkModeTransitionPending && widgetData.id === "darkMode") {
|
|
||||||
root.darkModeTransitionPending = false
|
|
||||||
Theme.screenTransition()
|
|
||||||
Theme.toggleLightMode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.editMode)
|
if (root.editMode)
|
||||||
@@ -581,7 +600,8 @@ enabled: !root.editMode
|
|||||||
}
|
}
|
||||||
case "darkMode":
|
case "darkMode":
|
||||||
{
|
{
|
||||||
root.darkModeTransitionPending = true
|
Theme.screenTransition()
|
||||||
|
Theme.setLightMode(!SessionData.isLightMode)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case "doNotDisturb":
|
case "doNotDisturb":
|
||||||
@@ -623,9 +643,10 @@ enabled: !root.editMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
iconRotation: {
|
iconRotation: {
|
||||||
if (widgetData.id !== "darkMode") return 0
|
if (widgetData.id !== "darkMode")
|
||||||
|
return 0
|
||||||
if (darkModeTransitionPending) {
|
if (darkModeTransitionPending) {
|
||||||
return SessionData.isLightMode ? 0 : 180
|
return SessionData.isLightMode ? 180 : 0
|
||||||
}
|
}
|
||||||
return SessionData.isLightMode ? 180 : 0
|
return SessionData.isLightMode ? 180 : 0
|
||||||
}
|
}
|
||||||
@@ -635,7 +656,7 @@ enabled: !root.editMode
|
|||||||
case "nightMode":
|
case "nightMode":
|
||||||
return DisplayService.nightModeEnabled || false
|
return DisplayService.nightModeEnabled || false
|
||||||
case "darkMode":
|
case "darkMode":
|
||||||
return !SessionData.isLightMode
|
return SessionData.isLightMode
|
||||||
case "doNotDisturb":
|
case "doNotDisturb":
|
||||||
return SessionData.doNotDisturb || false
|
return SessionData.doNotDisturb || false
|
||||||
case "idleInhibitor":
|
case "idleInhibitor":
|
||||||
@@ -645,15 +666,7 @@ enabled: !root.editMode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enabled: !root.editMode
|
enabled: !root.editMode
|
||||||
|
|
||||||
onIconRotationCompleted: {
|
|
||||||
if (root.darkModeTransitionPending && widgetData.id === "darkMode") {
|
|
||||||
root.darkModeTransitionPending = false
|
|
||||||
Theme.screenTransition()
|
|
||||||
Theme.toggleLightMode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.editMode)
|
if (root.editMode)
|
||||||
@@ -667,7 +680,8 @@ enabled: !root.editMode
|
|||||||
}
|
}
|
||||||
case "darkMode":
|
case "darkMode":
|
||||||
{
|
{
|
||||||
root.darkModeTransitionPending = true
|
Theme.screenTransition()
|
||||||
|
Theme.setLightMode(!SessionData.isLightMode)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case "doNotDisturb":
|
case "doNotDisturb":
|
||||||
@@ -715,4 +729,251 @@ enabled: !root.editMode
|
|||||||
colorPickerModal: root.colorPickerModal
|
colorPickerModal: root.colorPickerModal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: builtinPluginWidgetComponent
|
||||||
|
Loader {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property int widgetWidth: widgetData.width || 50
|
||||||
|
width: parent.width
|
||||||
|
height: 60
|
||||||
|
|
||||||
|
property var builtinInstance: null
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
const id = widgetData.id || ""
|
||||||
|
if (id === "builtin_vpn") {
|
||||||
|
if (root.model?.vpnLoader) {
|
||||||
|
root.model.vpnLoader.active = true
|
||||||
|
}
|
||||||
|
builtinInstance = Qt.binding(() => root.model?.vpnBuiltinInstance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceComponent: {
|
||||||
|
if (!builtinInstance)
|
||||||
|
return null
|
||||||
|
|
||||||
|
const hasDetail = builtinInstance.ccDetailContent !== null
|
||||||
|
|
||||||
|
if (widgetWidth <= 25) {
|
||||||
|
return builtinSmallToggleComponent
|
||||||
|
} else if (hasDetail) {
|
||||||
|
return builtinCompoundPillComponent
|
||||||
|
} else {
|
||||||
|
return builtinToggleComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: builtinCompoundPillComponent
|
||||||
|
CompoundPill {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var builtinInstance: parent.builtinInstance
|
||||||
|
|
||||||
|
iconName: builtinInstance?.ccWidgetIcon || "extension"
|
||||||
|
primaryText: builtinInstance?.ccWidgetPrimaryText || "Built-in"
|
||||||
|
secondaryText: builtinInstance?.ccWidgetSecondaryText || ""
|
||||||
|
isActive: builtinInstance?.ccWidgetIsActive || false
|
||||||
|
|
||||||
|
onToggled: {
|
||||||
|
if (root.editMode)
|
||||||
|
return
|
||||||
|
if (builtinInstance) {
|
||||||
|
builtinInstance.ccWidgetToggled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExpandClicked: {
|
||||||
|
if (root.editMode)
|
||||||
|
return
|
||||||
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: builtinToggleComponent
|
||||||
|
ToggleButton {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var builtinInstance: parent.builtinInstance
|
||||||
|
|
||||||
|
iconName: builtinInstance?.ccWidgetIcon || "extension"
|
||||||
|
text: builtinInstance?.ccWidgetPrimaryText || "Built-in"
|
||||||
|
isActive: builtinInstance?.ccWidgetIsActive || false
|
||||||
|
enabled: !root.editMode
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.editMode)
|
||||||
|
return
|
||||||
|
if (builtinInstance) {
|
||||||
|
builtinInstance.ccWidgetToggled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: builtinSmallToggleComponent
|
||||||
|
SmallToggleButton {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var builtinInstance: parent.builtinInstance
|
||||||
|
|
||||||
|
iconName: builtinInstance?.ccWidgetIcon || "extension"
|
||||||
|
isActive: builtinInstance?.ccWidgetIsActive || false
|
||||||
|
enabled: !root.editMode
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.editMode)
|
||||||
|
return
|
||||||
|
if (builtinInstance) {
|
||||||
|
builtinInstance.ccWidgetToggled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: pluginWidgetComponent
|
||||||
|
Loader {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property int widgetWidth: widgetData.width || 50
|
||||||
|
width: parent.width
|
||||||
|
height: 60
|
||||||
|
|
||||||
|
property var pluginInstance: null
|
||||||
|
property string pluginId: widgetData.id?.replace("plugin_", "") || ""
|
||||||
|
|
||||||
|
sourceComponent: {
|
||||||
|
if (!pluginInstance)
|
||||||
|
return null
|
||||||
|
|
||||||
|
const hasDetail = pluginInstance.ccDetailContent !== null
|
||||||
|
|
||||||
|
if (widgetWidth <= 25) {
|
||||||
|
return pluginSmallToggleComponent
|
||||||
|
} else if (hasDetail) {
|
||||||
|
return pluginCompoundPillComponent
|
||||||
|
} else {
|
||||||
|
return pluginToggleComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
Qt.callLater(() => {
|
||||||
|
const pluginComponent = PluginService.pluginWidgetComponents[pluginId]
|
||||||
|
if (pluginComponent) {
|
||||||
|
const instance = pluginComponent.createObject(null, {
|
||||||
|
"pluginId": pluginId,
|
||||||
|
"pluginService": PluginService,
|
||||||
|
"visible": false,
|
||||||
|
"width": 0,
|
||||||
|
"height": 0
|
||||||
|
})
|
||||||
|
if (instance) {
|
||||||
|
pluginInstance = instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: PluginService
|
||||||
|
function onPluginDataChanged(changedPluginId) {
|
||||||
|
if (changedPluginId === pluginId && pluginInstance) {
|
||||||
|
pluginInstance.loadPluginData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
if (pluginInstance) {
|
||||||
|
pluginInstance.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: pluginCompoundPillComponent
|
||||||
|
CompoundPill {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var pluginInstance: parent.pluginInstance
|
||||||
|
|
||||||
|
iconName: pluginInstance?.ccWidgetIcon || "extension"
|
||||||
|
primaryText: pluginInstance?.ccWidgetPrimaryText || "Plugin"
|
||||||
|
secondaryText: pluginInstance?.ccWidgetSecondaryText || ""
|
||||||
|
isActive: pluginInstance?.ccWidgetIsActive || false
|
||||||
|
|
||||||
|
onToggled: {
|
||||||
|
if (root.editMode)
|
||||||
|
return
|
||||||
|
if (pluginInstance) {
|
||||||
|
pluginInstance.ccWidgetToggled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExpandClicked: {
|
||||||
|
if (root.editMode)
|
||||||
|
return
|
||||||
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: pluginToggleComponent
|
||||||
|
ToggleButton {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var pluginInstance: parent.pluginInstance
|
||||||
|
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
|
||||||
|
|
||||||
|
iconName: pluginInstance?.ccWidgetIcon || widgetDef?.icon || "extension"
|
||||||
|
text: pluginInstance?.ccWidgetPrimaryText || widgetDef?.text || "Plugin"
|
||||||
|
secondaryText: pluginInstance?.ccWidgetSecondaryText || ""
|
||||||
|
isActive: pluginInstance?.ccWidgetIsActive || false
|
||||||
|
enabled: !root.editMode
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.editMode)
|
||||||
|
return
|
||||||
|
if (pluginInstance) {
|
||||||
|
pluginInstance.ccWidgetToggled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: pluginSmallToggleComponent
|
||||||
|
SmallToggleButton {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var pluginInstance: parent.pluginInstance
|
||||||
|
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
|
||||||
|
|
||||||
|
iconName: pluginInstance?.ccWidgetIcon || widgetDef?.icon || "extension"
|
||||||
|
isActive: pluginInstance?.ccWidgetIsActive || false
|
||||||
|
enabled: !root.editMode
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.editMode)
|
||||||
|
return
|
||||||
|
if (pluginInstance && pluginInstance.ccDetailContent) {
|
||||||
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
|
} else if (pluginInstance) {
|
||||||
|
pluginInstance.ccWidgetToggled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: "Add Widget"
|
text: I18n.tr("Add Widget")
|
||||||
style: Typography.Style.Subtitle
|
style: Typography.Style.Subtitle
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -155,7 +155,7 @@ Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: "Add Widget"
|
text: I18n.tr("Add Widget")
|
||||||
style: Typography.Style.Button
|
style: Typography.Style.Button
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -189,7 +189,7 @@ Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: "Defaults"
|
text: I18n.tr("Defaults")
|
||||||
style: Typography.Style.Button
|
style: Typography.Style.Button
|
||||||
color: Theme.warning
|
color: Theme.warning
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -223,7 +223,7 @@ Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: "Reset"
|
text: I18n.tr("Reset")
|
||||||
style: Typography.Style.Button
|
style: Typography.Style.Button
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|||||||
@@ -6,10 +6,9 @@ import qs.Widgets
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool powerOptionsExpanded: false
|
|
||||||
property bool editMode: false
|
property bool editMode: false
|
||||||
|
|
||||||
signal powerActionRequested(string action, string title, string message)
|
signal powerButtonClicked()
|
||||||
signal lockRequested()
|
signal lockRequested()
|
||||||
signal editModeToggled()
|
signal editModeToggled()
|
||||||
|
|
||||||
@@ -83,13 +82,11 @@ Rectangle {
|
|||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
buttonSize: 36
|
buttonSize: 36
|
||||||
iconName: root.powerOptionsExpanded ? "expand_less" : "power_settings_new"
|
iconName: "power_settings_new"
|
||||||
iconSize: Theme.iconSize - 4
|
iconSize: Theme.iconSize - 4
|
||||||
iconColor: root.powerOptionsExpanded ? Theme.primary : Theme.surfaceText
|
iconColor: Theme.surfaceText
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
onClicked: {
|
onClicked: root.powerButtonClicked()
|
||||||
root.powerOptionsExpanded = !root.powerOptionsExpanded
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool expanded: false
|
|
||||||
|
|
||||||
signal powerActionRequested(string action, string title, string message)
|
|
||||||
|
|
||||||
implicitHeight: expanded ? 60 : 0
|
|
||||||
height: implicitHeight
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: 60
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: Theme.surfaceContainerHigh
|
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: root.expanded ? 1 : 0
|
|
||||||
opacity: root.expanded ? 1 : 0
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: SessionService.hibernateSupported ? Theme.spacingS : Theme.spacingL
|
|
||||||
visible: root.expanded
|
|
||||||
|
|
||||||
PowerButton {
|
|
||||||
width: SessionService.hibernateSupported ? 85 : 100
|
|
||||||
iconName: "logout"
|
|
||||||
text: "Logout"
|
|
||||||
onPressed: root.powerActionRequested("logout", "Logout", "Are you sure you want to logout?")
|
|
||||||
}
|
|
||||||
|
|
||||||
PowerButton {
|
|
||||||
width: SessionService.hibernateSupported ? 85 : 100
|
|
||||||
iconName: "restart_alt"
|
|
||||||
text: "Restart"
|
|
||||||
onPressed: root.powerActionRequested("reboot", "Restart", "Are you sure you want to restart?")
|
|
||||||
}
|
|
||||||
|
|
||||||
PowerButton {
|
|
||||||
width: SessionService.hibernateSupported ? 85 : 100
|
|
||||||
iconName: "bedtime"
|
|
||||||
text: "Suspend"
|
|
||||||
onPressed: root.powerActionRequested("suspend", "Suspend", "Are you sure you want to suspend?")
|
|
||||||
}
|
|
||||||
|
|
||||||
PowerButton {
|
|
||||||
width: SessionService.hibernateSupported ? 85 : 100
|
|
||||||
iconName: "ac_unit"
|
|
||||||
text: "Hibernate"
|
|
||||||
visible: SessionService.hibernateSupported
|
|
||||||
onPressed: root.powerActionRequested("hibernate", "Hibernate", "Are you sure you want to hibernate?")
|
|
||||||
}
|
|
||||||
|
|
||||||
PowerButton {
|
|
||||||
width: SessionService.hibernateSupported ? 85 : 100
|
|
||||||
iconName: "power_settings_new"
|
|
||||||
text: "Shutdown"
|
|
||||||
onPressed: root.powerActionRequested("poweroff", "Shutdown", "Are you sure you want to shutdown?")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,13 +21,11 @@ DankPopout {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string expandedSection: ""
|
property string expandedSection: ""
|
||||||
property bool powerOptionsExpanded: false
|
|
||||||
property var triggerScreen: null
|
property var triggerScreen: null
|
||||||
property bool editMode: false
|
property bool editMode: false
|
||||||
property int expandedWidgetIndex: -1
|
property int expandedWidgetIndex: -1
|
||||||
property var expandedWidgetData: null
|
property var expandedWidgetData: null
|
||||||
|
|
||||||
signal powerActionRequested(string action, string title, string message)
|
|
||||||
signal lockRequested
|
signal lockRequested
|
||||||
|
|
||||||
function collapseAll() {
|
function collapseAll() {
|
||||||
@@ -75,13 +73,17 @@ DankPopout {
|
|||||||
onShouldBeVisibleChanged: {
|
onShouldBeVisibleChanged: {
|
||||||
if (shouldBeVisible) {
|
if (shouldBeVisible) {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
NetworkService.autoRefreshEnabled = NetworkService.wifiEnabled
|
if (NetworkService.activeService) {
|
||||||
|
NetworkService.activeService.autoRefreshEnabled = NetworkService.wifiEnabled
|
||||||
|
}
|
||||||
if (UserInfoService)
|
if (UserInfoService)
|
||||||
UserInfoService.getUptime()
|
UserInfoService.getUptime()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
NetworkService.autoRefreshEnabled = false
|
if (NetworkService.activeService) {
|
||||||
|
NetworkService.activeService.autoRefreshEnabled = false
|
||||||
|
}
|
||||||
if (BluetoothService.adapter && BluetoothService.adapter.discovering)
|
if (BluetoothService.adapter && BluetoothService.adapter.discovering)
|
||||||
BluetoothService.adapter.discovering = false
|
BluetoothService.adapter.discovering = false
|
||||||
editMode = false
|
editMode = false
|
||||||
@@ -122,28 +124,24 @@ DankPopout {
|
|||||||
HeaderPane {
|
HeaderPane {
|
||||||
id: headerPane
|
id: headerPane
|
||||||
width: parent.width
|
width: parent.width
|
||||||
powerOptionsExpanded: root.powerOptionsExpanded
|
|
||||||
editMode: root.editMode
|
editMode: root.editMode
|
||||||
onPowerOptionsExpandedChanged: root.powerOptionsExpanded = powerOptionsExpanded
|
|
||||||
onEditModeToggled: root.editMode = !root.editMode
|
onEditModeToggled: root.editMode = !root.editMode
|
||||||
onPowerActionRequested: (action, title, message) => root.powerActionRequested(action, title, message)
|
onPowerButtonClicked: {
|
||||||
|
if (powerMenuModalLoader) {
|
||||||
|
powerMenuModalLoader.active = true
|
||||||
|
if (powerMenuModalLoader.item) {
|
||||||
|
const popoutPos = controlContent.mapToItem(null, 0, 0)
|
||||||
|
const bounds = Qt.rect(popoutPos.x, popoutPos.y, controlContent.width, controlContent.height)
|
||||||
|
powerMenuModalLoader.item.openFromControlCenter(bounds, root.triggerScreen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
onLockRequested: {
|
onLockRequested: {
|
||||||
root.close()
|
root.close()
|
||||||
root.lockRequested()
|
root.lockRequested()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerOptionsPane {
|
|
||||||
id: powerOptionsPane
|
|
||||||
width: parent.width
|
|
||||||
expanded: root.powerOptionsExpanded
|
|
||||||
onPowerActionRequested: (action, title, message) => {
|
|
||||||
root.powerOptionsExpanded = false
|
|
||||||
root.close()
|
|
||||||
root.powerActionRequested(action, title, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DragDropGrid {
|
DragDropGrid {
|
||||||
id: widgetGrid
|
id: widgetGrid
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -173,8 +171,10 @@ DankPopout {
|
|||||||
visible: editMode
|
visible: editMode
|
||||||
popoutContent: controlContent
|
popoutContent: controlContent
|
||||||
availableWidgets: {
|
availableWidgets: {
|
||||||
|
if (!editMode) return []
|
||||||
const existingIds = (SettingsData.controlCenterWidgets || []).map(w => w.id)
|
const existingIds = (SettingsData.controlCenterWidgets || []).map(w => w.id)
|
||||||
return widgetModel.baseWidgetDefinitions.filter(w => w.allowMultiple || !existingIds.includes(w.id))
|
const allWidgets = widgetModel.baseWidgetDefinitions.concat(widgetModel.getPluginWidgets())
|
||||||
|
return allWidgets.filter(w => w.allowMultiple || !existingIds.includes(w.id))
|
||||||
}
|
}
|
||||||
onAddWidget: (widgetId) => widgetModel.addWidget(widgetId)
|
onAddWidget: (widgetId) => widgetModel.addWidget(widgetId)
|
||||||
onResetToDefault: () => widgetModel.resetToDefault()
|
onResetToDefault: () => widgetModel.resetToDefault()
|
||||||
@@ -226,4 +226,5 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
property var colorPickerModal: null
|
property var colorPickerModal: null
|
||||||
|
property var powerMenuModalLoader: null
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: headerText
|
id: headerText
|
||||||
text: "Input Devices"
|
text: I18n.tr("Input Devices")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: headerText
|
id: headerText
|
||||||
text: "Audio Devices"
|
text: I18n.tr("Audio Devices")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ Rectangle {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Health"
|
text: I18n.tr("Health")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -168,7 +168,7 @@ Rectangle {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Capacity"
|
text: I18n.tr("Capacity")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -237,7 +237,7 @@ Rectangle {
|
|||||||
width: parent.width - Theme.iconSize - Theme.spacingM
|
width: parent.width - Theme.iconSize - Theme.spacingM
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Power Profile Degradation"
|
text: I18n.tr("Power Profile Degradation")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Audio Codec Selection"
|
text: I18n.tr("Audio Codec Selection")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceTextMedium
|
color: Theme.surfaceTextMedium
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: headerText
|
id: headerText
|
||||||
text: "Bluetooth Settings"
|
text: I18n.tr("Bluetooth Settings")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -422,7 +422,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "No Bluetooth adapter found"
|
text: I18n.tr("No Bluetooth adapter found")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
}
|
}
|
||||||
@@ -473,7 +473,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Audio Codec"
|
text: I18n.tr("Audio Codec")
|
||||||
height: bluetoothContextMenu.currentDevice && BluetoothService.isAudioDevice(bluetoothContextMenu.currentDevice) && bluetoothContextMenu.currentDevice.connected ? 32 : 0
|
height: bluetoothContextMenu.currentDevice && BluetoothService.isAudioDevice(bluetoothContextMenu.currentDevice) && bluetoothContextMenu.currentDevice.connected ? 32 : 0
|
||||||
visible: bluetoothContextMenu.currentDevice && BluetoothService.isAudioDevice(bluetoothContextMenu.currentDevice) && bluetoothContextMenu.currentDevice.connected
|
visible: bluetoothContextMenu.currentDevice && BluetoothService.isAudioDevice(bluetoothContextMenu.currentDevice) && bluetoothContextMenu.currentDevice.connected
|
||||||
|
|
||||||
@@ -498,7 +498,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Forget Device"
|
text: I18n.tr("Forget Device")
|
||||||
height: 32
|
height: 32
|
||||||
|
|
||||||
contentItem: StyledText {
|
contentItem: StyledText {
|
||||||
|
|||||||
@@ -20,12 +20,9 @@ Rectangle {
|
|||||||
color: Theme.surfaceContainerHigh
|
color: Theme.surfaceContainerHigh
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
border.width: 0
|
border.width: 0
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
NetworkService.addRef()
|
NetworkService.addRef()
|
||||||
if (NetworkService.wifiEnabled) {
|
|
||||||
NetworkService.scanWifi()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
@@ -44,7 +41,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: headerText
|
id: headerText
|
||||||
text: "Network Settings"
|
text: I18n.tr("Network Settings")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -59,15 +56,30 @@ Rectangle {
|
|||||||
DankButtonGroup {
|
DankButtonGroup {
|
||||||
id: preferenceControls
|
id: preferenceControls
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: NetworkService.ethernetConnected && NetworkService.wifiConnected
|
visible: NetworkService.ethernetConnected
|
||||||
|
|
||||||
property int currentPreferenceIndex: NetworkService.userPreference === "ethernet" ? 0 : 1
|
property int currentPreferenceIndex: {
|
||||||
|
const pref = NetworkService.userPreference
|
||||||
|
const status = NetworkService.networkStatus
|
||||||
|
let index = 1
|
||||||
|
|
||||||
|
if (pref === "ethernet") {
|
||||||
|
index = 0
|
||||||
|
} else if (pref === "wifi") {
|
||||||
|
index = 1
|
||||||
|
} else {
|
||||||
|
index = status === "ethernet" ? 0 : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
model: ["Ethernet", "WiFi"]
|
model: ["Ethernet", "WiFi"]
|
||||||
currentIndex: currentPreferenceIndex
|
currentIndex: currentPreferenceIndex
|
||||||
selectionMode: "single"
|
selectionMode: "single"
|
||||||
onSelectionChanged: (index, selected) => {
|
onSelectionChanged: (index, selected) => {
|
||||||
if (!selected) return
|
if (!selected) return
|
||||||
|
console.log("NetworkDetail: Setting preference to", index === 0 ? "ethernet" : "wifi")
|
||||||
NetworkService.setNetworkPreference(index === 0 ? "ethernet" : "wifi")
|
NetworkService.setNetworkPreference(index === 0 ? "ethernet" : "wifi")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,17 +94,17 @@ Rectangle {
|
|||||||
anchors.topMargin: Theme.spacingM
|
anchors.topMargin: Theme.spacingM
|
||||||
visible: NetworkService.wifiToggling
|
visible: NetworkService.wifiToggling
|
||||||
height: visible ? 80 : 0
|
height: visible ? 80 : 0
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
name: "sync"
|
name: "sync"
|
||||||
size: 32
|
size: 32
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
|
|
||||||
RotationAnimation on rotation {
|
RotationAnimation on rotation {
|
||||||
running: NetworkService.wifiToggling
|
running: NetworkService.wifiToggling
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
@@ -101,7 +113,7 @@ Rectangle {
|
|||||||
duration: 1000
|
duration: 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
text: NetworkService.wifiEnabled ? "Disabling WiFi..." : "Enabling WiFi..."
|
text: NetworkService.wifiEnabled ? "Disabling WiFi..." : "Enabling WiFi..."
|
||||||
@@ -136,7 +148,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
text: "WiFi is off"
|
text: I18n.tr("WiFi is off")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -154,7 +166,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Enable WiFi"
|
text: I18n.tr("Enable WiFi")
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -192,16 +204,16 @@ Rectangle {
|
|||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 200
|
height: 200
|
||||||
visible: NetworkService.wifiInterface && NetworkService.wifiNetworks?.length < 1 && !NetworkService.wifiToggling
|
visible: NetworkService.wifiInterface && NetworkService.wifiNetworks?.length < 1 && !NetworkService.wifiToggling && NetworkService.isScanning
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
name: "refresh"
|
name: "refresh"
|
||||||
size: 48
|
size: 48
|
||||||
color: Qt.rgba(Theme.surfaceText.r || 0.8, Theme.surfaceText.g || 0.8, Theme.surfaceText.b || 0.8, 0.3)
|
color: Qt.rgba(Theme.surfaceText.r || 0.8, Theme.surfaceText.g || 0.8, Theme.surfaceText.b || 0.8, 0.3)
|
||||||
|
|
||||||
RotationAnimation on rotation {
|
RotationAnimation on rotation {
|
||||||
running: true
|
running: NetworkService.isScanning
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
from: 0
|
from: 0
|
||||||
to: 360
|
to: 360
|
||||||
@@ -211,14 +223,18 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: {
|
model: sortedNetworks
|
||||||
let networks = [...NetworkService.wifiNetworks]
|
|
||||||
networks.sort((a, b) => {
|
property var sortedNetworks: {
|
||||||
if (a.ssid === NetworkService.currentWifiSSID) return -1
|
const ssid = NetworkService.currentWifiSSID
|
||||||
if (b.ssid === NetworkService.currentWifiSSID) return 1
|
const networks = NetworkService.wifiNetworks
|
||||||
|
let sorted = [...networks]
|
||||||
|
sorted.sort((a, b) => {
|
||||||
|
if (a.ssid === ssid) return -1
|
||||||
|
if (b.ssid === ssid) return 1
|
||||||
return b.signal - a.signal
|
return b.signal - a.signal
|
||||||
})
|
})
|
||||||
return networks
|
return sorted
|
||||||
}
|
}
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
required property var modelData
|
required property var modelData
|
||||||
@@ -261,10 +277,10 @@ Rectangle {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
width: parent.width
|
width: parent.width
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: modelData.ssid === NetworkService.currentWifiSSID ? "Connected" : (modelData.secured ? "Secured" : "Open")
|
text: modelData.ssid === NetworkService.currentWifiSSID ? "Connected" : (modelData.secured ? "Secured" : "Open")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
@@ -380,7 +396,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Network Info"
|
text: I18n.tr("Network Info")
|
||||||
height: 32
|
height: 32
|
||||||
|
|
||||||
contentItem: StyledText {
|
contentItem: StyledText {
|
||||||
@@ -403,7 +419,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Forget Network"
|
text: I18n.tr("Forget Network")
|
||||||
height: networkContextMenu.currentSaved || networkContextMenu.currentConnected ? 32 : 0
|
height: networkContextMenu.currentSaved || networkContextMenu.currentConnected ? 32 : 0
|
||||||
visible: networkContextMenu.currentSaved || networkContextMenu.currentConnected
|
visible: networkContextMenu.currentSaved || networkContextMenu.currentConnected
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,38 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
import qs.Modules.ControlCenter.BuiltinPlugins
|
||||||
import "../utils/widgets.js" as WidgetUtils
|
import "../utils/widgets.js" as WidgetUtils
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property var baseWidgetDefinitions: [
|
property var vpnBuiltinInstance: null
|
||||||
{
|
|
||||||
|
property var vpnLoader: Loader {
|
||||||
|
active: false
|
||||||
|
sourceComponent: Component {
|
||||||
|
VpnWidget {}
|
||||||
|
}
|
||||||
|
|
||||||
|
onItemChanged: {
|
||||||
|
root.vpnBuiltinInstance = item
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SettingsData
|
||||||
|
function onControlCenterWidgetsChanged() {
|
||||||
|
const widgets = SettingsData.controlCenterWidgets || []
|
||||||
|
const hasVpnWidget = widgets.some(w => w.id === "builtin_vpn")
|
||||||
|
if (!hasVpnWidget && vpnLoader.active) {
|
||||||
|
console.log("VpnWidget: No VPN widget in control center, deactivating loader")
|
||||||
|
vpnLoader.active = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property var coreWidgetDefinitions: [{
|
||||||
"id": "nightMode",
|
"id": "nightMode",
|
||||||
"text": "Night Mode",
|
"text": "Night Mode",
|
||||||
"description": "Blue light filter",
|
"description": "Blue light filter",
|
||||||
@@ -15,32 +40,28 @@ QtObject {
|
|||||||
"type": "toggle",
|
"type": "toggle",
|
||||||
"enabled": DisplayService.automationAvailable,
|
"enabled": DisplayService.automationAvailable,
|
||||||
"warning": !DisplayService.automationAvailable ? "Requires night mode support" : undefined
|
"warning": !DisplayService.automationAvailable ? "Requires night mode support" : undefined
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "darkMode",
|
"id": "darkMode",
|
||||||
"text": "Dark Mode",
|
"text": "Dark Mode",
|
||||||
"description": "System theme toggle",
|
"description": "System theme toggle",
|
||||||
"icon": "contrast",
|
"icon": "contrast",
|
||||||
"type": "toggle",
|
"type": "toggle",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "doNotDisturb",
|
"id": "doNotDisturb",
|
||||||
"text": "Do Not Disturb",
|
"text": "Do Not Disturb",
|
||||||
"description": "Block notifications",
|
"description": "Block notifications",
|
||||||
"icon": "do_not_disturb_on",
|
"icon": "do_not_disturb_on",
|
||||||
"type": "toggle",
|
"type": "toggle",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "idleInhibitor",
|
"id": "idleInhibitor",
|
||||||
"text": "Keep Awake",
|
"text": "Keep Awake",
|
||||||
"description": "Prevent screen timeout",
|
"description": "Prevent screen timeout",
|
||||||
"icon": "motion_sensor_active",
|
"icon": "motion_sensor_active",
|
||||||
"type": "toggle",
|
"type": "toggle",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "wifi",
|
"id": "wifi",
|
||||||
"text": "Network",
|
"text": "Network",
|
||||||
"description": "Wi-Fi and Ethernet connection",
|
"description": "Wi-Fi and Ethernet connection",
|
||||||
@@ -48,8 +69,7 @@ QtObject {
|
|||||||
"type": "connection",
|
"type": "connection",
|
||||||
"enabled": NetworkService.wifiAvailable,
|
"enabled": NetworkService.wifiAvailable,
|
||||||
"warning": !NetworkService.wifiAvailable ? "Wi-Fi not available" : undefined
|
"warning": !NetworkService.wifiAvailable ? "Wi-Fi not available" : undefined
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "bluetooth",
|
"id": "bluetooth",
|
||||||
"text": "Bluetooth",
|
"text": "Bluetooth",
|
||||||
"description": "Device connections",
|
"description": "Device connections",
|
||||||
@@ -57,32 +77,28 @@ QtObject {
|
|||||||
"type": "connection",
|
"type": "connection",
|
||||||
"enabled": BluetoothService.available,
|
"enabled": BluetoothService.available,
|
||||||
"warning": !BluetoothService.available ? "Bluetooth not available" : undefined
|
"warning": !BluetoothService.available ? "Bluetooth not available" : undefined
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "audioOutput",
|
"id": "audioOutput",
|
||||||
"text": "Audio Output",
|
"text": "Audio Output",
|
||||||
"description": "Speaker settings",
|
"description": "Speaker settings",
|
||||||
"icon": "volume_up",
|
"icon": "volume_up",
|
||||||
"type": "connection",
|
"type": "connection",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "audioInput",
|
"id": "audioInput",
|
||||||
"text": "Audio Input",
|
"text": "Audio Input",
|
||||||
"description": "Microphone settings",
|
"description": "Microphone settings",
|
||||||
"icon": "mic",
|
"icon": "mic",
|
||||||
"type": "connection",
|
"type": "connection",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "volumeSlider",
|
"id": "volumeSlider",
|
||||||
"text": "Volume Slider",
|
"text": "Volume Slider",
|
||||||
"description": "Audio volume control",
|
"description": "Audio volume control",
|
||||||
"icon": "volume_up",
|
"icon": "volume_up",
|
||||||
"type": "slider",
|
"type": "slider",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "brightnessSlider",
|
"id": "brightnessSlider",
|
||||||
"text": "Brightness Slider",
|
"text": "Brightness Slider",
|
||||||
"description": "Display brightness control",
|
"description": "Display brightness control",
|
||||||
@@ -90,24 +106,21 @@ QtObject {
|
|||||||
"type": "slider",
|
"type": "slider",
|
||||||
"enabled": DisplayService.brightnessAvailable,
|
"enabled": DisplayService.brightnessAvailable,
|
||||||
"warning": !DisplayService.brightnessAvailable ? "Brightness control not available" : undefined
|
"warning": !DisplayService.brightnessAvailable ? "Brightness control not available" : undefined
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "inputVolumeSlider",
|
"id": "inputVolumeSlider",
|
||||||
"text": "Input Volume Slider",
|
"text": "Input Volume Slider",
|
||||||
"description": "Microphone volume control",
|
"description": "Microphone volume control",
|
||||||
"icon": "mic",
|
"icon": "mic",
|
||||||
"type": "slider",
|
"type": "slider",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "battery",
|
"id": "battery",
|
||||||
"text": "Battery",
|
"text": "Battery",
|
||||||
"description": "Battery and power management",
|
"description": "Battery and power management",
|
||||||
"icon": "battery_std",
|
"icon": "battery_std",
|
||||||
"type": "action",
|
"type": "action",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "diskUsage",
|
"id": "diskUsage",
|
||||||
"text": "Disk Usage",
|
"text": "Disk Usage",
|
||||||
"description": "Filesystem usage monitoring",
|
"description": "Filesystem usage monitoring",
|
||||||
@@ -116,16 +129,68 @@ QtObject {
|
|||||||
"enabled": DgopService.dgopAvailable,
|
"enabled": DgopService.dgopAvailable,
|
||||||
"warning": !DgopService.dgopAvailable ? "Requires 'dgop' tool" : undefined,
|
"warning": !DgopService.dgopAvailable ? "Requires 'dgop' tool" : undefined,
|
||||||
"allowMultiple": true
|
"allowMultiple": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "colorPicker",
|
"id": "colorPicker",
|
||||||
"text": "Color Picker",
|
"text": "Color Picker",
|
||||||
"description": "Choose colors from palette",
|
"description": "Choose colors from palette",
|
||||||
"icon": "palette",
|
"icon": "palette",
|
||||||
"type": "action",
|
"type": "action",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
|
}, {
|
||||||
|
"id": "builtin_vpn",
|
||||||
|
"text": "VPN",
|
||||||
|
"description": "VPN connections",
|
||||||
|
"icon": "vpn_key",
|
||||||
|
"type": "builtin_plugin",
|
||||||
|
"enabled": VpnService.available,
|
||||||
|
"warning": !VpnService.available ? "VPN not available" : undefined,
|
||||||
|
"isBuiltinPlugin": true
|
||||||
|
}]
|
||||||
|
|
||||||
|
function getPluginWidgets() {
|
||||||
|
const plugins = []
|
||||||
|
const loadedPlugins = PluginService.getLoadedPlugins()
|
||||||
|
|
||||||
|
for (var i = 0; i < loadedPlugins.length; i++) {
|
||||||
|
const plugin = loadedPlugins[i]
|
||||||
|
|
||||||
|
if (plugin.type === "daemon") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const pluginComponent = PluginService.pluginWidgetComponents[plugin.id]
|
||||||
|
if (!pluginComponent) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const tempInstance = pluginComponent.createObject(null)
|
||||||
|
if (!tempInstance) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasCCWidget = tempInstance.ccWidgetIcon && tempInstance.ccWidgetIcon.length > 0
|
||||||
|
tempInstance.destroy()
|
||||||
|
|
||||||
|
if (!hasCCWidget) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.push({
|
||||||
|
"id": "plugin_" + plugin.id,
|
||||||
|
"pluginId": plugin.id,
|
||||||
|
"text": plugin.name || "Plugin",
|
||||||
|
"description": plugin.description || "",
|
||||||
|
"icon": plugin.icon || "extension",
|
||||||
|
"type": "plugin",
|
||||||
|
"enabled": true,
|
||||||
|
"isPlugin": true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
]
|
|
||||||
|
return plugins
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property var baseWidgetDefinitions: coreWidgetDefinitions
|
||||||
|
|
||||||
function getWidgetForId(widgetId) {
|
function getWidgetForId(widgetId) {
|
||||||
return WidgetUtils.getWidgetForId(baseWidgetDefinitions, widgetId)
|
return WidgetUtils.getWidgetForId(baseWidgetDefinitions, widgetId)
|
||||||
@@ -154,4 +219,4 @@ QtObject {
|
|||||||
function clearAll() {
|
function clearAll() {
|
||||||
WidgetUtils.clearAll()
|
WidgetUtils.clearAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ import qs.Widgets
|
|||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
readonly property string powerOptionsText: I18n.tr("Power Options")
|
||||||
|
readonly property string logOutText: I18n.tr("Log Out")
|
||||||
|
readonly property string suspendText: I18n.tr("Suspend")
|
||||||
|
readonly property string rebootText: I18n.tr("Reboot")
|
||||||
|
readonly property string powerOffText: I18n.tr("Power Off")
|
||||||
|
|
||||||
property bool powerMenuVisible: false
|
property bool powerMenuVisible: false
|
||||||
signal powerActionRequested(string action, string title, string message)
|
signal powerActionRequested(string action, string title, string message)
|
||||||
|
|
||||||
@@ -65,7 +71,7 @@ PanelWindow {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Power Options"
|
text: root.powerOptionsText
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -118,7 +124,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Log Out"
|
text: root.logOutText
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -168,7 +174,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Suspend"
|
text: root.suspendText
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -218,7 +224,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Reboot"
|
text: root.rebootText
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: rebootArea.containsMouse ? Theme.warning : Theme.surfaceText
|
color: rebootArea.containsMouse ? Theme.warning : Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -268,7 +274,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Power Off"
|
text: root.powerOffText
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: powerOffArea.containsMouse ? Theme.error : Theme.surfaceText
|
color: powerOffArea.containsMouse ? Theme.error : Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -69,9 +69,6 @@ Row {
|
|||||||
valueOverride: actualVolumePercent
|
valueOverride: actualVolumePercent
|
||||||
thumbOutlineColor: Theme.surfaceContainer
|
thumbOutlineColor: Theme.surfaceContainer
|
||||||
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.surfaceContainerHigh
|
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.surfaceContainerHigh
|
||||||
onIsDraggingChanged: {
|
|
||||||
AudioService.suppressOSD = isDragging
|
|
||||||
}
|
|
||||||
onSliderValueChanged: function(newValue) {
|
onSliderValueChanged: function(newValue) {
|
||||||
if (defaultSink) {
|
if (defaultSink) {
|
||||||
defaultSink.audio.volume = newValue / 100.0
|
defaultSink.audio.volume = newValue / 100.0
|
||||||
|
|||||||
51
Modules/ControlCenter/Widgets/ErrorPill.qml
Normal file
51
Modules/ControlCenter/Widgets/ErrorPill.qml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string primaryMessage: ""
|
||||||
|
property string secondaryMessage: ""
|
||||||
|
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.1)
|
||||||
|
border.color: Theme.warning
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingM
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "warning"
|
||||||
|
size: 16
|
||||||
|
color: Theme.warning
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width - 16 - parent.spacing
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
width: parent.width
|
||||||
|
text: root.primaryMessage
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.warning
|
||||||
|
font.weight: Font.Medium
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
width: parent.width
|
||||||
|
text: root.secondaryMessage
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.warning
|
||||||
|
visible: text.length > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import Quickshell
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
import qs.Modules.ControlCenter.Widgets
|
|
||||||
|
|
||||||
CompoundPill {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
isActive: {
|
|
||||||
if (NetworkService.wifiToggling) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (NetworkService.networkStatus === "ethernet") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (NetworkService.networkStatus === "wifi") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return NetworkService.wifiEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
iconName: {
|
|
||||||
if (NetworkService.wifiToggling) {
|
|
||||||
return "sync"
|
|
||||||
}
|
|
||||||
if (NetworkService.networkStatus === "ethernet") {
|
|
||||||
return "settings_ethernet"
|
|
||||||
}
|
|
||||||
if (NetworkService.networkStatus === "wifi") {
|
|
||||||
return NetworkService.wifiSignalIcon
|
|
||||||
}
|
|
||||||
if (NetworkService.wifiEnabled) {
|
|
||||||
return "wifi_off"
|
|
||||||
}
|
|
||||||
return "wifi_off"
|
|
||||||
}
|
|
||||||
|
|
||||||
primaryText: {
|
|
||||||
if (NetworkService.wifiToggling) {
|
|
||||||
return NetworkService.wifiEnabled ? "Disabling WiFi..." : "Enabling WiFi..."
|
|
||||||
}
|
|
||||||
if (NetworkService.networkStatus === "ethernet") {
|
|
||||||
return "Ethernet"
|
|
||||||
}
|
|
||||||
if (NetworkService.networkStatus === "wifi" && NetworkService.currentWifiSSID) {
|
|
||||||
return NetworkService.currentWifiSSID
|
|
||||||
}
|
|
||||||
if (NetworkService.wifiEnabled) {
|
|
||||||
return "Not connected"
|
|
||||||
}
|
|
||||||
return "WiFi off"
|
|
||||||
}
|
|
||||||
|
|
||||||
secondaryText: {
|
|
||||||
if (NetworkService.wifiToggling) {
|
|
||||||
return "Please wait..."
|
|
||||||
}
|
|
||||||
if (NetworkService.networkStatus === "ethernet") {
|
|
||||||
return "Connected"
|
|
||||||
}
|
|
||||||
if (NetworkService.networkStatus === "wifi") {
|
|
||||||
return NetworkService.wifiSignalStrength > 0 ? NetworkService.wifiSignalStrength + "%" : "Connected"
|
|
||||||
}
|
|
||||||
if (NetworkService.wifiEnabled) {
|
|
||||||
return "Select network"
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
onToggled: {
|
|
||||||
if (NetworkService.networkStatus !== "ethernet" && !NetworkService.wifiToggling) {
|
|
||||||
NetworkService.toggleWifiRadio()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -207,4 +207,121 @@ Item {
|
|||||||
ctx.fill()
|
ctx.fill()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Canvas {
|
||||||
|
id: barBorder
|
||||||
|
anchors.fill: parent
|
||||||
|
antialiasing: true
|
||||||
|
visible: SettingsData.dankBarBorderEnabled
|
||||||
|
renderTarget: Canvas.FramebufferObject
|
||||||
|
renderStrategy: Canvas.Cooperative
|
||||||
|
|
||||||
|
readonly property real correctWidth: root.width
|
||||||
|
readonly property real correctHeight: root.height
|
||||||
|
canvasSize: Qt.size(barWindow.px(correctWidth), barWindow.px(correctHeight))
|
||||||
|
|
||||||
|
property real wing: SettingsData.dankBarGothCornersEnabled ? barWindow._wingR : 0
|
||||||
|
property real rt: SettingsData.dankBarSquareCorners ? 0 : Theme.cornerRadius
|
||||||
|
property bool borderEnabled: SettingsData.dankBarBorderEnabled
|
||||||
|
|
||||||
|
onWingChanged: requestPaint()
|
||||||
|
onRtChanged: requestPaint()
|
||||||
|
onBorderEnabledChanged: requestPaint()
|
||||||
|
onCorrectWidthChanged: requestPaint()
|
||||||
|
onCorrectHeightChanged: requestPaint()
|
||||||
|
onVisibleChanged: if (visible) requestPaint()
|
||||||
|
Component.onCompleted: requestPaint()
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: barWindow
|
||||||
|
function on_DprChanged() { barBorder.requestPaint() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Theme
|
||||||
|
function onSecondaryChanged() { barBorder.requestPaint() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SettingsData
|
||||||
|
function onDankBarSpacingChanged() { barBorder.requestPaint() }
|
||||||
|
function onDankBarSquareCornersChanged() { barBorder.requestPaint() }
|
||||||
|
function onCornerRadiusChanged() { barBorder.requestPaint() }
|
||||||
|
}
|
||||||
|
|
||||||
|
onPaint: {
|
||||||
|
if (!borderEnabled) return
|
||||||
|
|
||||||
|
const ctx = getContext("2d")
|
||||||
|
const scale = barWindow._dpr
|
||||||
|
const W = barWindow.px(barWindow.isVertical ? correctHeight : correctWidth)
|
||||||
|
const H_raw = barWindow.px(barWindow.isVertical ? correctWidth : correctHeight)
|
||||||
|
const R = barWindow.px(wing)
|
||||||
|
const RT = barWindow.px(rt)
|
||||||
|
const H = H_raw - (R > 0 ? R : 0)
|
||||||
|
const isTop = SettingsData.dankBarPosition === SettingsData.Position.Top
|
||||||
|
const isBottom = SettingsData.dankBarPosition === SettingsData.Position.Bottom
|
||||||
|
const isLeft = SettingsData.dankBarPosition === SettingsData.Position.Left
|
||||||
|
const isRight = SettingsData.dankBarPosition === SettingsData.Position.Right
|
||||||
|
|
||||||
|
const spacing = SettingsData.dankBarSpacing
|
||||||
|
const hasEdgeGap = spacing > 0 || RT > 0
|
||||||
|
|
||||||
|
ctx.scale(scale, scale)
|
||||||
|
|
||||||
|
function drawTopBorder() {
|
||||||
|
ctx.beginPath()
|
||||||
|
|
||||||
|
if (!hasEdgeGap) {
|
||||||
|
ctx.moveTo(0, H)
|
||||||
|
ctx.lineTo(W, H)
|
||||||
|
} else {
|
||||||
|
ctx.moveTo(RT, 0)
|
||||||
|
ctx.lineTo(W - RT, 0)
|
||||||
|
ctx.arcTo(W, 0, W, RT, RT)
|
||||||
|
ctx.lineTo(W, H)
|
||||||
|
|
||||||
|
if (R > 0) {
|
||||||
|
ctx.lineTo(W, H + R)
|
||||||
|
ctx.arc(W - R, H + R, R, 0, -Math.PI / 2, true)
|
||||||
|
ctx.lineTo(R, H)
|
||||||
|
ctx.arc(R, H + R, R, -Math.PI / 2, -Math.PI, true)
|
||||||
|
ctx.lineTo(0, H + R)
|
||||||
|
} else {
|
||||||
|
ctx.lineTo(W, H - RT)
|
||||||
|
ctx.arcTo(W, H, W - RT, H, RT)
|
||||||
|
ctx.lineTo(RT, H)
|
||||||
|
ctx.arcTo(0, H, 0, H - RT, RT)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.lineTo(0, RT)
|
||||||
|
ctx.arcTo(0, 0, RT, 0, RT)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.closePath()
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.reset()
|
||||||
|
ctx.clearRect(0, 0, W, H_raw)
|
||||||
|
|
||||||
|
ctx.save()
|
||||||
|
if (isBottom) {
|
||||||
|
ctx.translate(W, H_raw)
|
||||||
|
ctx.rotate(Math.PI)
|
||||||
|
} else if (isLeft) {
|
||||||
|
ctx.translate(0, W)
|
||||||
|
ctx.rotate(-Math.PI / 2)
|
||||||
|
} else if (isRight) {
|
||||||
|
ctx.translate(H_raw, 0)
|
||||||
|
ctx.rotate(Math.PI / 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
drawTopBorder()
|
||||||
|
ctx.restore()
|
||||||
|
|
||||||
|
ctx.lineWidth = 1
|
||||||
|
ctx.strokeStyle = Theme.secondary
|
||||||
|
ctx.stroke()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -308,8 +308,10 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For plugin components, get from PluginService
|
// For plugin components, get from PluginService
|
||||||
let pluginMap = PluginService.getWidgetComponents()
|
var parts = widgetId.split(":")
|
||||||
return pluginMap[widgetId] || null
|
var pluginId = parts[0]
|
||||||
|
let pluginComponents = PluginService.getWidgetComponents()
|
||||||
|
return pluginComponents[pluginId] || null
|
||||||
}
|
}
|
||||||
|
|
||||||
height: parent.height
|
height: parent.height
|
||||||
@@ -397,12 +399,26 @@ Item {
|
|||||||
|
|
||||||
// Inject PluginService for plugin widgets
|
// Inject PluginService for plugin widgets
|
||||||
if (item.pluginService !== undefined) {
|
if (item.pluginService !== undefined) {
|
||||||
|
var parts = model.widgetId.split(":")
|
||||||
|
var pluginId = parts[0]
|
||||||
|
var variantId = parts.length > 1 ? parts[1] : null
|
||||||
|
|
||||||
if (item.pluginId !== undefined) {
|
if (item.pluginId !== undefined) {
|
||||||
item.pluginId = model.widgetId
|
item.pluginId = pluginId
|
||||||
|
}
|
||||||
|
if (item.variantId !== undefined) {
|
||||||
|
item.variantId = variantId
|
||||||
|
}
|
||||||
|
if (item.variantData !== undefined && variantId) {
|
||||||
|
item.variantData = PluginService.getPluginVariantData(pluginId, variantId)
|
||||||
}
|
}
|
||||||
item.pluginService = PluginService
|
item.pluginService = PluginService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.popoutService !== undefined) {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
|
|
||||||
layoutTimer.restart()
|
layoutTimer.restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,8 +442,8 @@ Item {
|
|||||||
// Force refresh of component lookups
|
// Force refresh of component lookups
|
||||||
for (var i = 0; i < centerRepeater.count; i++) {
|
for (var i = 0; i < centerRepeater.count; i++) {
|
||||||
var item = centerRepeater.itemAt(i)
|
var item = centerRepeater.itemAt(i)
|
||||||
if (item && item.widgetId === pluginId) {
|
if (item && item.widgetId.startsWith(pluginId)) {
|
||||||
item.sourceComponent = root.getWidgetComponent(pluginId)
|
item.sourceComponent = root.getWidgetComponent(item.widgetId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,8 +451,8 @@ Item {
|
|||||||
// Force refresh of component lookups
|
// Force refresh of component lookups
|
||||||
for (var i = 0; i < centerRepeater.count; i++) {
|
for (var i = 0; i < centerRepeater.count; i++) {
|
||||||
var item = centerRepeater.itemAt(i)
|
var item = centerRepeater.itemAt(i)
|
||||||
if (item && item.widgetId === pluginId) {
|
if (item && item.widgetId.startsWith(pluginId)) {
|
||||||
item.sourceComponent = root.getWidgetComponent(pluginId)
|
item.sourceComponent = root.getWidgetComponent(item.widgetId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ Item {
|
|||||||
implicitWidth: isVertical ? px(effectiveBarThickness + SettingsData.dankBarSpacing + (SettingsData.dankBarGothCornersEnabled ? _wingR : 0)) : 0
|
implicitWidth: isVertical ? px(effectiveBarThickness + SettingsData.dankBarSpacing + (SettingsData.dankBarGothCornersEnabled ? _wingR : 0)) : 0
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
|
property var nativeInhibitor: null
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
const fonts = Qt.fontFamilies()
|
const fonts = Qt.fontFamilies()
|
||||||
if (fonts.indexOf("Material Symbols Rounded") === -1) {
|
if (fonts.indexOf("Material Symbols Rounded") === -1) {
|
||||||
@@ -93,6 +95,19 @@ Item {
|
|||||||
|
|
||||||
updateGpuTempConfig()
|
updateGpuTempConfig()
|
||||||
Qt.callLater(() => Qt.callLater(forceWidgetRefresh))
|
Qt.callLater(() => Qt.callLater(forceWidgetRefresh))
|
||||||
|
|
||||||
|
inhibitorInitTimer.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: inhibitorInitTimer
|
||||||
|
interval: 300
|
||||||
|
repeat: false
|
||||||
|
onTriggered: {
|
||||||
|
if (SessionService.nativeInhibitorAvailable) {
|
||||||
|
createNativeInhibitor()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -124,6 +139,38 @@ Item {
|
|||||||
DgopService.nonNvidiaGpuTempEnabled = hasGpuTempWidget || SessionData.nonNvidiaGpuTempEnabled
|
DgopService.nonNvidiaGpuTempEnabled = hasGpuTempWidget || SessionData.nonNvidiaGpuTempEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createNativeInhibitor() {
|
||||||
|
if (!SessionService.nativeInhibitorAvailable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const qmlString = `
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell.Wayland
|
||||||
|
|
||||||
|
IdleInhibitor {
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
nativeInhibitor = Qt.createQmlObject(qmlString, barWindow, "DankBar.NativeInhibitor")
|
||||||
|
nativeInhibitor.window = barWindow
|
||||||
|
nativeInhibitor.enabled = Qt.binding(() => SessionService.idleInhibited)
|
||||||
|
nativeInhibitor.enabledChanged.connect(function() {
|
||||||
|
console.log("DankBar: Native inhibitor enabled changed to:", nativeInhibitor.enabled)
|
||||||
|
if (SessionService.idleInhibited !== nativeInhibitor.enabled) {
|
||||||
|
SessionService.idleInhibited = nativeInhibitor.enabled
|
||||||
|
SessionService.inhibitorChanged()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log("DankBar: Created native Wayland IdleInhibitor for", barWindow.screenName)
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("DankBar: Failed to create native IdleInhibitor:", e)
|
||||||
|
nativeInhibitor = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onDankBarLeftWidgetsChanged() {
|
function onDankBarLeftWidgetsChanged() {
|
||||||
barWindow.updateGpuTempConfig()
|
barWindow.updateGpuTempConfig()
|
||||||
@@ -189,8 +236,10 @@ Item {
|
|||||||
|
|
||||||
readonly property int barThickness: px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing)
|
readonly property int barThickness: px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing)
|
||||||
|
|
||||||
readonly property bool showing: SettingsData.dankBarVisible && (topBarCore.reveal
|
readonly property bool inOverviewWithShow: CompositorService.isNiri && NiriService.inOverview && SettingsData.dankBarOpenOnOverview
|
||||||
|| (CompositorService.isNiri && NiriService.inOverview && SettingsData.dankBarOpenOnOverview)
|
readonly property bool effectiveVisible: SettingsData.dankBarVisible || inOverviewWithShow
|
||||||
|
readonly property bool showing: effectiveVisible && (topBarCore.reveal
|
||||||
|
|| inOverviewWithShow
|
||||||
|| !topBarCore.autoHide)
|
|| !topBarCore.autoHide)
|
||||||
|
|
||||||
readonly property int maskThickness: showing ? barThickness : 1
|
readonly property int maskThickness: showing ? barThickness : 1
|
||||||
@@ -789,6 +838,7 @@ Item {
|
|||||||
return processListPopoutLoader.item
|
return processListPopoutLoader.item
|
||||||
}
|
}
|
||||||
parentScreen: barWindow.screen
|
parentScreen: barWindow.screen
|
||||||
|
widgetData: parent.widgetData
|
||||||
toggleProcessList: () => {
|
toggleProcessList: () => {
|
||||||
processListPopoutLoader.active = true
|
processListPopoutLoader.active = true
|
||||||
return processListPopoutLoader.item?.toggle()
|
return processListPopoutLoader.item?.toggle()
|
||||||
@@ -808,6 +858,7 @@ Item {
|
|||||||
return processListPopoutLoader.item
|
return processListPopoutLoader.item
|
||||||
}
|
}
|
||||||
parentScreen: barWindow.screen
|
parentScreen: barWindow.screen
|
||||||
|
widgetData: parent.widgetData
|
||||||
toggleProcessList: () => {
|
toggleProcessList: () => {
|
||||||
processListPopoutLoader.active = true
|
processListPopoutLoader.active = true
|
||||||
return processListPopoutLoader.item?.toggle()
|
return processListPopoutLoader.item?.toggle()
|
||||||
@@ -837,6 +888,7 @@ Item {
|
|||||||
return processListPopoutLoader.item
|
return processListPopoutLoader.item
|
||||||
}
|
}
|
||||||
parentScreen: barWindow.screen
|
parentScreen: barWindow.screen
|
||||||
|
widgetData: parent.widgetData
|
||||||
toggleProcessList: () => {
|
toggleProcessList: () => {
|
||||||
processListPopoutLoader.active = true
|
processListPopoutLoader.active = true
|
||||||
return processListPopoutLoader.item?.toggle()
|
return processListPopoutLoader.item?.toggle()
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ DankPopout {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Health"
|
text: I18n.tr("Health")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -346,7 +346,7 @@ DankPopout {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Capacity"
|
text: I18n.tr("Capacity")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -415,7 +415,7 @@ DankPopout {
|
|||||||
width: parent.width - Theme.iconSize - Theme.spacingM
|
width: parent.width - Theme.iconSize - Theme.spacingM
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Power Profile Degradation"
|
text: I18n.tr("Power Profile Degradation")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import qs.Widgets
|
|||||||
DankPopout {
|
DankPopout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
Ref {
|
||||||
|
service: VpnService
|
||||||
|
}
|
||||||
|
|
||||||
property var triggerScreen: null
|
property var triggerScreen: null
|
||||||
|
|
||||||
function setTriggerPosition(x, y, width, section, screen) {
|
function setTriggerPosition(x, y, width, section, screen) {
|
||||||
@@ -96,7 +100,7 @@ DankPopout {
|
|||||||
height: 32
|
height: 32
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "VPN Connections"
|
text: I18n.tr("VPN Connections")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -206,7 +210,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Disconnect"
|
text: I18n.tr("Disconnect")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -262,14 +266,14 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "No VPN profiles found"
|
text: I18n.tr("No VPN profiles found")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Add a VPN in NetworkManager"
|
text: I18n.tr("Add a VPN in NetworkManager")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|||||||
@@ -65,6 +65,14 @@ Loader {
|
|||||||
restoreMode: Binding.RestoreNone
|
restoreMode: Binding.RestoreNone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
target: root.item
|
||||||
|
when: root.item && "widgetData" in root.item
|
||||||
|
property: "widgetData"
|
||||||
|
value: root.widgetData
|
||||||
|
restoreMode: Binding.RestoreNone
|
||||||
|
}
|
||||||
|
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
if (item) {
|
if (item) {
|
||||||
contentItemReady(item)
|
contentItemReady(item)
|
||||||
@@ -79,11 +87,25 @@ Loader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (item.pluginService !== undefined) {
|
if (item.pluginService !== undefined) {
|
||||||
|
var parts = widgetId.split(":")
|
||||||
|
var pluginId = parts[0]
|
||||||
|
var variantId = parts.length > 1 ? parts[1] : null
|
||||||
|
|
||||||
if (item.pluginId !== undefined) {
|
if (item.pluginId !== undefined) {
|
||||||
item.pluginId = widgetId
|
item.pluginId = pluginId
|
||||||
|
}
|
||||||
|
if (item.variantId !== undefined) {
|
||||||
|
item.variantId = variantId
|
||||||
|
}
|
||||||
|
if (item.variantData !== undefined && variantId) {
|
||||||
|
item.variantData = PluginService.getPluginVariantData(pluginId, variantId)
|
||||||
}
|
}
|
||||||
item.pluginService = PluginService
|
item.pluginService = PluginService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.popoutService !== undefined) {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,8 +144,11 @@ Loader {
|
|||||||
return componentMap[widgetId]
|
return componentMap[widgetId]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var parts = widgetId.split(":")
|
||||||
|
var pluginId = parts[0]
|
||||||
|
|
||||||
let pluginMap = PluginService.getWidgetComponents()
|
let pluginMap = PluginService.getWidgetComponents()
|
||||||
return pluginMap[widgetId] || null
|
return pluginMap[pluginId] || null
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWidgetVisible(widgetId, dgopAvailable) {
|
function getWidgetVisible(widgetId, dgopAvailable) {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: BatteryService.getBatteryIcon()
|
name: BatteryService.getBatteryIcon()
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (!BatteryService.batteryAvailable) {
|
if (!BatteryService.batteryAvailable) {
|
||||||
return Theme.surfaceText
|
return Theme.surfaceText
|
||||||
@@ -61,7 +61,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: BatteryService.batteryLevel.toString()
|
text: BatteryService.batteryLevel.toString()
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -77,7 +77,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: BatteryService.getBatteryIcon()
|
name: BatteryService.getBatteryIcon()
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness, -4)
|
||||||
color: {
|
color: {
|
||||||
if (!BatteryService.batteryAvailable) {
|
if (!BatteryService.batteryAvailable) {
|
||||||
return Theme.surfaceText;
|
return Theme.surfaceText;
|
||||||
@@ -98,7 +98,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: `${BatteryService.batteryLevel}%`
|
text: `${BatteryService.batteryLevel}%`
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ Item {
|
|||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
name: "content_paste"
|
name: "content_paste"
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ Rectangle {
|
|||||||
return String(display).padStart(2, '0').charAt(0)
|
return String(display).padStart(2, '0').charAt(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
width: 9
|
width: 9
|
||||||
@@ -67,7 +67,7 @@ Rectangle {
|
|||||||
return String(display).padStart(2, '0').charAt(1)
|
return String(display).padStart(2, '0').charAt(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
width: 9
|
width: 9
|
||||||
@@ -81,7 +81,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(0)
|
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(0)
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
width: 9
|
width: 9
|
||||||
@@ -90,7 +90,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(1)
|
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(1)
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
width: 9
|
width: 9
|
||||||
@@ -123,7 +123,7 @@ Rectangle {
|
|||||||
const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0')
|
const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0')
|
||||||
return value.charAt(0)
|
return value.charAt(0)
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Light
|
font.weight: Font.Light
|
||||||
width: 9
|
width: 9
|
||||||
@@ -138,7 +138,7 @@ Rectangle {
|
|||||||
const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0')
|
const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0')
|
||||||
return value.charAt(1)
|
return value.charAt(1)
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Light
|
font.weight: Font.Light
|
||||||
width: 9
|
width: 9
|
||||||
@@ -158,7 +158,7 @@ Rectangle {
|
|||||||
const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0')
|
const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0')
|
||||||
return value.charAt(0)
|
return value.charAt(0)
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Light
|
font.weight: Font.Light
|
||||||
width: 9
|
width: 9
|
||||||
@@ -173,7 +173,7 @@ Rectangle {
|
|||||||
const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0')
|
const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0')
|
||||||
return value.charAt(1)
|
return value.charAt(1)
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Light
|
font.weight: Font.Light
|
||||||
width: 9
|
width: 9
|
||||||
@@ -194,7 +194,7 @@ Rectangle {
|
|||||||
const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP"
|
const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP"
|
||||||
return systemClock?.date?.toLocaleTimeString(Qt.locale(), format)
|
return systemClock?.date?.toLocaleTimeString(Qt.locale(), format)
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeMedium - 1
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,7 @@ Rectangle {
|
|||||||
|
|
||||||
return systemClock?.date?.toLocaleDateString(Qt.locale(), "ddd d")
|
return systemClock?.date?.toLocaleDateString(Qt.locale(), "ddd d")
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeMedium - 1
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: !SettingsData.clockCompactMode
|
visible: !SettingsData.clockCompactMode
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ Rectangle {
|
|||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
name: "palette"
|
name: "palette"
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness, -4)
|
||||||
color: colorPickerArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
color: colorPickerArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ Rectangle {
|
|||||||
|
|
||||||
return NetworkService.wifiSignalIcon
|
return NetworkService.wifiSignalIcon
|
||||||
}
|
}
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (NetworkService.wifiToggling) {
|
if (NetworkService.wifiToggling) {
|
||||||
return Theme.primary
|
return Theme.primary
|
||||||
@@ -61,12 +61,12 @@ Rectangle {
|
|||||||
return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton
|
return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton
|
||||||
}
|
}
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
visible: root.showNetworkIcon
|
visible: root.showNetworkIcon && NetworkService.networkAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "bluetooth"
|
name: "bluetooth"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
|
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
visible: root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled
|
visible: root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled
|
||||||
@@ -94,7 +94,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
return "volume_up"
|
return "volume_up"
|
||||||
}
|
}
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "settings"
|
name: "settings"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: controlCenterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
color: controlCenterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
visible: !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon
|
visible: !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon
|
||||||
@@ -151,7 +151,7 @@ Rectangle {
|
|||||||
|
|
||||||
return NetworkService.wifiSignalIcon;
|
return NetworkService.wifiSignalIcon;
|
||||||
}
|
}
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (NetworkService.wifiToggling) {
|
if (NetworkService.wifiToggling) {
|
||||||
return Theme.primary;
|
return Theme.primary;
|
||||||
@@ -160,7 +160,7 @@ Rectangle {
|
|||||||
return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton;
|
return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton;
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: root.showNetworkIcon
|
visible: root.showNetworkIcon && NetworkService.networkAvailable
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ Rectangle {
|
|||||||
id: bluetoothIcon
|
id: bluetoothIcon
|
||||||
|
|
||||||
name: "bluetooth"
|
name: "bluetooth"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
|
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled
|
visible: root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled
|
||||||
@@ -197,7 +197,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
return "volume_up";
|
return "volume_up";
|
||||||
}
|
}
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "mic"
|
name: "mic"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: false // TODO: Add mic detection
|
visible: false // TODO: Add mic detection
|
||||||
@@ -239,7 +239,7 @@ Rectangle {
|
|||||||
// Fallback settings icon when all other icons are hidden
|
// Fallback settings icon when all other icons are hidden
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "settings"
|
name: "settings"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: controlCenterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
color: controlCenterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon
|
visible: !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ Rectangle {
|
|||||||
property var parentScreen: null
|
property var parentScreen: null
|
||||||
property real barThickness: 48
|
property real barThickness: 48
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
|
property var widgetData: null
|
||||||
|
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (cpuContent.implicitWidth + horizontalPadding * 2)
|
width: isVertical ? widgetThickness : (cpuContent.implicitWidth + horizontalPadding * 2)
|
||||||
@@ -66,7 +68,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "memory"
|
name: "memory"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (DgopService.cpuUsage > 80) {
|
if (DgopService.cpuUsage > 80) {
|
||||||
return Theme.tempDanger;
|
return Theme.tempDanger;
|
||||||
@@ -89,7 +91,7 @@ Rectangle {
|
|||||||
|
|
||||||
return DgopService.cpuUsage.toFixed(0);
|
return DgopService.cpuUsage.toFixed(0);
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -104,7 +106,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "memory"
|
name: "memory"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (DgopService.cpuUsage > 80) {
|
if (DgopService.cpuUsage > 80) {
|
||||||
return Theme.tempDanger;
|
return Theme.tempDanger;
|
||||||
@@ -127,7 +129,7 @@ Rectangle {
|
|||||||
|
|
||||||
return DgopService.cpuUsage.toFixed(0) + "%";
|
return DgopService.cpuUsage.toFixed(0) + "%";
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -136,12 +138,12 @@ Rectangle {
|
|||||||
|
|
||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
id: cpuBaseline
|
id: cpuBaseline
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
text: "100%"
|
text: "100%"
|
||||||
}
|
}
|
||||||
|
|
||||||
width: Math.max(cpuBaseline.width, paintedWidth)
|
width: root.minimumWidth ? Math.max(cpuBaseline.width, paintedWidth) : paintedWidth
|
||||||
|
|
||||||
Behavior on width {
|
Behavior on width {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ Rectangle {
|
|||||||
property var parentScreen: null
|
property var parentScreen: null
|
||||||
property real barThickness: 48
|
property real barThickness: 48
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
|
property var widgetData: null
|
||||||
|
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (cpuTempContent.implicitWidth + horizontalPadding * 2)
|
width: isVertical ? widgetThickness : (cpuTempContent.implicitWidth + horizontalPadding * 2)
|
||||||
@@ -65,8 +67,8 @@ Rectangle {
|
|||||||
spacing: 1
|
spacing: 1
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "memory"
|
name: "device_thermostat"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (DgopService.cpuTemperature > 85) {
|
if (DgopService.cpuTemperature > 85) {
|
||||||
return Theme.tempDanger;
|
return Theme.tempDanger;
|
||||||
@@ -89,7 +91,7 @@ Rectangle {
|
|||||||
|
|
||||||
return Math.round(DgopService.cpuTemperature).toString();
|
return Math.round(DgopService.cpuTemperature).toString();
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -103,8 +105,8 @@ Rectangle {
|
|||||||
spacing: 3
|
spacing: 3
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "memory"
|
name: "device_thermostat"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (DgopService.cpuTemperature > 85) {
|
if (DgopService.cpuTemperature > 85) {
|
||||||
return Theme.tempDanger;
|
return Theme.tempDanger;
|
||||||
@@ -127,7 +129,7 @@ Rectangle {
|
|||||||
|
|
||||||
return Math.round(DgopService.cpuTemperature) + "°";
|
return Math.round(DgopService.cpuTemperature) + "°";
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -136,12 +138,12 @@ Rectangle {
|
|||||||
|
|
||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
id: tempBaseline
|
id: tempBaseline
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
text: "100°"
|
text: "100°"
|
||||||
}
|
}
|
||||||
|
|
||||||
width: Math.max(tempBaseline.width, paintedWidth)
|
width: root.minimumWidth ? Math.max(tempBaseline.width, paintedWidth) : paintedWidth
|
||||||
|
|
||||||
Behavior on width {
|
Behavior on width {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ Rectangle {
|
|||||||
property var widgetData: null
|
property var widgetData: null
|
||||||
property var parentScreen: null
|
property var parentScreen: null
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
|
property real barThickness: 48
|
||||||
property string mountPath: (widgetData && widgetData.mountPath !== undefined) ? widgetData.mountPath : "/"
|
property string mountPath: (widgetData && widgetData.mountPath !== undefined) ? widgetData.mountPath : "/"
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||||
|
|
||||||
@@ -144,7 +145,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "storage"
|
name: "storage"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (root.diskUsagePercent > 90) {
|
if (root.diskUsagePercent > 90) {
|
||||||
return Theme.tempDanger
|
return Theme.tempDanger
|
||||||
@@ -164,7 +165,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
return root.diskUsagePercent.toFixed(0)
|
return root.diskUsagePercent.toFixed(0)
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -179,7 +180,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "storage"
|
name: "storage"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (root.diskUsagePercent > 90) {
|
if (root.diskUsagePercent > 90) {
|
||||||
return Theme.tempDanger
|
return Theme.tempDanger
|
||||||
@@ -199,7 +200,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
return root.selectedMount.mount
|
return root.selectedMount.mount
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -214,7 +215,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
return root.diskUsagePercent.toFixed(0) + "%"
|
return root.diskUsagePercent.toFixed(0) + "%"
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -223,7 +224,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
id: diskBaseline
|
id: diskBaseline
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
text: "100%"
|
text: "100%"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ Rectangle {
|
|||||||
property bool compactMode: SettingsData.focusedWindowCompactMode
|
property bool compactMode: SettingsData.focusedWindowCompactMode
|
||||||
property int availableWidth: 400
|
property int availableWidth: 400
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
|
property real barThickness: 48
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
||||||
readonly property int baseWidth: contentRow.implicitWidth + horizontalPadding * 2
|
readonly property int baseWidth: contentRow.implicitWidth + horizontalPadding * 2
|
||||||
readonly property int maxNormalWidth: 456
|
readonly property int maxNormalWidth: 456
|
||||||
@@ -171,7 +172,7 @@ Rectangle {
|
|||||||
const desktopEntry = DesktopEntries.heuristicLookup(activeWindow.appId);
|
const desktopEntry = DesktopEntries.heuristicLookup(activeWindow.appId);
|
||||||
return desktopEntry && desktopEntry.name ? desktopEntry.name : activeWindow.appId;
|
return desktopEntry && desktopEntry.name ? desktopEntry.name : activeWindow.appId;
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -183,7 +184,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "•"
|
text: "•"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.outlineButton
|
color: Theme.outlineButton
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: !compactMode && appText.text && titleText.text
|
visible: !compactMode && appText.text && titleText.text
|
||||||
@@ -209,7 +210,7 @@ Rectangle {
|
|||||||
|
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ Rectangle {
|
|||||||
property real barThickness: 48
|
property real barThickness: 48
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex !== undefined) ? widgetData.selectedGpuIndex : 0
|
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex !== undefined) ? widgetData.selectedGpuIndex : 0
|
||||||
|
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||||
property real displayTemp: {
|
property real displayTemp: {
|
||||||
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
|
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
|
||||||
@@ -134,7 +135,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "auto_awesome_mosaic"
|
name: "auto_awesome_mosaic"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (root.displayTemp > 80) {
|
if (root.displayTemp > 80) {
|
||||||
return Theme.tempDanger;
|
return Theme.tempDanger;
|
||||||
@@ -157,7 +158,7 @@ Rectangle {
|
|||||||
|
|
||||||
return Math.round(root.displayTemp).toString();
|
return Math.round(root.displayTemp).toString();
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -172,7 +173,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "auto_awesome_mosaic"
|
name: "auto_awesome_mosaic"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (root.displayTemp > 80) {
|
if (root.displayTemp > 80) {
|
||||||
return Theme.tempDanger;
|
return Theme.tempDanger;
|
||||||
@@ -195,7 +196,7 @@ Rectangle {
|
|||||||
|
|
||||||
return Math.round(root.displayTemp) + "°";
|
return Math.round(root.displayTemp) + "°";
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -204,12 +205,12 @@ Rectangle {
|
|||||||
|
|
||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
id: gpuTempBaseline
|
id: gpuTempBaseline
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
text: "100°"
|
text: "100°"
|
||||||
}
|
}
|
||||||
|
|
||||||
width: Math.max(gpuTempBaseline.width, paintedWidth)
|
width: root.minimumWidth ? Math.max(gpuTempBaseline.width, paintedWidth) : paintedWidth
|
||||||
|
|
||||||
Behavior on width {
|
Behavior on width {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ Rectangle {
|
|||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
name: SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
|
name: SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness, -4)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ Rectangle {
|
|||||||
property bool isVertical: axis?.isVertical ?? false
|
property bool isVertical: axis?.isVertical ?? false
|
||||||
property var axis: null
|
property var axis: null
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
|
property real barThickness: 48
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||||
property string currentLayout: ""
|
property string currentLayout: ""
|
||||||
property string hyprlandKeyboard: ""
|
property string hyprlandKeyboard: ""
|
||||||
@@ -59,7 +60,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "keyboard"
|
name: "keyboard"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
@@ -73,7 +74,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
return currentLayout.substring(0, 2).toUpperCase()
|
return currentLayout.substring(0, 2).toUpperCase()
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -89,7 +90,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: currentLayout
|
text: currentLayout
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
@@ -53,22 +56,65 @@ Item {
|
|||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemLogo {
|
|
||||||
visible: SettingsData.useOSLogo
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: Theme.iconSize - 3
|
|
||||||
height: Theme.iconSize - 3
|
|
||||||
colorOverride: SettingsData.osLogoColorOverride
|
|
||||||
brightnessOverride: SettingsData.osLogoBrightness
|
|
||||||
contrastOverride: SettingsData.osLogoContrast
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
visible: !SettingsData.useOSLogo
|
visible: SettingsData.launcherLogoMode === "apps"
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
name: "apps"
|
name: "apps"
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness, -4)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SystemLogo {
|
||||||
|
visible: SettingsData.launcherLogoMode === "os"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: Theme.barIconSize(barThickness, SettingsData.launcherLogoSizeOffset)
|
||||||
|
height: Theme.barIconSize(barThickness, SettingsData.launcherLogoSizeOffset)
|
||||||
|
colorOverride: Theme.effectiveLogoColor
|
||||||
|
brightnessOverride: SettingsData.launcherLogoBrightness
|
||||||
|
contrastOverride: SettingsData.launcherLogoContrast
|
||||||
|
}
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
visible: SettingsData.launcherLogoMode === "compositor"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: Theme.barIconSize(barThickness, SettingsData.launcherLogoSizeOffset)
|
||||||
|
height: Theme.barIconSize(barThickness, SettingsData.launcherLogoSizeOffset)
|
||||||
|
smooth: true
|
||||||
|
asynchronous: true
|
||||||
|
source: {
|
||||||
|
if (CompositorService.isNiri) {
|
||||||
|
return "file://" + Theme.shellDir + "/assets/niri.svg"
|
||||||
|
} else if (CompositorService.isHyprland) {
|
||||||
|
return "file://" + Theme.shellDir + "/assets/hyprland.svg"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
layer.enabled: Theme.effectiveLogoColor !== ""
|
||||||
|
layer.effect: MultiEffect {
|
||||||
|
saturation: 0
|
||||||
|
colorization: 1
|
||||||
|
colorizationColor: Theme.effectiveLogoColor
|
||||||
|
brightness: SettingsData.launcherLogoBrightness
|
||||||
|
contrast: SettingsData.launcherLogoContrast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
visible: SettingsData.launcherLogoMode === "custom" && SettingsData.launcherLogoCustomPath !== ""
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: Theme.barIconSize(barThickness, SettingsData.launcherLogoSizeOffset)
|
||||||
|
height: Theme.barIconSize(barThickness, SettingsData.launcherLogoSizeOffset)
|
||||||
|
smooth: true
|
||||||
|
asynchronous: true
|
||||||
|
source: SettingsData.launcherLogoCustomPath ? "file://" + SettingsData.launcherLogoCustomPath.replace("file://", "") : ""
|
||||||
|
layer.enabled: Theme.effectiveLogoColor !== ""
|
||||||
|
layer.effect: MultiEffect {
|
||||||
|
saturation: 0
|
||||||
|
colorization: 1
|
||||||
|
colorizationColor: Theme.effectiveLogoColor
|
||||||
|
brightness: SettingsData.launcherLogoBrightness
|
||||||
|
contrast: SettingsData.launcherLogoContrast
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ Rectangle {
|
|||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: textContainer.displayText
|
text: textContainer.displayText
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ Rectangle {
|
|||||||
readonly property int baseWidth: contentRow.implicitWidth + Theme.spacingS * 2
|
readonly property int baseWidth: contentRow.implicitWidth + Theme.spacingS * 2
|
||||||
readonly property int maxNormalWidth: 456
|
readonly property int maxNormalWidth: 456
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
|
property real barThickness: 48
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||||
|
|
||||||
function formatNetworkSpeed(bytesPerSec) {
|
function formatNetworkSpeed(bytesPerSec) {
|
||||||
@@ -63,7 +64,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "network_check"
|
name: "network_check"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
@@ -75,7 +76,7 @@ Rectangle {
|
|||||||
if (rate < 1024 * 1024) return (rate / 1024).toFixed(0) + "K"
|
if (rate < 1024 * 1024) return (rate / 1024).toFixed(0) + "K"
|
||||||
return (rate / (1024 * 1024)).toFixed(0) + "M"
|
return (rate / (1024 * 1024)).toFixed(0) + "M"
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.info
|
color: Theme.info
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -88,7 +89,7 @@ Rectangle {
|
|||||||
if (rate < 1024 * 1024) return (rate / 1024).toFixed(0) + "K"
|
if (rate < 1024 * 1024) return (rate / 1024).toFixed(0) + "K"
|
||||||
return (rate / (1024 * 1024)).toFixed(0) + "M"
|
return (rate / (1024 * 1024)).toFixed(0) + "M"
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -104,7 +105,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "network_check"
|
name: "network_check"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
@@ -115,13 +116,13 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "↓"
|
text: "↓"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.info
|
color: Theme.info
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: DgopService.networkRxRate > 0 ? formatNetworkSpeed(DgopService.networkRxRate) : "0 B/s"
|
text: DgopService.networkRxRate > 0 ? formatNetworkSpeed(DgopService.networkRxRate) : "0 B/s"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -131,7 +132,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
id: rxBaseline
|
id: rxBaseline
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
text: "88.8 MB/s"
|
text: "88.8 MB/s"
|
||||||
}
|
}
|
||||||
@@ -154,13 +155,13 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "↑"
|
text: "↑"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: DgopService.networkTxRate > 0 ? formatNetworkSpeed(DgopService.networkTxRate) : "0 B/s"
|
text: DgopService.networkTxRate > 0 ? formatNetworkSpeed(DgopService.networkTxRate) : "0 B/s"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -170,7 +171,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
id: txBaseline
|
id: txBaseline
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
text: "88.8 MB/s"
|
text: "88.8 MB/s"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ Rectangle {
|
|||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
name: "assignment"
|
name: "assignment"
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness, -4)
|
||||||
color: notepadArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
color: notepadArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ Item {
|
|||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
|
name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness, -4)
|
||||||
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText)
|
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ Rectangle {
|
|||||||
property var popupTarget: null
|
property var popupTarget: null
|
||||||
property var parentScreen: null
|
property var parentScreen: null
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
|
property real barThickness: 48
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
||||||
readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive
|
readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive
|
||||||
readonly property int activeCount: PrivacyService.microphoneActive + PrivacyService.cameraActive + PrivacyService.screensharingActive
|
readonly property int activeCount: PrivacyService.microphoneActive + PrivacyService.cameraActive + PrivacyService.screensharingActive
|
||||||
@@ -198,7 +199,7 @@ Rectangle {
|
|||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: PrivacyService.getPrivacySummary()
|
text: PrivacyService.getPrivacySummary()
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ Rectangle {
|
|||||||
property var parentScreen: null
|
property var parentScreen: null
|
||||||
property real barThickness: 48
|
property real barThickness: 48
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
|
property var widgetData: null
|
||||||
|
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (ramContent.implicitWidth + horizontalPadding * 2)
|
width: isVertical ? widgetThickness : (ramContent.implicitWidth + horizontalPadding * 2)
|
||||||
@@ -30,6 +32,7 @@ Rectangle {
|
|||||||
const baseColor = ramArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
const baseColor = ramArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
DgopService.addRef(["memory"]);
|
DgopService.addRef(["memory"]);
|
||||||
}
|
}
|
||||||
@@ -66,7 +69,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "developer_board"
|
name: "developer_board"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (DgopService.memoryUsage > 90) {
|
if (DgopService.memoryUsage > 90) {
|
||||||
return Theme.tempDanger;
|
return Theme.tempDanger;
|
||||||
@@ -89,7 +92,7 @@ Rectangle {
|
|||||||
|
|
||||||
return DgopService.memoryUsage.toFixed(0);
|
return DgopService.memoryUsage.toFixed(0);
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -104,7 +107,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: "developer_board"
|
name: "developer_board"
|
||||||
size: Theme.iconSize - 8
|
size: Theme.barIconSize(barThickness)
|
||||||
color: {
|
color: {
|
||||||
if (DgopService.memoryUsage > 90) {
|
if (DgopService.memoryUsage > 90) {
|
||||||
return Theme.tempDanger;
|
return Theme.tempDanger;
|
||||||
@@ -127,7 +130,7 @@ Rectangle {
|
|||||||
|
|
||||||
return DgopService.memoryUsage.toFixed(0) + "%";
|
return DgopService.memoryUsage.toFixed(0) + "%";
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -136,12 +139,12 @@ Rectangle {
|
|||||||
|
|
||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
id: ramBaseline
|
id: ramBaseline
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
text: "100%"
|
text: "100%"
|
||||||
}
|
}
|
||||||
|
|
||||||
width: Math.max(ramBaseline.width, paintedWidth)
|
width: root.minimumWidth ? Math.max(ramBaseline.width, paintedWidth) : paintedWidth
|
||||||
|
|
||||||
Behavior on width {
|
Behavior on width {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ Rectangle {
|
|||||||
property var hoveredItem: null
|
property var hoveredItem: null
|
||||||
property var topBar: null
|
property var topBar: null
|
||||||
property real widgetThickness: 30
|
property real widgetThickness: 30
|
||||||
|
property real barThickness: 48
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
||||||
property Item windowRoot: (Window.window ? Window.window.contentItem : null)
|
property Item windowRoot: (Window.window ? Window.window.contentItem : null)
|
||||||
readonly property var sortedToplevels: {
|
readonly property var sortedToplevels: {
|
||||||
@@ -272,7 +273,7 @@ Rectangle {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: !SettingsData.runningAppsCompactMode
|
visible: !SettingsData.runningAppsCompactMode
|
||||||
text: windowTitle
|
text: windowTitle
|
||||||
font.pixelSize: Theme.fontSizeMedium - 1
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
@@ -463,7 +464,7 @@ Rectangle {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: !SettingsData.runningAppsCompactMode
|
visible: !SettingsData.runningAppsCompactMode
|
||||||
text: windowTitle
|
text: windowTitle
|
||||||
font.pixelSize: Theme.fontSizeMedium - 1
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
@@ -610,7 +611,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Close"
|
text: I18n.tr("Close")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
|
|||||||
@@ -66,7 +66,10 @@ Rectangle {
|
|||||||
|
|
||||||
const name = split[0];
|
const name = split[0];
|
||||||
const path = split[1];
|
const path = split[1];
|
||||||
const fileName = name.substring(name.lastIndexOf("/") + 1);
|
let fileName = name.substring(name.lastIndexOf("/") + 1);
|
||||||
|
if (fileName.startsWith("dropboxstatus")) {
|
||||||
|
fileName = `hicolor/16x16/status/${fileName}`;
|
||||||
|
}
|
||||||
return `file://${path}/${fileName}`;
|
return `file://${path}/${fileName}`;
|
||||||
}
|
}
|
||||||
if (icon.startsWith("/") && !icon.startsWith("file://")) {
|
if (icon.startsWith("/") && !icon.startsWith("file://")) {
|
||||||
@@ -445,7 +448,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Back"
|
text: I18n.tr("Back")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Rectangle {
|
|||||||
if (hasUpdates) return "system_update_alt";
|
if (hasUpdates) return "system_update_alt";
|
||||||
return "check_circle";
|
return "check_circle";
|
||||||
}
|
}
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness, -4)
|
||||||
color: {
|
color: {
|
||||||
if (SystemUpdateService.hasError) return Theme.error;
|
if (SystemUpdateService.hasError) return Theme.error;
|
||||||
if (hasUpdates) return Theme.primary;
|
if (hasUpdates) return Theme.primary;
|
||||||
@@ -97,7 +97,7 @@ Rectangle {
|
|||||||
if (hasUpdates) return "system_update_alt";
|
if (hasUpdates) return "system_update_alt";
|
||||||
return "check_circle";
|
return "check_circle";
|
||||||
}
|
}
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness, -4)
|
||||||
color: {
|
color: {
|
||||||
if (SystemUpdateService.hasError) return Theme.error;
|
if (SystemUpdateService.hasError) return Theme.error;
|
||||||
if (hasUpdates) return Theme.primary;
|
if (hasUpdates) return Theme.primary;
|
||||||
@@ -127,7 +127,7 @@ Rectangle {
|
|||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: SystemUpdateService.updateCount.toString()
|
text: SystemUpdateService.updateCount.toString()
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
visible: hasUpdates && !isChecking
|
visible: hasUpdates && !isChecking
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import qs.Widgets
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
Ref {
|
||||||
|
service: VpnService
|
||||||
|
}
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
property bool isVertical: axis?.isVertical ?? false
|
||||||
property var axis: null
|
property var axis: null
|
||||||
property int widgetThickness: 28
|
property int widgetThickness: 28
|
||||||
@@ -34,7 +38,7 @@ Rectangle {
|
|||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
name: VpnService.isBusy ? "sync" : (VpnService.connected ? "vpn_lock" : "vpn_key_off")
|
name: VpnService.isBusy ? "sync" : (VpnService.connected ? "vpn_lock" : "vpn_key_off")
|
||||||
size: Theme.iconSize - 6
|
size: Theme.barIconSize(barThickness, -4)
|
||||||
color: VpnService.connected ? Theme.primary : Theme.surfaceText
|
color: VpnService.connected ? Theme.primary : Theme.surfaceText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
||||||
size: Theme.iconSize - 4
|
size: Theme.barIconSize(barThickness, -6)
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ Rectangle {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
||||||
size: Theme.iconSize - 4
|
size: Theme.barIconSize(barThickness, -6)
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ Rectangle {
|
|||||||
|
|
||||||
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
|
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ Rectangle {
|
|||||||
property var axis: null
|
property var axis: null
|
||||||
property string screenName: ""
|
property string screenName: ""
|
||||||
property real widgetHeight: 30
|
property real widgetHeight: 30
|
||||||
|
property real barThickness: 48
|
||||||
property int currentWorkspace: {
|
property int currentWorkspace: {
|
||||||
if (CompositorService.isNiri) {
|
if (CompositorService.isNiri) {
|
||||||
return getNiriActiveWorkspace()
|
return getNiriActiveWorkspace()
|
||||||
@@ -29,6 +30,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
if (CompositorService.isHyprland) {
|
if (CompositorService.isHyprland) {
|
||||||
const baseList = getHyprlandWorkspaces()
|
const baseList = getHyprlandWorkspaces()
|
||||||
|
// Filter out special:scratch_term
|
||||||
|
const filteredList = baseList.filter(ws => ws.name !== "special:scratch_term" && ws.id !== -98)
|
||||||
return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList
|
return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList
|
||||||
}
|
}
|
||||||
return [1]
|
return [1]
|
||||||
@@ -293,19 +296,30 @@ Rectangle {
|
|||||||
property bool isHovered: mouseArea.containsMouse
|
property bool isHovered: mouseArea.containsMouse
|
||||||
|
|
||||||
property var loadedWorkspaceData: null
|
property var loadedWorkspaceData: null
|
||||||
|
property bool loadedIsUrgent: false
|
||||||
|
property bool isUrgent: {
|
||||||
|
if (CompositorService.isHyprland) {
|
||||||
|
return modelData?.urgent ?? false
|
||||||
|
}
|
||||||
|
if (CompositorService.isNiri) {
|
||||||
|
return loadedIsUrgent
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
property var loadedIconData: null
|
property var loadedIconData: null
|
||||||
property bool loadedHasIcon: false
|
property bool loadedHasIcon: false
|
||||||
property var loadedIcons: []
|
property var loadedIcons: []
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: dataUpdateTimer
|
id: dataUpdateTimer
|
||||||
interval: 50 // Defer data calculation by 50ms
|
interval: 50
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (isPlaceholder) {
|
if (isPlaceholder) {
|
||||||
delegateRoot.loadedWorkspaceData = null
|
delegateRoot.loadedWorkspaceData = null
|
||||||
delegateRoot.loadedIconData = null
|
delegateRoot.loadedIconData = null
|
||||||
delegateRoot.loadedHasIcon = false
|
delegateRoot.loadedHasIcon = false
|
||||||
delegateRoot.loadedIcons = []
|
delegateRoot.loadedIcons = []
|
||||||
|
delegateRoot.loadedIsUrgent = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,6 +330,7 @@ Rectangle {
|
|||||||
wsData = modelData;
|
wsData = modelData;
|
||||||
}
|
}
|
||||||
delegateRoot.loadedWorkspaceData = wsData;
|
delegateRoot.loadedWorkspaceData = wsData;
|
||||||
|
delegateRoot.loadedIsUrgent = wsData?.is_urgent ?? false;
|
||||||
|
|
||||||
var icData = null;
|
var icData = null;
|
||||||
if (wsData?.name) {
|
if (wsData?.name) {
|
||||||
@@ -363,7 +378,10 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
radius: Math.min(width, height) / 2
|
radius: Math.min(width, height) / 2
|
||||||
color: isActive ? Theme.primary : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.outlineButton : Theme.surfaceTextAlpha
|
color: isActive ? Theme.primary : isUrgent ? Theme.error : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.outlineButton : Theme.surfaceTextAlpha
|
||||||
|
|
||||||
|
border.width: isUrgent && !isActive ? 2 : 0
|
||||||
|
border.color: isUrgent && !isActive ? Theme.error : Theme.withAlpha(Theme.error, 0)
|
||||||
|
|
||||||
Behavior on width {
|
Behavior on width {
|
||||||
enabled: (!SettingsData.showWorkspaceApps || SettingsData.maxWorkspaceIcons <= 3)
|
enabled: (!SettingsData.showWorkspaceApps || SettingsData.maxWorkspaceIcons <= 3)
|
||||||
@@ -381,12 +399,26 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Theme.mediumDuration
|
||||||
|
easing.type: Theme.emphasizedEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on border.width {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.emphasizedEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: root.isVertical ? parent.width + Theme.spacingXL : parent.width
|
width: root.isVertical ? parent.width + Theme.spacingXL : parent.width
|
||||||
height: root.isVerical ? parent.height : parent.height + Theme.spacingXL
|
height: root.isVertical ? parent.height : parent.height + Theme.spacingXL
|
||||||
hoverEnabled: !isPlaceholder
|
hoverEnabled: !isPlaceholder
|
||||||
cursorShape: isPlaceholder ? Qt.ArrowCursor : Qt.PointingHandCursor
|
cursorShape: isPlaceholder ? Qt.ArrowCursor : Qt.PointingHandCursor
|
||||||
enabled: !isPlaceholder
|
enabled: !isPlaceholder
|
||||||
@@ -580,7 +612,7 @@ Rectangle {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: loadedIconData ? loadedIconData.value : "" // NULL CHECK
|
text: loadedIconData ? loadedIconData.value : "" // NULL CHECK
|
||||||
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium
|
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
|
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -601,8 +633,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
return CompositorService.isHyprland ? (modelData?.id || "") : (modelData - 1);
|
return CompositorService.isHyprland ? (modelData?.id || "") : (modelData - 1);
|
||||||
}
|
}
|
||||||
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
|
color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.barTextSize(barThickness)
|
||||||
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
|
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -619,6 +651,7 @@ Rectangle {
|
|||||||
target: NiriService
|
target: NiriService
|
||||||
enabled: CompositorService.isNiri
|
enabled: CompositorService.isNiri
|
||||||
function onAllWorkspacesChanged() { delegateRoot.updateAllData() }
|
function onAllWorkspacesChanged() { delegateRoot.updateAllData() }
|
||||||
|
function onWindowUrgentChanged() { delegateRoot.updateAllData() }
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: SettingsData
|
target: SettingsData
|
||||||
|
|||||||
@@ -131,15 +131,15 @@ DankPopout {
|
|||||||
|
|
||||||
model: {
|
model: {
|
||||||
let tabs = [
|
let tabs = [
|
||||||
{ icon: "dashboard", text: "Overview" },
|
{ icon: "dashboard", text: I18n.tr("Overview") },
|
||||||
{ icon: "music_note", text: "Media" }
|
{ icon: "music_note", text: I18n.tr("Media") }
|
||||||
]
|
]
|
||||||
|
|
||||||
if (SettingsData.weatherEnabled) {
|
if (SettingsData.weatherEnabled) {
|
||||||
tabs.push({ icon: "wb_sunny", text: "Weather" })
|
tabs.push({ icon: "wb_sunny", text: I18n.tr("Weather") })
|
||||||
}
|
}
|
||||||
|
|
||||||
tabs.push({ icon: "settings", text: "Settings", isAction: true })
|
tabs.push({ icon: "settings", text: I18n.tr("Settings"), isAction: true })
|
||||||
return tabs
|
return tabs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "No Active Players"
|
text: I18n.tr("No Active Players")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -406,7 +406,7 @@ Item {
|
|||||||
anchors.margins: Theme.spacingM
|
anchors.margins: Theme.spacingM
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Audio Output Devices (" + audioDevicesDropdown.availableDevices.length + ")"
|
text: I18n.tr("Audio Output Devices (") + audioDevicesDropdown.availableDevices.length + ")"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
@@ -564,7 +564,7 @@ Item {
|
|||||||
anchors.margins: Theme.spacingM
|
anchors.margins: Theme.spacingM
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Media Players (" + (allPlayers?.length || 0) + ")"
|
text: I18n.tr("Media Players (") + (allPlayers?.length || 0) + ")"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ Card {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "No Media"
|
text: I18n.tr("No Media")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ Card {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "Refresh"
|
text: I18n.tr("Refresh")
|
||||||
flat: true
|
flat: true
|
||||||
visible: !WeatherService.weather.loading
|
visible: !WeatherService.weather.loading
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "No Weather Data Available"
|
text: I18n.tr("No Weather Data Available")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -257,7 +257,7 @@ Item {
|
|||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Feels Like"
|
text: I18n.tr("Feels Like")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -304,7 +304,7 @@ Item {
|
|||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Humidity"
|
text: I18n.tr("Humidity")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -351,7 +351,7 @@ Item {
|
|||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Wind"
|
text: I18n.tr("Wind")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -398,7 +398,7 @@ Item {
|
|||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Pressure"
|
text: I18n.tr("Pressure")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -445,7 +445,7 @@ Item {
|
|||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Rain Chance"
|
text: I18n.tr("Rain Chance")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -492,14 +492,14 @@ Item {
|
|||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Visibility"
|
text: I18n.tr("Visibility")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Good"
|
text: I18n.tr("Good")
|
||||||
font.pixelSize: Theme.fontSizeSmall + 1
|
font.pixelSize: Theme.fontSizeSmall + 1
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -522,7 +522,7 @@ Item {
|
|||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "7-Day Forecast"
|
text: I18n.tr("7-Day Forecast")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ Variants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
property bool reveal: {
|
property bool reveal: {
|
||||||
if (CompositorService.isNiri && NiriService.inOverview) {
|
if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) {
|
||||||
return SettingsData.dockOpenOnOverview
|
return true
|
||||||
}
|
}
|
||||||
return (!autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky) && !windowIsFullscreen
|
return (!autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky) && !windowIsFullscreen
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ Variants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
screen: modelData
|
screen: modelData
|
||||||
visible: SettingsData.showDock
|
visible: SettingsData.showDock || (CompositorService.isNiri && SettingsData.dockOpenOnOverview && NiriService.inOverview)
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
|
|
||||||
@@ -264,19 +264,21 @@ Variants {
|
|||||||
x: {
|
x: {
|
||||||
if (!dock.isVertical) return 0
|
if (!dock.isVertical) return 0
|
||||||
if (dock.reveal) return 0
|
if (dock.reveal) return 0
|
||||||
|
const hideDistance = 58 + SettingsData.dockSpacing + SettingsData.dockBottomGap + 10
|
||||||
if (SettingsData.dockPosition === SettingsData.Position.Right) {
|
if (SettingsData.dockPosition === SettingsData.Position.Right) {
|
||||||
return 60
|
return hideDistance
|
||||||
} else {
|
} else {
|
||||||
return -60
|
return -hideDistance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y: {
|
y: {
|
||||||
if (dock.isVertical) return 0
|
if (dock.isVertical) return 0
|
||||||
if (dock.reveal) return 0
|
if (dock.reveal) return 0
|
||||||
|
const hideDistance = 58 + SettingsData.dockSpacing + SettingsData.dockBottomGap + 10
|
||||||
if (SettingsData.dockPosition === SettingsData.Position.Bottom) {
|
if (SettingsData.dockPosition === SettingsData.Position.Bottom) {
|
||||||
return 60
|
return hideDistance
|
||||||
} else {
|
} else {
|
||||||
return -60
|
return -hideDistance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -316,9 +316,8 @@ Item {
|
|||||||
console.warn("No toplevel found for grouped app")
|
console.warn("No toplevel found for grouped app")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For multiple windows, show context menu (hide pin option for left-click)
|
|
||||||
if (contextMenu) {
|
if (contextMenu) {
|
||||||
contextMenu.showForButton(root, appData, 65, true)
|
contextMenu.showForButton(root, appData, 65, true, cachedDesktopEntry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,8 +337,7 @@ Item {
|
|||||||
}
|
}
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
if (contextMenu && appData) {
|
if (contextMenu && appData) {
|
||||||
console.log("Right-clicked on app:", appData.appId, "type:", appData.type, "windowCount:", appData.windowCount || 0)
|
contextMenu.showForButton(root, appData, 40, false, cachedDesktopEntry)
|
||||||
contextMenu.showForButton(root, appData, 40, false)
|
|
||||||
} else {
|
} else {
|
||||||
console.warn("No context menu or appData available")
|
console.warn("No context menu or appData available")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
@@ -16,12 +15,14 @@ PanelWindow {
|
|||||||
property real dockVisibleHeight: 40
|
property real dockVisibleHeight: 40
|
||||||
property int margin: 10
|
property int margin: 10
|
||||||
property bool hidePin: false
|
property bool hidePin: false
|
||||||
|
property var desktopEntry: null
|
||||||
|
|
||||||
function showForButton(button, data, dockHeight, hidePinOption) {
|
function showForButton(button, data, dockHeight, hidePinOption, entry) {
|
||||||
anchorItem = button
|
anchorItem = button
|
||||||
appData = data
|
appData = data
|
||||||
dockVisibleHeight = dockHeight || 40
|
dockVisibleHeight = dockHeight || 40
|
||||||
hidePin = hidePinOption || false
|
hidePin = hidePinOption || false
|
||||||
|
desktopEntry = entry || null
|
||||||
|
|
||||||
const dockWindow = button.Window.window
|
const dockWindow = button.Window.window
|
||||||
if (dockWindow) {
|
if (dockWindow) {
|
||||||
@@ -134,9 +135,6 @@ PanelWindow {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: menuContainer
|
id: menuContainer
|
||||||
|
|
||||||
width: Math.min(400, Math.max(200, menuColumn.implicitWidth + Theme.spacingS * 2))
|
|
||||||
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
|
|
||||||
|
|
||||||
x: {
|
x: {
|
||||||
const isVertical = SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right
|
const isVertical = SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right
|
||||||
if (isVertical) {
|
if (isVertical) {
|
||||||
@@ -169,12 +167,23 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
width: Math.min(400, Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2))
|
||||||
|
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
|
||||||
color: Theme.popupBackground()
|
color: Theme.popupBackground()
|
||||||
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)
|
||||||
border.width: 1
|
border.width: 1
|
||||||
opacity: showContextMenu ? 1 : 0
|
|
||||||
scale: showContextMenu ? 1 : 0.85
|
opacity: root.showContextMenu ? 1 : 0
|
||||||
|
visible: opacity > 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.emphasizedEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -184,7 +193,7 @@ PanelWindow {
|
|||||||
anchors.bottomMargin: -4
|
anchors.bottomMargin: -4
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
color: Qt.rgba(0, 0, 0, 0.15)
|
color: Qt.rgba(0, 0, 0, 0.15)
|
||||||
z: parent.z - 1
|
z: -1
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -223,7 +232,7 @@ PanelWindow {
|
|||||||
anchors.right: closeButton.left
|
anchors.right: closeButton.left
|
||||||
anchors.rightMargin: Theme.spacingXS
|
anchors.rightMargin: Theme.spacingXS
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: (modelData && modelData.title) ? modelData.title : "(Unnamed)"
|
text: (modelData && modelData.title) ? modelData.title: I18n.tr("(Unnamed)")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
@@ -289,6 +298,71 @@ PanelWindow {
|
|||||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: root.desktopEntry && root.desktopEntry.actions ? root.desktopEntry.actions : []
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 28
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: actionArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 16
|
||||||
|
height: 16
|
||||||
|
visible: modelData.icon && modelData.icon !== ""
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: modelData.icon ? Quickshell.iconPath(modelData.icon, true) : ""
|
||||||
|
smooth: true
|
||||||
|
asynchronous: true
|
||||||
|
visible: status === Image.Ready
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: modelData.name || ""
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Normal
|
||||||
|
elide: Text.ElideRight
|
||||||
|
wrapMode: Text.NoWrap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: actionArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
if (modelData) {
|
||||||
|
SessionService.launchDesktopAction(root.desktopEntry, modelData)
|
||||||
|
}
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: root.desktopEntry && root.desktopEntry.actions && root.desktopEntry.actions.length > 0
|
||||||
|
width: parent.width
|
||||||
|
height: 1
|
||||||
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: !root.hidePin
|
visible: !root.hidePin
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -302,7 +376,7 @@ PanelWindow {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Theme.spacingS
|
anchors.rightMargin: Theme.spacingS
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: root.appData && root.appData.isPinned ? "Unpin from Dock" : "Pin to Dock"
|
text: root.appData && root.appData.isPinned ? I18n.tr("Unpin from Dock") : I18n.tr("Pin to Dock")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
@@ -330,14 +404,49 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: root.appData && root.appData.type === "window"
|
visible: (root.appData && root.appData.type === "window") || (root.desktopEntry && SessionService.hasPrimeRun)
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 1
|
height: 1
|
||||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: root.appData && root.appData.type === "window"
|
visible: root.desktopEntry && SessionService.hasPrimeRun
|
||||||
|
width: parent.width
|
||||||
|
height: 28
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: primeRunArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: I18n.tr("Launch on dGPU")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Normal
|
||||||
|
elide: Text.ElideRight
|
||||||
|
wrapMode: Text.NoWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: primeRunArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
if (root.desktopEntry) {
|
||||||
|
SessionService.launchDesktopEntry(root.desktopEntry, true)
|
||||||
|
}
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: root.appData && (root.appData.type === "window" || (root.appData.type === "grouped" && root.appData.windowCount > 0))
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 1
|
height: 1
|
||||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||||
@@ -377,7 +486,6 @@ PanelWindow {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
const sortedToplevels = CompositorService.sortedToplevels
|
const sortedToplevels = CompositorService.sortedToplevels
|
||||||
if (root.appData && root.appData.type === "window") {
|
if (root.appData && root.appData.type === "window") {
|
||||||
// Find and close the specific window
|
|
||||||
for (var i = 0; i < sortedToplevels.length; i++) {
|
for (var i = 0; i < sortedToplevels.length; i++) {
|
||||||
const toplevel = sortedToplevels[i]
|
const toplevel = sortedToplevels[i]
|
||||||
const checkId = toplevel.title + "|" + (toplevel.appId || "") + "|" + i
|
const checkId = toplevel.title + "|" + (toplevel.appId || "") + "|" + i
|
||||||
@@ -387,7 +495,6 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (root.appData && root.appData.type === "grouped") {
|
} else if (root.appData && root.appData.type === "grouped") {
|
||||||
// Close all windows for this app
|
|
||||||
const allToplevels = ToplevelManager.toplevels.values
|
const allToplevels = ToplevelManager.toplevels.values
|
||||||
for (let i = 0; i < allToplevels.length; i++) {
|
for (let i = 0; i < allToplevels.length; i++) {
|
||||||
const toplevel = allToplevels[i]
|
const toplevel = allToplevels[i]
|
||||||
@@ -401,27 +508,11 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.mediumDuration
|
|
||||||
easing.type: Theme.emphasizedEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on scale {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.mediumDuration
|
|
||||||
easing.type: Theme.emphasizedEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
z: -1
|
z: -1
|
||||||
onClicked: {
|
onClicked: root.close()
|
||||||
root.close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import Quickshell.Services.Mpris
|
|||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
import qs.Modules.Lock
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -322,6 +323,8 @@ Item {
|
|||||||
TextInput {
|
TextInput {
|
||||||
id: inputField
|
id: inputField
|
||||||
|
|
||||||
|
property bool syncingFromState: false
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: lockIcon.width + Theme.spacingM * 2
|
anchors.leftMargin: lockIcon.width + Theme.spacingM * 2
|
||||||
anchors.rightMargin: {
|
anchors.rightMargin: {
|
||||||
@@ -329,6 +332,9 @@ Item {
|
|||||||
if (GreeterState.showPasswordInput && revealButton.visible) {
|
if (GreeterState.showPasswordInput && revealButton.visible) {
|
||||||
margin += revealButton.width
|
margin += revealButton.width
|
||||||
}
|
}
|
||||||
|
if (virtualKeyboardButton.visible) {
|
||||||
|
margin += virtualKeyboardButton.width
|
||||||
|
}
|
||||||
if (enterButton.visible) {
|
if (enterButton.visible) {
|
||||||
margin += enterButton.width + 2
|
margin += enterButton.width + 2
|
||||||
}
|
}
|
||||||
@@ -338,6 +344,7 @@ Item {
|
|||||||
focus: true
|
focus: true
|
||||||
echoMode: GreeterState.showPasswordInput ? (parent.showPassword ? TextInput.Normal : TextInput.Password) : TextInput.Normal
|
echoMode: GreeterState.showPasswordInput ? (parent.showPassword ? TextInput.Normal : TextInput.Password) : TextInput.Normal
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
|
if (syncingFromState) return
|
||||||
if (GreeterState.showPasswordInput) {
|
if (GreeterState.showPasswordInput) {
|
||||||
GreeterState.passwordBuffer = text
|
GreeterState.passwordBuffer = text
|
||||||
} else {
|
} else {
|
||||||
@@ -355,13 +362,17 @@ Item {
|
|||||||
GreeterState.showPasswordInput = true
|
GreeterState.showPasswordInput = true
|
||||||
PortalService.getGreeterUserProfileImage(GreeterState.username)
|
PortalService.getGreeterUserProfileImage(GreeterState.username)
|
||||||
GreeterState.passwordBuffer = ""
|
GreeterState.passwordBuffer = ""
|
||||||
inputField.text = ""
|
syncingFromState = true
|
||||||
|
text = ""
|
||||||
|
syncingFromState = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
syncingFromState = true
|
||||||
text = GreeterState.showPasswordInput ? GreeterState.passwordBuffer : GreeterState.usernameInput
|
text = GreeterState.showPasswordInput ? GreeterState.passwordBuffer : GreeterState.usernameInput
|
||||||
|
syncingFromState = false
|
||||||
if (isPrimaryScreen)
|
if (isPrimaryScreen)
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
}
|
}
|
||||||
@@ -371,12 +382,18 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyboardController {
|
||||||
|
id: keyboard_controller
|
||||||
|
target: inputField
|
||||||
|
rootObject: root
|
||||||
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: placeholder
|
id: placeholder
|
||||||
|
|
||||||
anchors.left: lockIcon.right
|
anchors.left: lockIcon.right
|
||||||
anchors.leftMargin: Theme.spacingM
|
anchors.leftMargin: Theme.spacingM
|
||||||
anchors.right: (GreeterState.showPasswordInput && revealButton.visible ? revealButton.left : (enterButton.visible ? enterButton.left : parent.right))
|
anchors.right: (GreeterState.showPasswordInput && revealButton.visible ? revealButton.left : (virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : parent.right)))
|
||||||
anchors.rightMargin: 2
|
anchors.rightMargin: 2
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: {
|
text: {
|
||||||
@@ -413,7 +430,7 @@ Item {
|
|||||||
StyledText {
|
StyledText {
|
||||||
anchors.left: lockIcon.right
|
anchors.left: lockIcon.right
|
||||||
anchors.leftMargin: Theme.spacingM
|
anchors.leftMargin: Theme.spacingM
|
||||||
anchors.right: (GreeterState.showPasswordInput && revealButton.visible ? revealButton.left : (enterButton.visible ? enterButton.left : parent.right))
|
anchors.right: (GreeterState.showPasswordInput && revealButton.visible ? revealButton.left : (virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : parent.right)))
|
||||||
anchors.rightMargin: 2
|
anchors.rightMargin: 2
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: {
|
text: {
|
||||||
@@ -441,8 +458,8 @@ Item {
|
|||||||
DankActionButton {
|
DankActionButton {
|
||||||
id: revealButton
|
id: revealButton
|
||||||
|
|
||||||
anchors.right: enterButton.visible ? enterButton.left : parent.right
|
anchors.right: virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : parent.right)
|
||||||
anchors.rightMargin: enterButton.visible ? 0 : Theme.spacingS
|
anchors.rightMargin: 0
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
iconName: parent.showPassword ? "visibility_off" : "visibility"
|
iconName: parent.showPassword ? "visibility_off" : "visibility"
|
||||||
buttonSize: 32
|
buttonSize: 32
|
||||||
@@ -450,6 +467,24 @@ Item {
|
|||||||
enabled: visible
|
enabled: visible
|
||||||
onClicked: parent.showPassword = !parent.showPassword
|
onClicked: parent.showPassword = !parent.showPassword
|
||||||
}
|
}
|
||||||
|
DankActionButton {
|
||||||
|
id: virtualKeyboardButton
|
||||||
|
|
||||||
|
anchors.right: enterButton.visible ? enterButton.left : parent.right
|
||||||
|
anchors.rightMargin: enterButton.visible ? 0 : Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
iconName: "keyboard"
|
||||||
|
buttonSize: 32
|
||||||
|
visible: Greetd.state === GreetdState.Inactive && !GreeterState.unlocking
|
||||||
|
enabled: visible
|
||||||
|
onClicked: {
|
||||||
|
if (keyboard_controller.isKeyboardActive) {
|
||||||
|
keyboard_controller.hide()
|
||||||
|
} else {
|
||||||
|
keyboard_controller.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
id: enterButton
|
id: enterButton
|
||||||
@@ -549,7 +584,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: "Switch User"
|
text: I18n.tr("Switch User")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -1325,7 +1360,7 @@ Item {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Cancel"
|
text: I18n.tr("Cancel")
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ Enable the greeter with this in your NixOS config:
|
|||||||
```nix
|
```nix
|
||||||
programs.dankMaterialShell.greeter = {
|
programs.dankMaterialShell.greeter = {
|
||||||
enable = true;
|
enable = true;
|
||||||
compositor = "niri"; # or set to hyprland
|
compositor.name = "niri"; # or set to hyprland
|
||||||
configHome = "/home/user"; # optionally symlinks that users DMS settings to the greeters data directory
|
configHome = "/home/user"; # optionally copyies that users DMS settings (and wallpaper if set) to the greeters data directory as root before greeter starts
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ Rectangle {
|
|||||||
],
|
],
|
||||||
"row_4": [
|
"row_4": [
|
||||||
{
|
{
|
||||||
text: '123',
|
text: "123",
|
||||||
symbol: 'ABC',
|
symbol: 'ABC',
|
||||||
width: 1.5
|
width: 1.5
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,120 +7,57 @@ import qs.Services
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
property string sid: Quickshell.env("XDG_SESSION_ID") || "self"
|
|
||||||
property string sessionPath: ""
|
|
||||||
|
|
||||||
function activate() {
|
function activate() {
|
||||||
loader.activeAsync = true
|
loader.activeAsync = true
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
getSessionPath.running = true
|
if (SessionService.loginctlAvailable || SessionService.sessionPath) {
|
||||||
}
|
if (SessionService.locked || SessionService.lockedHint) {
|
||||||
|
console.log("Lock: Session locked on startup")
|
||||||
Component.onDestruction: {
|
loader.activeAsync = true
|
||||||
lockStateMonitor.running = false
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: IdleService
|
target: IdleService
|
||||||
function onLockRequested() {
|
function onLockRequested() {
|
||||||
console.log("Lock: Received lock request from IdleService")
|
console.log("Lock: Received lock request from IdleService")
|
||||||
activate()
|
loader.activeAsync = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
Connections {
|
||||||
id: getSessionPath
|
target: SessionService
|
||||||
command: ["gdbus", "call", "--system", "--dest", "org.freedesktop.login1", "--object-path", "/org/freedesktop/login1", "--method", "org.freedesktop.login1.Manager.GetSession", sid]
|
|
||||||
running: false
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
function onSessionLocked() {
|
||||||
onStreamFinished: {
|
console.log("Lock: Lock signal received -> show lock")
|
||||||
const match = text.match(/objectpath '([^']+)'/)
|
loader.activeAsync = true
|
||||||
if (match) {
|
}
|
||||||
root.sessionPath = match[1]
|
|
||||||
console.log("Found session path:", root.sessionPath)
|
function onSessionUnlocked() {
|
||||||
checkCurrentLockState.running = true
|
console.log("Lock: Unlock signal received -> hide lock")
|
||||||
lockStateMonitor.running = true
|
loader.active = false
|
||||||
} else {
|
}
|
||||||
console.warn("Could not determine session path")
|
|
||||||
}
|
function onLoginctlStateChanged() {
|
||||||
|
if (SessionService.lockedHint && !loader.active) {
|
||||||
|
console.log("Lock: LockedHint=true -> show lock")
|
||||||
|
loader.activeAsync = true
|
||||||
|
} else if (!SessionService.locked && !SessionService.lockedHint && loader.active) {
|
||||||
|
console.log("Lock: LockedHint=false -> hide lock")
|
||||||
|
loader.active = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onExited: (exitCode, exitStatus) => {
|
function onPrepareForSleep() {
|
||||||
if (exitCode !== 0) {
|
if (SessionService.preparingForSleep && SessionData.lockBeforeSuspend) {
|
||||||
console.warn("Failed to get session path, exit code:", exitCode)
|
console.log("Lock: PrepareForSleep -> lock before suspend")
|
||||||
}
|
loader.activeAsync = true
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: checkCurrentLockState
|
|
||||||
command: root.sessionPath ? ["gdbus", "call", "--system", "--dest", "org.freedesktop.login1", "--object-path", root.sessionPath, "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.login1.Session", "LockedHint"] : []
|
|
||||||
running: false
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
if (text.includes("true")) {
|
|
||||||
console.log("Session is locked on startup, activating lock screen")
|
|
||||||
loader.activeAsync = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onExited: (exitCode, exitStatus) => {
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
console.warn("Failed to check initial lock state, exit code:", exitCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: lockStateMonitor
|
|
||||||
command: root.sessionPath ? ["gdbus", "monitor", "--system", "--dest", "org.freedesktop.login1"] : []
|
|
||||||
running: false
|
|
||||||
|
|
||||||
stdout: SplitParser {
|
|
||||||
splitMarker: "\n"
|
|
||||||
|
|
||||||
onRead: line => {
|
|
||||||
if (line.includes(root.sessionPath)) {
|
|
||||||
if (line.includes("org.freedesktop.login1.Session.Lock")) {
|
|
||||||
console.log("login1: Lock signal received -> show lock")
|
|
||||||
loader.activeAsync = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (line.includes("org.freedesktop.login1.Session.Unlock")) {
|
|
||||||
console.log("login1: Unlock signal received -> hide lock")
|
|
||||||
loader.active = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (line.includes("LockedHint") && line.includes("true")) {
|
|
||||||
console.log("login1: LockedHint=true -> show lock")
|
|
||||||
loader.activeAsync = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (line.includes("LockedHint") && line.includes("false")) {
|
|
||||||
console.log("login1: LockedHint=false -> hide lock")
|
|
||||||
loader.active = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (line.includes("PrepareForSleep") &&
|
|
||||||
line.includes("true") &&
|
|
||||||
SessionData.lockBeforeSuspend) {
|
|
||||||
loader.activeAsync = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onExited: (exitCode, exitStatus) => {
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
console.warn("gdbus monitor failed, exit code:", exitCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
@@ -169,7 +106,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isLocked(): bool {
|
function isLocked(): bool {
|
||||||
return loader.active
|
return SessionService.locked || loader.active
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -609,7 +609,7 @@ Item {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.margins: Theme.spacingXL
|
anchors.margins: Theme.spacingXL
|
||||||
text: "DEMO MODE - Click anywhere to exit"
|
text: I18n.tr("DEMO MODE - Click anywhere to exit")
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: "white"
|
color: "white"
|
||||||
opacity: 0.7
|
opacity: 0.7
|
||||||
@@ -1244,7 +1244,7 @@ Item {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Cancel"
|
text: I18n.tr("Cancel")
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,6 +211,10 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
isVisible: showSettingsMenu
|
isVisible: showSettingsMenu
|
||||||
onSettingsRequested: showSettingsMenu = !showSettingsMenu
|
onSettingsRequested: showSettingsMenu = !showSettingsMenu
|
||||||
|
onFindRequested: {
|
||||||
|
showSettingsMenu = false
|
||||||
|
textEditor.showSearch()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
FileView {
|
||||||
@@ -250,7 +254,7 @@ Item {
|
|||||||
FileBrowserModal {
|
FileBrowserModal {
|
||||||
id: saveBrowser
|
id: saveBrowser
|
||||||
|
|
||||||
browserTitle: qsTr("Save Notepad File")
|
browserTitle: I18n.tr("Save Notepad File")
|
||||||
browserIcon: "save"
|
browserIcon: "save"
|
||||||
browserType: "notepad_save"
|
browserType: "notepad_save"
|
||||||
fileExtensions: ["*.txt", "*.md", "*.*"]
|
fileExtensions: ["*.txt", "*.md", "*.*"]
|
||||||
@@ -314,7 +318,7 @@ Item {
|
|||||||
FileBrowserModal {
|
FileBrowserModal {
|
||||||
id: loadBrowser
|
id: loadBrowser
|
||||||
|
|
||||||
browserTitle: qsTr("Open Notepad File")
|
browserTitle: I18n.tr("Open Notepad File")
|
||||||
browserIcon: "folder_open"
|
browserIcon: "folder_open"
|
||||||
browserType: "notepad_load"
|
browserType: "notepad_load"
|
||||||
fileExtensions: ["*.txt", "*.md", "*.*"]
|
fileExtensions: ["*.txt", "*.md", "*.*"]
|
||||||
@@ -377,7 +381,7 @@ Item {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: qsTr("Unsaved Changes")
|
text: I18n.tr("Unsaved Changes")
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -385,12 +389,12 @@ Item {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: root.pendingAction === "new" ?
|
text: root.pendingAction === "new" ?
|
||||||
qsTr("You have unsaved changes. Save before creating a new file?") :
|
I18n.tr("You have unsaved changes. Save before creating a new file?") :
|
||||||
root.pendingAction.startsWith("close_tab_") ?
|
root.pendingAction.startsWith("close_tab_") ?
|
||||||
qsTr("You have unsaved changes. Save before closing this tab?") :
|
I18n.tr("You have unsaved changes. Save before closing this tab?") :
|
||||||
root.pendingAction === "load_file" || root.pendingAction === "open" ?
|
root.pendingAction === "load_file" || root.pendingAction === "open" ?
|
||||||
qsTr("You have unsaved changes. Save before opening a file?") :
|
I18n.tr("You have unsaved changes. Save before opening a file?") :
|
||||||
qsTr("You have unsaved changes. Save before continuing?")
|
I18n.tr("You have unsaved changes. Save before continuing?")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceTextMedium
|
color: Theme.surfaceTextMedium
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -429,7 +433,7 @@ Item {
|
|||||||
StyledText {
|
StyledText {
|
||||||
id: discardText
|
id: discardText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: qsTr("Don't Save")
|
text: I18n.tr("Don't Save")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -469,7 +473,7 @@ Item {
|
|||||||
StyledText {
|
StyledText {
|
||||||
id: saveAsText
|
id: saveAsText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: qsTr("Save")
|
text: I18n.tr("Save")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.background
|
color: Theme.background
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user