mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-25 14:02:53 -05:00
Compare commits
1 Commits
v0.1.8
...
surface-co
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e103d7ba7 |
90
.github/workflows/release.yml
vendored
90
.github/workflows/release.yml
vendored
@@ -1,97 +1,59 @@
|
|||||||
# Release from a dispatch event from the danklinux repo
|
name: Create Release
|
||||||
name: Create Release from DMS
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
repository_dispatch:
|
push:
|
||||||
types: [dms_release]
|
tags:
|
||||||
|
- 'v*'
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: release-${{ github.event.client_payload.tag }}
|
group: release-${{ github.ref_name }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
create_release_from_dms:
|
create_release:
|
||||||
|
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-depth: 0 # Fetch full history for changelog generation
|
||||||
|
|
||||||
- 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: |
|
||||||
set -e
|
# Get the previous tag
|
||||||
PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || echo "")
|
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 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
|
||||||
CHANGELOG=$(git log --oneline --pretty=format:"- %s (%h)" "${PREVIOUS_TAG}..${TAG}")
|
echo "Generating changelog from $PREVIOUS_TAG to HEAD"
|
||||||
|
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}...${TAG}
|
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREVIOUS_TAG}...${{ github.ref_name }}
|
||||||
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
|
||||||
|
|
||||||
- name: Create/Update DankMaterialShell Release
|
# Create GitHub Release
|
||||||
uses: softprops/action-gh-release@v2
|
- name: Create GitHub Release
|
||||||
|
uses: comnoco/create-release-action@v2.0.5
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ env.TAG }}
|
tag_name: ${{ github.ref_name }}
|
||||||
name: Release ${{ env.TAG }}
|
release_name: Release ${{ github.ref_name }}
|
||||||
body: ${{ steps.changelog.outputs.changelog }}
|
body: ${{ steps.changelog.outputs.changelog }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: ${{ contains(env.TAG, '-') }}
|
prerelease: ${{ contains(github.ref_name, '-') }}
|
||||||
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 }}
|
|
||||||
|
|||||||
233
CLAUDE.md
233
CLAUDE.md
@@ -63,9 +63,6 @@ quickshell -p shell.qml
|
|||||||
# Or use the shorthand
|
# Or use the shorthand
|
||||||
qs -p .
|
qs -p .
|
||||||
|
|
||||||
# Run with verbose output for debugging
|
|
||||||
qs -v -p shell.qml
|
|
||||||
|
|
||||||
# Code formatting and linting
|
# Code formatting and linting
|
||||||
qmlfmt -t 4 -i 4 -b 250 -w /path/to/file.qml # Format a QML file (requires qmlfmt, do not use qmlformat)
|
qmlfmt -t 4 -i 4 -b 250 -w /path/to/file.qml # Format a QML file (requires qmlfmt, do not use qmlformat)
|
||||||
qmllint **/*.qml # Lint all QML files for syntax errors
|
qmllint **/*.qml # Lint all QML files for syntax errors
|
||||||
@@ -92,7 +89,6 @@ shell.qml # Main entry point (minimal orchestration)
|
|||||||
│ ├── DisplayService.qml
|
│ ├── DisplayService.qml
|
||||||
│ ├── NotificationService.qml
|
│ ├── NotificationService.qml
|
||||||
│ ├── WeatherService.qml
|
│ ├── WeatherService.qml
|
||||||
│ ├── PluginService.qml
|
|
||||||
│ └── [14 more services]
|
│ └── [14 more services]
|
||||||
├── Modules/ # UI components (93 files)
|
├── Modules/ # UI components (93 files)
|
||||||
│ ├── TopBar/ # Panel components (13 files)
|
│ ├── TopBar/ # Panel components (13 files)
|
||||||
@@ -108,21 +104,15 @@ shell.qml # Main entry point (minimal orchestration)
|
|||||||
│ ├── SettingsModal.qml
|
│ ├── SettingsModal.qml
|
||||||
│ ├── ClipboardHistoryModal.qml
|
│ ├── ClipboardHistoryModal.qml
|
||||||
│ ├── ProcessListModal.qml
|
│ ├── ProcessListModal.qml
|
||||||
│ ├── PluginSettingsModal.qml
|
|
||||||
│ └── [7 more modals]
|
│ └── [7 more modals]
|
||||||
├── Widgets/ # Reusable UI controls (19 files)
|
└── Widgets/ # Reusable UI controls (19 files)
|
||||||
│ ├── DankIcon.qml
|
├── DankIcon.qml
|
||||||
│ ├── DankSlider.qml
|
├── DankSlider.qml
|
||||||
│ ├── DankToggle.qml
|
├── DankToggle.qml
|
||||||
│ ├── DankTabBar.qml
|
├── DankTabBar.qml
|
||||||
│ ├── DankGridView.qml
|
├── DankGridView.qml
|
||||||
│ ├── DankListView.qml
|
├── DankListView.qml
|
||||||
│ └── [13 more widgets]
|
└── [13 more widgets]
|
||||||
└── plugins/ # External plugins directory ($CONFIGPATH/DankMaterialShell/plugins/)
|
|
||||||
└── PluginName/ # Example Plugin structure
|
|
||||||
├── plugin.json # Plugin manifest
|
|
||||||
├── PluginNameWidget.qml # Widget component
|
|
||||||
└── PluginNameSettings.qml # Settings UI
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Component Organization
|
### Component Organization
|
||||||
@@ -173,12 +163,6 @@ shell.qml # Main entry point (minimal orchestration)
|
|||||||
- **DankLocationSearch**: Location picker with search
|
- **DankLocationSearch**: Location picker with search
|
||||||
- **SystemLogo**: Animated system branding component
|
- **SystemLogo**: Animated system branding component
|
||||||
|
|
||||||
7. **Plugins/** - External plugin system (`$CONFIGPATH/DankMaterialShell/plugins/`)
|
|
||||||
- **PluginService**: Discovers, loads, and manages plugin lifecycle
|
|
||||||
- **Dynamic Loading**: Plugins loaded at runtime from external directory
|
|
||||||
- **DankBar Integration**: Plugin widgets rendered alongside built-in widgets
|
|
||||||
- **Settings System**: Per-plugin settings with persistence
|
|
||||||
|
|
||||||
### Key Architectural Patterns
|
### Key Architectural Patterns
|
||||||
|
|
||||||
1. **Singleton Services Pattern**:
|
1. **Singleton Services Pattern**:
|
||||||
@@ -424,10 +408,10 @@ When modifying the shell:
|
|||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool featureAvailable: false
|
property bool featureAvailable: false
|
||||||
property type currentValue: defaultValue
|
property type currentValue: defaultValue
|
||||||
|
|
||||||
function performAction(param) {
|
function performAction(param) {
|
||||||
// Implementation
|
// Implementation
|
||||||
}
|
}
|
||||||
@@ -438,7 +422,7 @@ When modifying the shell:
|
|||||||
```qml
|
```qml
|
||||||
// In module files
|
// In module files
|
||||||
property alias serviceValue: NewService.currentValue
|
property alias serviceValue: NewService.currentValue
|
||||||
|
|
||||||
SomeControl {
|
SomeControl {
|
||||||
visible: NewService.featureAvailable
|
visible: NewService.featureAvailable
|
||||||
enabled: NewService.featureAvailable
|
enabled: NewService.featureAvailable
|
||||||
@@ -446,200 +430,6 @@ When modifying the shell:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Creating Plugins
|
|
||||||
|
|
||||||
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**:
|
|
||||||
```bash
|
|
||||||
mkdir -p ~/.config/DankMaterialShell/plugins/YourPlugin
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Create manifest** (`plugin.json`):
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "yourPlugin",
|
|
||||||
"name": "Your Plugin",
|
|
||||||
"description": "Widget description",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"author": "Your Name",
|
|
||||||
"icon": "extension",
|
|
||||||
"type": "widget",
|
|
||||||
"component": "./YourWidget.qml",
|
|
||||||
"settings": "./YourSettings.qml",
|
|
||||||
"permissions": ["settings_read", "settings_write"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Create widget component** (`YourWidget.qml`):
|
|
||||||
```qml
|
|
||||||
import QtQuick
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool compactMode: false
|
|
||||||
property string section: "center"
|
|
||||||
property real widgetHeight: 30
|
|
||||||
property var pluginService: null
|
|
||||||
|
|
||||||
width: content.implicitWidth + 16
|
|
||||||
height: widgetHeight
|
|
||||||
radius: 8
|
|
||||||
color: "#20FFFFFF"
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (pluginService) {
|
|
||||||
var data = pluginService.loadPluginData("yourPlugin", "key", defaultValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Create settings component** (`YourSettings.qml`):
|
|
||||||
```qml
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
|
|
||||||
FocusScope {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property var pluginService: null
|
|
||||||
|
|
||||||
implicitHeight: settingsColumn.implicitHeight
|
|
||||||
height: implicitHeight
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: settingsColumn
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 16
|
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Your Plugin Settings"
|
|
||||||
font.pixelSize: 18
|
|
||||||
font.weight: Font.Bold
|
|
||||||
}
|
|
||||||
|
|
||||||
// Your settings UI here
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveSettings(key, value) {
|
|
||||||
if (pluginService) {
|
|
||||||
pluginService.savePluginData("yourPlugin", key, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadSettings(key, defaultValue) {
|
|
||||||
if (pluginService) {
|
|
||||||
return pluginService.loadPluginData("yourPlugin", key, defaultValue)
|
|
||||||
}
|
|
||||||
return defaultValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Enable plugin**:
|
|
||||||
- Open Settings → Plugins
|
|
||||||
- Click "Scan for Plugins"
|
|
||||||
- Toggle plugin to enable
|
|
||||||
- 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:**
|
|
||||||
```
|
|
||||||
~/.config/DankMaterialShell/
|
|
||||||
├── settings.json # Core DMS settings + plugin settings
|
|
||||||
│ └── pluginSettings: {
|
|
||||||
│ └── yourPlugin: {
|
|
||||||
│ ├── enabled: true,
|
|
||||||
│ └── customData: {...}
|
|
||||||
│ }
|
|
||||||
│ }
|
|
||||||
└── plugins/ # Plugin files directory
|
|
||||||
└── YourPlugin/ # Plugin directory (matches manifest ID)
|
|
||||||
├── plugin.json # Plugin manifest
|
|
||||||
├── YourWidget.qml # Widget component
|
|
||||||
└── YourSettings.qml # Settings UI (optional)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Key Plugin APIs:**
|
|
||||||
- `pluginService.loadPluginData(pluginId, key, default)` - Load persistent data
|
|
||||||
- `pluginService.savePluginData(pluginId, key, value)` - Save persistent data
|
|
||||||
- `PluginService.enablePlugin(pluginId)` - Load plugin
|
|
||||||
- `PluginService.disablePlugin(pluginId)` - Unload plugin
|
|
||||||
|
|
||||||
**Important Notes:**
|
|
||||||
- Plugin settings are automatically injected by the PluginService via `item.pluginService = PluginService`
|
|
||||||
- Settings are stored in the main settings.json but namespaced under `pluginSettings.{pluginId}`
|
|
||||||
- Plugin directories must match the plugin ID in the manifest
|
|
||||||
- Use the injected `pluginService` property in both widget and settings components
|
|
||||||
|
|
||||||
### Debugging Common Issues
|
### Debugging Common Issues
|
||||||
|
|
||||||
1. **Import errors**: Check import paths
|
1. **Import errors**: Check import paths
|
||||||
@@ -664,7 +454,6 @@ Daemon plugins run invisibly in the background without any UI components. They'r
|
|||||||
- **Function Discovery**: Use grep/search tools to find existing utility functions before implementing new ones
|
- **Function Discovery**: Use grep/search tools to find existing utility functions before implementing new ones
|
||||||
- **Modern QML Patterns**: Leverage new widgets like DankTextField, DankDropdown, CachingImage
|
- **Modern QML Patterns**: Leverage new widgets like DankTextField, DankDropdown, CachingImage
|
||||||
- **Structured Organization**: Follow the established Services/Modules/Widgets/Modals separation
|
- **Structured Organization**: Follow the established Services/Modules/Widgets/Modals separation
|
||||||
- **Plugin System**: For user extensions, create plugins instead of modifying core modules - see docs/PLUGINS.md
|
|
||||||
|
|
||||||
### Common Widget Patterns
|
### Common Widget Patterns
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Contributions are welcome and encouraged.
|
Contributions are welcome and encourages.
|
||||||
|
|
||||||
## Formatting
|
## Formatting
|
||||||
|
|
||||||
@@ -27,4 +27,4 @@ Sometimes it just breaks code though. Like turning `"_\""` into `"_""`, so you m
|
|||||||
|
|
||||||
## Pull request
|
## Pull request
|
||||||
|
|
||||||
Include screenshots/video if applicable in your pull request if applicable, to visualize what your change is affecting.
|
Include screenshots/video if applicable in your pull request if applicable, to visualize what your change is affecting.
|
||||||
@@ -72,6 +72,10 @@ 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) {
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
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++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
pragma Singleton
|
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
|
|
||||||
Singleton {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
readonly property var facts: [
|
|
||||||
"A photon takes 100,000 to 200,000 years bouncing through the Sun's dense core, then races to Earth in just 8 minutes 20 seconds.",
|
|
||||||
"A teaspoon of neutron star matter would weigh a billion metric tons here on Earth.",
|
|
||||||
"Right now, 100 trillion solar neutrinos are passing through your body every second.",
|
|
||||||
"The Sun converts 4 million metric tons of matter into pure energy every second—enough to power Earth for 500,000 years.",
|
|
||||||
"The universe still glows with leftover heat from the Big Bang—just 2.7 degrees above absolute zero.",
|
|
||||||
"There's a nebula out there that's actually colder than empty space itself.",
|
|
||||||
"We've detected black holes crashing together by measuring spacetime stretch by less than 1/10,000th the width of a proton.",
|
|
||||||
"Fast radio bursts can release more energy in 5 milliseconds than our Sun produces in 3 days.",
|
|
||||||
"Our galaxy might be crawling with billions of rogue planets drifting alone in the dark.",
|
|
||||||
"Distant galaxies can move away from us faster than light because space itself is stretching.",
|
|
||||||
"The edge of what we can see is 46.5 billion light-years away, even though the universe is only 13.8 billion years old.",
|
|
||||||
"The universe is mostly invisible: 5% regular matter, 27% dark matter, 68% dark energy.",
|
|
||||||
"A day on Venus lasts longer than its entire year around the Sun.",
|
|
||||||
"On Mercury, the time between sunrises is 176 Earth days long.",
|
|
||||||
"In about 4.5 billion years, our galaxy will smash into Andromeda.",
|
|
||||||
"Most of the gold in your jewelry was forged when neutron stars collided somewhere in space.",
|
|
||||||
"PSR J1748-2446ad, the fastest spinning star, rotates 716 times per second—its equator moves at 24% the speed of light.",
|
|
||||||
"Cosmic rays create particles that shouldn't make it to Earth's surface, but time dilation lets them sneak through.",
|
|
||||||
"Jupiter's magnetic field is so huge that if we could see it, it would look bigger than the Moon in our sky.",
|
|
||||||
"Interstellar space is so empty it's like a cube 32 kilometers wide containing just a single grain of sand.",
|
|
||||||
"Voyager 1 is 24 billion kilometers away but won't leave the Sun's gravitational influence for another 30,000 years.",
|
|
||||||
"Counting to a billion at one number per second would take over 31 years.",
|
|
||||||
"Space is so vast, even speeding at light-speed, you'd never return past the cosmic horizon.",
|
|
||||||
"Astronauts on the ISS age about 0.01 seconds less each year than people on Earth.",
|
|
||||||
"Sagittarius B2, a dust cloud near our galaxy's center, contains ethyl formate—the compound that gives raspberries their flavor and rum its smell.",
|
|
||||||
"Beyond 16 billion light-years, the cosmic event horizon marks where space expands too fast for light to ever reach us again.",
|
|
||||||
"Even at light-speed, you'd never catch up to most galaxies—space expands faster.",
|
|
||||||
"Only around 5% of galaxies are ever reachable—even at light-speed.",
|
|
||||||
"If the Sun vanished, we'd still orbit it for 8 minutes before drifting away.",
|
|
||||||
"If a planet 65 million light-years away looked at Earth now, it'd see dinosaurs.",
|
|
||||||
"Our oldest radio signals will reach the Milky Way's center in 26,000 years.",
|
|
||||||
"Every atom in your body heavier than hydrogen was forged in the nuclear furnace of a dying star.",
|
|
||||||
"The Moon moves 3.8 centimeters farther from Earth every year.",
|
|
||||||
"The universe creates 275 million new stars every single day.",
|
|
||||||
"Jupiter's Great Red Spot is a storm twice the size of Earth that has been raging for at least 350 years.",
|
|
||||||
"If you watched someone fall into a black hole, they'd appear frozen at the event horizon forever—time effectively stops from your perspective.",
|
|
||||||
"The Boötes Supervoid is a cosmic desert 1.8 billion light-years across with 60% fewer galaxies than it should have."
|
|
||||||
]
|
|
||||||
|
|
||||||
function getRandomFact() {
|
|
||||||
return facts[Math.floor(Math.random() * facts.length)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
113
Common/I18n.qml
113
Common/I18n.qml
@@ -1,113 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Qt.labs.folderlistmodel
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Io
|
|
||||||
pragma Singleton
|
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
Singleton {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
readonly property string _rawLocale: Qt.locale().name
|
|
||||||
readonly property string _lang: _rawLocale.split(/[_-]/)[0]
|
|
||||||
readonly property var _candidates: {
|
|
||||||
const fullUnderscore = _rawLocale;
|
|
||||||
const fullHyphen = _rawLocale.replace("_", "-");
|
|
||||||
return [fullUnderscore, fullHyphen, _lang].filter(c => c && c !== "en");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
readonly property url translationsFolder: Qt.resolvedUrl("../translations/poexports")
|
|
||||||
|
|
||||||
property string currentLocale: "en"
|
|
||||||
property var translations: ({})
|
|
||||||
property bool translationsLoaded: false
|
|
||||||
|
|
||||||
property url _selectedPath: ""
|
|
||||||
|
|
||||||
FolderListModel {
|
|
||||||
id: dir
|
|
||||||
folder: root.translationsFolder
|
|
||||||
nameFilters: ["*.json"]
|
|
||||||
showDirs: false
|
|
||||||
showDotAndDotDot: false
|
|
||||||
|
|
||||||
onStatusChanged: if (status === FolderListModel.Ready) root._pickTranslation()
|
|
||||||
}
|
|
||||||
|
|
||||||
FileView {
|
|
||||||
id: translationLoader
|
|
||||||
path: root._selectedPath
|
|
||||||
|
|
||||||
onLoaded: {
|
|
||||||
try {
|
|
||||||
root.translations = JSON.parse(text())
|
|
||||||
root.translationsLoaded = true
|
|
||||||
console.log(`I18n: Loaded translations for '${root.currentLocale}' ` +
|
|
||||||
`(${Object.keys(root.translations).length} contexts)`)
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(`I18n: Error parsing '${root.currentLocale}':`, e,
|
|
||||||
"- falling back to English")
|
|
||||||
root._fallbackToEnglish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoadFailed: (error) => {
|
|
||||||
console.warn(`I18n: Failed to load '${root.currentLocale}' (${error}), ` +
|
|
||||||
"falling back to English")
|
|
||||||
root._fallbackToEnglish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _pickTranslation() {
|
|
||||||
const present = new Set()
|
|
||||||
for (let i = 0; i < dir.count; i++) {
|
|
||||||
const name = dir.get(i, "fileName") // e.g. "zh_CN.json"
|
|
||||||
if (name && name.endsWith(".json")) {
|
|
||||||
present.add(name.slice(0, -5))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < _candidates.length; i++) {
|
|
||||||
const cand = _candidates[i]
|
|
||||||
if (present.has(cand)) {
|
|
||||||
_useLocale(cand, dir.folder + "/" + cand + ".json")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_fallbackToEnglish()
|
|
||||||
}
|
|
||||||
|
|
||||||
function _useLocale(localeTag, fileUrl) {
|
|
||||||
currentLocale = localeTag
|
|
||||||
_selectedPath = fileUrl
|
|
||||||
translationsLoaded = false
|
|
||||||
translations = ({})
|
|
||||||
console.log(`I18n: Using locale '${localeTag}' from ${fileUrl}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
function _fallbackToEnglish() {
|
|
||||||
currentLocale = "en"
|
|
||||||
_selectedPath = ""
|
|
||||||
translationsLoaded = false
|
|
||||||
translations = ({})
|
|
||||||
console.warn("I18n: Falling back to built-in English strings")
|
|
||||||
}
|
|
||||||
|
|
||||||
function tr(term, context) {
|
|
||||||
if (!translationsLoaded || !translations) return term
|
|
||||||
const ctx = context || term
|
|
||||||
if (translations[ctx] && translations[ctx][term]) return translations[ctx][term]
|
|
||||||
for (const c in translations) {
|
|
||||||
if (translations[c] && translations[c][term]) return translations[c][term]
|
|
||||||
}
|
|
||||||
return term
|
|
||||||
}
|
|
||||||
|
|
||||||
function trContext(context, term) {
|
|
||||||
if (!translationsLoaded || !translations) return term
|
|
||||||
if (translations[context] && translations[context][term]) return translations[context][term]
|
|
||||||
return term
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -38,10 +38,6 @@ Singleton {
|
|||||||
return stringify(path).replace("file://", "")
|
return stringify(path).replace("file://", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
function toFileUrl(path: string): string {
|
|
||||||
return path.startsWith("file://") ? path : "file://" + path
|
|
||||||
}
|
|
||||||
|
|
||||||
function mkdir(path: url): void {
|
function mkdir(path: url): void {
|
||||||
Quickshell.execDetached(["mkdir", "-p", strip(path)])
|
Quickshell.execDetached(["mkdir", "-p", strip(path)])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,19 +12,12 @@ Singleton {
|
|||||||
|
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true"
|
|
||||||
|
|
||||||
property bool isLightMode: false
|
property bool isLightMode: false
|
||||||
property string wallpaperPath: ""
|
property string wallpaperPath: ""
|
||||||
property string wallpaperLastPath: ""
|
property string wallpaperLastPath: ""
|
||||||
property string profileLastPath: ""
|
property string profileLastPath: ""
|
||||||
property bool perMonitorWallpaper: false
|
property bool perMonitorWallpaper: false
|
||||||
property var monitorWallpapers: ({})
|
property var monitorWallpapers: ({})
|
||||||
property bool perModeWallpaper: false
|
|
||||||
property string wallpaperPathLight: ""
|
|
||||||
property string wallpaperPathDark: ""
|
|
||||||
property var monitorWallpapersLight: ({})
|
|
||||||
property var monitorWallpapersDark: ({})
|
|
||||||
property bool doNotDisturb: false
|
property bool doNotDisturb: false
|
||||||
property bool nightModeEnabled: false
|
property bool nightModeEnabled: false
|
||||||
property int nightModeTemperature: 4500
|
property int nightModeTemperature: 4500
|
||||||
@@ -70,23 +63,14 @@ Singleton {
|
|||||||
property int batteryHibernateTimeout: 0 // Never
|
property int batteryHibernateTimeout: 0 // Never
|
||||||
|
|
||||||
property bool lockBeforeSuspend: false
|
property bool lockBeforeSuspend: false
|
||||||
property bool loginctlLockIntegration: true
|
|
||||||
property var recentColors: []
|
|
||||||
property bool showThirdPartyPlugins: false
|
|
||||||
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (!isGreeterMode) {
|
loadSettings()
|
||||||
loadSettings()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSettings() {
|
function loadSettings() {
|
||||||
if (isGreeterMode) {
|
parseSettings(settingsFile.text())
|
||||||
parseSettings(greeterSessionFile.text())
|
|
||||||
} else {
|
|
||||||
parseSettings(settingsFile.text())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSettings(content) {
|
function parseSettings(content) {
|
||||||
@@ -99,11 +83,6 @@ Singleton {
|
|||||||
profileLastPath = settings.profileLastPath !== undefined ? settings.profileLastPath : ""
|
profileLastPath = settings.profileLastPath !== undefined ? settings.profileLastPath : ""
|
||||||
perMonitorWallpaper = settings.perMonitorWallpaper !== undefined ? settings.perMonitorWallpaper : false
|
perMonitorWallpaper = settings.perMonitorWallpaper !== undefined ? settings.perMonitorWallpaper : false
|
||||||
monitorWallpapers = settings.monitorWallpapers !== undefined ? settings.monitorWallpapers : {}
|
monitorWallpapers = settings.monitorWallpapers !== undefined ? settings.monitorWallpapers : {}
|
||||||
perModeWallpaper = settings.perModeWallpaper !== undefined ? settings.perModeWallpaper : false
|
|
||||||
wallpaperPathLight = settings.wallpaperPathLight !== undefined ? settings.wallpaperPathLight : ""
|
|
||||||
wallpaperPathDark = settings.wallpaperPathDark !== undefined ? settings.wallpaperPathDark : ""
|
|
||||||
monitorWallpapersLight = settings.monitorWallpapersLight !== undefined ? settings.monitorWallpapersLight : {}
|
|
||||||
monitorWallpapersDark = settings.monitorWallpapersDark !== undefined ? settings.monitorWallpapersDark : {}
|
|
||||||
doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false
|
doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false
|
||||||
nightModeEnabled = settings.nightModeEnabled !== undefined ? settings.nightModeEnabled : false
|
nightModeEnabled = settings.nightModeEnabled !== undefined ? settings.nightModeEnabled : false
|
||||||
nightModeTemperature = settings.nightModeTemperature !== undefined ? settings.nightModeTemperature : 4500
|
nightModeTemperature = settings.nightModeTemperature !== undefined ? settings.nightModeTemperature : 4500
|
||||||
@@ -153,14 +132,10 @@ 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
|
||||||
loginctlLockIntegration = settings.loginctlLockIntegration !== undefined ? settings.loginctlLockIntegration : true
|
|
||||||
recentColors = settings.recentColors !== undefined ? settings.recentColors : []
|
// Generate system themes but don't override user's theme choice
|
||||||
showThirdPartyPlugins = settings.showThirdPartyPlugins !== undefined ? settings.showThirdPartyPlugins : false
|
if (typeof Theme !== "undefined") {
|
||||||
|
Theme.generateSystemThemesFromCurrentTheme()
|
||||||
if (!isGreeterMode) {
|
|
||||||
if (typeof Theme !== "undefined") {
|
|
||||||
Theme.generateSystemThemesFromCurrentTheme()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -169,7 +144,6 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
if (isGreeterMode) return
|
|
||||||
settingsFile.setText(JSON.stringify({
|
settingsFile.setText(JSON.stringify({
|
||||||
"isLightMode": isLightMode,
|
"isLightMode": isLightMode,
|
||||||
"wallpaperPath": wallpaperPath,
|
"wallpaperPath": wallpaperPath,
|
||||||
@@ -177,11 +151,6 @@ Singleton {
|
|||||||
"profileLastPath": profileLastPath,
|
"profileLastPath": profileLastPath,
|
||||||
"perMonitorWallpaper": perMonitorWallpaper,
|
"perMonitorWallpaper": perMonitorWallpaper,
|
||||||
"monitorWallpapers": monitorWallpapers,
|
"monitorWallpapers": monitorWallpapers,
|
||||||
"perModeWallpaper": perModeWallpaper,
|
|
||||||
"wallpaperPathLight": wallpaperPathLight,
|
|
||||||
"wallpaperPathDark": wallpaperPathDark,
|
|
||||||
"monitorWallpapersLight": monitorWallpapersLight,
|
|
||||||
"monitorWallpapersDark": monitorWallpapersDark,
|
|
||||||
"doNotDisturb": doNotDisturb,
|
"doNotDisturb": doNotDisturb,
|
||||||
"nightModeEnabled": nightModeEnabled,
|
"nightModeEnabled": nightModeEnabled,
|
||||||
"nightModeTemperature": nightModeTemperature,
|
"nightModeTemperature": nightModeTemperature,
|
||||||
@@ -216,30 +185,15 @@ Singleton {
|
|||||||
"batteryLockTimeout": batteryLockTimeout,
|
"batteryLockTimeout": batteryLockTimeout,
|
||||||
"batterySuspendTimeout": batterySuspendTimeout,
|
"batterySuspendTimeout": batterySuspendTimeout,
|
||||||
"batteryHibernateTimeout": batteryHibernateTimeout,
|
"batteryHibernateTimeout": batteryHibernateTimeout,
|
||||||
"lockBeforeSuspend": lockBeforeSuspend,
|
"lockBeforeSuspend": lockBeforeSuspend
|
||||||
"loginctlLockIntegration": loginctlLockIntegration,
|
|
||||||
"recentColors": recentColors,
|
|
||||||
"showThirdPartyPlugins": showThirdPartyPlugins
|
|
||||||
}, null, 2))
|
}, null, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLightMode(lightMode) {
|
function setLightMode(lightMode) {
|
||||||
isLightMode = lightMode
|
isLightMode = lightMode
|
||||||
syncWallpaperForCurrentMode()
|
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncWallpaperForCurrentMode() {
|
|
||||||
if (!perModeWallpaper) return
|
|
||||||
|
|
||||||
if (perMonitorWallpaper) {
|
|
||||||
monitorWallpapers = isLightMode ? Object.assign({}, monitorWallpapersLight) : Object.assign({}, monitorWallpapersDark)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
wallpaperPath = isLightMode ? wallpaperPathLight : wallpaperPathDark
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDoNotDisturb(enabled) {
|
function setDoNotDisturb(enabled) {
|
||||||
doNotDisturb = enabled
|
doNotDisturb = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
@@ -310,32 +264,24 @@ Singleton {
|
|||||||
|
|
||||||
function setWallpaper(imagePath) {
|
function setWallpaper(imagePath) {
|
||||||
wallpaperPath = imagePath
|
wallpaperPath = imagePath
|
||||||
if (perModeWallpaper) {
|
|
||||||
if (isLightMode) {
|
|
||||||
wallpaperPathLight = imagePath
|
|
||||||
} else {
|
|
||||||
wallpaperPathDark = imagePath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
saveSettings()
|
saveSettings()
|
||||||
|
|
||||||
if (typeof Theme !== "undefined") {
|
if (typeof Theme !== "undefined") {
|
||||||
|
if (Theme.currentTheme === Theme.dynamic) {
|
||||||
|
Theme.extractColors()
|
||||||
|
}
|
||||||
Theme.generateSystemThemesFromCurrentTheme()
|
Theme.generateSystemThemesFromCurrentTheme()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWallpaperColor(color) {
|
function setWallpaperColor(color) {
|
||||||
wallpaperPath = color
|
wallpaperPath = color
|
||||||
if (perModeWallpaper) {
|
|
||||||
if (isLightMode) {
|
|
||||||
wallpaperPathLight = color
|
|
||||||
} else {
|
|
||||||
wallpaperPathDark = color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
saveSettings()
|
saveSettings()
|
||||||
|
|
||||||
if (typeof Theme !== "undefined") {
|
if (typeof Theme !== "undefined") {
|
||||||
|
if (Theme.currentTheme === Theme.dynamic) {
|
||||||
|
Theme.extractColors()
|
||||||
|
}
|
||||||
Theme.generateSystemThemesFromCurrentTheme()
|
Theme.generateSystemThemesFromCurrentTheme()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,16 +314,6 @@ 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
|
||||||
@@ -490,52 +426,13 @@ Singleton {
|
|||||||
|
|
||||||
function setPerMonitorWallpaper(enabled) {
|
function setPerMonitorWallpaper(enabled) {
|
||||||
perMonitorWallpaper = enabled
|
perMonitorWallpaper = enabled
|
||||||
if (enabled && perModeWallpaper) {
|
|
||||||
syncWallpaperForCurrentMode()
|
|
||||||
}
|
|
||||||
saveSettings()
|
saveSettings()
|
||||||
|
|
||||||
|
// Refresh dynamic theming when per-monitor mode changes
|
||||||
if (typeof Theme !== "undefined") {
|
if (typeof Theme !== "undefined") {
|
||||||
Theme.generateSystemThemesFromCurrentTheme()
|
if (Theme.currentTheme === Theme.dynamic) {
|
||||||
}
|
Theme.extractColors()
|
||||||
}
|
|
||||||
|
|
||||||
function setPerModeWallpaper(enabled) {
|
|
||||||
if (enabled && wallpaperCyclingEnabled) {
|
|
||||||
setWallpaperCyclingEnabled(false)
|
|
||||||
}
|
|
||||||
if (enabled && perMonitorWallpaper) {
|
|
||||||
var monitorCyclingAny = false
|
|
||||||
for (var key in monitorCyclingSettings) {
|
|
||||||
if (monitorCyclingSettings[key].enabled) {
|
|
||||||
monitorCyclingAny = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (monitorCyclingAny) {
|
|
||||||
var newSettings = Object.assign({}, monitorCyclingSettings)
|
|
||||||
for (var screenName in newSettings) {
|
|
||||||
newSettings[screenName].enabled = false
|
|
||||||
}
|
|
||||||
monitorCyclingSettings = newSettings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
perModeWallpaper = enabled
|
|
||||||
if (enabled) {
|
|
||||||
if (perMonitorWallpaper) {
|
|
||||||
monitorWallpapersLight = Object.assign({}, monitorWallpapers)
|
|
||||||
monitorWallpapersDark = Object.assign({}, monitorWallpapers)
|
|
||||||
} else {
|
|
||||||
wallpaperPathLight = wallpaperPath
|
|
||||||
wallpaperPathDark = wallpaperPath
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
syncWallpaperForCurrentMode()
|
|
||||||
}
|
|
||||||
saveSettings()
|
|
||||||
|
|
||||||
if (typeof Theme !== "undefined") {
|
|
||||||
Theme.generateSystemThemesFromCurrentTheme()
|
Theme.generateSystemThemesFromCurrentTheme()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -548,32 +445,15 @@ Singleton {
|
|||||||
delete newMonitorWallpapers[screenName]
|
delete newMonitorWallpapers[screenName]
|
||||||
}
|
}
|
||||||
monitorWallpapers = newMonitorWallpapers
|
monitorWallpapers = newMonitorWallpapers
|
||||||
|
|
||||||
if (perModeWallpaper) {
|
|
||||||
if (isLightMode) {
|
|
||||||
var newLight = Object.assign({}, monitorWallpapersLight)
|
|
||||||
if (path && path !== "") {
|
|
||||||
newLight[screenName] = path
|
|
||||||
} else {
|
|
||||||
delete newLight[screenName]
|
|
||||||
}
|
|
||||||
monitorWallpapersLight = newLight
|
|
||||||
} else {
|
|
||||||
var newDark = Object.assign({}, monitorWallpapersDark)
|
|
||||||
if (path && path !== "") {
|
|
||||||
newDark[screenName] = path
|
|
||||||
} else {
|
|
||||||
delete newDark[screenName]
|
|
||||||
}
|
|
||||||
monitorWallpapersDark = newDark
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
saveSettings()
|
saveSettings()
|
||||||
|
|
||||||
|
// Trigger dynamic theming if this is the first monitor and dynamic theming is enabled
|
||||||
if (typeof Theme !== "undefined" && typeof Quickshell !== "undefined") {
|
if (typeof Theme !== "undefined" && typeof Quickshell !== "undefined") {
|
||||||
var screens = Quickshell.screens
|
var screens = Quickshell.screens
|
||||||
if (screens.length > 0 && screenName === screens[0].name) {
|
if (screens.length > 0 && screenName === screens[0].name) {
|
||||||
|
if (Theme.currentTheme === Theme.dynamic) {
|
||||||
|
Theme.extractColors()
|
||||||
|
}
|
||||||
Theme.generateSystemThemesFromCurrentTheme()
|
Theme.generateSystemThemesFromCurrentTheme()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -646,61 +526,30 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLoginctlLockIntegration(enabled) {
|
|
||||||
loginctlLockIntegration = enabled
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setShowThirdPartyPlugins(enabled) {
|
|
||||||
showThirdPartyPlugins = enabled
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
FileView {
|
FileView {
|
||||||
id: settingsFile
|
id: settingsFile
|
||||||
|
|
||||||
path: isGreeterMode ? "" : StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
|
path: StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
|
||||||
blockLoading: isGreeterMode
|
blockLoading: true
|
||||||
blockWrites: true
|
blockWrites: true
|
||||||
watchChanges: !isGreeterMode
|
watchChanges: true
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
if (!isGreeterMode) {
|
parseSettings(settingsFile.text())
|
||||||
parseSettings(settingsFile.text())
|
hasTriedDefaultSession = false
|
||||||
hasTriedDefaultSession = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
onLoadFailed: error => {
|
onLoadFailed: error => {
|
||||||
if (!isGreeterMode && !hasTriedDefaultSession) {
|
if (!hasTriedDefaultSession) {
|
||||||
hasTriedDefaultSession = true
|
hasTriedDefaultSession = true
|
||||||
defaultSessionCheckProcess.running = true
|
defaultSessionCheckProcess.running = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
|
||||||
id: greeterSessionFile
|
|
||||||
|
|
||||||
path: {
|
|
||||||
const greetCfgDir = Quickshell.env("DMS_GREET_CFG_DIR") || "/etc/greetd/.dms"
|
|
||||||
return greetCfgDir + "/session.json"
|
|
||||||
}
|
|
||||||
preload: isGreeterMode
|
|
||||||
blockLoading: false
|
|
||||||
blockWrites: true
|
|
||||||
watchChanges: false
|
|
||||||
printErrors: true
|
|
||||||
onLoaded: {
|
|
||||||
if (isGreeterMode) {
|
|
||||||
parseSettings(greeterSessionFile.text())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
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 --no-preserve=mode \"$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 \"$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) {
|
||||||
@@ -846,4 +695,4 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,30 +12,13 @@ import qs.Services
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true"
|
|
||||||
|
|
||||||
enum Position {
|
|
||||||
Top,
|
|
||||||
Bottom,
|
|
||||||
Left,
|
|
||||||
Right
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AnimationSpeed {
|
|
||||||
None,
|
|
||||||
Shortest,
|
|
||||||
Short,
|
|
||||||
Medium,
|
|
||||||
Long
|
|
||||||
}
|
|
||||||
|
|
||||||
// Theme settings
|
// Theme settings
|
||||||
property string currentThemeName: "blue"
|
property string currentThemeName: "blue"
|
||||||
property string customThemeFile: ""
|
property string customThemeFile: ""
|
||||||
property string matugenScheme: "scheme-tonal-spot"
|
property string matugenScheme: "scheme-tonal-spot"
|
||||||
property real dankBarTransparency: 1.0
|
property real topBarTransparency: 0.75
|
||||||
property real dankBarWidgetTransparency: 1.0
|
property real topBarWidgetTransparency: 0.85
|
||||||
property real popupTransparency: 1.0
|
property real popupTransparency: 0.92
|
||||||
property real dockTransparency: 1
|
property real dockTransparency: 1
|
||||||
property bool use24HourClock: true
|
property bool use24HourClock: true
|
||||||
property bool useFahrenheit: false
|
property bool useFahrenheit: false
|
||||||
@@ -87,13 +70,12 @@ Singleton {
|
|||||||
property string clockDateFormat: ""
|
property string clockDateFormat: ""
|
||||||
property string lockDateFormat: ""
|
property string lockDateFormat: ""
|
||||||
property int mediaSize: 1
|
property int mediaSize: 1
|
||||||
property var dankBarLeftWidgets: ["launcherButton", "workspaceSwitcher", "focusedWindow"]
|
property var topBarLeftWidgets: ["launcherButton", "workspaceSwitcher", "focusedWindow"]
|
||||||
property var dankBarCenterWidgets: ["music", "clock", "weather"]
|
property var topBarCenterWidgets: ["music", "clock", "weather"]
|
||||||
property var dankBarRightWidgets: ["systemTray", "clipboard", "cpuUsage", "memUsage", "notificationButton", "battery", "controlCenterButton"]
|
property var topBarRightWidgets: ["systemTray", "clipboard", "cpuUsage", "memUsage", "notificationButton", "battery", "controlCenterButton"]
|
||||||
property var dankBarWidgetOrder: []
|
property alias topBarLeftWidgetsModel: leftWidgetsModel
|
||||||
property alias dankBarLeftWidgetsModel: leftWidgetsModel
|
property alias topBarCenterWidgetsModel: centerWidgetsModel
|
||||||
property alias dankBarCenterWidgetsModel: centerWidgetsModel
|
property alias topBarRightWidgetsModel: rightWidgetsModel
|
||||||
property alias dankBarRightWidgetsModel: rightWidgetsModel
|
|
||||||
property string appLauncherViewMode: "list"
|
property string appLauncherViewMode: "list"
|
||||||
property string spotlightModalViewMode: "list"
|
property string spotlightModalViewMode: "list"
|
||||||
property string networkPreference: "auto"
|
property string networkPreference: "auto"
|
||||||
@@ -103,19 +85,15 @@ 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 string launcherLogoMode: "apps"
|
property bool useOSLogo: false
|
||||||
property string launcherLogoCustomPath: ""
|
property string osLogoColorOverride: ""
|
||||||
property string launcherLogoColorOverride: ""
|
property real osLogoBrightness: 0.5
|
||||||
property bool launcherLogoColorInvertOnMode: false
|
property real osLogoContrast: 1
|
||||||
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
|
||||||
@@ -139,51 +117,36 @@ Singleton {
|
|||||||
property bool showDock: false
|
property bool showDock: false
|
||||||
property bool dockAutoHide: false
|
property bool dockAutoHide: false
|
||||||
property bool dockGroupByApp: false
|
property bool dockGroupByApp: false
|
||||||
property bool dockOpenOnOverview: false
|
|
||||||
property int dockPosition: SettingsData.Position.Bottom
|
|
||||||
property real dockSpacing: 4
|
|
||||||
property real dockBottomGap: 0
|
|
||||||
property real cornerRadius: 12
|
property real cornerRadius: 12
|
||||||
property bool notificationOverlayEnabled: false
|
property bool notificationOverlayEnabled: false
|
||||||
property bool dankBarAutoHide: false
|
property bool topBarAutoHide: false
|
||||||
property bool dankBarOpenOnOverview: false
|
property bool topBarOpenOnOverview: false
|
||||||
property bool dankBarVisible: true
|
property bool topBarVisible: true
|
||||||
property real dankBarSpacing: 4
|
property real topBarSpacing: 4
|
||||||
property real dankBarBottomGap: 0
|
property real topBarBottomGap: 0
|
||||||
property real dankBarInnerPadding: 4
|
property real topBarInnerPadding: 8
|
||||||
property bool dankBarSquareCorners: false
|
property bool topBarSquareCorners: false
|
||||||
property bool dankBarNoBackground: false
|
property bool topBarNoBackground: false
|
||||||
property bool dankBarGothCornersEnabled: false
|
property bool topBarGothCornersEnabled: false
|
||||||
property bool dankBarBorderEnabled: false
|
|
||||||
property int dankBarPosition: SettingsData.Position.Top
|
|
||||||
property bool dankBarIsVertical: dankBarPosition === SettingsData.Position.Left || dankBarPosition === SettingsData.Position.Right
|
|
||||||
property bool lockScreenShowPowerActions: true
|
property bool lockScreenShowPowerActions: true
|
||||||
property bool hideBrightnessSlider: false
|
property bool hideBrightnessSlider: false
|
||||||
property string widgetBackgroundColor: "sch"
|
property string widgetBackgroundColor: "sch"
|
||||||
property string surfaceBase: "s"
|
property string surfaceBase: "sc"
|
||||||
property int notificationTimeoutLow: 5000
|
property int notificationTimeoutLow: 5000
|
||||||
property int notificationTimeoutNormal: 5000
|
property int notificationTimeoutNormal: 5000
|
||||||
property int notificationTimeoutCritical: 0
|
property int notificationTimeoutCritical: 0
|
||||||
property int notificationPopupPosition: SettingsData.Position.Top
|
|
||||||
property bool osdAlwaysShowValue: false
|
|
||||||
property var screenPreferences: ({})
|
property var screenPreferences: ({})
|
||||||
property int animationSpeed: SettingsData.AnimationSpeed.Short
|
|
||||||
readonly property string defaultFontFamily: "Inter Variable"
|
readonly property string defaultFontFamily: "Inter Variable"
|
||||||
readonly property string defaultMonoFontFamily: "Fira Code"
|
readonly property string defaultMonoFontFamily: "Fira Code"
|
||||||
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 forceTopBarLayoutRefresh
|
||||||
signal forceDockLayoutRefresh
|
|
||||||
signal widgetDataChanged
|
signal widgetDataChanged
|
||||||
signal workspaceIconsUpdated
|
signal workspaceIconsUpdated
|
||||||
|
|
||||||
property bool _loading: false
|
property bool _loading: false
|
||||||
property bool _pluginSettingsLoading: false
|
|
||||||
|
|
||||||
property var pluginSettings: ({})
|
|
||||||
|
|
||||||
function getEffectiveTimeFormat() {
|
function getEffectiveTimeFormat() {
|
||||||
if (use24HourClock) {
|
if (use24HourClock) {
|
||||||
@@ -210,57 +173,28 @@ 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)
|
||||||
rightWidgetsModel.append(dummyItem)
|
rightWidgetsModel.append(dummyItem)
|
||||||
|
|
||||||
updateListModel(leftWidgetsModel, dankBarLeftWidgets)
|
updateListModel(leftWidgetsModel, topBarLeftWidgets)
|
||||||
updateListModel(centerWidgetsModel, dankBarCenterWidgets)
|
updateListModel(centerWidgetsModel, topBarCenterWidgets)
|
||||||
updateListModel(rightWidgetsModel, dankBarRightWidgets)
|
updateListModel(rightWidgetsModel, topBarRightWidgets)
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSettings() {
|
function loadSettings() {
|
||||||
_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"]
|
||||||
@@ -275,9 +209,9 @@ Singleton {
|
|||||||
}
|
}
|
||||||
customThemeFile = settings.customThemeFile !== undefined ? settings.customThemeFile : ""
|
customThemeFile = settings.customThemeFile !== undefined ? settings.customThemeFile : ""
|
||||||
matugenScheme = settings.matugenScheme !== undefined ? settings.matugenScheme : "scheme-tonal-spot"
|
matugenScheme = settings.matugenScheme !== undefined ? settings.matugenScheme : "scheme-tonal-spot"
|
||||||
dankBarTransparency = settings.dankBarTransparency !== undefined ? (settings.dankBarTransparency > 1 ? settings.dankBarTransparency / 100 : settings.dankBarTransparency) : (settings.topBarTransparency !== undefined ? (settings.topBarTransparency > 1 ? settings.topBarTransparency / 100 : settings.topBarTransparency) : 1.0)
|
topBarTransparency = settings.topBarTransparency !== undefined ? (settings.topBarTransparency > 1 ? settings.topBarTransparency / 100 : settings.topBarTransparency) : 0.75
|
||||||
dankBarWidgetTransparency = settings.dankBarWidgetTransparency !== undefined ? (settings.dankBarWidgetTransparency > 1 ? settings.dankBarWidgetTransparency / 100 : settings.dankBarWidgetTransparency) : (settings.topBarWidgetTransparency !== undefined ? (settings.topBarWidgetTransparency > 1 ? settings.topBarWidgetTransparency / 100 : settings.topBarWidgetTransparency) : 1.0)
|
topBarWidgetTransparency = settings.topBarWidgetTransparency !== undefined ? (settings.topBarWidgetTransparency > 1 ? settings.topBarWidgetTransparency / 100 : settings.topBarWidgetTransparency) : 0.85
|
||||||
popupTransparency = settings.popupTransparency !== undefined ? (settings.popupTransparency > 1 ? settings.popupTransparency / 100 : settings.popupTransparency) : 1.0
|
popupTransparency = settings.popupTransparency !== undefined ? (settings.popupTransparency > 1 ? settings.popupTransparency / 100 : settings.popupTransparency) : 0.92
|
||||||
dockTransparency = settings.dockTransparency !== undefined ? (settings.dockTransparency > 1 ? settings.dockTransparency / 100 : settings.dockTransparency) : 1
|
dockTransparency = settings.dockTransparency !== undefined ? (settings.dockTransparency > 1 ? settings.dockTransparency / 100 : settings.dockTransparency) : 1
|
||||||
use24HourClock = settings.use24HourClock !== undefined ? settings.use24HourClock : true
|
use24HourClock = settings.use24HourClock !== undefined ? settings.use24HourClock : true
|
||||||
useFahrenheit = settings.useFahrenheit !== undefined ? settings.useFahrenheit : false
|
useFahrenheit = settings.useFahrenheit !== undefined ? settings.useFahrenheit : false
|
||||||
@@ -330,24 +264,23 @@ Singleton {
|
|||||||
clockDateFormat = settings.clockDateFormat !== undefined ? settings.clockDateFormat : ""
|
clockDateFormat = settings.clockDateFormat !== undefined ? settings.clockDateFormat : ""
|
||||||
lockDateFormat = settings.lockDateFormat !== undefined ? settings.lockDateFormat : ""
|
lockDateFormat = settings.lockDateFormat !== undefined ? settings.lockDateFormat : ""
|
||||||
mediaSize = settings.mediaSize !== undefined ? settings.mediaSize : (settings.mediaCompactMode !== undefined ? (settings.mediaCompactMode ? 0 : 1) : 1)
|
mediaSize = settings.mediaSize !== undefined ? settings.mediaSize : (settings.mediaCompactMode !== undefined ? (settings.mediaCompactMode ? 0 : 1) : 1)
|
||||||
if (settings.dankBarWidgetOrder || settings.topBarWidgetOrder) {
|
if (settings.topBarWidgetOrder) {
|
||||||
var widgetOrder = settings.dankBarWidgetOrder || settings.topBarWidgetOrder
|
topBarLeftWidgets = settings.topBarWidgetOrder.filter(w => {
|
||||||
dankBarLeftWidgets = widgetOrder.filter(w => {
|
|
||||||
return ["launcherButton", "workspaceSwitcher", "focusedWindow"].includes(w)
|
return ["launcherButton", "workspaceSwitcher", "focusedWindow"].includes(w)
|
||||||
})
|
})
|
||||||
dankBarCenterWidgets = widgetOrder.filter(w => {
|
topBarCenterWidgets = settings.topBarWidgetOrder.filter(w => {
|
||||||
return ["clock", "music", "weather"].includes(w)
|
return ["clock", "music", "weather"].includes(w)
|
||||||
})
|
})
|
||||||
dankBarRightWidgets = widgetOrder.filter(w => {
|
topBarRightWidgets = settings.topBarWidgetOrder.filter(w => {
|
||||||
return ["systemTray", "clipboard", "systemResources", "notificationButton", "battery", "controlCenterButton"].includes(w)
|
return ["systemTray", "clipboard", "systemResources", "notificationButton", "battery", "controlCenterButton"].includes(w)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
var leftWidgets = settings.dankBarLeftWidgets !== undefined ? settings.dankBarLeftWidgets : (settings.topBarLeftWidgets !== undefined ? settings.topBarLeftWidgets : ["launcherButton", "workspaceSwitcher", "focusedWindow"])
|
var leftWidgets = settings.topBarLeftWidgets !== undefined ? settings.topBarLeftWidgets : ["launcherButton", "workspaceSwitcher", "focusedWindow"]
|
||||||
var centerWidgets = settings.dankBarCenterWidgets !== undefined ? settings.dankBarCenterWidgets : (settings.topBarCenterWidgets !== undefined ? settings.topBarCenterWidgets : ["music", "clock", "weather"])
|
var centerWidgets = settings.topBarCenterWidgets !== undefined ? settings.topBarCenterWidgets : ["music", "clock", "weather"]
|
||||||
var rightWidgets = settings.dankBarRightWidgets !== undefined ? settings.dankBarRightWidgets : (settings.topBarRightWidgets !== undefined ? settings.topBarRightWidgets : ["systemTray", "clipboard", "cpuUsage", "memUsage", "notificationButton", "battery", "controlCenterButton"])
|
var rightWidgets = settings.topBarRightWidgets !== undefined ? settings.topBarRightWidgets : ["systemTray", "clipboard", "cpuUsage", "memUsage", "notificationButton", "battery", "controlCenterButton"]
|
||||||
dankBarLeftWidgets = leftWidgets
|
topBarLeftWidgets = leftWidgets
|
||||||
dankBarCenterWidgets = centerWidgets
|
topBarCenterWidgets = centerWidgets
|
||||||
dankBarRightWidgets = rightWidgets
|
topBarRightWidgets = rightWidgets
|
||||||
updateListModel(leftWidgetsModel, leftWidgets)
|
updateListModel(leftWidgetsModel, leftWidgets)
|
||||||
updateListModel(centerWidgetsModel, centerWidgets)
|
updateListModel(centerWidgetsModel, centerWidgets)
|
||||||
updateListModel(rightWidgetsModel, rightWidgets)
|
updateListModel(rightWidgetsModel, rightWidgets)
|
||||||
@@ -356,25 +289,14 @@ 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"
|
||||||
if (settings.useOSLogo !== undefined) {
|
useOSLogo = settings.useOSLogo !== undefined ? settings.useOSLogo : false
|
||||||
launcherLogoMode = settings.useOSLogo ? "os" : "apps"
|
osLogoColorOverride = settings.osLogoColorOverride !== undefined ? settings.osLogoColorOverride : ""
|
||||||
launcherLogoColorOverride = settings.osLogoColorOverride !== undefined ? settings.osLogoColorOverride : ""
|
osLogoBrightness = settings.osLogoBrightness !== undefined ? settings.osLogoBrightness : 0.5
|
||||||
launcherLogoBrightness = settings.osLogoBrightness !== undefined ? settings.osLogoBrightness : 0.5
|
osLogoContrast = settings.osLogoContrast !== undefined ? settings.osLogoContrast : 1
|
||||||
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
|
||||||
@@ -386,34 +308,25 @@ Singleton {
|
|||||||
showDock = settings.showDock !== undefined ? settings.showDock : false
|
showDock = settings.showDock !== undefined ? settings.showDock : false
|
||||||
dockAutoHide = settings.dockAutoHide !== undefined ? settings.dockAutoHide : false
|
dockAutoHide = settings.dockAutoHide !== undefined ? settings.dockAutoHide : false
|
||||||
dockGroupByApp = settings.dockGroupByApp !== undefined ? settings.dockGroupByApp : false
|
dockGroupByApp = settings.dockGroupByApp !== undefined ? settings.dockGroupByApp : false
|
||||||
dockPosition = settings.dockPosition !== undefined ? settings.dockPosition : SettingsData.Position.Bottom
|
|
||||||
dockSpacing = settings.dockSpacing !== undefined ? settings.dockSpacing : 4
|
|
||||||
dockBottomGap = settings.dockBottomGap !== undefined ? settings.dockBottomGap : 0
|
|
||||||
cornerRadius = settings.cornerRadius !== undefined ? settings.cornerRadius : 12
|
cornerRadius = settings.cornerRadius !== undefined ? settings.cornerRadius : 12
|
||||||
notificationOverlayEnabled = settings.notificationOverlayEnabled !== undefined ? settings.notificationOverlayEnabled : false
|
notificationOverlayEnabled = settings.notificationOverlayEnabled !== undefined ? settings.notificationOverlayEnabled : false
|
||||||
dankBarAutoHide = settings.dankBarAutoHide !== undefined ? settings.dankBarAutoHide : (settings.topBarAutoHide !== undefined ? settings.topBarAutoHide : false)
|
topBarAutoHide = settings.topBarAutoHide !== undefined ? settings.topBarAutoHide : false
|
||||||
dankBarOpenOnOverview = settings.dankBarOpenOnOverview !== undefined ? settings.dankBarOpenOnOverview : (settings.topBarOpenOnOverview !== undefined ? settings.topBarOpenOnOverview : false)
|
topBarOpenOnOverview = settings.topBarOpenOnOverview !== undefined ? settings.topBarOpenOnOverview : false
|
||||||
dankBarVisible = settings.dankBarVisible !== undefined ? settings.dankBarVisible : (settings.topBarVisible !== undefined ? settings.topBarVisible : true)
|
topBarVisible = settings.topBarVisible !== undefined ? settings.topBarVisible : true
|
||||||
dockOpenOnOverview = settings.dockOpenOnOverview !== undefined ? settings.dockOpenOnOverview : false
|
|
||||||
notificationTimeoutLow = settings.notificationTimeoutLow !== undefined ? settings.notificationTimeoutLow : 5000
|
notificationTimeoutLow = settings.notificationTimeoutLow !== undefined ? settings.notificationTimeoutLow : 5000
|
||||||
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
|
topBarSpacing = settings.topBarSpacing !== undefined ? settings.topBarSpacing : 4
|
||||||
osdAlwaysShowValue = settings.osdAlwaysShowValue !== undefined ? settings.osdAlwaysShowValue : false
|
topBarBottomGap = settings.topBarBottomGap !== undefined ? settings.topBarBottomGap : 0
|
||||||
dankBarSpacing = settings.dankBarSpacing !== undefined ? settings.dankBarSpacing : (settings.topBarSpacing !== undefined ? settings.topBarSpacing : 4)
|
topBarInnerPadding = settings.topBarInnerPadding !== undefined ? settings.topBarInnerPadding : 8
|
||||||
dankBarBottomGap = settings.dankBarBottomGap !== undefined ? settings.dankBarBottomGap : (settings.topBarBottomGap !== undefined ? settings.topBarBottomGap : 0)
|
topBarSquareCorners = settings.topBarSquareCorners !== undefined ? settings.topBarSquareCorners : false
|
||||||
dankBarInnerPadding = settings.dankBarInnerPadding !== undefined ? settings.dankBarInnerPadding : (settings.topBarInnerPadding !== undefined ? settings.topBarInnerPadding : 4)
|
topBarNoBackground = settings.topBarNoBackground !== undefined ? settings.topBarNoBackground : false
|
||||||
dankBarSquareCorners = settings.dankBarSquareCorners !== undefined ? settings.dankBarSquareCorners : (settings.topBarSquareCorners !== undefined ? settings.topBarSquareCorners : false)
|
topBarGothCornersEnabled = settings.topBarGothCornersEnabled !== undefined ? settings.topBarGothCornersEnabled : 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)
|
|
||||||
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))
|
|
||||||
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 : "sc"
|
||||||
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({})
|
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({})
|
||||||
animationSpeed = settings.animationSpeed !== undefined ? settings.animationSpeed : SettingsData.AnimationSpeed.Short
|
|
||||||
applyStoredTheme()
|
applyStoredTheme()
|
||||||
detectAvailableIconThemes()
|
detectAvailableIconThemes()
|
||||||
detectQtTools()
|
detectQtTools()
|
||||||
@@ -427,11 +340,6 @@ Singleton {
|
|||||||
} finally {
|
} finally {
|
||||||
_loading = false
|
_loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldMigrate) {
|
|
||||||
savePluginSettings()
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
@@ -441,8 +349,8 @@ Singleton {
|
|||||||
"currentThemeName": currentThemeName,
|
"currentThemeName": currentThemeName,
|
||||||
"customThemeFile": customThemeFile,
|
"customThemeFile": customThemeFile,
|
||||||
"matugenScheme": matugenScheme,
|
"matugenScheme": matugenScheme,
|
||||||
"dankBarTransparency": dankBarTransparency,
|
"topBarTransparency": topBarTransparency,
|
||||||
"dankBarWidgetTransparency": dankBarWidgetTransparency,
|
"topBarWidgetTransparency": topBarWidgetTransparency,
|
||||||
"popupTransparency": popupTransparency,
|
"popupTransparency": popupTransparency,
|
||||||
"dockTransparency": dockTransparency,
|
"dockTransparency": dockTransparency,
|
||||||
"use24HourClock": use24HourClock,
|
"use24HourClock": use24HourClock,
|
||||||
@@ -487,25 +395,21 @@ Singleton {
|
|||||||
"clockDateFormat": clockDateFormat,
|
"clockDateFormat": clockDateFormat,
|
||||||
"lockDateFormat": lockDateFormat,
|
"lockDateFormat": lockDateFormat,
|
||||||
"mediaSize": mediaSize,
|
"mediaSize": mediaSize,
|
||||||
"dankBarLeftWidgets": dankBarLeftWidgets,
|
"topBarLeftWidgets": topBarLeftWidgets,
|
||||||
"dankBarCenterWidgets": dankBarCenterWidgets,
|
"topBarCenterWidgets": topBarCenterWidgets,
|
||||||
"dankBarRightWidgets": dankBarRightWidgets,
|
"topBarRightWidgets": topBarRightWidgets,
|
||||||
"appLauncherViewMode": appLauncherViewMode,
|
"appLauncherViewMode": appLauncherViewMode,
|
||||||
"spotlightModalViewMode": spotlightModalViewMode,
|
"spotlightModalViewMode": spotlightModalViewMode,
|
||||||
"networkPreference": networkPreference,
|
"networkPreference": networkPreference,
|
||||||
"iconTheme": iconTheme,
|
"iconTheme": iconTheme,
|
||||||
"launcherLogoMode": launcherLogoMode,
|
"useOSLogo": useOSLogo,
|
||||||
"launcherLogoCustomPath": launcherLogoCustomPath,
|
"osLogoColorOverride": osLogoColorOverride,
|
||||||
"launcherLogoColorOverride": launcherLogoColorOverride,
|
"osLogoBrightness": osLogoBrightness,
|
||||||
"launcherLogoColorInvertOnMode": launcherLogoColorInvertOnMode,
|
"osLogoContrast": osLogoContrast,
|
||||||
"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,
|
||||||
@@ -517,23 +421,17 @@ Singleton {
|
|||||||
"showDock": showDock,
|
"showDock": showDock,
|
||||||
"dockAutoHide": dockAutoHide,
|
"dockAutoHide": dockAutoHide,
|
||||||
"dockGroupByApp": dockGroupByApp,
|
"dockGroupByApp": dockGroupByApp,
|
||||||
"dockOpenOnOverview": dockOpenOnOverview,
|
|
||||||
"dockPosition": dockPosition,
|
|
||||||
"dockSpacing": dockSpacing,
|
|
||||||
"dockBottomGap": dockBottomGap,
|
|
||||||
"cornerRadius": cornerRadius,
|
"cornerRadius": cornerRadius,
|
||||||
"notificationOverlayEnabled": notificationOverlayEnabled,
|
"notificationOverlayEnabled": notificationOverlayEnabled,
|
||||||
"dankBarAutoHide": dankBarAutoHide,
|
"topBarAutoHide": topBarAutoHide,
|
||||||
"dankBarOpenOnOverview": dankBarOpenOnOverview,
|
"topBarOpenOnOverview": topBarOpenOnOverview,
|
||||||
"dankBarVisible": dankBarVisible,
|
"topBarVisible": topBarVisible,
|
||||||
"dankBarSpacing": dankBarSpacing,
|
"topBarSpacing": topBarSpacing,
|
||||||
"dankBarBottomGap": dankBarBottomGap,
|
"topBarBottomGap": topBarBottomGap,
|
||||||
"dankBarInnerPadding": dankBarInnerPadding,
|
"topBarInnerPadding": topBarInnerPadding,
|
||||||
"dankBarSquareCorners": dankBarSquareCorners,
|
"topBarSquareCorners": topBarSquareCorners,
|
||||||
"dankBarNoBackground": dankBarNoBackground,
|
"topBarNoBackground": topBarNoBackground,
|
||||||
"dankBarGothCornersEnabled": dankBarGothCornersEnabled,
|
"topBarGothCornersEnabled": topBarGothCornersEnabled,
|
||||||
"dankBarBorderEnabled": dankBarBorderEnabled,
|
|
||||||
"dankBarPosition": dankBarPosition,
|
|
||||||
"lockScreenShowPowerActions": lockScreenShowPowerActions,
|
"lockScreenShowPowerActions": lockScreenShowPowerActions,
|
||||||
"hideBrightnessSlider": hideBrightnessSlider,
|
"hideBrightnessSlider": hideBrightnessSlider,
|
||||||
"widgetBackgroundColor": widgetBackgroundColor,
|
"widgetBackgroundColor": widgetBackgroundColor,
|
||||||
@@ -541,19 +439,10 @@ Singleton {
|
|||||||
"notificationTimeoutLow": notificationTimeoutLow,
|
"notificationTimeoutLow": notificationTimeoutLow,
|
||||||
"notificationTimeoutNormal": notificationTimeoutNormal,
|
"notificationTimeoutNormal": notificationTimeoutNormal,
|
||||||
"notificationTimeoutCritical": notificationTimeoutCritical,
|
"notificationTimeoutCritical": notificationTimeoutCritical,
|
||||||
"notificationPopupPosition": notificationPopupPosition,
|
"screenPreferences": screenPreferences
|
||||||
"osdAlwaysShowValue": osdAlwaysShowValue,
|
|
||||||
"screenPreferences": screenPreferences,
|
|
||||||
"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()
|
||||||
@@ -666,11 +555,11 @@ Singleton {
|
|||||||
|
|
||||||
function applyStoredTheme() {
|
function applyStoredTheme() {
|
||||||
if (typeof Theme !== "undefined")
|
if (typeof Theme !== "undefined")
|
||||||
Theme.switchTheme(currentThemeName, false, false)
|
Theme.switchTheme(currentThemeName, false)
|
||||||
else
|
else
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (typeof Theme !== "undefined")
|
if (typeof Theme !== "undefined")
|
||||||
Theme.switchTheme(currentThemeName, false, false)
|
Theme.switchTheme(currentThemeName, false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,17 +582,20 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
|
|
||||||
if (typeof Theme !== "undefined") {
|
if (typeof Theme !== "undefined") {
|
||||||
|
if (Theme.currentTheme === Theme.dynamic) {
|
||||||
|
Theme.extractColors()
|
||||||
|
}
|
||||||
Theme.generateSystemThemesFromCurrentTheme()
|
Theme.generateSystemThemesFromCurrentTheme()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarTransparency(transparency) {
|
function setTopBarTransparency(transparency) {
|
||||||
dankBarTransparency = transparency
|
topBarTransparency = transparency
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarWidgetTransparency(transparency) {
|
function setTopBarWidgetTransparency(transparency) {
|
||||||
dankBarWidgetTransparency = transparency
|
topBarWidgetTransparency = transparency
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -838,25 +730,25 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarWidgetOrder(order) {
|
function setTopBarWidgetOrder(order) {
|
||||||
dankBarWidgetOrder = order
|
topBarWidgetOrder = order
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarLeftWidgets(order) {
|
function setTopBarLeftWidgets(order) {
|
||||||
dankBarLeftWidgets = order
|
topBarLeftWidgets = order
|
||||||
updateListModel(leftWidgetsModel, order)
|
updateListModel(leftWidgetsModel, order)
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarCenterWidgets(order) {
|
function setTopBarCenterWidgets(order) {
|
||||||
dankBarCenterWidgets = order
|
topBarCenterWidgets = order
|
||||||
updateListModel(centerWidgetsModel, order)
|
updateListModel(centerWidgetsModel, order)
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarRightWidgets(order) {
|
function setTopBarRightWidgets(order) {
|
||||||
dankBarRightWidgets = order
|
topBarRightWidgets = order
|
||||||
updateListModel(rightWidgetsModel, order)
|
updateListModel(rightWidgetsModel, order)
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
@@ -870,7 +762,6 @@ 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
|
||||||
@@ -883,8 +774,6 @@ 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)
|
||||||
}
|
}
|
||||||
@@ -892,13 +781,13 @@ Singleton {
|
|||||||
widgetDataChanged()
|
widgetDataChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetDankBarWidgetsToDefault() {
|
function resetTopBarWidgetsToDefault() {
|
||||||
var defaultLeft = ["launcherButton", "workspaceSwitcher", "focusedWindow"]
|
var defaultLeft = ["launcherButton", "workspaceSwitcher", "focusedWindow"]
|
||||||
var defaultCenter = ["music", "clock", "weather"]
|
var defaultCenter = ["music", "clock", "weather"]
|
||||||
var defaultRight = ["systemTray", "clipboard", "notificationButton", "battery", "controlCenterButton"]
|
var defaultRight = ["systemTray", "clipboard", "notificationButton", "battery", "controlCenterButton"]
|
||||||
dankBarLeftWidgets = defaultLeft
|
topBarLeftWidgets = defaultLeft
|
||||||
dankBarCenterWidgets = defaultCenter
|
topBarCenterWidgets = defaultCenter
|
||||||
dankBarRightWidgets = defaultRight
|
topBarRightWidgets = defaultRight
|
||||||
updateListModel(leftWidgetsModel, defaultLeft)
|
updateListModel(leftWidgetsModel, defaultLeft)
|
||||||
updateListModel(centerWidgetsModel, defaultCenter)
|
updateListModel(centerWidgetsModel, defaultCenter)
|
||||||
updateListModel(rightWidgetsModel, defaultRight)
|
updateListModel(rightWidgetsModel, defaultRight)
|
||||||
@@ -1007,38 +896,23 @@ Singleton {
|
|||||||
updateQtIconTheme(iconTheme)
|
updateQtIconTheme(iconTheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLauncherLogoMode(mode) {
|
function setUseOSLogo(enabled) {
|
||||||
launcherLogoMode = mode
|
useOSLogo = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLauncherLogoCustomPath(path) {
|
function setOSLogoColorOverride(color) {
|
||||||
launcherLogoCustomPath = path
|
osLogoColorOverride = color
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLauncherLogoColorOverride(color) {
|
function setOSLogoBrightness(brightness) {
|
||||||
launcherLogoColorOverride = color
|
osLogoBrightness = brightness
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLauncherLogoColorInvertOnMode(invert) {
|
function setOSLogoContrast(contrast) {
|
||||||
launcherLogoColorInvertOnMode = invert
|
osLogoContrast = contrast
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLauncherLogoBrightness(brightness) {
|
|
||||||
launcherLogoBrightness = brightness
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLauncherLogoContrast(contrast) {
|
|
||||||
launcherLogoContrast = contrast
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLauncherLogoSizeOffset(offset) {
|
|
||||||
launcherLogoSizeOffset = offset
|
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,11 +936,6 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarFontScale(scale) {
|
|
||||||
dankBarFontScale = scale
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setGtkThemingEnabled(enabled) {
|
function setGtkThemingEnabled(enabled) {
|
||||||
gtkThemingEnabled = enabled
|
gtkThemingEnabled = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
@@ -1085,24 +954,6 @@ Singleton {
|
|||||||
|
|
||||||
function setShowDock(enabled) {
|
function setShowDock(enabled) {
|
||||||
showDock = enabled
|
showDock = enabled
|
||||||
if (enabled && dockPosition === dankBarPosition) {
|
|
||||||
if (dankBarPosition === SettingsData.Position.Top) {
|
|
||||||
setDockPosition(SettingsData.Position.Bottom)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (dankBarPosition === SettingsData.Position.Bottom) {
|
|
||||||
setDockPosition(SettingsData.Position.Top)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (dankBarPosition === SettingsData.Position.Left) {
|
|
||||||
setDockPosition(SettingsData.Position.Right)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (dankBarPosition === SettingsData.Position.Right) {
|
|
||||||
setDockPosition(SettingsData.Position.Left)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1116,11 +967,6 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setdockOpenOnOverview(enabled) {
|
|
||||||
dockOpenOnOverview = enabled
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCornerRadius(radius) {
|
function setCornerRadius(radius) {
|
||||||
cornerRadius = radius
|
cornerRadius = radius
|
||||||
saveSettings()
|
saveSettings()
|
||||||
@@ -1131,23 +977,23 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarAutoHide(enabled) {
|
function setTopBarAutoHide(enabled) {
|
||||||
dankBarAutoHide = enabled
|
topBarAutoHide = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarOpenOnOverview(enabled) {
|
function setTopBarOpenOnOverview(enabled) {
|
||||||
dankBarOpenOnOverview = enabled
|
topBarOpenOnOverview = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarVisible(visible) {
|
function setTopBarVisible(visible) {
|
||||||
dankBarVisible = visible
|
topBarVisible = visible
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleDankBarVisible() {
|
function toggleTopBarVisible() {
|
||||||
dankBarVisible = !dankBarVisible
|
topBarVisible = !topBarVisible
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,172 +1012,36 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setNotificationPopupPosition(position) {
|
function setTopBarSpacing(spacing) {
|
||||||
notificationPopupPosition = position
|
topBarSpacing = spacing
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setOsdAlwaysShowValue(enabled) {
|
function setTopBarBottomGap(gap) {
|
||||||
osdAlwaysShowValue = enabled
|
topBarBottomGap = gap
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendTestNotifications() {
|
function setTopBarInnerPadding(padding) {
|
||||||
sendTestNotification(0)
|
topBarInnerPadding = padding
|
||||||
testNotifTimer1.start()
|
|
||||||
testNotifTimer2.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendTestNotification(index) {
|
|
||||||
const notifications = [
|
|
||||||
["Notification Position Test", "DMS test notification 1 of 3 ~ Hi there!", "preferences-system"],
|
|
||||||
["Second Test", "DMS Notification 2 of 3 ~ Check it out!", "applications-graphics"],
|
|
||||||
["Third Test", "DMS notification 3 of 3 ~ Enjoy!", "face-smile"]
|
|
||||||
]
|
|
||||||
|
|
||||||
if (index < 0 || index >= notifications.length) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const notif = notifications[index]
|
|
||||||
testNotificationProcess.command = ["notify-send", "-h", "int:transient:1", "-a", "DMS", "-i", notif[2], notif[0], notif[1]]
|
|
||||||
testNotificationProcess.running = true
|
|
||||||
}
|
|
||||||
|
|
||||||
property Process testNotificationProcess
|
|
||||||
|
|
||||||
testNotificationProcess: Process {
|
|
||||||
command: []
|
|
||||||
running: false
|
|
||||||
}
|
|
||||||
|
|
||||||
property Timer testNotifTimer1
|
|
||||||
|
|
||||||
testNotifTimer1: Timer {
|
|
||||||
interval: 400
|
|
||||||
repeat: false
|
|
||||||
onTriggered: sendTestNotification(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
property Timer testNotifTimer2
|
|
||||||
|
|
||||||
testNotifTimer2: Timer {
|
|
||||||
interval: 800
|
|
||||||
repeat: false
|
|
||||||
onTriggered: sendTestNotification(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDankBarSpacing(spacing) {
|
|
||||||
dankBarSpacing = spacing
|
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarBottomGap(gap) {
|
function setTopBarSquareCorners(enabled) {
|
||||||
dankBarBottomGap = gap
|
topBarSquareCorners = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarInnerPadding(padding) {
|
function setTopBarNoBackground(enabled) {
|
||||||
dankBarInnerPadding = padding
|
topBarNoBackground = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarSquareCorners(enabled) {
|
function setTopBarGothCornersEnabled(enabled) {
|
||||||
dankBarSquareCorners = enabled
|
topBarGothCornersEnabled = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDankBarNoBackground(enabled) {
|
|
||||||
dankBarNoBackground = enabled
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDankBarGothCornersEnabled(enabled) {
|
|
||||||
dankBarGothCornersEnabled = enabled
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDankBarBorderEnabled(enabled) {
|
|
||||||
dankBarBorderEnabled = enabled
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDankBarPosition(position) {
|
|
||||||
dankBarPosition = position
|
|
||||||
if (position === SettingsData.Position.Bottom && dockPosition === SettingsData.Position.Bottom && showDock) {
|
|
||||||
setDockPosition(SettingsData.Position.Top)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (position === SettingsData.Position.Top && dockPosition === SettingsData.Position.Top && showDock) {
|
|
||||||
setDockPosition(SettingsData.Position.Bottom)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (position === SettingsData.Position.Left && dockPosition === SettingsData.Position.Left && showDock) {
|
|
||||||
setDockPosition(SettingsData.Position.Right)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (position === SettingsData.Position.Right && dockPosition === SettingsData.Position.Right && showDock) {
|
|
||||||
setDockPosition(SettingsData.Position.Left)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDockPosition(position) {
|
|
||||||
dockPosition = position
|
|
||||||
if (position === SettingsData.Position.Bottom && dankBarPosition === SettingsData.Position.Bottom && showDock) {
|
|
||||||
setDankBarPosition(SettingsData.Position.Top)
|
|
||||||
}
|
|
||||||
if (position === SettingsData.Position.Top && dankBarPosition === SettingsData.Position.Top && showDock) {
|
|
||||||
setDankBarPosition(SettingsData.Position.Bottom)
|
|
||||||
}
|
|
||||||
if (position === SettingsData.Position.Left && dankBarPosition === SettingsData.Position.Left && showDock) {
|
|
||||||
setDankBarPosition(SettingsData.Position.Right)
|
|
||||||
}
|
|
||||||
if (position === SettingsData.Position.Right && dankBarPosition === SettingsData.Position.Right && showDock) {
|
|
||||||
setDankBarPosition(SettingsData.Position.Left)
|
|
||||||
}
|
|
||||||
saveSettings()
|
|
||||||
Qt.callLater(() => forceDockLayoutRefresh())
|
|
||||||
}
|
|
||||||
function setDockSpacing(spacing) {
|
|
||||||
dockSpacing = spacing
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
function setDockBottomGap(gap) {
|
|
||||||
dockBottomGap = gap
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
function setDockOpenOnOverview(enabled) {
|
|
||||||
dockOpenOnOverview = enabled
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPopupYPosition(barHeight) {
|
|
||||||
const gothOffset = dankBarGothCornersEnabled ? Theme.cornerRadius : 0
|
|
||||||
return barHeight + dankBarSpacing + dankBarBottomGap - gothOffset + Theme.popupDistance
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPopupTriggerPosition(globalPos, screen, barThickness, widgetWidth) {
|
|
||||||
const screenX = screen ? screen.x : 0
|
|
||||||
const screenY = screen ? screen.y : 0
|
|
||||||
const relativeX = globalPos.x - screenX
|
|
||||||
const relativeY = globalPos.y - screenY
|
|
||||||
|
|
||||||
if (dankBarPosition === SettingsData.Position.Left || dankBarPosition === SettingsData.Position.Right) {
|
|
||||||
return {
|
|
||||||
x: relativeY,
|
|
||||||
y: barThickness + dankBarSpacing + Theme.popupDistance,
|
|
||||||
width: widgetWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
x: relativeX,
|
|
||||||
y: barThickness + dankBarSpacing + dankBarBottomGap + Theme.popupDistance,
|
|
||||||
width: widgetWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLockScreenShowPowerActions(enabled) {
|
function setLockScreenShowPowerActions(enabled) {
|
||||||
lockScreenShowPowerActions = enabled
|
lockScreenShowPowerActions = enabled
|
||||||
saveSettings()
|
saveSettings()
|
||||||
@@ -1368,48 +1078,14 @@ Singleton {
|
|||||||
return Quickshell.screens.filter(screen => prefs.includes(screen.name))
|
return Quickshell.screens.filter(screen => prefs.includes(screen.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin settings functions
|
|
||||||
function getPluginSetting(pluginId, key, defaultValue) {
|
|
||||||
if (!pluginSettings[pluginId]) {
|
|
||||||
return defaultValue
|
|
||||||
}
|
|
||||||
return pluginSettings[pluginId][key] !== undefined ? pluginSettings[pluginId][key] : defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPluginSetting(pluginId, key, value) {
|
|
||||||
if (!pluginSettings[pluginId]) {
|
|
||||||
pluginSettings[pluginId] = {}
|
|
||||||
}
|
|
||||||
pluginSettings[pluginId][key] = value
|
|
||||||
savePluginSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function removePluginSettings(pluginId) {
|
|
||||||
if (pluginSettings[pluginId]) {
|
|
||||||
delete pluginSettings[pluginId]
|
|
||||||
savePluginSettings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPluginSettingsForPlugin(pluginId) {
|
|
||||||
return pluginSettings[pluginId] || {}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAnimationSpeed(speed) {
|
|
||||||
animationSpeed = speed
|
|
||||||
saveSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
function _shq(s) {
|
function _shq(s) {
|
||||||
return "'" + String(s).replace(/'/g, "'\\''") + "'"
|
return "'" + String(s).replace(/'/g, "'\\''") + "'"
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (!isGreeterMode) {
|
loadSettings()
|
||||||
loadSettings()
|
fontCheckTimer.start()
|
||||||
fontCheckTimer.start()
|
initializeListModels()
|
||||||
initializeListModels()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
@@ -1450,47 +1126,25 @@ Singleton {
|
|||||||
FileView {
|
FileView {
|
||||||
id: settingsFile
|
id: settingsFile
|
||||||
|
|
||||||
path: isGreeterMode ? "" : StandardPaths.writableLocation(StandardPaths.ConfigLocation) + "/DankMaterialShell/settings.json"
|
path: StandardPaths.writableLocation(StandardPaths.ConfigLocation) + "/DankMaterialShell/settings.json"
|
||||||
blockLoading: true
|
blockLoading: true
|
||||||
blockWrites: true
|
blockWrites: true
|
||||||
atomicWrites: true
|
atomicWrites: true
|
||||||
watchChanges: !isGreeterMode
|
watchChanges: true
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
if (!isGreeterMode) {
|
parseSettings(settingsFile.text())
|
||||||
parseSettings(settingsFile.text())
|
hasTriedDefaultSettings = false
|
||||||
hasTriedDefaultSettings = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
onLoadFailed: error => {
|
onLoadFailed: error => {
|
||||||
if (!isGreeterMode && !hasTriedDefaultSettings) {
|
if (!hasTriedDefaultSettings) {
|
||||||
hasTriedDefaultSettings = true
|
hasTriedDefaultSettings = true
|
||||||
defaultSettingsCheckProcess.running = true
|
defaultSettingsCheckProcess.running = true
|
||||||
} else if (!isGreeterMode) {
|
} else {
|
||||||
applyStoredTheme()
|
applyStoredTheme()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -1555,7 +1209,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 --no-preserve=mode \"$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 \"$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) {
|
||||||
@@ -1570,22 +1224,22 @@ Singleton {
|
|||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
function reveal(): string {
|
function reveal(): string {
|
||||||
root.setDankBarVisible(true)
|
root.setTopBarVisible(true)
|
||||||
return "BAR_SHOW_SUCCESS"
|
return "BAR_SHOW_SUCCESS"
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide(): string {
|
function hide(): string {
|
||||||
root.setDankBarVisible(false)
|
root.setTopBarVisible(false)
|
||||||
return "BAR_HIDE_SUCCESS"
|
return "BAR_HIDE_SUCCESS"
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle(): string {
|
function toggle(): string {
|
||||||
root.toggleDankBarVisible()
|
root.toggleTopBarVisible()
|
||||||
return root.dankBarVisible ? "BAR_SHOW_SUCCESS" : "BAR_HIDE_SUCCESS"
|
return topBarVisible ? "BAR_SHOW_SUCCESS" : "BAR_HIDE_SUCCESS"
|
||||||
}
|
}
|
||||||
|
|
||||||
function status(): string {
|
function status(): string {
|
||||||
return root.dankBarVisible ? "visible" : "hidden"
|
return topBarVisible ? "visible" : "hidden"
|
||||||
}
|
}
|
||||||
|
|
||||||
target: "bar"
|
target: "bar"
|
||||||
|
|||||||
@@ -2,101 +2,101 @@
|
|||||||
// Separated from Theme.qml to keep that file clean
|
// Separated from Theme.qml to keep that file clean
|
||||||
|
|
||||||
const CatppuccinMocha = {
|
const CatppuccinMocha = {
|
||||||
surface: "#313244",
|
surface: "#45475a",
|
||||||
surfaceText: "#cdd6f4",
|
surfaceText: "#cdd6f4",
|
||||||
surfaceVariant: "#313244",
|
surfaceVariant: "#45475a",
|
||||||
surfaceVariantText: "#a6adc8",
|
surfaceVariantText: "#a6adc8",
|
||||||
background: "#1e1e2e",
|
background: "#1e1e2e",
|
||||||
backgroundText: "#cdd6f4",
|
backgroundText: "#cdd6f4",
|
||||||
outline: "#6c7086",
|
outline: "#6c7086",
|
||||||
surfaceContainer: "#45475a",
|
surfaceContainer: "#313244",
|
||||||
surfaceContainerHigh: "#585b70",
|
surfaceContainerHigh: "#585b70",
|
||||||
surfaceContainerHighest: "#6c7086"
|
surfaceContainerHighest: "#7f849c"
|
||||||
}
|
}
|
||||||
|
|
||||||
const CatppuccinLatte = {
|
const CatppuccinLatte = {
|
||||||
surface: "#e6e9ef",
|
surface: "#bcc0cc",
|
||||||
surfaceText: "#4c4f69",
|
surfaceText: "#4c4f69",
|
||||||
surfaceVariant: "#e6e9ef",
|
surfaceVariant: "#bcc0cc",
|
||||||
surfaceVariantText: "#6c6f85",
|
surfaceVariantText: "#6c6f85",
|
||||||
background: "#eff1f5",
|
background: "#eff1f5",
|
||||||
backgroundText: "#4c4f69",
|
backgroundText: "#4c4f69",
|
||||||
outline: "#9ca0b0",
|
outline: "#9ca0b0",
|
||||||
surfaceContainer: "#dce0e8",
|
surfaceContainer: "#ccd0da",
|
||||||
surfaceContainerHigh: "#ccd0da",
|
surfaceContainerHigh: "#acb0be",
|
||||||
surfaceContainerHighest: "#bcc0cc"
|
surfaceContainerHighest: "#8c8fa1"
|
||||||
}
|
}
|
||||||
|
|
||||||
const CatppuccinVariants = {
|
const CatppuccinVariants = {
|
||||||
"cat-rosewater": {
|
"cat-rosewater": {
|
||||||
name: "Rosewater",
|
name: "Rosewater",
|
||||||
dark: { primary: "#f5e0dc", secondary: "#f2cdcd", primaryText: "#1e1e2e", primaryContainer: "#7d5d56", surfaceTint: "#f5e0dc" },
|
dark: { primary: "#f5e0dc", secondary: "#f2cdcd", primaryText: "#1e1e2e", primaryContainer: "#8b6b5e", surfaceTint: "#f5e0dc" },
|
||||||
light: { primary: "#dc8a78", secondary: "#dd7878", primaryText: "#ffffff", primaryContainer: "#f6e7e3", surfaceTint: "#dc8a78" }
|
light: { primary: "#dc8a78", secondary: "#dd7878", primaryText: "#ffffff", primaryContainer: "#f4d2ca", surfaceTint: "#dc8a78" }
|
||||||
},
|
},
|
||||||
"cat-flamingo": {
|
"cat-flamingo": {
|
||||||
name: "Flamingo",
|
name: "Flamingo",
|
||||||
dark: { primary: "#f2cdcd", secondary: "#f5e0dc", primaryText: "#1e1e2e", primaryContainer: "#7a555a", surfaceTint: "#f2cdcd" },
|
dark: { primary: "#f2cdcd", secondary: "#f5e0dc", primaryText: "#1e1e2e", primaryContainer: "#885d62", surfaceTint: "#f2cdcd" },
|
||||||
light: { primary: "#dd7878", secondary: "#dc8a78", primaryText: "#ffffff", primaryContainer: "#f6e5e5", surfaceTint: "#dd7878" }
|
light: { primary: "#dd7878", secondary: "#dc8a78", primaryText: "#ffffff", primaryContainer: "#f4caca", surfaceTint: "#dd7878" }
|
||||||
},
|
},
|
||||||
"cat-pink": {
|
"cat-pink": {
|
||||||
name: "Pink",
|
name: "Pink",
|
||||||
dark: { primary: "#f5c2e7", secondary: "#cba6f7", primaryText: "#1e1e2e", primaryContainer: "#7a3f69", surfaceTint: "#f5c2e7" },
|
dark: { primary: "#f5c2e7", secondary: "#cba6f7", primaryText: "#1e1e2e", primaryContainer: "#8b537a", surfaceTint: "#f5c2e7" },
|
||||||
light: { primary: "#ea76cb", secondary: "#8839ef", primaryText: "#ffffff", primaryContainer: "#f7d7ee", surfaceTint: "#ea76cb" }
|
light: { primary: "#ea76cb", secondary: "#8839ef", primaryText: "#ffffff", primaryContainer: "#f7c9e7", surfaceTint: "#ea76cb" }
|
||||||
},
|
},
|
||||||
"cat-mauve": {
|
"cat-mauve": {
|
||||||
name: "Mauve",
|
name: "Mauve",
|
||||||
dark: { primary: "#cba6f7", secondary: "#b4befe", primaryText: "#1e1e2e", primaryContainer: "#55307f", surfaceTint: "#cba6f7" },
|
dark: { primary: "#cba6f7", secondary: "#b4befe", primaryText: "#1e1e2e", primaryContainer: "#61378a", surfaceTint: "#cba6f7" },
|
||||||
light: { primary: "#8839ef", secondary: "#7287fd", primaryText: "#ffffff", primaryContainer: "#eadcff", surfaceTint: "#8839ef" }
|
light: { primary: "#8839ef", secondary: "#7287fd", primaryText: "#ffffff", primaryContainer: "#e4d3ff", surfaceTint: "#8839ef" }
|
||||||
},
|
},
|
||||||
"cat-red": {
|
"cat-red": {
|
||||||
name: "Red",
|
name: "Red",
|
||||||
dark: { primary: "#f38ba8", secondary: "#eba0ac", primaryText: "#1e1e2e", primaryContainer: "#6f2438", surfaceTint: "#f38ba8" },
|
dark: { primary: "#f38ba8", secondary: "#eba0ac", primaryText: "#1e1e2e", primaryContainer: "#891c3b", surfaceTint: "#f38ba8" },
|
||||||
light: { primary: "#d20f39", secondary: "#e64553", primaryText: "#ffffff", primaryContainer: "#f6d0d6", surfaceTint: "#d20f39" }
|
light: { primary: "#d20f39", secondary: "#e64553", primaryText: "#ffffff", primaryContainer: "#f1b8c4", surfaceTint: "#d20f39" }
|
||||||
},
|
},
|
||||||
"cat-maroon": {
|
"cat-maroon": {
|
||||||
name: "Maroon",
|
name: "Maroon",
|
||||||
dark: { primary: "#eba0ac", secondary: "#f38ba8", primaryText: "#1e1e2e", primaryContainer: "#6d3641", surfaceTint: "#eba0ac" },
|
dark: { primary: "#eba0ac", secondary: "#f38ba8", primaryText: "#1e1e2e", primaryContainer: "#81313f", surfaceTint: "#eba0ac" },
|
||||||
light: { primary: "#e64553", secondary: "#d20f39", primaryText: "#ffffff", primaryContainer: "#f7d8dc", surfaceTint: "#e64553" }
|
light: { primary: "#e64553", secondary: "#d20f39", primaryText: "#ffffff", primaryContainer: "#f4c3c8", surfaceTint: "#e64553" }
|
||||||
},
|
},
|
||||||
"cat-peach": {
|
"cat-peach": {
|
||||||
name: "Peach",
|
name: "Peach",
|
||||||
dark: { primary: "#fab387", secondary: "#f9e2af", primaryText: "#1e1e2e", primaryContainer: "#734226", surfaceTint: "#fab387" },
|
dark: { primary: "#fab387", secondary: "#f9e2af", primaryText: "#1e1e2e", primaryContainer: "#90441a", surfaceTint: "#fab387" },
|
||||||
light: { primary: "#fe640b", secondary: "#df8e1d", primaryText: "#ffffff", primaryContainer: "#ffe4d5", surfaceTint: "#fe640b" }
|
light: { primary: "#fe640b", secondary: "#df8e1d", primaryText: "#ffffff", primaryContainer: "#ffddcc", surfaceTint: "#fe640b" }
|
||||||
},
|
},
|
||||||
"cat-yellow": {
|
"cat-yellow": {
|
||||||
name: "Yellow",
|
name: "Yellow",
|
||||||
dark: { primary: "#f9e2af", secondary: "#a6e3a1", primaryText: "#1e1e2e", primaryContainer: "#6e5a2f", surfaceTint: "#f9e2af" },
|
dark: { primary: "#f9e2af", secondary: "#a6e3a1", primaryText: "#1e1e2e", primaryContainer: "#8f7342", surfaceTint: "#f9e2af" },
|
||||||
light: { primary: "#df8e1d", secondary: "#40a02b", primaryText: "#ffffff", primaryContainer: "#fff6d6", surfaceTint: "#df8e1d" }
|
light: { primary: "#df8e1d", secondary: "#40a02b", primaryText: "#ffffff", primaryContainer: "#fff3cc", surfaceTint: "#df8e1d" }
|
||||||
},
|
},
|
||||||
"cat-green": {
|
"cat-green": {
|
||||||
name: "Green",
|
name: "Green",
|
||||||
dark: { primary: "#a6e3a1", secondary: "#94e2d5", primaryText: "#1e1e2e", primaryContainer: "#2f5f36", surfaceTint: "#a6e3a1" },
|
dark: { primary: "#a6e3a1", secondary: "#94e2d5", primaryText: "#1e1e2e", primaryContainer: "#3c7534", surfaceTint: "#a6e3a1" },
|
||||||
light: { primary: "#40a02b", secondary: "#179299", primaryText: "#ffffff", primaryContainer: "#dff4e0", surfaceTint: "#40a02b" }
|
light: { primary: "#40a02b", secondary: "#179299", primaryText: "#ffffff", primaryContainer: "#d4f5d4", surfaceTint: "#40a02b" }
|
||||||
},
|
},
|
||||||
"cat-teal": {
|
"cat-teal": {
|
||||||
name: "Teal",
|
name: "Teal",
|
||||||
dark: { primary: "#94e2d5", secondary: "#89dceb", primaryText: "#1e1e2e", primaryContainer: "#2e5e59", surfaceTint: "#94e2d5" },
|
dark: { primary: "#94e2d5", secondary: "#89dceb", primaryText: "#1e1e2e", primaryContainer: "#2a7468", surfaceTint: "#94e2d5" },
|
||||||
light: { primary: "#179299", secondary: "#04a5e5", primaryText: "#ffffff", primaryContainer: "#daf3f1", surfaceTint: "#179299" }
|
light: { primary: "#179299", secondary: "#04a5e5", primaryText: "#ffffff", primaryContainer: "#ccf2f2", surfaceTint: "#179299" }
|
||||||
},
|
},
|
||||||
"cat-sky": {
|
"cat-sky": {
|
||||||
name: "Sky",
|
name: "Sky",
|
||||||
dark: { primary: "#89dceb", secondary: "#74c7ec", primaryText: "#1e1e2e", primaryContainer: "#24586a", surfaceTint: "#89dceb" },
|
dark: { primary: "#89dceb", secondary: "#74c7ec", primaryText: "#1e1e2e", primaryContainer: "#196e7e", surfaceTint: "#89dceb" },
|
||||||
light: { primary: "#04a5e5", secondary: "#209fb5", primaryText: "#ffffff", primaryContainer: "#dbf1fb", surfaceTint: "#04a5e5" }
|
light: { primary: "#04a5e5", secondary: "#209fb5", primaryText: "#ffffff", primaryContainer: "#ccebff", surfaceTint: "#04a5e5" }
|
||||||
},
|
},
|
||||||
"cat-sapphire": {
|
"cat-sapphire": {
|
||||||
name: "Sapphire",
|
name: "Sapphire",
|
||||||
dark: { primary: "#74c7ec", secondary: "#89b4fa", primaryText: "#1e1e2e", primaryContainer: "#1f4d6f", surfaceTint: "#74c7ec" },
|
dark: { primary: "#74c7ec", secondary: "#89b4fa", primaryText: "#1e1e2e", primaryContainer: "#0a597f", surfaceTint: "#74c7ec" },
|
||||||
light: { primary: "#209fb5", secondary: "#1e66f5", primaryText: "#ffffff", primaryContainer: "#def3f8", surfaceTint: "#209fb5" }
|
light: { primary: "#209fb5", secondary: "#1e66f5", primaryText: "#ffffff", primaryContainer: "#d0f0f5", surfaceTint: "#209fb5" }
|
||||||
},
|
},
|
||||||
"cat-blue": {
|
"cat-blue": {
|
||||||
name: "Blue",
|
name: "Blue",
|
||||||
dark: { primary: "#89b4fa", secondary: "#b4befe", primaryText: "#1e1e2e", primaryContainer: "#243f75", surfaceTint: "#89b4fa" },
|
dark: { primary: "#89b4fa", secondary: "#b4befe", primaryText: "#1e1e2e", primaryContainer: "#19468d", surfaceTint: "#89b4fa" },
|
||||||
light: { primary: "#1e66f5", secondary: "#7287fd", primaryText: "#ffffff", primaryContainer: "#e0e9ff", surfaceTint: "#1e66f5" }
|
light: { primary: "#1e66f5", secondary: "#7287fd", primaryText: "#ffffff", primaryContainer: "#ccd9ff", surfaceTint: "#1e66f5" }
|
||||||
},
|
},
|
||||||
"cat-lavender": {
|
"cat-lavender": {
|
||||||
name: "Lavender",
|
name: "Lavender",
|
||||||
dark: { primary: "#b4befe", secondary: "#cba6f7", primaryText: "#1e1e2e", primaryContainer: "#3f4481", surfaceTint: "#b4befe" },
|
dark: { primary: "#b4befe", secondary: "#cba6f7", primaryText: "#1e1e2e", primaryContainer: "#4a5091", surfaceTint: "#b4befe" },
|
||||||
light: { primary: "#7287fd", secondary: "#8839ef", primaryText: "#ffffff", primaryContainer: "#e5e8ff", surfaceTint: "#7287fd" }
|
light: { primary: "#7287fd", secondary: "#8839ef", primaryText: "#ffffff", primaryContainer: "#dde1ff", surfaceTint: "#7287fd" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,17 +120,17 @@ const StockThemes = {
|
|||||||
primaryText: "#000000",
|
primaryText: "#000000",
|
||||||
primaryContainer: "#0d47a1",
|
primaryContainer: "#0d47a1",
|
||||||
secondary: "#8ab4f8",
|
secondary: "#8ab4f8",
|
||||||
surface: "#101418",
|
surface: "#1a1c1e",
|
||||||
surfaceText: "#e0e2e8",
|
surfaceText: "#e3e8ef",
|
||||||
surfaceVariant: "#42474e",
|
surfaceVariant: "#44464f",
|
||||||
surfaceVariantText: "#c2c7cf",
|
surfaceVariantText: "#c4c7c5",
|
||||||
surfaceTint: "#8ab4f8",
|
surfaceTint: "#8ab4f8",
|
||||||
background: "#101418",
|
background: "#1a1c1e",
|
||||||
backgroundText: "#e0e2e8",
|
backgroundText: "#e3e8ef",
|
||||||
outline: "#8c9199",
|
outline: "#8e918f",
|
||||||
surfaceContainer: "#1d2024",
|
surfaceContainer: "#1e2023",
|
||||||
surfaceContainerHigh: "#272a2f",
|
surfaceContainerHigh: "#292b2f",
|
||||||
surfaceContainerHighest: "#32353a"
|
surfaceContainerHighest: "#343740"
|
||||||
},
|
},
|
||||||
purple: {
|
purple: {
|
||||||
name: "Purple",
|
name: "Purple",
|
||||||
@@ -138,17 +138,17 @@ const StockThemes = {
|
|||||||
primaryText: "#381E72",
|
primaryText: "#381E72",
|
||||||
primaryContainer: "#4F378B",
|
primaryContainer: "#4F378B",
|
||||||
secondary: "#CCC2DC",
|
secondary: "#CCC2DC",
|
||||||
surface: "#141218",
|
surface: "#10121E",
|
||||||
surfaceText: "#e6e0e9",
|
surfaceText: "#E6E0E9",
|
||||||
surfaceVariant: "#49454e",
|
surfaceVariant: "#49454F",
|
||||||
surfaceVariantText: "#cac4cf",
|
surfaceVariantText: "#CAC4D0",
|
||||||
surfaceTint: "#D0BCFF",
|
surfaceTint: "#D0BCFF",
|
||||||
background: "#141218",
|
background: "#10121E",
|
||||||
backgroundText: "#e6e0e9",
|
backgroundText: "#E6E0E9",
|
||||||
outline: "#948f99",
|
outline: "#938F99",
|
||||||
surfaceContainer: "#211f24",
|
surfaceContainer: "#1D1B20",
|
||||||
surfaceContainerHigh: "#2b292f",
|
surfaceContainerHigh: "#2B2930",
|
||||||
surfaceContainerHighest: "#36343a"
|
surfaceContainerHighest: "#36343B"
|
||||||
},
|
},
|
||||||
green: {
|
green: {
|
||||||
name: "Green",
|
name: "Green",
|
||||||
@@ -156,17 +156,17 @@ const StockThemes = {
|
|||||||
primaryText: "#000000",
|
primaryText: "#000000",
|
||||||
primaryContainer: "#1b5e20",
|
primaryContainer: "#1b5e20",
|
||||||
secondary: "#81c995",
|
secondary: "#81c995",
|
||||||
surface: "#10140f",
|
surface: "#0f1411",
|
||||||
surfaceText: "#e0e4db",
|
surfaceText: "#e1f5e3",
|
||||||
surfaceVariant: "#424940",
|
surfaceVariant: "#404943",
|
||||||
surfaceVariantText: "#c2c9bd",
|
surfaceVariantText: "#c1cbc4",
|
||||||
surfaceTint: "#81c995",
|
surfaceTint: "#81c995",
|
||||||
background: "#10140f",
|
background: "#0f1411",
|
||||||
backgroundText: "#e0e4db",
|
backgroundText: "#e1f5e3",
|
||||||
outline: "#8c9388",
|
outline: "#8b938c",
|
||||||
surfaceContainer: "#1d211b",
|
surfaceContainer: "#1a1f1b",
|
||||||
surfaceContainerHigh: "#272b25",
|
surfaceContainerHigh: "#252a26",
|
||||||
surfaceContainerHighest: "#323630"
|
surfaceContainerHighest: "#30352f"
|
||||||
},
|
},
|
||||||
orange: {
|
orange: {
|
||||||
name: "Orange",
|
name: "Orange",
|
||||||
@@ -174,17 +174,17 @@ const StockThemes = {
|
|||||||
primaryText: "#000000",
|
primaryText: "#000000",
|
||||||
primaryContainer: "#3e2723",
|
primaryContainer: "#3e2723",
|
||||||
secondary: "#ffb74d",
|
secondary: "#ffb74d",
|
||||||
surface: "#1a120e",
|
surface: "#1c1410",
|
||||||
surfaceText: "#f0dfd8",
|
surfaceText: "#f5f1ea",
|
||||||
surfaceVariant: "#52443d",
|
surfaceVariant: "#4a453a",
|
||||||
surfaceVariantText: "#d7c2b9",
|
surfaceVariantText: "#cbc5b8",
|
||||||
surfaceTint: "#ffb74d",
|
surfaceTint: "#ffb74d",
|
||||||
background: "#1a120e",
|
background: "#1c1410",
|
||||||
backgroundText: "#f0dfd8",
|
backgroundText: "#f5f1ea",
|
||||||
outline: "#a08d85",
|
outline: "#958f84",
|
||||||
surfaceContainer: "#271e1a",
|
surfaceContainer: "#211e17",
|
||||||
surfaceContainerHigh: "#322824",
|
surfaceContainerHigh: "#2c291f",
|
||||||
surfaceContainerHighest: "#3d332e"
|
surfaceContainerHighest: "#373427"
|
||||||
},
|
},
|
||||||
red: {
|
red: {
|
||||||
name: "Red",
|
name: "Red",
|
||||||
@@ -192,17 +192,17 @@ const StockThemes = {
|
|||||||
primaryText: "#000000",
|
primaryText: "#000000",
|
||||||
primaryContainer: "#4a0e0e",
|
primaryContainer: "#4a0e0e",
|
||||||
secondary: "#f28b82",
|
secondary: "#f28b82",
|
||||||
surface: "#1a1110",
|
surface: "#1c1011",
|
||||||
surfaceText: "#f1dedc",
|
surfaceText: "#f5e8ea",
|
||||||
surfaceVariant: "#534341",
|
surfaceVariant: "#4a3f41",
|
||||||
surfaceVariantText: "#d8c2be",
|
surfaceVariantText: "#cbc2c4",
|
||||||
surfaceTint: "#f28b82",
|
surfaceTint: "#f28b82",
|
||||||
background: "#1a1110",
|
background: "#1c1011",
|
||||||
backgroundText: "#f1dedc",
|
backgroundText: "#f5e8ea",
|
||||||
outline: "#a08c89",
|
outline: "#958b8d",
|
||||||
surfaceContainer: "#271d1c",
|
surfaceContainer: "#211b1c",
|
||||||
surfaceContainerHigh: "#322826",
|
surfaceContainerHigh: "#2c2426",
|
||||||
surfaceContainerHighest: "#3d3231"
|
surfaceContainerHighest: "#372f30"
|
||||||
},
|
},
|
||||||
cyan: {
|
cyan: {
|
||||||
name: "Cyan",
|
name: "Cyan",
|
||||||
@@ -210,15 +210,15 @@ const StockThemes = {
|
|||||||
primaryText: "#000000",
|
primaryText: "#000000",
|
||||||
primaryContainer: "#004d5c",
|
primaryContainer: "#004d5c",
|
||||||
secondary: "#4dd0e1",
|
secondary: "#4dd0e1",
|
||||||
surface: "#0e1416",
|
surface: "#0f1617",
|
||||||
surfaceText: "#dee3e5",
|
surfaceText: "#e8f4f5",
|
||||||
surfaceVariant: "#3f484a",
|
surfaceVariant: "#3f474a",
|
||||||
surfaceVariantText: "#bfc8ca",
|
surfaceVariantText: "#c2c9cb",
|
||||||
surfaceTint: "#4dd0e1",
|
surfaceTint: "#4dd0e1",
|
||||||
background: "#0e1416",
|
background: "#0f1617",
|
||||||
backgroundText: "#dee3e5",
|
backgroundText: "#e8f4f5",
|
||||||
outline: "#899295",
|
outline: "#8c9194",
|
||||||
surfaceContainer: "#1b2122",
|
surfaceContainer: "#1a1f20",
|
||||||
surfaceContainerHigh: "#252b2c",
|
surfaceContainerHigh: "#252b2c",
|
||||||
surfaceContainerHighest: "#303637"
|
surfaceContainerHighest: "#303637"
|
||||||
},
|
},
|
||||||
@@ -228,17 +228,17 @@ const StockThemes = {
|
|||||||
primaryText: "#000000",
|
primaryText: "#000000",
|
||||||
primaryContainer: "#4a0e2f",
|
primaryContainer: "#4a0e2f",
|
||||||
secondary: "#f8bbd9",
|
secondary: "#f8bbd9",
|
||||||
surface: "#191112",
|
surface: "#1a1014",
|
||||||
surfaceText: "#f0dee0",
|
surfaceText: "#f3e8ee",
|
||||||
surfaceVariant: "#524345",
|
surfaceVariant: "#483f45",
|
||||||
surfaceVariantText: "#d6c2c3",
|
surfaceVariantText: "#c9c2c7",
|
||||||
surfaceTint: "#f8bbd9",
|
surfaceTint: "#f8bbd9",
|
||||||
background: "#191112",
|
background: "#1a1014",
|
||||||
backgroundText: "#f0dee0",
|
backgroundText: "#f3e8ee",
|
||||||
outline: "#9f8c8e",
|
outline: "#938a90",
|
||||||
surfaceContainer: "#261d1e",
|
surfaceContainer: "#1f1b1e",
|
||||||
surfaceContainerHigh: "#312829",
|
surfaceContainerHigh: "#2a2428",
|
||||||
surfaceContainerHighest: "#3c3233"
|
surfaceContainerHighest: "#352f32"
|
||||||
},
|
},
|
||||||
amber: {
|
amber: {
|
||||||
name: "Amber",
|
name: "Amber",
|
||||||
@@ -246,17 +246,17 @@ const StockThemes = {
|
|||||||
primaryText: "#000000",
|
primaryText: "#000000",
|
||||||
primaryContainer: "#4a3c00",
|
primaryContainer: "#4a3c00",
|
||||||
secondary: "#ffd54f",
|
secondary: "#ffd54f",
|
||||||
surface: "#17130b",
|
surface: "#1a1710",
|
||||||
surfaceText: "#ebe1d4",
|
surfaceText: "#f3f0e8",
|
||||||
surfaceVariant: "#4d4639",
|
surfaceVariant: "#49453a",
|
||||||
surfaceVariantText: "#d0c5b4",
|
surfaceVariantText: "#cac5b8",
|
||||||
surfaceTint: "#ffd54f",
|
surfaceTint: "#ffd54f",
|
||||||
background: "#17130b",
|
background: "#1a1710",
|
||||||
backgroundText: "#ebe1d4",
|
backgroundText: "#f3f0e8",
|
||||||
outline: "#998f80",
|
outline: "#949084",
|
||||||
surfaceContainer: "#231f17",
|
surfaceContainer: "#1f1e17",
|
||||||
surfaceContainerHigh: "#2e2921",
|
surfaceContainerHigh: "#2a281f",
|
||||||
surfaceContainerHighest: "#39342b"
|
surfaceContainerHighest: "#353327"
|
||||||
},
|
},
|
||||||
coral: {
|
coral: {
|
||||||
name: "Coral",
|
name: "Coral",
|
||||||
@@ -265,16 +265,16 @@ const StockThemes = {
|
|||||||
primaryContainer: "#8c1d18",
|
primaryContainer: "#8c1d18",
|
||||||
secondary: "#f9dedc",
|
secondary: "#f9dedc",
|
||||||
surface: "#1a1110",
|
surface: "#1a1110",
|
||||||
surfaceText: "#f1dedc",
|
surfaceText: "#f1e8e7",
|
||||||
surfaceVariant: "#534341",
|
surfaceVariant: "#4a4142",
|
||||||
surfaceVariantText: "#d8c2bf",
|
surfaceVariantText: "#cdc2c1",
|
||||||
surfaceTint: "#ffb4ab",
|
surfaceTint: "#ffb4ab",
|
||||||
background: "#1a1110",
|
background: "#1a1110",
|
||||||
backgroundText: "#f1dedc",
|
backgroundText: "#f1e8e7",
|
||||||
outline: "#a08c8a",
|
outline: "#968b8a",
|
||||||
surfaceContainer: "#271d1c",
|
surfaceContainer: "#201a19",
|
||||||
surfaceContainerHigh: "#322826",
|
surfaceContainerHigh: "#2b2221",
|
||||||
surfaceContainerHighest: "#3d3231"
|
surfaceContainerHighest: "#362d29"
|
||||||
},
|
},
|
||||||
monochrome: {
|
monochrome: {
|
||||||
name: "Monochrome",
|
name: "Monochrome",
|
||||||
@@ -290,9 +290,9 @@ const StockThemes = {
|
|||||||
background: "#131315",
|
background: "#131315",
|
||||||
backgroundText: "#e4e2e3",
|
backgroundText: "#e4e2e3",
|
||||||
outline: "#929092",
|
outline: "#929092",
|
||||||
surfaceContainer: "#353535",
|
surfaceContainer: "#2a2a2a",
|
||||||
surfaceContainerHigh: "#424242",
|
surfaceContainerHigh: "#2a2a2b",
|
||||||
surfaceContainerHighest: "#505050",
|
surfaceContainerHighest: "#353535",
|
||||||
error: "#ffb4ab",
|
error: "#ffb4ab",
|
||||||
warning: "#3f4759",
|
warning: "#3f4759",
|
||||||
info: "#595e6c",
|
info: "#595e6c",
|
||||||
@@ -306,17 +306,17 @@ const StockThemes = {
|
|||||||
primaryText: "#ffffff",
|
primaryText: "#ffffff",
|
||||||
primaryContainer: "#e3f2fd",
|
primaryContainer: "#e3f2fd",
|
||||||
secondary: "#42a5f5",
|
secondary: "#42a5f5",
|
||||||
surface: "#f7f9ff",
|
surface: "#fefefe",
|
||||||
surfaceText: "#181c20",
|
surfaceText: "#1a1c1e",
|
||||||
surfaceVariant: "#dee3eb",
|
surfaceVariant: "#e7e0ec",
|
||||||
surfaceVariantText: "#42474e",
|
surfaceVariantText: "#49454f",
|
||||||
surfaceTint: "#1976d2",
|
surfaceTint: "#1976d2",
|
||||||
background: "#f7f9ff",
|
background: "#fefefe",
|
||||||
backgroundText: "#181c20",
|
backgroundText: "#1a1c1e",
|
||||||
outline: "#72777f",
|
outline: "#79747e",
|
||||||
surfaceContainer: "#eceef4",
|
surfaceContainer: "#f3f3f3",
|
||||||
surfaceContainerHigh: "#e6e8ee",
|
surfaceContainerHigh: "#ececec",
|
||||||
surfaceContainerHighest: "#e0e2e8"
|
surfaceContainerHighest: "#e6e6e6"
|
||||||
},
|
},
|
||||||
purple: {
|
purple: {
|
||||||
name: "Purple Light",
|
name: "Purple Light",
|
||||||
@@ -324,17 +324,17 @@ const StockThemes = {
|
|||||||
primaryText: "#ffffff",
|
primaryText: "#ffffff",
|
||||||
primaryContainer: "#EADDFF",
|
primaryContainer: "#EADDFF",
|
||||||
secondary: "#625B71",
|
secondary: "#625B71",
|
||||||
surface: "#fef7ff",
|
surface: "#FFFBFE",
|
||||||
surfaceText: "#1d1b20",
|
surfaceText: "#1C1B1F",
|
||||||
surfaceVariant: "#e7e0eb",
|
surfaceVariant: "#E7E0EC",
|
||||||
surfaceVariantText: "#49454e",
|
surfaceVariantText: "#49454F",
|
||||||
surfaceTint: "#6750A4",
|
surfaceTint: "#6750A4",
|
||||||
background: "#fef7ff",
|
background: "#FFFBFE",
|
||||||
backgroundText: "#1d1b20",
|
backgroundText: "#1C1B1F",
|
||||||
outline: "#7a757f",
|
outline: "#79747E",
|
||||||
surfaceContainer: "#f2ecf4",
|
surfaceContainer: "#F3EDF7",
|
||||||
surfaceContainerHigh: "#ece6ee",
|
surfaceContainerHigh: "#ECE6F0",
|
||||||
surfaceContainerHighest: "#e6e0e9"
|
surfaceContainerHighest: "#E6DFE9"
|
||||||
},
|
},
|
||||||
green: {
|
green: {
|
||||||
name: "Green Light",
|
name: "Green Light",
|
||||||
@@ -342,17 +342,17 @@ const StockThemes = {
|
|||||||
primaryText: "#ffffff",
|
primaryText: "#ffffff",
|
||||||
primaryContainer: "#e8f5e8",
|
primaryContainer: "#e8f5e8",
|
||||||
secondary: "#4caf50",
|
secondary: "#4caf50",
|
||||||
surface: "#f7fbf1",
|
surface: "#fefefe",
|
||||||
surfaceText: "#191d17",
|
surfaceText: "#1a1c1e",
|
||||||
surfaceVariant: "#dee5d8",
|
surfaceVariant: "#e7e0ec",
|
||||||
surfaceVariantText: "#424940",
|
surfaceVariantText: "#49454f",
|
||||||
surfaceTint: "#2e7d32",
|
surfaceTint: "#2e7d32",
|
||||||
background: "#f7fbf1",
|
background: "#fefefe",
|
||||||
backgroundText: "#191d17",
|
backgroundText: "#1a1c1e",
|
||||||
outline: "#72796f",
|
outline: "#79747e",
|
||||||
surfaceContainer: "#ecefe6",
|
surfaceContainer: "#f3f3f3",
|
||||||
surfaceContainerHigh: "#e6e9e0",
|
surfaceContainerHigh: "#ececec",
|
||||||
surfaceContainerHighest: "#e0e4db"
|
surfaceContainerHighest: "#e6e6e6"
|
||||||
},
|
},
|
||||||
orange: {
|
orange: {
|
||||||
name: "Orange Light",
|
name: "Orange Light",
|
||||||
@@ -360,17 +360,17 @@ const StockThemes = {
|
|||||||
primaryText: "#ffffff",
|
primaryText: "#ffffff",
|
||||||
primaryContainer: "#ffecb3",
|
primaryContainer: "#ffecb3",
|
||||||
secondary: "#ff9800",
|
secondary: "#ff9800",
|
||||||
surface: "#fff8f6",
|
surface: "#fefefe",
|
||||||
surfaceText: "#221a16",
|
surfaceText: "#1a1c1e",
|
||||||
surfaceVariant: "#f4ded5",
|
surfaceVariant: "#e7e0ec",
|
||||||
surfaceVariantText: "#52443d",
|
surfaceVariantText: "#49454f",
|
||||||
surfaceTint: "#e65100",
|
surfaceTint: "#e65100",
|
||||||
background: "#fff8f6",
|
background: "#fefefe",
|
||||||
backgroundText: "#221a16",
|
backgroundText: "#1a1c1e",
|
||||||
outline: "#85736c",
|
outline: "#79747e",
|
||||||
surfaceContainer: "#fceae3",
|
surfaceContainer: "#f3f3f3",
|
||||||
surfaceContainerHigh: "#f6e5de",
|
surfaceContainerHigh: "#ececec",
|
||||||
surfaceContainerHighest: "#f0dfd8"
|
surfaceContainerHighest: "#e6e6e6"
|
||||||
},
|
},
|
||||||
red: {
|
red: {
|
||||||
name: "Red Light",
|
name: "Red Light",
|
||||||
@@ -378,17 +378,17 @@ const StockThemes = {
|
|||||||
primaryText: "#ffffff",
|
primaryText: "#ffffff",
|
||||||
primaryContainer: "#ffebee",
|
primaryContainer: "#ffebee",
|
||||||
secondary: "#f44336",
|
secondary: "#f44336",
|
||||||
surface: "#fff8f7",
|
surface: "#fefefe",
|
||||||
surfaceText: "#231918",
|
surfaceText: "#1a1c1e",
|
||||||
surfaceVariant: "#f5ddda",
|
surfaceVariant: "#e7e0ec",
|
||||||
surfaceVariantText: "#534341",
|
surfaceVariantText: "#49454f",
|
||||||
surfaceTint: "#d32f2f",
|
surfaceTint: "#d32f2f",
|
||||||
background: "#fff8f7",
|
background: "#fefefe",
|
||||||
backgroundText: "#231918",
|
backgroundText: "#1a1c1e",
|
||||||
outline: "#857370",
|
outline: "#79747e",
|
||||||
surfaceContainer: "#fceae7",
|
surfaceContainer: "#f3f3f3",
|
||||||
surfaceContainerHigh: "#f7e4e1",
|
surfaceContainerHigh: "#ececec",
|
||||||
surfaceContainerHighest: "#f1dedc"
|
surfaceContainerHighest: "#e6e6e6"
|
||||||
},
|
},
|
||||||
cyan: {
|
cyan: {
|
||||||
name: "Cyan Light",
|
name: "Cyan Light",
|
||||||
@@ -396,17 +396,17 @@ const StockThemes = {
|
|||||||
primaryText: "#ffffff",
|
primaryText: "#ffffff",
|
||||||
primaryContainer: "#e0f2f1",
|
primaryContainer: "#e0f2f1",
|
||||||
secondary: "#00bcd4",
|
secondary: "#00bcd4",
|
||||||
surface: "#f5fafc",
|
surface: "#fefefe",
|
||||||
surfaceText: "#171d1e",
|
surfaceText: "#1a1c1e",
|
||||||
surfaceVariant: "#dbe4e6",
|
surfaceVariant: "#e7e0ec",
|
||||||
surfaceVariantText: "#3f484a",
|
surfaceVariantText: "#49454f",
|
||||||
surfaceTint: "#0097a7",
|
surfaceTint: "#0097a7",
|
||||||
background: "#f5fafc",
|
background: "#fefefe",
|
||||||
backgroundText: "#171d1e",
|
backgroundText: "#1a1c1e",
|
||||||
outline: "#6f797b",
|
outline: "#79747e",
|
||||||
surfaceContainer: "#e9eff0",
|
surfaceContainer: "#f3f3f3",
|
||||||
surfaceContainerHigh: "#e3e9eb",
|
surfaceContainerHigh: "#ececec",
|
||||||
surfaceContainerHighest: "#dee3e5"
|
surfaceContainerHighest: "#e6e6e6"
|
||||||
},
|
},
|
||||||
pink: {
|
pink: {
|
||||||
name: "Pink Light",
|
name: "Pink Light",
|
||||||
@@ -414,17 +414,17 @@ const StockThemes = {
|
|||||||
primaryText: "#ffffff",
|
primaryText: "#ffffff",
|
||||||
primaryContainer: "#fce4ec",
|
primaryContainer: "#fce4ec",
|
||||||
secondary: "#e91e63",
|
secondary: "#e91e63",
|
||||||
surface: "#fff8f7",
|
surface: "#fefefe",
|
||||||
surfaceText: "#22191a",
|
surfaceText: "#1a1c1e",
|
||||||
surfaceVariant: "#f3dddf",
|
surfaceVariant: "#e7e0ec",
|
||||||
surfaceVariantText: "#524345",
|
surfaceVariantText: "#49454f",
|
||||||
surfaceTint: "#c2185b",
|
surfaceTint: "#c2185b",
|
||||||
background: "#fff8f7",
|
background: "#fefefe",
|
||||||
backgroundText: "#22191a",
|
backgroundText: "#1a1c1e",
|
||||||
outline: "#847375",
|
outline: "#79747e",
|
||||||
surfaceContainer: "#fbeaeb",
|
surfaceContainer: "#f3f3f3",
|
||||||
surfaceContainerHigh: "#f5e4e5",
|
surfaceContainerHigh: "#ececec",
|
||||||
surfaceContainerHighest: "#f0dee0"
|
surfaceContainerHighest: "#e6e6e6"
|
||||||
},
|
},
|
||||||
amber: {
|
amber: {
|
||||||
name: "Amber Light",
|
name: "Amber Light",
|
||||||
@@ -432,17 +432,17 @@ const StockThemes = {
|
|||||||
primaryText: "#000000",
|
primaryText: "#000000",
|
||||||
primaryContainer: "#fff8e1",
|
primaryContainer: "#fff8e1",
|
||||||
secondary: "#ffc107",
|
secondary: "#ffc107",
|
||||||
surface: "#fff8f2",
|
surface: "#fefefe",
|
||||||
surfaceText: "#1f1b13",
|
surfaceText: "#1a1c1e",
|
||||||
surfaceVariant: "#ede1cf",
|
surfaceVariant: "#e7e0ec",
|
||||||
surfaceVariantText: "#4d4639",
|
surfaceVariantText: "#49454f",
|
||||||
surfaceTint: "#ff8f00",
|
surfaceTint: "#ff8f00",
|
||||||
background: "#fff8f2",
|
background: "#fefefe",
|
||||||
backgroundText: "#1f1b13",
|
backgroundText: "#1a1c1e",
|
||||||
outline: "#7f7667",
|
outline: "#79747e",
|
||||||
surfaceContainer: "#f6ecdf",
|
surfaceContainer: "#f3f3f3",
|
||||||
surfaceContainerHigh: "#f1e7d9",
|
surfaceContainerHigh: "#ececec",
|
||||||
surfaceContainerHighest: "#ebe1d4"
|
surfaceContainerHighest: "#e6e6e6"
|
||||||
},
|
},
|
||||||
coral: {
|
coral: {
|
||||||
name: "Coral Light",
|
name: "Coral Light",
|
||||||
@@ -450,17 +450,17 @@ const StockThemes = {
|
|||||||
primaryText: "#ffffff",
|
primaryText: "#ffffff",
|
||||||
primaryContainer: "#ffdad6",
|
primaryContainer: "#ffdad6",
|
||||||
secondary: "#ff5449",
|
secondary: "#ff5449",
|
||||||
surface: "#fff8f7",
|
surface: "#fefefe",
|
||||||
surfaceText: "#231918",
|
surfaceText: "#1a1c1e",
|
||||||
surfaceVariant: "#f5ddda",
|
surfaceVariant: "#e7e0ec",
|
||||||
surfaceVariantText: "#534341",
|
surfaceVariantText: "#49454f",
|
||||||
surfaceTint: "#8c1d18",
|
surfaceTint: "#8c1d18",
|
||||||
background: "#fff8f7",
|
background: "#fefefe",
|
||||||
backgroundText: "#231918",
|
backgroundText: "#1a1c1e",
|
||||||
outline: "#857371",
|
outline: "#79747e",
|
||||||
surfaceContainer: "#fceae7",
|
surfaceContainer: "#f3f3f3",
|
||||||
surfaceContainerHigh: "#f6e4e2",
|
surfaceContainerHigh: "#ececec",
|
||||||
surfaceContainerHighest: "#f1dedc"
|
surfaceContainerHighest: "#e6e6e6"
|
||||||
},
|
},
|
||||||
monochrome: {
|
monochrome: {
|
||||||
name: "Monochrome Light",
|
name: "Monochrome Light",
|
||||||
@@ -476,9 +476,8 @@ const StockThemes = {
|
|||||||
background: "#ffffff",
|
background: "#ffffff",
|
||||||
backgroundText: "#1a1a1a",
|
backgroundText: "#1a1a1a",
|
||||||
outline: "#757577",
|
outline: "#757577",
|
||||||
surfaceContainer: "#e8e8ea",
|
surfaceContainer: "#f5f5f6",
|
||||||
surfaceContainerHigh: "#dcdcde",
|
surfaceContainerHigh: "#eaeaeb",
|
||||||
surfaceContainerHighest: "#d0d0d2",
|
|
||||||
error: "#ba1a1a",
|
error: "#ba1a1a",
|
||||||
warning: "#f9e79f",
|
warning: "#f9e79f",
|
||||||
info: "#5d6475",
|
info: "#5d6475",
|
||||||
|
|||||||
443
Common/Theme.qml
443
Common/Theme.qml
@@ -16,12 +16,9 @@ Singleton {
|
|||||||
|
|
||||||
readonly property bool envDisableMatugen: Quickshell.env("DMS_DISABLE_MATUGEN") === "1" || Quickshell.env("DMS_DISABLE_MATUGEN") === "true"
|
readonly property bool envDisableMatugen: Quickshell.env("DMS_DISABLE_MATUGEN") === "1" || Quickshell.env("DMS_DISABLE_MATUGEN") === "true"
|
||||||
|
|
||||||
// ! TODO - Synchronize with niri/hyprland gaps?
|
|
||||||
readonly property real popupDistance: 2
|
|
||||||
|
|
||||||
property string currentTheme: "blue"
|
property string currentTheme: "blue"
|
||||||
property string currentThemeCategory: "generic"
|
property string currentThemeCategory: "generic"
|
||||||
property bool isLightMode: typeof SessionData !== "undefined" ? SessionData.isLightMode : false
|
property bool isLightMode: false
|
||||||
|
|
||||||
readonly property string dynamic: "dynamic"
|
readonly property string dynamic: "dynamic"
|
||||||
readonly property string custom : "custom"
|
readonly property string custom : "custom"
|
||||||
@@ -31,8 +28,9 @@ Singleton {
|
|||||||
readonly property string shellDir: Paths.strip(Qt.resolvedUrl(".").toString()).replace("/Common/", "")
|
readonly property string shellDir: Paths.strip(Qt.resolvedUrl(".").toString()).replace("/Common/", "")
|
||||||
readonly property string wallpaperPath: {
|
readonly property string wallpaperPath: {
|
||||||
if (typeof SessionData === "undefined") return ""
|
if (typeof SessionData === "undefined") return ""
|
||||||
|
|
||||||
if (SessionData.perMonitorWallpaper) {
|
if (SessionData.perMonitorWallpaper) {
|
||||||
|
// Use first monitor's wallpaper for dynamic theming
|
||||||
var screens = Quickshell.screens
|
var screens = Quickshell.screens
|
||||||
if (screens.length > 0) {
|
if (screens.length > 0) {
|
||||||
var firstMonitorWallpaper = SessionData.getMonitorWallpaper(screens[0].name)
|
var firstMonitorWallpaper = SessionData.getMonitorWallpaper(screens[0].name)
|
||||||
@@ -74,6 +72,8 @@ Singleton {
|
|||||||
property bool qtThemingEnabled: typeof SettingsData !== "undefined" ? (SettingsData.qt5ctAvailable || SettingsData.qt6ctAvailable) : false
|
property bool qtThemingEnabled: typeof SettingsData !== "undefined" ? (SettingsData.qt5ctAvailable || SettingsData.qt6ctAvailable) : false
|
||||||
property var workerRunning: false
|
property var workerRunning: false
|
||||||
property var matugenColors: ({})
|
property var matugenColors: ({})
|
||||||
|
property bool extractionRequested: false
|
||||||
|
property int colorUpdateTrigger: 0
|
||||||
property var customThemeData: null
|
property var customThemeData: null
|
||||||
|
|
||||||
readonly property string stateDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.CacheLocation).toString()) + "/dankshell"
|
readonly property string stateDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.CacheLocation).toString()) + "/dankshell"
|
||||||
@@ -81,23 +81,16 @@ Singleton {
|
|||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
Quickshell.execDetached(["mkdir", "-p", stateDir])
|
Quickshell.execDetached(["mkdir", "-p", stateDir])
|
||||||
matugenCheck.running = true
|
matugenCheck.running = true
|
||||||
if (typeof SessionData !== "undefined") {
|
if (typeof SessionData !== "undefined")
|
||||||
SessionData.isLightModeChanged.connect(root.onLightModeChanged)
|
SessionData.isLightModeChanged.connect(root.onLightModeChanged)
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof SettingsData !== "undefined" && SettingsData.currentThemeName) {
|
if (typeof SettingsData !== "undefined" && SettingsData.currentThemeName) {
|
||||||
switchTheme(SettingsData.currentThemeName, false, false)
|
switchTheme(SettingsData.currentThemeName, false)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyGreeterTheme(themeName) {
|
|
||||||
switchTheme(themeName, false, false)
|
|
||||||
if (themeName === dynamic && dynamicColorsFileView.path) {
|
|
||||||
dynamicColorsFileView.reload()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMatugenColor(path, fallback) {
|
function getMatugenColor(path, fallback) {
|
||||||
|
colorUpdateTrigger
|
||||||
const colorMode = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "light" : "dark"
|
const colorMode = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "light" : "dark"
|
||||||
let cur = matugenColors && matugenColors.colors && matugenColors.colors[colorMode]
|
let cur = matugenColors && matugenColors.colors && matugenColors.colors[colorMode]
|
||||||
for (const part of path.split(".")) {
|
for (const part of path.split(".")) {
|
||||||
@@ -238,22 +231,11 @@ Singleton {
|
|||||||
property color shadowMedium: Qt.rgba(0, 0, 0, 0.08)
|
property color shadowMedium: Qt.rgba(0, 0, 0, 0.08)
|
||||||
property color shadowStrong: Qt.rgba(0, 0, 0, 0.3)
|
property color shadowStrong: Qt.rgba(0, 0, 0, 0.3)
|
||||||
|
|
||||||
readonly property var animationDurations: [
|
property int shorterDuration: 100
|
||||||
{ shorter: 0, short: 0, medium: 0, long: 0, extraLong: 0 },
|
property int shortDuration: 150
|
||||||
{ shorter: 50, short: 75, medium: 150, long: 250, extraLong: 500 },
|
property int mediumDuration: 300
|
||||||
{ shorter: 100, short: 150, medium: 300, long: 500, extraLong: 1000 },
|
property int longDuration: 500
|
||||||
{ shorter: 150, short: 225, medium: 450, long: 750, extraLong: 1500 },
|
property int extraLongDuration: 1000
|
||||||
{ shorter: 200, short: 300, medium: 600, long: 1000, extraLong: 2000 }
|
|
||||||
]
|
|
||||||
|
|
||||||
readonly property int currentAnimationSpeed: typeof SettingsData !== "undefined" ? SettingsData.animationSpeed : SettingsData.AnimationSpeed.Short
|
|
||||||
readonly property var currentDurations: animationDurations[currentAnimationSpeed] || animationDurations[SettingsData.AnimationSpeed.Short]
|
|
||||||
|
|
||||||
property int shorterDuration: currentDurations.shorter
|
|
||||||
property int shortDuration: currentDurations.short
|
|
||||||
property int mediumDuration: currentDurations.medium
|
|
||||||
property int longDuration: currentDurations.long
|
|
||||||
property int extraLongDuration: currentDurations.extraLong
|
|
||||||
property int standardEasing: Easing.OutCubic
|
property int standardEasing: Easing.OutCubic
|
||||||
property int emphasizedEasing: Easing.OutQuart
|
property int emphasizedEasing: Easing.OutQuart
|
||||||
|
|
||||||
@@ -273,8 +255,8 @@ Singleton {
|
|||||||
property real iconSizeLarge: 32
|
property real iconSizeLarge: 32
|
||||||
|
|
||||||
property real panelTransparency: 0.85
|
property real panelTransparency: 0.85
|
||||||
property real widgetTransparency: typeof SettingsData !== "undefined" && SettingsData.dankBarWidgetTransparency !== undefined ? SettingsData.dankBarWidgetTransparency : 1.0
|
property real widgetTransparency: typeof SettingsData !== "undefined" && SettingsData.topBarWidgetTransparency !== undefined ? SettingsData.topBarWidgetTransparency : 0.85
|
||||||
property real popupTransparency: typeof SettingsData !== "undefined" && SettingsData.popupTransparency !== undefined ? SettingsData.popupTransparency : 1.0
|
property real popupTransparency: typeof SettingsData !== "undefined" && SettingsData.popupTransparency !== undefined ? SettingsData.popupTransparency : 0.92
|
||||||
|
|
||||||
function screenTransition() {
|
function screenTransition() {
|
||||||
CompositorService.isNiri && NiriService.doScreenTransition()
|
CompositorService.isNiri && NiriService.doScreenTransition()
|
||||||
@@ -283,15 +265,11 @@ Singleton {
|
|||||||
function switchTheme(themeName, savePrefs = true, enableTransition = true) {
|
function switchTheme(themeName, savePrefs = true, enableTransition = true) {
|
||||||
if (enableTransition) {
|
if (enableTransition) {
|
||||||
screenTransition()
|
screenTransition()
|
||||||
themeTransitionTimer.themeName = themeName
|
|
||||||
themeTransitionTimer.savePrefs = savePrefs
|
|
||||||
themeTransitionTimer.restart()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (themeName === dynamic) {
|
if (themeName === dynamic) {
|
||||||
currentTheme = dynamic
|
currentTheme = dynamic
|
||||||
currentThemeCategory = dynamic
|
currentThemeCategory = dynamic
|
||||||
|
extractColors()
|
||||||
} else if (themeName === custom) {
|
} else if (themeName === custom) {
|
||||||
currentTheme = custom
|
currentTheme = custom
|
||||||
currentThemeCategory = custom
|
currentThemeCategory = custom
|
||||||
@@ -300,45 +278,34 @@ Singleton {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentTheme = themeName
|
currentTheme = themeName
|
||||||
|
// Determine category based on theme name
|
||||||
if (StockThemes.isCatppuccinVariant(themeName)) {
|
if (StockThemes.isCatppuccinVariant(themeName)) {
|
||||||
currentThemeCategory = "catppuccin"
|
currentThemeCategory = "catppuccin"
|
||||||
} else {
|
} else {
|
||||||
currentThemeCategory = "generic"
|
currentThemeCategory = "generic"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode)
|
if (savePrefs && typeof SettingsData !== "undefined")
|
||||||
if (savePrefs && typeof SettingsData !== "undefined" && !isGreeterMode)
|
|
||||||
SettingsData.setTheme(currentTheme)
|
SettingsData.setTheme(currentTheme)
|
||||||
|
|
||||||
if (!isGreeterMode) {
|
generateSystemThemesFromCurrentTheme()
|
||||||
generateSystemThemesFromCurrentTheme()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLightMode(light, savePrefs = true, enableTransition = false) {
|
function setLightMode(light, savePrefs = true) {
|
||||||
if (enableTransition) {
|
screenTransition()
|
||||||
screenTransition()
|
|
||||||
lightModeTransitionTimer.lightMode = light
|
|
||||||
lightModeTransitionTimer.savePrefs = savePrefs
|
|
||||||
lightModeTransitionTimer.restart()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode)
|
|
||||||
isLightMode = light
|
isLightMode = light
|
||||||
if (savePrefs && typeof SessionData !== "undefined" && !isGreeterMode)
|
if (savePrefs && typeof SessionData !== "undefined")
|
||||||
SessionData.setLightMode(isLightMode)
|
SessionData.setLightMode(isLightMode)
|
||||||
if (!isGreeterMode) {
|
PortalService.setLightMode(isLightMode)
|
||||||
PortalService.setLightMode(isLightMode)
|
generateSystemThemesFromCurrentTheme()
|
||||||
generateSystemThemesFromCurrentTheme()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleLightMode(savePrefs = true) {
|
function toggleLightMode(savePrefs = true) {
|
||||||
setLightMode(!isLightMode, savePrefs, true)
|
setLightMode(!isLightMode, savePrefs)
|
||||||
}
|
}
|
||||||
|
|
||||||
function forceGenerateSystemThemes() {
|
function forceGenerateSystemThemes() {
|
||||||
|
screenTransition()
|
||||||
if (!matugenAvailable) {
|
if (!matugenAvailable) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -362,10 +329,8 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function switchThemeCategory(category, defaultTheme) {
|
function switchThemeCategory(category, defaultTheme) {
|
||||||
screenTransition()
|
currentThemeCategory = category
|
||||||
themeCategoryTransitionTimer.category = category
|
switchTheme(defaultTheme, true, false)
|
||||||
themeCategoryTransitionTimer.defaultTheme = defaultTheme
|
|
||||||
themeCategoryTransitionTimer.restart()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCatppuccinColor(variantName) {
|
function getCatppuccinColor(variantName) {
|
||||||
@@ -389,6 +354,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadCustomTheme(themeData) {
|
function loadCustomTheme(themeData) {
|
||||||
|
screenTransition()
|
||||||
if (themeData.dark || themeData.light) {
|
if (themeData.dark || themeData.light) {
|
||||||
const colorMode = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "light" : "dark"
|
const colorMode = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "light" : "dark"
|
||||||
const selectedTheme = themeData[colorMode] || themeData.dark || themeData.light
|
const selectedTheme = themeData[colorMode] || themeData.dark || themeData.light
|
||||||
@@ -470,19 +436,6 @@ 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()
|
||||||
@@ -573,8 +526,23 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractColors() {
|
||||||
|
extractionRequested = true
|
||||||
|
if (matugenAvailable)
|
||||||
|
if (rawWallpaperPath.startsWith("we:")) {
|
||||||
|
fileCheckerTimer.start()
|
||||||
|
} else {
|
||||||
|
fileChecker.running = true
|
||||||
|
}
|
||||||
|
else
|
||||||
|
matugenCheck.running = true
|
||||||
|
}
|
||||||
|
|
||||||
function onLightModeChanged() {
|
function onLightModeChanged() {
|
||||||
|
if (matugenColors && Object.keys(matugenColors).length > 0) {
|
||||||
|
colorUpdateTrigger++
|
||||||
|
}
|
||||||
|
|
||||||
if (currentTheme === "custom" && customThemeFileView.path) {
|
if (currentTheme === "custom" && customThemeFileView.path) {
|
||||||
customThemeFileView.reload()
|
customThemeFileView.reload()
|
||||||
}
|
}
|
||||||
@@ -608,17 +576,16 @@ 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}' '${configDir}' --run`
|
`sleep 1 && ${shellDir}/scripts/matugen-worker.sh '${stateDir}' '${shellDir}' --run`
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
systemThemeGenerator.command = [shellDir + "/scripts/matugen-worker.sh", stateDir, shellDir, configDir, "--run"]
|
systemThemeGenerator.command = [shellDir + "/scripts/matugen-worker.sh", stateDir, shellDir, "--run"]
|
||||||
}
|
}
|
||||||
systemThemeGenerator.running = true
|
systemThemeGenerator.running = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateSystemThemesFromCurrentTheme() {
|
function generateSystemThemesFromCurrentTheme() {
|
||||||
const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode)
|
if (!matugenAvailable)
|
||||||
if (!matugenAvailable || isGreeterMode)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode)
|
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode)
|
||||||
@@ -682,71 +649,78 @@ Singleton {
|
|||||||
qtApplier.running = true
|
qtApplier.running = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function withAlpha(c, a) { return Qt.rgba(c.r, c.g, c.b, a); }
|
function extractJsonFromText(text) {
|
||||||
|
if (!text)
|
||||||
|
return null
|
||||||
|
|
||||||
function snap(value, dpr) {
|
const start = text.search(/[{\[]/)
|
||||||
return Math.round(value * dpr) / dpr
|
if (start === -1)
|
||||||
}
|
return null
|
||||||
|
|
||||||
function invertHex(hex) {
|
const open = text[start]
|
||||||
hex = hex.replace('#', '');
|
const pairs = {
|
||||||
|
"{": '}',
|
||||||
if (!/^[0-9A-Fa-f]{6}$/.test(hex)) {
|
"[": ']'
|
||||||
return hex;
|
|
||||||
}
|
}
|
||||||
|
const close = pairs[open]
|
||||||
|
if (!close)
|
||||||
|
return null
|
||||||
|
|
||||||
const r = parseInt(hex.substr(0, 2), 16);
|
let inString = false
|
||||||
const g = parseInt(hex.substr(2, 2), 16);
|
let escape = false
|
||||||
const b = parseInt(hex.substr(4, 2), 16);
|
const stack = [open]
|
||||||
|
|
||||||
const invR = (255 - r).toString(16).padStart(2, '0');
|
for (var i = start + 1; i < text.length; i++) {
|
||||||
const invG = (255 - g).toString(16).padStart(2, '0');
|
const ch = text[i]
|
||||||
const invB = (255 - b).toString(16).padStart(2, '0');
|
|
||||||
|
|
||||||
return `#${invR}${invG}${invB}`;
|
if (inString) {
|
||||||
}
|
if (escape) {
|
||||||
|
escape = false
|
||||||
|
} else if (ch === '\\') {
|
||||||
|
escape = true
|
||||||
|
} else if (ch === '"') {
|
||||||
|
inString = false
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
property string baseLogoColor: {
|
if (ch === '"') {
|
||||||
if (typeof SettingsData === "undefined") return ""
|
inString = true
|
||||||
const colorOverride = SettingsData.launcherLogoColorOverride
|
continue
|
||||||
if (!colorOverride || colorOverride === "") return ""
|
}
|
||||||
if (colorOverride === "primary") return primary
|
if (ch === '{' || ch === '[') {
|
||||||
if (colorOverride === "surface") return surfaceText
|
stack.push(ch)
|
||||||
return colorOverride
|
continue
|
||||||
}
|
}
|
||||||
|
if (ch === '}' || ch === ']') {
|
||||||
property string effectiveLogoColor: {
|
const last = stack.pop()
|
||||||
if (typeof SettingsData === "undefined") return ""
|
if (!last || pairs[last] !== ch) {
|
||||||
|
return null
|
||||||
const colorOverride = SettingsData.launcherLogoColorOverride
|
}
|
||||||
if (!colorOverride || colorOverride === "") return ""
|
if (stack.length === 0) {
|
||||||
|
return text.slice(start, i + 1)
|
||||||
if (colorOverride === "primary") return primary
|
}
|
||||||
if (colorOverride === "surface") return surfaceText
|
}
|
||||||
|
|
||||||
if (!SettingsData.launcherLogoColorInvertOnMode) {
|
|
||||||
return colorOverride
|
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
if (isLightMode) {
|
|
||||||
return invertHex(colorOverride)
|
|
||||||
}
|
|
||||||
|
|
||||||
return colorOverride
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: matugenCheck
|
id: matugenCheck
|
||||||
command: ["which", "matugen"]
|
command: ["which", "matugen"]
|
||||||
onExited: code => {
|
onExited: code => {
|
||||||
matugenAvailable = (code === 0) && !envDisableMatugen
|
matugenAvailable = (code === 0) && !envDisableMatugen
|
||||||
const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode)
|
if (!matugenAvailable) {
|
||||||
|
console.log("matugen not not available in path or disabled via DMS_DISABLE_MATUGEN")
|
||||||
if (!matugenAvailable || isGreeterMode) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (extractionRequested) {
|
||||||
|
if (rawWallpaperPath.startsWith("we:")) {
|
||||||
|
fileCheckerTimer.start()
|
||||||
|
} else {
|
||||||
|
fileChecker.running = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode)
|
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode)
|
||||||
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
|
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
|
||||||
@@ -782,7 +756,128 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: fileChecker
|
||||||
|
command: ["test", "-r", wallpaperPath]
|
||||||
|
onExited: code => {
|
||||||
|
if (code === 0) {
|
||||||
|
matugenProcess.running = true
|
||||||
|
} else if (wallpaperPath.startsWith("#")) {
|
||||||
|
colorMatugenProcess.running = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: fileCheckerTimer
|
||||||
|
interval: 1000
|
||||||
|
repeat: false
|
||||||
|
onTriggered: {
|
||||||
|
fileChecker.running = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: matugenProcess
|
||||||
|
command: {
|
||||||
|
const scheme = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot"
|
||||||
|
return ["matugen", "image", wallpaperPath, "--json", "hex", "-t", scheme]
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
id: matugenCollector
|
||||||
|
onStreamFinished: {
|
||||||
|
if (!matugenCollector.text) {
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.wallpaperErrorStatus = "error"
|
||||||
|
ToastService.showError("Wallpaper Processing Failed: Empty JSON extracted from matugen output.")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const extractedJson = extractJsonFromText(matugenCollector.text)
|
||||||
|
if (!extractedJson) {
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.wallpaperErrorStatus = "error"
|
||||||
|
ToastService.showError("Wallpaper Processing Failed: Invalid JSON extracted from matugen output.")
|
||||||
|
}
|
||||||
|
console.log("Raw matugen output:", matugenCollector.text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
root.matugenColors = JSON.parse(extractedJson)
|
||||||
|
root.colorUpdateTrigger++
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.clearWallpaperError()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.wallpaperErrorStatus = "error"
|
||||||
|
ToastService.showError("Wallpaper processing failed (JSON parse error after extraction)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: code => {
|
||||||
|
if (code !== 0) {
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.wallpaperErrorStatus = "error"
|
||||||
|
ToastService.showError("Matugen command failed with exit code " + code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: colorMatugenProcess
|
||||||
|
command: {
|
||||||
|
const scheme = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot"
|
||||||
|
return ["matugen", "color", "hex", wallpaperPath, "--json", "hex", "-t", scheme]
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
id: colorMatugenCollector
|
||||||
|
onStreamFinished: {
|
||||||
|
if (!colorMatugenCollector.text) {
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.wallpaperErrorStatus = "error"
|
||||||
|
ToastService.showError("Color Processing Failed: Empty JSON extracted from matugen output.")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const extractedJson = extractJsonFromText(colorMatugenCollector.text)
|
||||||
|
if (!extractedJson) {
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.wallpaperErrorStatus = "error"
|
||||||
|
ToastService.showError("Color Processing Failed: Invalid JSON extracted from matugen output.")
|
||||||
|
}
|
||||||
|
console.log("Raw matugen output:", colorMatugenCollector.text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
root.matugenColors = JSON.parse(extractedJson)
|
||||||
|
root.colorUpdateTrigger++
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.clearWallpaperError()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.wallpaperErrorStatus = "error"
|
||||||
|
ToastService.showError("Color processing failed (JSON parse error after extraction)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: code => {
|
||||||
|
if (code !== 0) {
|
||||||
|
if (typeof ToastService !== "undefined") {
|
||||||
|
ToastService.wallpaperErrorStatus = "error"
|
||||||
|
ToastService.showError("Matugen color command failed with exit code " + code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: ensureStateDir
|
id: ensureStateDir
|
||||||
@@ -795,7 +890,10 @@ Singleton {
|
|||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
workerRunning = false
|
workerRunning = false
|
||||||
|
|
||||||
if (exitCode !== 0 && exitCode !== 2) {
|
if (exitCode === 2) {
|
||||||
|
// Exit code 2 means wallpaper/color not found - this is expected on first run
|
||||||
|
console.log("Theme worker: wallpaper/color not found, skipping theme generation")
|
||||||
|
} else if (exitCode !== 0) {
|
||||||
if (typeof ToastService !== "undefined") {
|
if (typeof ToastService !== "undefined") {
|
||||||
ToastService.showError("Theme worker failed (" + exitCode + ")")
|
ToastService.showError("Theme worker failed (" + exitCode + ")")
|
||||||
}
|
}
|
||||||
@@ -882,69 +980,21 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
|
||||||
id: dynamicColorsFileView
|
|
||||||
path: {
|
|
||||||
const greetCfgDir = Quickshell.env("DMS_GREET_CFG_DIR") || "/etc/greetd/.dms"
|
|
||||||
const colorsPath = SessionData.isGreeterMode
|
|
||||||
? greetCfgDir + "/colors.json"
|
|
||||||
: stateDir + "/dms-colors.json"
|
|
||||||
return colorsPath
|
|
||||||
}
|
|
||||||
watchChanges: currentTheme === dynamic && !SessionData.isGreeterMode
|
|
||||||
|
|
||||||
function parseAndLoadColors() {
|
|
||||||
try {
|
|
||||||
const colorsText = dynamicColorsFileView.text()
|
|
||||||
if (colorsText) {
|
|
||||||
root.matugenColors = JSON.parse(colorsText)
|
|
||||||
if (typeof ToastService !== "undefined") {
|
|
||||||
ToastService.clearWallpaperError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Theme: Failed to parse dynamic colors:", e)
|
|
||||||
if (typeof ToastService !== "undefined") {
|
|
||||||
ToastService.wallpaperErrorStatus = "error"
|
|
||||||
ToastService.showError("Dynamic colors parse error: " + e.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoaded: {
|
|
||||||
if (currentTheme === dynamic) {
|
|
||||||
parseAndLoadColors()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onFileChanged: {
|
|
||||||
if (currentTheme === dynamic) {
|
|
||||||
dynamicColorsFileView.reload()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoadFailed: function (error) {
|
|
||||||
if (currentTheme === dynamic && typeof ToastService !== "undefined") {
|
|
||||||
ToastService.showError("Failed to read dynamic colors: " + error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
target: "theme"
|
target: "theme"
|
||||||
|
|
||||||
function toggle(): string {
|
function toggle(): string {
|
||||||
root.toggleLightMode()
|
root.toggleLightMode()
|
||||||
return root.isLightMode ? "dark" : "light"
|
return root.isLightMode ? "light" : "dark"
|
||||||
}
|
}
|
||||||
|
|
||||||
function light(): string {
|
function light(): string {
|
||||||
root.setLightMode(true, true, true)
|
root.setLightMode(true)
|
||||||
return "light"
|
return "light"
|
||||||
}
|
}
|
||||||
|
|
||||||
function dark(): string {
|
function dark(): string {
|
||||||
root.setLightMode(false, true, true)
|
root.setLightMode(false)
|
||||||
return "dark"
|
return "dark"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -952,35 +1002,4 @@ Singleton {
|
|||||||
return root.isLightMode ? "light" : "dark"
|
return root.isLightMode ? "light" : "dark"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// These timers are for screen transitions, since sometimes QML still beats the niri call
|
|
||||||
Timer {
|
|
||||||
id: themeTransitionTimer
|
|
||||||
interval: 50
|
|
||||||
repeat: false
|
|
||||||
property string themeName: ""
|
|
||||||
property bool savePrefs: true
|
|
||||||
onTriggered: root.switchTheme(themeName, savePrefs, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: lightModeTransitionTimer
|
|
||||||
interval: 100
|
|
||||||
repeat: false
|
|
||||||
property bool lightMode: false
|
|
||||||
property bool savePrefs: true
|
|
||||||
onTriggered: root.setLightMode(lightMode, savePrefs, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: themeCategoryTransitionTimer
|
|
||||||
interval: 50
|
|
||||||
repeat: false
|
|
||||||
property string category: ""
|
|
||||||
property string defaultTheme: ""
|
|
||||||
onTriggered: {
|
|
||||||
root.currentThemeCategory = category
|
|
||||||
root.switchTheme(defaultTheme, true, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Wayland
|
|
||||||
import Quickshell.Services.Greetd
|
|
||||||
import qs.Common
|
|
||||||
import qs.Modules.Greetd
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
WlSessionLock {
|
|
||||||
id: sessionLock
|
|
||||||
locked: false
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
Qt.callLater(() => { locked = true })
|
|
||||||
}
|
|
||||||
|
|
||||||
onLockedChanged: {
|
|
||||||
if (!locked) {
|
|
||||||
console.log("Greetd session unlocked, exiting")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GreeterSurface {
|
|
||||||
lock: sessionLock
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
524
DMSShell.qml
524
DMSShell.qml
@@ -1,524 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Io
|
|
||||||
import qs.Common
|
|
||||||
import qs.Modals
|
|
||||||
import qs.Modals.Clipboard
|
|
||||||
import qs.Modals.Common
|
|
||||||
import qs.Modals.Settings
|
|
||||||
import qs.Modals.Spotlight
|
|
||||||
import qs.Modules
|
|
||||||
import qs.Modules.AppDrawer
|
|
||||||
import qs.Modules.DankDash
|
|
||||||
import qs.Modules.ControlCenter
|
|
||||||
import qs.Modules.Dock
|
|
||||||
import qs.Modules.Lock
|
|
||||||
import qs.Modules.Notepad
|
|
||||||
import qs.Modules.Notifications.Center
|
|
||||||
import qs.Widgets
|
|
||||||
import qs.Modules.Notifications.Popup
|
|
||||||
import qs.Modules.OSD
|
|
||||||
import qs.Modules.ProcessList
|
|
||||||
import qs.Modules.Settings
|
|
||||||
import qs.Modules.DankBar
|
|
||||||
import qs.Modules.DankBar.Popouts
|
|
||||||
import qs.Modules.Plugins
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
Instantiator {
|
|
||||||
id: daemonPluginInstantiator
|
|
||||||
asynchronous: true
|
|
||||||
model: Object.keys(PluginService.pluginDaemonComponents)
|
|
||||||
|
|
||||||
delegate: Loader {
|
|
||||||
id: daemonLoader
|
|
||||||
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 {}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: lockLoader
|
|
||||||
active: false
|
|
||||||
|
|
||||||
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 {
|
|
||||||
id: dankBarLoader
|
|
||||||
asynchronous: false
|
|
||||||
|
|
||||||
property var currentPosition: SettingsData.dankBarPosition
|
|
||||||
property bool initialized: false
|
|
||||||
|
|
||||||
sourceComponent: DankBar {
|
|
||||||
onColorPickerRequested: colorPickerModal.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
initialized = true
|
|
||||||
}
|
|
||||||
|
|
||||||
onCurrentPositionChanged: {
|
|
||||||
if (!initialized) return
|
|
||||||
|
|
||||||
const component = sourceComponent
|
|
||||||
sourceComponent = null
|
|
||||||
sourceComponent = component
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: dockLoader
|
|
||||||
active: true
|
|
||||||
asynchronous: false
|
|
||||||
|
|
||||||
property var currentPosition: SettingsData.dockPosition
|
|
||||||
property bool initialized: false
|
|
||||||
|
|
||||||
sourceComponent: Dock {
|
|
||||||
contextMenu: dockContextMenuLoader.item ? dockContextMenuLoader.item : null
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoaded: {
|
|
||||||
if (item) {
|
|
||||||
dockContextMenuLoader.active = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
initialized = true
|
|
||||||
}
|
|
||||||
|
|
||||||
onCurrentPositionChanged: {
|
|
||||||
if (!initialized) return
|
|
||||||
|
|
||||||
console.log("DEBUG: Dock position changed to:", currentPosition, "- recreating dock")
|
|
||||||
const comp = sourceComponent
|
|
||||||
sourceComponent = null
|
|
||||||
sourceComponent = comp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: dankDashPopoutLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
asynchronous: true
|
|
||||||
|
|
||||||
sourceComponent: Component {
|
|
||||||
DankDashPopout {
|
|
||||||
id: dankDashPopout
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.dankDashPopout = dankDashPopout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: dockContextMenuLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
DockContextMenu {
|
|
||||||
id: dockContextMenu
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: notificationCenterLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
NotificationCenterPopout {
|
|
||||||
id: notificationCenter
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.notificationCenterPopout = notificationCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variants {
|
|
||||||
model: SettingsData.getFilteredScreens("notifications")
|
|
||||||
|
|
||||||
delegate: NotificationPopupManager {
|
|
||||||
modelData: item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: controlCenterLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
property var modalRef: colorPickerModal
|
|
||||||
property LazyLoader powerModalLoaderRef: powerMenuModalLoader
|
|
||||||
|
|
||||||
ControlCenterPopout {
|
|
||||||
id: controlCenterPopout
|
|
||||||
colorPickerModal: controlCenterLoader.modalRef
|
|
||||||
powerMenuModalLoader: controlCenterLoader.powerModalLoaderRef
|
|
||||||
|
|
||||||
onLockRequested: {
|
|
||||||
lockLoader.item.activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.controlCenterPopout = controlCenterPopout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: wifiPasswordModalLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
WifiPasswordModal {
|
|
||||||
id: wifiPasswordModal
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.wifiPasswordModal = wifiPasswordModal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: networkInfoModalLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
NetworkInfoModal {
|
|
||||||
id: networkInfoModal
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.networkInfoModal = networkInfoModal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: batteryPopoutLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
BatteryPopout {
|
|
||||||
id: batteryPopout
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.batteryPopout = batteryPopout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: vpnPopoutLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
VpnPopout {
|
|
||||||
id: vpnPopout
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.vpnPopout = vpnPopout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: powerMenuLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
PowerMenu {
|
|
||||||
id: powerMenu
|
|
||||||
|
|
||||||
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 () {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: powerConfirmModalLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
ConfirmModal {
|
|
||||||
id: powerConfirmModal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: processListPopoutLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
ProcessListPopout {
|
|
||||||
id: processListPopout
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.processListPopout = processListPopout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsModal {
|
|
||||||
id: settingsModal
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.settingsModal = settingsModal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: appDrawerLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
AppDrawerPopout {
|
|
||||||
id: appDrawerPopout
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.appDrawerPopout = appDrawerPopout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SpotlightModal {
|
|
||||||
id: spotlightModal
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.spotlightModal = spotlightModal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ClipboardHistoryModal {
|
|
||||||
id: clipboardHistoryModalPopup
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.clipboardHistoryModal = clipboardHistoryModalPopup
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationModal {
|
|
||||||
id: notificationModal
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.notificationModal = notificationModal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DankColorPickerModal {
|
|
||||||
id: colorPickerModal
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.colorPickerModal = colorPickerModal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: processListModalLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
ProcessListModal {
|
|
||||||
id: processListModal
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.processListModal = processListModal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: systemUpdateLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
SystemUpdatePopout {
|
|
||||||
id: systemUpdatePopout
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.systemUpdatePopout = systemUpdatePopout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variants {
|
|
||||||
id: notepadSlideoutVariants
|
|
||||||
model: SettingsData.getFilteredScreens("notepad")
|
|
||||||
|
|
||||||
delegate: DankSlideout {
|
|
||||||
id: notepadSlideout
|
|
||||||
modelData: item
|
|
||||||
title: I18n.tr("Notepad")
|
|
||||||
slideoutWidth: 480
|
|
||||||
expandable: true
|
|
||||||
expandedWidthValue: 960
|
|
||||||
customTransparency: SettingsData.notepadTransparencyOverride
|
|
||||||
|
|
||||||
content: Component {
|
|
||||||
Notepad {
|
|
||||||
onHideRequested: {
|
|
||||||
notepadSlideout.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggle() {
|
|
||||||
if (isVisible) {
|
|
||||||
hide()
|
|
||||||
} else {
|
|
||||||
show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: powerMenuModalLoader
|
|
||||||
|
|
||||||
active: false
|
|
||||||
|
|
||||||
PowerMenuModal {
|
|
||||||
id: powerMenuModal
|
|
||||||
|
|
||||||
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 () {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.powerMenuModal = powerMenuModal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DMSShellIPC {
|
|
||||||
powerMenuModalLoader: powerMenuModalLoader
|
|
||||||
processListModalLoader: processListModalLoader
|
|
||||||
controlCenterLoader: controlCenterLoader
|
|
||||||
dankDashPopoutLoader: dankDashPopoutLoader
|
|
||||||
notepadSlideoutVariants: notepadSlideoutVariants
|
|
||||||
}
|
|
||||||
|
|
||||||
Variants {
|
|
||||||
model: SettingsData.getFilteredScreens("toast")
|
|
||||||
|
|
||||||
delegate: Toast {
|
|
||||||
modelData: item
|
|
||||||
visible: ToastService.toastVisible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variants {
|
|
||||||
model: SettingsData.getFilteredScreens("osd")
|
|
||||||
|
|
||||||
delegate: VolumeOSD {
|
|
||||||
modelData: item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variants {
|
|
||||||
model: SettingsData.getFilteredScreens("osd")
|
|
||||||
|
|
||||||
delegate: MicMuteOSD {
|
|
||||||
modelData: item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variants {
|
|
||||||
model: SettingsData.getFilteredScreens("osd")
|
|
||||||
|
|
||||||
delegate: BrightnessOSD {
|
|
||||||
modelData: item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variants {
|
|
||||||
model: SettingsData.getFilteredScreens("osd")
|
|
||||||
|
|
||||||
delegate: IdleInhibitorOSD {
|
|
||||||
modelData: item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
265
DMSShellIPC.qml
265
DMSShellIPC.qml
@@ -1,265 +0,0 @@
|
|||||||
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(I18n.tr("Clear All History?"), I18n.tr("This will permanently delete all clipboard history."), function () {
|
clearConfirmDialog.show("Clear All History?", "This will permanently delete all clipboard history.", function () {
|
||||||
modal.clearAll()
|
modal.clearAll()
|
||||||
modal.hide()
|
modal.hide()
|
||||||
}, function () {})
|
}, function () {})
|
||||||
@@ -46,6 +46,7 @@ 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
|
||||||
@@ -76,12 +77,15 @@ Item {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height - ClipboardConstants.headerHeight - 70
|
height: parent.height - ClipboardConstants.headerHeight - 70
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: "transparent"
|
color: Theme.surfaceLight
|
||||||
|
border.color: Theme.outlineLight
|
||||||
|
border.width: 1
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
DankListView {
|
DankListView {
|
||||||
id: clipboardListView
|
id: clipboardListView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingS
|
||||||
model: filteredModel
|
model: filteredModel
|
||||||
|
|
||||||
currentIndex: clipboardContent.modal ? clipboardContent.modal.selectedIndex : 0
|
currentIndex: clipboardContent.modal ? clipboardContent.modal.selectedIndex : 0
|
||||||
@@ -115,7 +119,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("No clipboard entries found")
|
text: "No clipboard entries found"
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
|
|||||||
@@ -24,10 +24,17 @@ Rectangle {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: {
|
color: {
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
return Theme.primaryPressed
|
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2)
|
||||||
}
|
}
|
||||||
return mouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
return mouseArea.containsMouse ? Theme.primaryHover : Theme.primaryBackground
|
||||||
}
|
}
|
||||||
|
border.color: {
|
||||||
|
if (isSelected) {
|
||||||
|
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.5)
|
||||||
|
}
|
||||||
|
return Theme.outlineStrong
|
||||||
|
}
|
||||||
|
border.width: isSelected ? 1.5 : 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -80,11 +87,11 @@ Rectangle {
|
|||||||
text: {
|
text: {
|
||||||
switch (entryType) {
|
switch (entryType) {
|
||||||
case "image":
|
case "image":
|
||||||
return I18n.tr("Image") + " • " + entryPreview
|
return "Image • " + entryPreview
|
||||||
case "long_text":
|
case "long_text":
|
||||||
return I18n.tr("Long Text")
|
return "Long Text"
|
||||||
default:
|
default:
|
||||||
return I18n.tr("Text")
|
return "Text"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Clipboard History") + ` (${totalCount})`
|
text: `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(I18n.tr("Copied to clipboard"))
|
ToastService.showInfo("Copied to clipboard")
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ DankModal {
|
|||||||
|
|
||||||
ConfirmModal {
|
ConfirmModal {
|
||||||
id: clearConfirmDialog
|
id: clearConfirmDialog
|
||||||
confirmButtonText: I18n.tr("Clear All")
|
confirmButtonText: "Clear All"
|
||||||
confirmButtonColor: Theme.primary
|
confirmButtonColor: Theme.primary
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ QtObject {
|
|||||||
modal.hide()
|
modal.hide()
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
}
|
}
|
||||||
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Tab) {
|
} else if (event.key === Qt.Key_Down) {
|
||||||
if (!modal.keyboardNavigationActive) {
|
if (!modal.keyboardNavigationActive) {
|
||||||
modal.keyboardNavigationActive = true
|
modal.keyboardNavigationActive = true
|
||||||
modal.selectedIndex = 0
|
modal.selectedIndex = 0
|
||||||
@@ -62,7 +62,7 @@ QtObject {
|
|||||||
selectNext()
|
selectNext()
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
}
|
}
|
||||||
} else if (event.key === Qt.Key_Up || event.key === Qt.Key_Backtab) {
|
} else if (event.key === Qt.Key_Up) {
|
||||||
if (!modal.keyboardNavigationActive) {
|
if (!modal.keyboardNavigationActive) {
|
||||||
modal.keyboardNavigationActive = true
|
modal.keyboardNavigationActive = true
|
||||||
modal.selectedIndex = 0
|
modal.selectedIndex = 0
|
||||||
@@ -74,42 +74,6 @@ QtObject {
|
|||||||
selectPrevious()
|
selectPrevious()
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
}
|
}
|
||||||
} else if (event.key === Qt.Key_N && event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (!modal.keyboardNavigationActive) {
|
|
||||||
modal.keyboardNavigationActive = true
|
|
||||||
modal.selectedIndex = 0
|
|
||||||
} else {
|
|
||||||
selectNext()
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_P && event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (!modal.keyboardNavigationActive) {
|
|
||||||
modal.keyboardNavigationActive = true
|
|
||||||
modal.selectedIndex = 0
|
|
||||||
} else if (modal.selectedIndex === 0) {
|
|
||||||
modal.keyboardNavigationActive = false
|
|
||||||
} else {
|
|
||||||
selectPrevious()
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_J && event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (!modal.keyboardNavigationActive) {
|
|
||||||
modal.keyboardNavigationActive = true
|
|
||||||
modal.selectedIndex = 0
|
|
||||||
} else {
|
|
||||||
selectNext()
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_K && event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (!modal.keyboardNavigationActive) {
|
|
||||||
modal.keyboardNavigationActive = true
|
|
||||||
modal.selectedIndex = 0
|
|
||||||
} else if (modal.selectedIndex === 0) {
|
|
||||||
modal.keyboardNavigationActive = false
|
|
||||||
} else {
|
|
||||||
selectPrevious()
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_Delete && (event.modifiers & Qt.ShiftModifier)) {
|
} else if (event.key === Qt.Key_Delete && (event.modifiers & Qt.ShiftModifier)) {
|
||||||
modal.clearAll()
|
modal.clearAll()
|
||||||
modal.hide()
|
modal.hide()
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ 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)
|
||||||
@@ -28,7 +26,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: keyboardHints.hintsText
|
text: "Shift+Del: Clear All • Esc: Close"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|||||||
37
Modals/ColorPickerModal.qml
Normal file
37
Modals/ColorPickerModal.qml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -93,48 +93,6 @@ DankModal {
|
|||||||
selectedButton = 1
|
selectedButton = 1
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
break
|
break
|
||||||
case Qt.Key_N:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
keyboardNavigation = true
|
|
||||||
selectedButton = (selectedButton + 1) % 2
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_P:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
keyboardNavigation = true
|
|
||||||
selectedButton = selectedButton === -1 ? 1 : (selectedButton - 1 + 2) % 2
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_J:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
keyboardNavigation = true
|
|
||||||
selectedButton = 1
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_K:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
keyboardNavigation = true
|
|
||||||
selectedButton = 0
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_H:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
keyboardNavigation = true
|
|
||||||
selectedButton = 0
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_L:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
keyboardNavigation = true
|
|
||||||
selectedButton = 1
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_Tab:
|
case Qt.Key_Tab:
|
||||||
keyboardNavigation = true
|
keyboardNavigation = true
|
||||||
selectedButton = selectedButton === -1 ? 0 : (selectedButton + 1) % 2
|
selectedButton = selectedButton === -1 ? 0 : (selectedButton + 1) % 2
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -14,15 +15,6 @@ 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"
|
||||||
@@ -30,7 +22,7 @@ PanelWindow {
|
|||||||
property bool closeOnEscapeKey: true
|
property bool closeOnEscapeKey: true
|
||||||
property bool closeOnBackgroundClick: true
|
property bool closeOnBackgroundClick: true
|
||||||
property string animationType: "scale"
|
property string animationType: "scale"
|
||||||
property int animationDuration: Theme.shortDuration
|
property int animationDuration: Theme.shorterDuration
|
||||||
property var animationEasing: Theme.emphasizedEasing
|
property var animationEasing: Theme.emphasizedEasing
|
||||||
property color backgroundColor: Theme.surfaceContainer
|
property color backgroundColor: Theme.surfaceContainer
|
||||||
property color borderColor: Theme.outlineMedium
|
property color borderColor: Theme.outlineMedium
|
||||||
@@ -42,7 +34,6 @@ PanelWindow {
|
|||||||
property bool shouldHaveFocus: shouldBeVisible
|
property bool shouldHaveFocus: shouldBeVisible
|
||||||
property bool allowFocusOverride: false
|
property bool allowFocusOverride: false
|
||||||
property bool allowStacking: false
|
property bool allowStacking: false
|
||||||
property bool keepContentLoaded: false
|
|
||||||
|
|
||||||
signal opened
|
signal opened
|
||||||
signal dialogClosed
|
signal dialogClosed
|
||||||
@@ -99,7 +90,7 @@ PanelWindow {
|
|||||||
Timer {
|
Timer {
|
||||||
id: closeTimer
|
id: closeTimer
|
||||||
|
|
||||||
interval: animationDuration + 100
|
interval: animationDuration + 50
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
visible = false
|
visible = false
|
||||||
}
|
}
|
||||||
@@ -142,26 +133,22 @@ PanelWindow {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: contentContainer
|
id: contentContainer
|
||||||
|
|
||||||
width: px(root.width)
|
width: root.width
|
||||||
height: px(root.height)
|
height: root.height
|
||||||
anchors.centerIn: undefined
|
anchors.centerIn: positioning === "center" ? parent : undefined
|
||||||
x: {
|
x: {
|
||||||
if (positioning === "center") {
|
if (positioning === "top-right") {
|
||||||
return snap((root.screenWidth - width) / 2)
|
return Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL)
|
||||||
} 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 snap(root.customPosition.x)
|
return root.customPosition.x
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
y: {
|
y: {
|
||||||
if (positioning === "center") {
|
if (positioning === "top-right") {
|
||||||
return snap((root.screenHeight - height) / 2)
|
return Theme.barHeight + Theme.spacingXS
|
||||||
} else if (positioning === "top-right") {
|
|
||||||
return px(Theme.barHeight + Theme.spacingXS)
|
|
||||||
} else if (positioning === "custom") {
|
} else if (positioning === "custom") {
|
||||||
return snap(root.customPosition.y)
|
return root.customPosition.y
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -169,48 +156,50 @@ PanelWindow {
|
|||||||
radius: root.cornerRadius
|
radius: root.cornerRadius
|
||||||
border.color: root.borderColor
|
border.color: root.borderColor
|
||||||
border.width: root.borderWidth
|
border.width: root.borderWidth
|
||||||
clip: false
|
layer.enabled: root.enableShadow
|
||||||
opacity: root.shouldBeVisible ? 1 : 0
|
opacity: root.shouldBeVisible ? 1 : 0
|
||||||
|
scale: root.animationType === "scale" ? (root.shouldBeVisible ? 1 : 0.9) : 1
|
||||||
transform: root.animationType === "slide" ? slideTransform : null
|
transform: root.animationType === "slide" ? slideTransform : null
|
||||||
|
|
||||||
Translate {
|
Translate {
|
||||||
id: slideTransform
|
id: slideTransform
|
||||||
|
|
||||||
readonly property real rawX: root.shouldBeVisible ? 0 : 15
|
x: root.shouldBeVisible ? 0 : 15
|
||||||
readonly property real rawY: root.shouldBeVisible ? 0 : -30
|
y: root.shouldBeVisible ? 0 : -30
|
||||||
|
}
|
||||||
|
|
||||||
x: snap(rawX)
|
Loader {
|
||||||
y: snap(rawY)
|
id: contentLoader
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
active: root.visible
|
||||||
|
asynchronous: false
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: animationDuration
|
duration: root.animationDuration
|
||||||
easing.type: animationEasing
|
easing.type: root.animationEasing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FocusScope {
|
Behavior on scale {
|
||||||
anchors.fill: parent
|
enabled: root.animationType === "scale"
|
||||||
focus: root.shouldBeVisible
|
|
||||||
clip: false
|
|
||||||
|
|
||||||
Loader {
|
NumberAnimation {
|
||||||
id: contentLoader
|
duration: root.animationDuration
|
||||||
|
easing.type: root.animationEasing
|
||||||
anchors.fill: parent
|
|
||||||
active: root.keepContentLoaded || root.shouldBeVisible || root.visible
|
|
||||||
asynchronous: false
|
|
||||||
focus: true
|
|
||||||
clip: false
|
|
||||||
|
|
||||||
onLoaded: {
|
|
||||||
if (item) {
|
|
||||||
Qt.callLater(() => item.forceActiveFocus())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layer.effect: MultiEffect {
|
||||||
|
shadowEnabled: true
|
||||||
|
shadowHorizontalOffset: 0
|
||||||
|
shadowVerticalOffset: 8
|
||||||
|
shadowBlur: 1
|
||||||
|
shadowColor: Theme.shadowStrong
|
||||||
|
shadowOpacity: 0.3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FocusScope {
|
FocusScope {
|
||||||
@@ -218,8 +207,8 @@ PanelWindow {
|
|||||||
|
|
||||||
objectName: "modalFocusScope"
|
objectName: "modalFocusScope"
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: root.shouldBeVisible || root.visible
|
visible: root.visible // Only active when the modal is visible
|
||||||
focus: root.shouldBeVisible
|
focus: root.visible
|
||||||
Keys.onEscapePressed: event => {
|
Keys.onEscapePressed: event => {
|
||||||
if (root.closeOnEscapeKey && shouldHaveFocus) {
|
if (root.closeOnEscapeKey && shouldHaveFocus) {
|
||||||
root.close()
|
root.close()
|
||||||
@@ -234,7 +223,7 @@ PanelWindow {
|
|||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onShouldHaveFocusChanged() {
|
function onShouldHaveFocusChanged() {
|
||||||
if (shouldHaveFocus && shouldBeVisible) {
|
if (shouldHaveFocus && visible) {
|
||||||
Qt.callLater(() => focusScope.forceActiveFocus())
|
Qt.callLater(() => focusScope.forceActiveFocus())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,580 +0,0 @@
|
|||||||
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,7 +35,6 @@ 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)
|
||||||
|
|
||||||
@@ -132,8 +131,6 @@ DankModal {
|
|||||||
|
|
||||||
objectName: "fileBrowserModal"
|
objectName: "fileBrowserModal"
|
||||||
allowStacking: true
|
allowStacking: true
|
||||||
closeOnEscapeKey: false
|
|
||||||
shouldHaveFocus: shouldBeVisible
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
currentPath = getLastPath()
|
currentPath = getLastPath()
|
||||||
}
|
}
|
||||||
@@ -168,23 +165,10 @@ DankModal {
|
|||||||
visible: false
|
visible: false
|
||||||
onBackgroundClicked: close()
|
onBackgroundClicked: close()
|
||||||
onOpened: {
|
onOpened: {
|
||||||
if (parentModal) {
|
modalFocusScope.forceActiveFocus()
|
||||||
parentModal.shouldHaveFocus = false
|
|
||||||
parentModal.allowFocusOverride = true
|
|
||||||
}
|
|
||||||
Qt.callLater(() => {
|
|
||||||
if (contentLoader && contentLoader.item) {
|
|
||||||
contentLoader.item.forceActiveFocus()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
onDialogClosed: {
|
modalFocusScope.Keys.onPressed: function (event) {
|
||||||
if (parentModal) {
|
keyboardController.handleKey(event)
|
||||||
parentModal.allowFocusOverride = false
|
|
||||||
parentModal.shouldHaveFocus = Qt.binding(() => {
|
|
||||||
return parentModal.shouldBeVisible
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
@@ -255,12 +239,7 @@ DankModal {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!keyboardNavigationActive) {
|
if (!keyboardNavigationActive) {
|
||||||
const isInitKey = event.key === Qt.Key_Tab || event.key === Qt.Key_Down || event.key === Qt.Key_Right ||
|
if (event.key === Qt.Key_Tab || event.key === Qt.Key_Down || event.key === Qt.Key_Right) {
|
||||||
(event.key === Qt.Key_N && event.modifiers & Qt.ControlModifier) ||
|
|
||||||
(event.key === Qt.Key_J && event.modifiers & Qt.ControlModifier) ||
|
|
||||||
(event.key === Qt.Key_L && event.modifiers & Qt.ControlModifier)
|
|
||||||
|
|
||||||
if (isInitKey) {
|
|
||||||
keyboardNavigationActive = true
|
keyboardNavigationActive = true
|
||||||
if (currentPath !== homeDir) {
|
if (currentPath !== homeDir) {
|
||||||
backButtonFocused = true
|
backButtonFocused = true
|
||||||
@@ -302,69 +281,6 @@ DankModal {
|
|||||||
}
|
}
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
break
|
break
|
||||||
case Qt.Key_N:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (backButtonFocused) {
|
|
||||||
backButtonFocused = false
|
|
||||||
selectedIndex = 0
|
|
||||||
} else if (selectedIndex < totalItems - 1) {
|
|
||||||
selectedIndex++
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_P:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (selectedIndex > 0) {
|
|
||||||
selectedIndex--
|
|
||||||
} else if (currentPath !== homeDir) {
|
|
||||||
backButtonFocused = true
|
|
||||||
selectedIndex = -1
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_J:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (selectedIndex < totalItems - 1) {
|
|
||||||
selectedIndex++
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_K:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (selectedIndex > 0) {
|
|
||||||
selectedIndex--
|
|
||||||
} else if (currentPath !== homeDir) {
|
|
||||||
backButtonFocused = true
|
|
||||||
selectedIndex = -1
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_H:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (!backButtonFocused && selectedIndex > 0) {
|
|
||||||
selectedIndex--
|
|
||||||
} else if (currentPath !== homeDir) {
|
|
||||||
backButtonFocused = true
|
|
||||||
selectedIndex = -1
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_L:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (backButtonFocused) {
|
|
||||||
backButtonFocused = false
|
|
||||||
selectedIndex = 0
|
|
||||||
} else if (selectedIndex < totalItems - 1) {
|
|
||||||
selectedIndex++
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case Qt.Key_Left:
|
case Qt.Key_Left:
|
||||||
if (backButtonFocused)
|
if (backButtonFocused)
|
||||||
return
|
return
|
||||||
@@ -471,16 +387,6 @@ 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
|
||||||
@@ -621,6 +527,7 @@ DankModal {
|
|||||||
required property bool fileIsDir
|
required property bool fileIsDir
|
||||||
required property string filePath
|
required property string filePath
|
||||||
required property string fileName
|
required property string fileName
|
||||||
|
required property url fileURL
|
||||||
required property int index
|
required property int index
|
||||||
|
|
||||||
width: weMode ? 245 : 140
|
width: weMode ? 245 : 140
|
||||||
@@ -780,7 +687,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: I18n.tr("Enter filename...")
|
placeholderText: "Enter filename..."
|
||||||
ignoreLeftRightKeys: false
|
ignoreLeftRightKeys: false
|
||||||
focus: saveMode
|
focus: saveMode
|
||||||
topPadding: Theme.spacingS
|
topPadding: Theme.spacingS
|
||||||
@@ -813,7 +720,7 @@ DankModal {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: I18n.tr("Save")
|
text: "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
|
||||||
}
|
}
|
||||||
@@ -917,7 +824,7 @@ DankModal {
|
|||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("File Already Exists")
|
text: qsTr("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
|
||||||
@@ -925,7 +832,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("A file with this name already exists. Do you want to overwrite it?")
|
text: qsTr("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
|
||||||
@@ -947,7 +854,7 @@ DankModal {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: I18n.tr("Cancel")
|
text: qsTr("Cancel")
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -973,7 +880,7 @@ DankModal {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: I18n.tr("Overwrite")
|
text: qsTr("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: I18n.tr("File Information")
|
text: "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: I18n.tr("F1/I: Toggle • F10: Help")
|
text: "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: I18n.tr("Tab/Shift+Tab: Nav • ←→↑↓: Grid Nav • Enter/Space: Select")
|
text: "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: I18n.tr("Alt+←/Backspace: Back • F1/I: File Info • F10: Help • Esc: Close")
|
text: "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: I18n.tr("Network Information")
|
text: "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: I18n.tr("Close")
|
text: "Close"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.background
|
color: Theme.background
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
|||||||
@@ -9,47 +9,31 @@ 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": I18n.tr("Log Out"),
|
"title": "Log Out",
|
||||||
"message": I18n.tr("Are you sure you want to log out?")
|
"message": "Are you sure you want to log out?"
|
||||||
},
|
},
|
||||||
"suspend": {
|
"suspend": {
|
||||||
"title": I18n.tr("Suspend"),
|
"title": "Suspend",
|
||||||
"message": I18n.tr("Are you sure you want to suspend the system?")
|
"message": "Are you sure you want to suspend the system?"
|
||||||
},
|
},
|
||||||
"hibernate": {
|
"hibernate": {
|
||||||
"title": I18n.tr("Hibernate"),
|
"title": "Hibernate",
|
||||||
"message": I18n.tr("Are you sure you want to hibernate the system?")
|
"message": "Are you sure you want to hibernate the system?"
|
||||||
},
|
},
|
||||||
"reboot": {
|
"reboot": {
|
||||||
"title": I18n.tr("Reboot"),
|
"title": "Reboot",
|
||||||
"message": I18n.tr("Are you sure you want to reboot the system?")
|
"message": "Are you sure you want to reboot the system?"
|
||||||
},
|
},
|
||||||
"poweroff": {
|
"poweroff": {
|
||||||
"title": I18n.tr("Power Off"),
|
"title": "Power Off",
|
||||||
"message": I18n.tr("Are you sure you want to power off the system?")
|
"message": "Are you sure you want to power off the system?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const selected = actions[action]
|
const selected = actions[action]
|
||||||
@@ -63,16 +47,6 @@ 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();
|
||||||
}
|
}
|
||||||
@@ -83,11 +57,13 @@ DankModal {
|
|||||||
modalFocusScope.Keys.onPressed: (event) => {
|
modalFocusScope.Keys.onPressed: (event) => {
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case Qt.Key_Up:
|
case Qt.Key_Up:
|
||||||
case Qt.Key_Backtab:
|
|
||||||
selectedIndex = (selectedIndex - 1 + optionCount) % optionCount;
|
selectedIndex = (selectedIndex - 1 + optionCount) % optionCount;
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
break;
|
break;
|
||||||
case Qt.Key_Down:
|
case Qt.Key_Down:
|
||||||
|
selectedIndex = (selectedIndex + 1) % optionCount;
|
||||||
|
event.accepted = true;
|
||||||
|
break;
|
||||||
case Qt.Key_Tab:
|
case Qt.Key_Tab:
|
||||||
selectedIndex = (selectedIndex + 1) % optionCount;
|
selectedIndex = (selectedIndex + 1) % optionCount;
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
@@ -102,30 +78,6 @@ DankModal {
|
|||||||
}
|
}
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
break;
|
break;
|
||||||
case Qt.Key_N:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
selectedIndex = (selectedIndex + 1) % optionCount;
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Qt.Key_P:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
selectedIndex = (selectedIndex - 1 + optionCount) % optionCount;
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Qt.Key_J:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
selectedIndex = (selectedIndex + 1) % optionCount;
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Qt.Key_K:
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
selectedIndex = (selectedIndex - 1 + optionCount) % optionCount;
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +96,7 @@ DankModal {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Power Options")
|
text: "Power Options"
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -201,7 +153,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Log Out")
|
text: "Log Out"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -254,7 +206,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Suspend")
|
text: "Suspend"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -308,7 +260,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Hibernate")
|
text: "Hibernate"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -362,7 +314,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Reboot")
|
text: "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
|
||||||
@@ -416,7 +368,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Power Off")
|
text: "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: I18n.tr("System Monitor Unavailable")
|
text: "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: I18n.tr("The 'dgop' tool is required for system monitoring.\nPlease install dgop to use this feature.")
|
text: "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: I18n.tr("System Monitor")
|
text: "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: I18n.tr("Battery not detected - only AC power settings available")
|
text: "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: I18n.tr("Idle Settings")
|
text: "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,8 @@ 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: I18n.tr("Automatically lock after")
|
width: parent.width
|
||||||
|
text: "Automatically lock after"
|
||||||
options: timeoutOptions
|
options: timeoutOptions
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -115,7 +116,8 @@ 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: I18n.tr("Turn off monitors after")
|
width: parent.width
|
||||||
|
text: "Turn off monitors after"
|
||||||
options: timeoutOptions
|
options: timeoutOptions
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -151,7 +153,8 @@ 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: I18n.tr("Suspend system after")
|
width: parent.width
|
||||||
|
text: "Suspend system after"
|
||||||
options: timeoutOptions
|
options: timeoutOptions
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -187,7 +190,8 @@ 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: I18n.tr("Hibernate system after")
|
width: parent.width
|
||||||
|
text: "Hibernate system after"
|
||||||
options: timeoutOptions
|
options: timeoutOptions
|
||||||
visible: SessionService.hibernateSupported
|
visible: SessionService.hibernateSupported
|
||||||
|
|
||||||
@@ -221,23 +225,14 @@ Item {
|
|||||||
|
|
||||||
DankToggle {
|
DankToggle {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
text: I18n.tr("Enable loginctl lock integration")
|
text: "Lock before suspend"
|
||||||
description: "Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen."
|
|
||||||
checked: SessionData.loginctlLockIntegration
|
|
||||||
onToggled: checked => SessionData.setLoginctlLockIntegration(checked)
|
|
||||||
}
|
|
||||||
|
|
||||||
DankToggle {
|
|
||||||
width: parent.width
|
|
||||||
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
|
||||||
visible: SessionData.loginctlLockIntegration
|
|
||||||
onToggled: checked => SessionData.setLockBeforeSuspend(checked)
|
onToggled: checked => SessionData.setLockBeforeSuspend(checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Idle monitoring not supported - requires newer Quickshell version")
|
text: "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,12 +2,11 @@ import QtQuick
|
|||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Modules.Settings
|
import qs.Modules.Settings
|
||||||
|
|
||||||
FocusScope {
|
Item {
|
||||||
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,8 +67,7 @@ FocusScope {
|
|||||||
visible: active
|
visible: active
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
|
||||||
sourceComponent: DankBarTab {
|
sourceComponent: TopBarTab {
|
||||||
parentModal: root.parentModal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -155,25 +153,11 @@ FocusScope {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: pluginsLoader
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
active: root.currentIndex === 10
|
|
||||||
visible: active
|
|
||||||
asynchronous: true
|
|
||||||
|
|
||||||
sourceComponent: PluginsTab {
|
|
||||||
parentModal: root.parentModal
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: aboutLoader
|
id: aboutLoader
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: root.currentIndex === 11
|
active: root.currentIndex === 10
|
||||||
visible: active
|
visible: active
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ DankModal {
|
|||||||
|
|
||||||
objectName: "settingsModal"
|
objectName: "settingsModal"
|
||||||
width: 800
|
width: 800
|
||||||
height: 800
|
height: 750
|
||||||
visible: false
|
visible: false
|
||||||
onBackgroundClicked: () => {
|
onBackgroundClicked: () => {
|
||||||
return hide();
|
return hide();
|
||||||
@@ -78,7 +78,6 @@ 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"
|
||||||
@@ -88,6 +87,12 @@ DankModal {
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
onDialogClosed: () => {
|
onDialogClosed: () => {
|
||||||
|
if (settingsModal) {
|
||||||
|
settingsModal.allowFocusOverride = false;
|
||||||
|
settingsModal.shouldHaveFocus = Qt.binding(() => {
|
||||||
|
return settingsModal.shouldBeVisible;
|
||||||
|
});
|
||||||
|
}
|
||||||
allowStacking = true;
|
allowStacking = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,7 +101,6 @@ 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"
|
||||||
@@ -111,7 +115,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
settingsContent: Component {
|
settingsContent: Component {
|
||||||
FocusScope {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
focus: true
|
focus: true
|
||||||
|
|
||||||
@@ -140,7 +144,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Settings")
|
text: "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,37 @@ 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": I18n.tr("Personalization"),
|
"text": "Personalization",
|
||||||
"icon": "person"
|
"icon": "person"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Time & Date"),
|
"text": "Time & Date",
|
||||||
"icon": "schedule"
|
"icon": "schedule"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Weather"),
|
"text": "Weather",
|
||||||
"icon": "cloud"
|
"icon": "cloud"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Dank Bar"),
|
"text": "Top Bar",
|
||||||
"icon": "toolbar"
|
"icon": "toolbar"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Widgets"),
|
"text": "Widgets",
|
||||||
"icon": "widgets"
|
"icon": "widgets"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Dock"),
|
"text": "Dock",
|
||||||
"icon": "dock_to_bottom"
|
"icon": "dock_to_bottom"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Displays"),
|
"text": "Displays",
|
||||||
"icon": "monitor"
|
"icon": "monitor"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Launcher"),
|
"text": "Launcher",
|
||||||
"icon": "apps"
|
"icon": "apps"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Theme & Colors"),
|
"text": "Theme & Colors",
|
||||||
"icon": "palette"
|
"icon": "palette"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Power"),
|
"text": "Power",
|
||||||
"icon": "power_settings_new"
|
"icon": "power_settings_new"
|
||||||
}, {
|
}, {
|
||||||
"text": I18n.tr("Plugins"),
|
"text": "About",
|
||||||
"icon": "extension"
|
|
||||||
}, {
|
|
||||||
"text": I18n.tr("About"),
|
|
||||||
"icon": "info"
|
"icon": "info"
|
||||||
}]
|
}]
|
||||||
|
|
||||||
@@ -86,7 +83,7 @@ Rectangle {
|
|||||||
width: parent.width - Theme.spacingS * 2
|
width: parent.width - Theme.spacingS * 2
|
||||||
height: 44
|
height: 44
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: isActive ? Theme.primary : tabMouseArea.containsMouse ? Theme.surfaceHover : "transparent"
|
color: isActive ? Theme.primaryContainer : tabMouseArea.containsMouse ? Theme.surfaceHover : "transparent"
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -97,14 +94,14 @@ Rectangle {
|
|||||||
DankIcon {
|
DankIcon {
|
||||||
name: modelData.icon || ""
|
name: modelData.icon || ""
|
||||||
size: Theme.iconSize - 2
|
size: Theme.iconSize - 2
|
||||||
color: parent.parent.isActive ? Theme.primaryText : Theme.surfaceText
|
color: parent.parent.isActive ? Theme.surfaceText : Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: modelData.text || ""
|
text: modelData.text || ""
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: parent.parent.isActive ? Theme.primaryText : Theme.surfaceText
|
color: parent.parent.isActive ? Theme.surfaceText : Theme.surfaceText
|
||||||
font.weight: parent.parent.isActive ? Font.Medium : Font.Normal
|
font.weight: parent.parent.isActive ? Font.Medium : Font.Normal
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,8 @@ 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)
|
||||||
@@ -38,49 +33,13 @@ Item {
|
|||||||
} else if (event.key === Qt.Key_Left && appLauncher.viewMode === "grid") {
|
} else if (event.key === Qt.Key_Left && appLauncher.viewMode === "grid") {
|
||||||
appLauncher.selectPreviousInRow()
|
appLauncher.selectPreviousInRow()
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
} else if (event.key == Qt.Key_J && event.modifiers & Qt.ControlModifier) {
|
|
||||||
appLauncher.selectNext()
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key == Qt.Key_K && event.modifiers & Qt.ControlModifier) {
|
|
||||||
appLauncher.selectPrevious()
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key == Qt.Key_L && event.modifiers & Qt.ControlModifier && appLauncher.viewMode === "grid") {
|
|
||||||
appLauncher.selectNextInRow()
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key == Qt.Key_H && event.modifiers & Qt.ControlModifier && appLauncher.viewMode === "grid") {
|
|
||||||
appLauncher.selectPreviousInRow()
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_Tab) {
|
|
||||||
if (appLauncher.viewMode === "grid") {
|
|
||||||
appLauncher.selectNextInRow()
|
|
||||||
} else {
|
|
||||||
appLauncher.selectNext()
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_Backtab) {
|
|
||||||
if (appLauncher.viewMode === "grid") {
|
|
||||||
appLauncher.selectPreviousInRow()
|
|
||||||
} else {
|
|
||||||
appLauncher.selectPrevious()
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_N && event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (appLauncher.viewMode === "grid") {
|
|
||||||
appLauncher.selectNextInRow()
|
|
||||||
} else {
|
|
||||||
appLauncher.selectNext()
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
} else if (event.key === Qt.Key_P && event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (appLauncher.viewMode === "grid") {
|
|
||||||
appLauncher.selectPreviousInRow()
|
|
||||||
} else {
|
|
||||||
appLauncher.selectPrevious()
|
|
||||||
}
|
|
||||||
event.accepted = true
|
|
||||||
} 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,19 +59,40 @@ Item {
|
|||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.spacingM
|
anchors.margins: Theme.spacingL
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingL
|
||||||
clip: false
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: categorySelector.height + Theme.spacingM * 2
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Theme.surfaceVariantAlpha
|
||||||
|
border.color: Theme.outlineMedium
|
||||||
|
border.width: 1
|
||||||
|
visible: appLauncher.categories.length > 1 || appLauncher.model.count > 0
|
||||||
|
|
||||||
|
CategorySelector {
|
||||||
|
id: categorySelector
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - Theme.spacingM * 2
|
||||||
|
categories: appLauncher.categories
|
||||||
|
selectedCategory: appLauncher.selectedCategory
|
||||||
|
compact: false
|
||||||
|
onCategorySelected: category => {
|
||||||
|
appLauncher.setCategory(category)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
leftPadding: Theme.spacingS
|
|
||||||
|
|
||||||
DankTextField {
|
DankTextField {
|
||||||
id: searchField
|
id: searchField
|
||||||
|
|
||||||
width: parent.width - 80 - Theme.spacingL
|
width: parent.width - 80 - Theme.spacingM
|
||||||
height: 56
|
height: 56
|
||||||
cornerRadius: Theme.cornerRadius
|
cornerRadius: Theme.cornerRadius
|
||||||
backgroundColor: Theme.surfaceContainerHigh
|
backgroundColor: Theme.surfaceContainerHigh
|
||||||
@@ -127,7 +107,7 @@ Item {
|
|||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
enabled: parentModal ? parentModal.spotlightOpen : true
|
enabled: parentModal ? parentModal.spotlightOpen : true
|
||||||
placeholderText: ""
|
placeholderText: ""
|
||||||
ignoreLeftRightKeys: appLauncher.viewMode !== "list"
|
ignoreLeftRightKeys: true
|
||||||
keyForwardTargets: [spotlightKeyHandler]
|
keyForwardTargets: [spotlightKeyHandler]
|
||||||
text: appLauncher.searchQuery
|
text: appLauncher.searchQuery
|
||||||
onTextEdited: () => {
|
onTextEdited: () => {
|
||||||
@@ -145,7 +125,7 @@ Item {
|
|||||||
else if (appLauncher.model.count > 0)
|
else if (appLauncher.model.count > 0)
|
||||||
appLauncher.launchApp(appLauncher.model.get(0))
|
appLauncher.launchApp(appLauncher.model.get(0))
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Up || event.key === Qt.Key_Left || event.key === Qt.Key_Right || event.key === Qt.Key_Tab || event.key === Qt.Key_Backtab || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
|
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Up || event.key === Qt.Key_Left || event.key === Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
|
||||||
event.accepted = false
|
event.accepted = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,6 +141,8 @@ Item {
|
|||||||
height: 36
|
height: 36
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: appLauncher.viewMode === "list" ? Theme.primaryHover : listViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
color: appLauncher.viewMode === "list" ? Theme.primaryHover : listViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
||||||
|
border.color: appLauncher.viewMode === "list" ? Theme.primarySelected : "transparent"
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -186,6 +168,8 @@ Item {
|
|||||||
height: 36
|
height: 36
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: appLauncher.viewMode === "grid" ? Theme.primaryHover : gridViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
color: appLauncher.viewMode === "grid" ? Theme.primaryHover : gridViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
||||||
|
border.color: appLauncher.viewMode === "grid" ? Theme.primarySelected : "transparent"
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -209,7 +193,6 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SpotlightResults {
|
SpotlightResults {
|
||||||
id: resultsView
|
|
||||||
appLauncher: spotlightKeyHandler.appLauncher
|
appLauncher: spotlightKeyHandler.appLauncher
|
||||||
contextMenu: contextMenu
|
contextMenu: contextMenu
|
||||||
}
|
}
|
||||||
@@ -227,7 +210,7 @@ Item {
|
|||||||
visible: contextMenu.visible
|
visible: contextMenu.visible
|
||||||
z: 999
|
z: 999
|
||||||
onClicked: () => {
|
onClicked: () => {
|
||||||
contextMenu.hide()
|
contextMenu.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -1,72 +1,65 @@
|
|||||||
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
|
||||||
|
|
||||||
Popup {
|
Rectangle {
|
||||||
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
|
||||||
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 (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 hide() {
|
function close() {
|
||||||
contextMenu.close()
|
contextMenu.menuVisible = false
|
||||||
|
Qt.callLater(() => {
|
||||||
|
contextMenu.visible = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
width: Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2)
|
visible: false
|
||||||
|
width: 180
|
||||||
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
||||||
padding: 0
|
radius: Theme.cornerRadius
|
||||||
closePolicy: Popup.CloseOnPressOutside
|
color: Theme.popupBackground()
|
||||||
modal: false
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
dim: false
|
border.width: 1
|
||||||
|
z: 1000
|
||||||
|
opacity: menuVisible ? 1 : 0
|
||||||
|
scale: menuVisible ? 1 : 0.85
|
||||||
|
|
||||||
background: Rectangle {
|
Rectangle {
|
||||||
radius: Theme.cornerRadius
|
anchors.fill: parent
|
||||||
color: Theme.popupBackground()
|
anchors.topMargin: 4
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
anchors.leftMargin: 2
|
||||||
border.width: 1
|
anchors.rightMargin: -2
|
||||||
|
anchors.bottomMargin: -4
|
||||||
Rectangle {
|
radius: parent.radius
|
||||||
anchors.fill: parent
|
color: Qt.rgba(0, 0, 0, 0.15)
|
||||||
anchors.topMargin: 4
|
z: parent.z - 1
|
||||||
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 {
|
||||||
@@ -105,10 +98,10 @@ Popup {
|
|||||||
StyledText {
|
StyledText {
|
||||||
text: {
|
text: {
|
||||||
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
|
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
|
||||||
return I18n.tr("Pin to Dock")
|
return "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) ? I18n.tr("Unpin from Dock") : I18n.tr("Pin to Dock")
|
return SessionData.isPinnedApp(appId) ? "Unpin from Dock" : "Pin to Dock"
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
@@ -132,7 +125,7 @@ Popup {
|
|||||||
SessionData.removePinnedApp(appId)
|
SessionData.removePinnedApp(appId)
|
||||||
else
|
else
|
||||||
SessionData.addPinnedApp(appId)
|
SessionData.addPinnedApp(appId)
|
||||||
contextMenu.hide()
|
contextMenu.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,82 +144,6 @@ Popup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -248,7 +165,7 @@ Popup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Launch")
|
text: "Launch"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
@@ -266,72 +183,23 @@ Popup {
|
|||||||
if (contextMenu.currentApp && appLauncher)
|
if (contextMenu.currentApp && appLauncher)
|
||||||
appLauncher.launchApp(contextMenu.currentApp)
|
appLauncher.launchApp(contextMenu.currentApp)
|
||||||
|
|
||||||
contextMenu.hide()
|
contextMenu.close()
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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,32 +18,24 @@ 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()
|
||||||
}
|
if (contentLoader.item && contentLoader.item.appLauncher) {
|
||||||
|
contentLoader.item.appLauncher.searchQuery = ""
|
||||||
onDialogClosed: {
|
contentLoader.item.appLauncher.selectedIndex = 0
|
||||||
if (contentLoader.item) {
|
contentLoader.item.appLauncher.setCategory("All")
|
||||||
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 = ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,13 +49,12 @@ DankModal {
|
|||||||
|
|
||||||
shouldBeVisible: spotlightOpen
|
shouldBeVisible: spotlightOpen
|
||||||
width: 550
|
width: 550
|
||||||
height: 700
|
height: 600
|
||||||
backgroundColor: Theme.popupBackground()
|
backgroundColor: Theme.popupBackground()
|
||||||
cornerRadius: Theme.cornerRadius
|
cornerRadius: Theme.cornerRadius
|
||||||
borderColor: Theme.outlineMedium
|
borderColor: Theme.outlineMedium
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
enableShadow: true
|
enableShadow: true
|
||||||
keepContentLoaded: true
|
|
||||||
onVisibleChanged: () => {
|
onVisibleChanged: () => {
|
||||||
if (visible && !spotlightOpen) {
|
if (visible && !spotlightOpen) {
|
||||||
show()
|
show()
|
||||||
|
|||||||
@@ -10,16 +10,12 @@ 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: Theme.surfaceContainerHigh
|
||||||
clip: true
|
border.color: Theme.outlineLight
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
DankListView {
|
DankListView {
|
||||||
id: resultsList
|
id: resultsList
|
||||||
@@ -79,7 +75,9 @@ Rectangle {
|
|||||||
width: ListView.view.width
|
width: ListView.view.width
|
||||||
height: resultsList.itemHeight
|
height: resultsList.itemHeight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : "transparent"
|
||||||
|
border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium
|
||||||
|
border.width: ListView.isCurrentItem ? 2 : 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -163,8 +161,7 @@ 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 globalPos = mapToItem(null, mouse.x, mouse.y)
|
const modalPos = mapToItem(resultsContainer.parent, 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,7 +238,9 @@ Rectangle {
|
|||||||
width: resultsGrid.cellWidth - resultsGrid.cellPadding
|
width: resultsGrid.cellWidth - resultsGrid.cellPadding
|
||||||
height: resultsGrid.cellHeight - resultsGrid.cellPadding
|
height: resultsGrid.cellHeight - resultsGrid.cellPadding
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: resultsGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
color: resultsGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : "transparent"
|
||||||
|
border.color: resultsGrid.currentIndex === index ? Theme.primarySelected : Theme.outlineMedium
|
||||||
|
border.width: resultsGrid.currentIndex === index ? 2 : 1
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -315,8 +314,7 @@ 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 globalPos = mapToItem(null, mouse.x, mouse.y)
|
const modalPos = mapToItem(resultsContainer.parent, 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,53 +9,33 @@ 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) {
|
if (contentLoader.item && contentLoader.item.passwordInput)
|
||||||
if (requiresEnterprise && contentLoader.item.usernameInput) {
|
contentLoader.item.passwordInput.forceActiveFocus()
|
||||||
contentLoader.item.usernameInput.forceActiveFocus()
|
|
||||||
} else if (contentLoader.item.passwordInput) {
|
|
||||||
contentLoader.item.passwordInput.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldBeVisible: false
|
shouldBeVisible: false
|
||||||
width: 420
|
width: 420
|
||||||
height: requiresEnterprise ? 310 : 230
|
height: 230
|
||||||
onShouldBeVisibleChanged: () => {
|
onShouldBeVisibleChanged: () => {
|
||||||
if (!shouldBeVisible) {
|
if (!shouldBeVisible)
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
wifiUsernameInput = ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
onOpened: {
|
onOpened: {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (contentLoader.item) {
|
if (contentLoader.item && contentLoader.item.passwordInput)
|
||||||
if (requiresEnterprise && contentLoader.item.usernameInput) {
|
contentLoader.item.passwordInput.forceActiveFocus()
|
||||||
contentLoader.item.usernameInput.forceActiveFocus()
|
|
||||||
} else if (contentLoader.item.passwordInput) {
|
|
||||||
contentLoader.item.passwordInput.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onBackgroundClicked: () => {
|
onBackgroundClicked: () => {
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
wifiUsernameInput = ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -75,7 +55,6 @@ 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
|
||||||
@@ -83,7 +62,6 @@ DankModal {
|
|||||||
Keys.onEscapePressed: event => {
|
Keys.onEscapePressed: event => {
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
wifiUsernameInput = ""
|
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,14 +78,14 @@ DankModal {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Connect to Wi-Fi")
|
text: "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: requiresEnterprise ? `Enter credentials for "${wifiPasswordSSID}"` : `Enter password for "${wifiPasswordSSID}"`
|
text: `Enter password for "${wifiPasswordSSID}"`
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceTextMedium
|
color: Theme.surfaceTextMedium
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -122,48 +100,10 @@ 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
|
||||||
@@ -187,24 +127,21 @@ 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: requiresEnterprise ? "Password" : ""
|
placeholderText: ""
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
focus: !requiresEnterprise
|
focus: true
|
||||||
enabled: root.shouldBeVisible
|
enabled: root.shouldBeVisible
|
||||||
onTextEdited: () => {
|
onTextEdited: () => {
|
||||||
wifiPasswordInput = text
|
wifiPasswordInput = text
|
||||||
}
|
}
|
||||||
onAccepted: () => {
|
onAccepted: () => {
|
||||||
const username = requiresEnterprise ? usernameInput.text : ""
|
NetworkService.connectToWifi(wifiPasswordSSID, passwordInput.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 && !requiresEnterprise)
|
if (root.shouldBeVisible)
|
||||||
focusDelayTimer.start()
|
focusDelayTimer.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,13 +151,8 @@ DankModal {
|
|||||||
interval: 100
|
interval: 100
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: () => {
|
onTriggered: () => {
|
||||||
if (root.shouldBeVisible) {
|
if (root.shouldBeVisible)
|
||||||
if (requiresEnterprise && usernameInput) {
|
passwordInput.forceActiveFocus()
|
||||||
usernameInput.forceActiveFocus()
|
|
||||||
} else {
|
|
||||||
passwordInput.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +201,7 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Show password")
|
text: "Show password"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -297,7 +229,7 @@ DankModal {
|
|||||||
id: cancelText
|
id: cancelText
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: I18n.tr("Cancel")
|
text: "Cancel"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -312,7 +244,6 @@ DankModal {
|
|||||||
onClicked: () => {
|
onClicked: () => {
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
wifiUsernameInput = ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,14 +253,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: requiresEnterprise ? (usernameInput.text.length > 0 && passwordInput.text.length > 0) : passwordInput.text.length > 0
|
enabled: 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: I18n.tr("Connect")
|
text: "Connect"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.background
|
color: Theme.background
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -343,13 +274,10 @@ DankModal {
|
|||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
enabled: parent.enabled
|
enabled: parent.enabled
|
||||||
onClicked: () => {
|
onClicked: () => {
|
||||||
const username = requiresEnterprise ? usernameInput.text : ""
|
NetworkService.connectToWifi(wifiPasswordSSID, passwordInput.text)
|
||||||
NetworkService.connectToWifi(wifiPasswordSSID, passwordInput.text, username)
|
|
||||||
close()
|
close()
|
||||||
wifiPasswordInput = ""
|
wifiPasswordInput = ""
|
||||||
wifiUsernameInput = ""
|
|
||||||
passwordInput.text = ""
|
passwordInput.text = ""
|
||||||
if (requiresEnterprise) usernameInput.text = ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
@@ -13,6 +12,7 @@ import qs.Widgets
|
|||||||
DankPopout {
|
DankPopout {
|
||||||
id: appDrawerPopout
|
id: appDrawerPopout
|
||||||
|
|
||||||
|
property string triggerSection: "left"
|
||||||
property var triggerScreen: null
|
property var triggerScreen: null
|
||||||
|
|
||||||
// Setting to Exclusive, so virtual keyboards can send input to app drawer
|
// Setting to Exclusive, so virtual keyboards can send input to app drawer
|
||||||
@@ -33,16 +33,16 @@ DankPopout {
|
|||||||
popupWidth: 520
|
popupWidth: 520
|
||||||
popupHeight: 600
|
popupHeight: 600
|
||||||
triggerX: Theme.spacingL
|
triggerX: Theme.spacingL
|
||||||
triggerY: Math.max(26 + SettingsData.dankBarInnerPadding + 4, Theme.barHeight - 4 - (8 - SettingsData.dankBarInnerPadding)) + SettingsData.dankBarSpacing + SettingsData.dankBarBottomGap - 2
|
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingXS
|
||||||
triggerWidth: 40
|
triggerWidth: 40
|
||||||
positioning: ""
|
positioning: "center"
|
||||||
screen: triggerScreen
|
screen: triggerScreen
|
||||||
|
|
||||||
onShouldBeVisibleChanged: {
|
onShouldBeVisibleChanged: {
|
||||||
if (shouldBeVisible) {
|
if (shouldBeVisible) {
|
||||||
appLauncher.searchQuery = ""
|
appLauncher.searchQuery = ""
|
||||||
appLauncher.selectedIndex = 0
|
appLauncher.selectedIndex = 0
|
||||||
appLauncher.setCategory(I18n.tr("All"))
|
appLauncher.setCategory("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 = ""
|
||||||
@@ -95,7 +95,7 @@ DankPopout {
|
|||||||
color: "transparent"
|
color: "transparent"
|
||||||
radius: parent.radius + Math.abs(modelData.margin)
|
radius: parent.radius + Math.abs(modelData.margin)
|
||||||
border.color: modelData.color
|
border.color: modelData.color
|
||||||
border.width: 0
|
border.width: 1
|
||||||
z: modelData.z
|
z: modelData.z
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,70 +128,38 @@ DankPopout {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === Qt.Key_N && event.modifiers & Qt.ControlModifier) {
|
if (!searchField.activeFocus && event.text && /[a-zA-Z0-9\s]/.test(event.text)) {
|
||||||
appLauncher.selectNext()
|
searchField.forceActiveFocus()
|
||||||
|
searchField.insertText(event.text)
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === Qt.Key_P && event.modifiers & Qt.ControlModifier) {
|
|
||||||
appLauncher.selectPrevious()
|
|
||||||
event.accepted = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key === Qt.Key_J && event.modifiers & Qt.ControlModifier) {
|
|
||||||
appLauncher.selectNext()
|
|
||||||
event.accepted = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key === Qt.Key_K && event.modifiers & Qt.ControlModifier) {
|
|
||||||
appLauncher.selectPrevious()
|
|
||||||
event.accepted = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appLauncher.viewMode === "grid") {
|
|
||||||
if (event.key === Qt.Key_L && event.modifiers & Qt.ControlModifier) {
|
|
||||||
appLauncher.selectNextInRow()
|
|
||||||
event.accepted = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key === Qt.Key_H && event.modifiers & Qt.ControlModifier) {
|
|
||||||
appLauncher.selectPreviousInRow()
|
|
||||||
event.accepted = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
width: parent.width - Theme.spacingS * 2
|
width: parent.width - Theme.spacingL * 2
|
||||||
height: parent.height - Theme.spacingS * 2
|
height: parent.height - Theme.spacingL * 2
|
||||||
x: Theme.spacingS
|
x: Theme.spacingL
|
||||||
y: Theme.spacingS
|
y: Theme.spacingL
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingL
|
||||||
|
|
||||||
Item {
|
Row {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 40
|
height: 40
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: I18n.tr("Applications")
|
text: "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
|
||||||
@@ -202,8 +170,7 @@ DankPopout {
|
|||||||
DankTextField {
|
DankTextField {
|
||||||
id: searchField
|
id: searchField
|
||||||
|
|
||||||
width: parent.width - Theme.spacingS * 2
|
width: parent.width
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
height: 52
|
height: 52
|
||||||
cornerRadius: Theme.cornerRadius
|
cornerRadius: Theme.cornerRadius
|
||||||
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7)
|
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7)
|
||||||
@@ -216,7 +183,7 @@ DankPopout {
|
|||||||
showClearButton: true
|
showClearButton: true
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
enabled: appDrawerPopout.shouldBeVisible
|
enabled: appDrawerPopout.shouldBeVisible
|
||||||
ignoreLeftRightKeys: appLauncher.viewMode !== "list"
|
ignoreLeftRightKeys: true
|
||||||
keyForwardTargets: [keyHandler]
|
keyForwardTargets: [keyHandler]
|
||||||
onTextEdited: {
|
onTextEdited: {
|
||||||
appLauncher.searchQuery = text
|
appLauncher.searchQuery = text
|
||||||
@@ -264,18 +231,14 @@ DankPopout {
|
|||||||
height: 40
|
height: 40
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
visible: searchField.text.length === 0
|
visible: searchField.text.length === 0
|
||||||
leftPadding: Theme.spacingS
|
|
||||||
|
|
||||||
Rectangle {
|
Item {
|
||||||
width: 180
|
width: 200
|
||||||
height: 40
|
height: 36
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
DankDropdown {
|
DankDropdown {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
text: ""
|
text: ""
|
||||||
dropdownWidth: 180
|
|
||||||
currentValue: appLauncher.selectedCategory
|
currentValue: appLauncher.selectedCategory
|
||||||
options: appLauncher.categories
|
options: appLauncher.categories
|
||||||
optionIcons: appLauncher.categoryIcons
|
optionIcons: appLauncher.categoryIcons
|
||||||
@@ -286,7 +249,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
width: parent.width - 290
|
width: parent.width - 300
|
||||||
height: 1
|
height: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,13 +286,15 @@ DankPopout {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: {
|
height: {
|
||||||
let usedHeight = 40 + Theme.spacingS
|
let usedHeight = 40 + Theme.spacingL
|
||||||
usedHeight += 52 + Theme.spacingS
|
usedHeight += 52 + Theme.spacingL
|
||||||
usedHeight += (searchField.text.length === 0 ? 40 : 0)
|
usedHeight += (searchField.text.length === 0 ? 40 + Theme.spacingL : 0)
|
||||||
return parent.height - usedHeight
|
return parent.height - usedHeight
|
||||||
}
|
}
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: "transparent"
|
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1)
|
||||||
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
DankListView {
|
DankListView {
|
||||||
id: appList
|
id: appList
|
||||||
@@ -358,9 +323,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingS
|
anchors.margins: Theme.spacingS
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
|
||||||
visible: appLauncher.viewMode === "list"
|
visible: appLauncher.viewMode === "list"
|
||||||
model: appLauncher.model
|
model: appLauncher.model
|
||||||
currentIndex: appLauncher.selectedIndex
|
currentIndex: appLauncher.selectedIndex
|
||||||
@@ -390,7 +353,9 @@ DankPopout {
|
|||||||
width: ListView.view.width
|
width: ListView.view.width
|
||||||
height: appList.itemHeight
|
height: appList.itemHeight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
|
||||||
|
border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium
|
||||||
|
border.width: ListView.isCurrentItem ? 2 : 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -406,7 +371,6 @@ DankPopout {
|
|||||||
id: listIconImg
|
id: listIconImg
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.spacingXS
|
|
||||||
source: Quickshell.iconPath(model.icon, true)
|
source: Quickshell.iconPath(model.icon, true)
|
||||||
smooth: true
|
smooth: true
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
@@ -415,13 +379,10 @@ DankPopout {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingM
|
|
||||||
visible: !listIconImg.visible
|
visible: !listIconImg.visible
|
||||||
color: Theme.surfaceLight
|
color: Theme.surfaceLight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.width: 0
|
border.width: 1
|
||||||
border.color: Theme.primarySelected
|
border.color: Theme.primarySelected
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -464,9 +425,6 @@ DankPopout {
|
|||||||
id: listMouseArea
|
id: listMouseArea
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingM
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
@@ -482,8 +440,7 @@ 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 globalPos = mapToItem(null, mouse.x, mouse.y)
|
var panelPos = mapToItem(contextMenu.parent, 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -527,9 +484,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingS
|
anchors.margins: Theme.spacingS
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
|
||||||
visible: appLauncher.viewMode === "grid"
|
visible: appLauncher.viewMode === "grid"
|
||||||
model: appLauncher.model
|
model: appLauncher.model
|
||||||
clip: true
|
clip: true
|
||||||
@@ -561,7 +516,9 @@ DankPopout {
|
|||||||
width: appGrid.cellWidth - appGrid.cellPadding
|
width: appGrid.cellWidth - appGrid.cellPadding
|
||||||
height: appGrid.cellHeight - appGrid.cellPadding
|
height: appGrid.cellHeight - appGrid.cellPadding
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: appGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
|
color: appGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
|
||||||
|
border.color: appGrid.currentIndex === index ? Theme.primarySelected : Theme.outlineMedium
|
||||||
|
border.width: appGrid.currentIndex === index ? 2 : 1
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -578,9 +535,6 @@ DankPopout {
|
|||||||
id: gridIconImg
|
id: gridIconImg
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
|
||||||
source: Quickshell.iconPath(model.icon, true)
|
source: Quickshell.iconPath(model.icon, true)
|
||||||
smooth: true
|
smooth: true
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
@@ -589,13 +543,10 @@ DankPopout {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
|
||||||
visible: !gridIconImg.visible
|
visible: !gridIconImg.visible
|
||||||
color: Theme.surfaceLight
|
color: Theme.surfaceLight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.width: 0
|
border.width: 1
|
||||||
border.color: Theme.primarySelected
|
border.color: Theme.primarySelected
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -626,9 +577,6 @@ DankPopout {
|
|||||||
id: gridMouseArea
|
id: gridMouseArea
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.bottomMargin: Theme.spacingS
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
@@ -644,8 +592,7 @@ 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 globalPos = mapToItem(null, mouse.x, mouse.y)
|
var panelPos = mapToItem(contextMenu.parent, 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -658,68 +605,68 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Popup {
|
Rectangle {
|
||||||
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
|
|
||||||
contextMenu.y = y + 4
|
const menuWidth = 180
|
||||||
contextMenu.open()
|
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
|
||||||
|
|
||||||
|
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 hide() {
|
function close() {
|
||||||
contextMenu.close()
|
contextMenu.menuVisible = false
|
||||||
|
Qt.callLater(() => {
|
||||||
|
contextMenu.visible = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
width: Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2)
|
visible: false
|
||||||
|
width: 180
|
||||||
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
||||||
padding: 0
|
radius: Theme.cornerRadius
|
||||||
closePolicy: Popup.CloseOnPressOutside
|
color: Theme.popupBackground()
|
||||||
modal: false
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
dim: false
|
border.width: 1
|
||||||
|
z: 1000
|
||||||
|
opacity: menuVisible ? 1 : 0
|
||||||
|
scale: menuVisible ? 1 : 0.85
|
||||||
|
|
||||||
background: Rectangle {
|
Rectangle {
|
||||||
radius: Theme.cornerRadius
|
anchors.fill: parent
|
||||||
color: Theme.popupBackground()
|
anchors.topMargin: 4
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
anchors.leftMargin: 2
|
||||||
border.width: 1
|
anchors.rightMargin: -2
|
||||||
|
anchors.bottomMargin: -4
|
||||||
Rectangle {
|
radius: parent.radius
|
||||||
anchors.fill: parent
|
color: Qt.rgba(0, 0, 0, 0.15)
|
||||||
anchors.topMargin: 4
|
z: parent.z - 1
|
||||||
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 {
|
||||||
@@ -750,7 +697,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: contextMenu.isPinned ? I18n.tr("Unpin from Dock") : I18n.tr("Pin to Dock")
|
text: contextMenu.isPinned ? "Unpin from Dock" : "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
|
||||||
@@ -774,7 +721,7 @@ DankPopout {
|
|||||||
} else {
|
} else {
|
||||||
SessionData.addPinnedApp(contextMenu.appId)
|
SessionData.addPinnedApp(contextMenu.appId)
|
||||||
}
|
}
|
||||||
contextMenu.hide()
|
contextMenu.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -793,76 +740,6 @@ 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
|
||||||
@@ -884,7 +761,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Launch")
|
text: "Launch"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Normal
|
font.weight: Font.Normal
|
||||||
@@ -902,70 +779,23 @@ DankPopout {
|
|||||||
if (contextMenu.currentApp)
|
if (contextMenu.currentApp)
|
||||||
appLauncher.launchApp(contextMenu.currentApp)
|
appLauncher.launchApp(contextMenu.currentApp)
|
||||||
|
|
||||||
contextMenu.hide()
|
contextMenu.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Behavior on opacity {
|
||||||
visible: SessionService.hasPrimeRun
|
NumberAnimation {
|
||||||
width: parent.width - Theme.spacingS * 2
|
duration: Theme.mediumDuration
|
||||||
height: 5
|
easing.type: Theme.emphasizedEasing
|
||||||
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 {
|
Behavior on scale {
|
||||||
visible: SessionService.hasPrimeRun
|
NumberAnimation {
|
||||||
width: parent.width
|
duration: Theme.mediumDuration
|
||||||
height: 32
|
easing.type: Theme.emphasizedEasing
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -975,7 +805,7 @@ DankPopout {
|
|||||||
visible: contextMenu.visible
|
visible: contextMenu.visible
|
||||||
z: 999
|
z: 999
|
||||||
onClicked: {
|
onClicked: {
|
||||||
contextMenu.hide()
|
contextMenu.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Item {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string searchQuery: ""
|
property string searchQuery: ""
|
||||||
property string selectedCategory: I18n.tr("All")
|
property string selectedCategory: "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 = [I18n.tr("All")]
|
const result = ["All"]
|
||||||
return result.concat(allCategories.filter(cat => cat !== I18n.tr("All")))
|
return result.concat(allCategories.filter(cat => cat !== "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,11 +42,10 @@ Item {
|
|||||||
keyboardNavigationActive = false
|
keyboardNavigationActive = false
|
||||||
|
|
||||||
let apps = []
|
let apps = []
|
||||||
const allCategory = I18n.tr("All")
|
|
||||||
if (searchQuery.length === 0) {
|
if (searchQuery.length === 0) {
|
||||||
apps = selectedCategory === allCategory ? AppSearchService.getAppsInCategory(allCategory) : AppSearchService.getAppsInCategory(selectedCategory).slice(0, maxResults)
|
apps = selectedCategory === "All" ? AppSearchService.getAppsInCategory("All") : AppSearchService.getAppsInCategory(selectedCategory).slice(0, maxResults)
|
||||||
} else {
|
} else {
|
||||||
if (selectedCategory === allCategory) {
|
if (selectedCategory === "All") {
|
||||||
apps = AppSearchService.searchApplications(searchQuery)
|
apps = AppSearchService.searchApplications(searchQuery)
|
||||||
} else {
|
} else {
|
||||||
const categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
|
const categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
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: I18n.tr("All")
|
property string selectedCategory: "All"
|
||||||
property bool compact: false
|
property bool compact: false
|
||||||
|
|
||||||
signal categorySelected(string category)
|
signal categorySelected(string category)
|
||||||
@@ -16,9 +15,10 @@ Item {
|
|||||||
readonly property int maxCompactItems: 8
|
readonly property int maxCompactItems: 8
|
||||||
readonly property int itemHeight: 36
|
readonly property int itemHeight: 36
|
||||||
readonly property color selectedBorderColor: "transparent"
|
readonly property color selectedBorderColor: "transparent"
|
||||||
readonly property color unselectedBorderColor: "transparent"
|
readonly property color unselectedBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
|
||||||
|
|
||||||
function handleCategoryClick(category) {
|
function handleCategoryClick(category) {
|
||||||
|
selectedCategory = category
|
||||||
categorySelected(category)
|
categorySelected(category)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,8 @@ Item {
|
|||||||
height: root.itemHeight
|
height: root.itemHeight
|
||||||
width: root.getButtonWidth(itemCount, parent.width)
|
width: root.getButtonWidth(itemCount, parent.width)
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: selectedCategory === modelData ? Theme.primary : Theme.surfaceContainerHigh
|
color: selectedCategory === modelData ? Theme.primary : "transparent"
|
||||||
|
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -81,7 +82,7 @@ Item {
|
|||||||
height: root.itemHeight
|
height: root.itemHeight
|
||||||
width: root.getButtonWidth(itemCount, parent.width)
|
width: root.getButtonWidth(itemCount, parent.width)
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: selectedCategory === modelData ? Theme.primary : Theme.surfaceContainerHigh
|
color: selectedCategory === modelData ? Theme.primary : "transparent"
|
||||||
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
|
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -117,7 +118,7 @@ Item {
|
|||||||
height: root.itemHeight
|
height: root.itemHeight
|
||||||
width: root.getButtonWidth(itemCount, parent.width)
|
width: root.getButtonWidth(itemCount, parent.width)
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: selectedCategory === modelData ? Theme.primary : Theme.surfaceContainerHigh
|
color: selectedCategory === modelData ? Theme.primary : "transparent"
|
||||||
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
|
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
|
|||||||
@@ -1,246 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -59,7 +59,7 @@ Rectangle {
|
|||||||
DankIcon {
|
DankIcon {
|
||||||
name: root.iconName
|
name: root.iconName
|
||||||
size: Theme.iconSize
|
size: Theme.iconSize
|
||||||
color: isActive ? Theme.primaryText : Theme.primary
|
color: isActive ? Theme.primaryContainer : Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
text: root.text
|
text: root.text
|
||||||
style: Typography.Style.Body
|
style: Typography.Style.Body
|
||||||
color: isActive ? Theme.primaryText : Theme.surfaceText
|
color: isActive ? Theme.primaryContainer : Theme.surfaceText
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
text: root.secondaryText
|
text: root.secondaryText
|
||||||
style: Typography.Style.Caption
|
style: Typography.Style.Caption
|
||||||
color: isActive ? Theme.primaryText : Theme.surfaceVariantText
|
color: isActive ? Theme.primaryContainer : Theme.surfaceVariantText
|
||||||
visible: text.length > 0
|
visible: text.length > 0
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
|
|||||||
@@ -1,107 +1,38 @@
|
|||||||
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
|
||||||
|
|
||||||
property string expandedSection: ""
|
property string expandedSection: ""
|
||||||
property var expandedWidgetData: null
|
property var expandedWidgetData: 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: false
|
active: parent.height > 0
|
||||||
sourceComponent: null
|
property string sectionKey: root.expandedSection
|
||||||
}
|
sourceComponent: {
|
||||||
|
switch (root.expandedSection) {
|
||||||
Loader {
|
case "network":
|
||||||
id: coreDetailLoader
|
case "wifi": return networkDetailComponent
|
||||||
width: parent.width
|
case "bluetooth": return bluetoothDetailComponent
|
||||||
height: 250
|
case "audioOutput": return audioOutputDetailComponent
|
||||||
y: Theme.spacingS
|
case "audioInput": return audioInputDetailComponent
|
||||||
active: false
|
case "battery": return batteryDetailComponent
|
||||||
sourceComponent: null
|
default:
|
||||||
}
|
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
|
|
||||||
}
|
}
|
||||||
builtinInstance = widgetModel.vpnBuiltinInstance
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!builtinInstance || !builtinInstance.ccDetailContent) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginDetailLoader.sourceComponent = builtinInstance.ccDetailContent
|
|
||||||
pluginDetailLoader.active = parent.height > 0
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
onSectionKeyChanged: {
|
||||||
if (root.expandedSection.startsWith("plugin_")) {
|
active = false
|
||||||
const pluginId = root.expandedSection.replace("plugin_", "")
|
active = true
|
||||||
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 {
|
||||||
@@ -111,17 +42,7 @@ Item {
|
|||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: bluetoothDetailComponent
|
id: bluetoothDetailComponent
|
||||||
BluetoothDetail {
|
BluetoothDetail {}
|
||||||
id: bluetoothDetail
|
|
||||||
onShowCodecSelector: function(device) {
|
|
||||||
if (root.bluetoothCodecSelector) {
|
|
||||||
root.bluetoothCodecSelector.show(device)
|
|
||||||
root.bluetoothCodecSelector.codecSelected.connect(function(deviceAddress, codecName) {
|
|
||||||
bluetoothDetail.updateDeviceCodecDisplay(deviceAddress, codecName)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Modules.ControlCenter.Details
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property string expandedSection: ""
|
|
||||||
property var expandedWidgetData: null
|
|
||||||
|
|
||||||
height: active ? 250 : 0
|
|
||||||
visible: active
|
|
||||||
|
|
||||||
readonly property bool active: expandedSection !== ""
|
|
||||||
|
|
||||||
Behavior on height {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.mediumDuration
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.topMargin: Theme.spacingS
|
|
||||||
sourceComponent: {
|
|
||||||
if (!root.active) return null
|
|
||||||
|
|
||||||
if (expandedSection.startsWith("diskUsage_")) {
|
|
||||||
return diskUsageDetailComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (expandedSection) {
|
|
||||||
case "wifi": return networkDetailComponent
|
|
||||||
case "bluetooth": return bluetoothDetailComponent
|
|
||||||
case "audioOutput": return audioOutputDetailComponent
|
|
||||||
case "audioInput": return audioInputDetailComponent
|
|
||||||
case "battery": return batteryDetailComponent
|
|
||||||
default: return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: networkDetailComponent
|
|
||||||
NetworkDetail {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: bluetoothDetailComponent
|
|
||||||
BluetoothDetail {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: audioOutputDetailComponent
|
|
||||||
AudioOutputDetail {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: audioInputDetailComponent
|
|
||||||
AudioInputDetail {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: batteryDetailComponent
|
|
||||||
BatteryDetail {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: diskUsageDetailComponent
|
|
||||||
DiskUsageDetail {
|
|
||||||
currentMountPath: root.expandedWidgetData?.mountPath || "/"
|
|
||||||
instanceId: root.expandedWidgetData?.instanceId || ""
|
|
||||||
|
|
||||||
onMountPathChanged: (newMountPath) => {
|
|
||||||
if (root.expandedWidgetData && root.expandedWidgetData.id === "diskUsage") {
|
|
||||||
const widgets = SettingsData.controlCenterWidgets || []
|
|
||||||
const newWidgets = widgets.map(w => {
|
|
||||||
if (w.id === "diskUsage" && w.instanceId === root.expandedWidgetData.instanceId) {
|
|
||||||
const updatedWidget = Object.assign({}, w)
|
|
||||||
updatedWidget.mountPath = newMountPath
|
|
||||||
return updatedWidget
|
|
||||||
}
|
|
||||||
return w
|
|
||||||
})
|
|
||||||
SettingsData.setControlCenterWidgets(newWidgets)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,979 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Modules.ControlCenter.Widgets
|
|
||||||
import qs.Modules.ControlCenter.Components
|
|
||||||
import "../utils/layout.js" as LayoutUtils
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool editMode: false
|
|
||||||
property string expandedSection: ""
|
|
||||||
property int expandedWidgetIndex: -1
|
|
||||||
property var model: null
|
|
||||||
property var expandedWidgetData: null
|
|
||||||
property var bluetoothCodecSelector: null
|
|
||||||
property bool darkModeTransitionPending: false
|
|
||||||
|
|
||||||
signal expandClicked(var widgetData, int globalIndex)
|
|
||||||
signal removeWidget(int index)
|
|
||||||
signal moveWidget(int fromIndex, int toIndex)
|
|
||||||
signal toggleWidgetSize(int index)
|
|
||||||
|
|
||||||
spacing: editMode ? Theme.spacingL : Theme.spacingS
|
|
||||||
|
|
||||||
property var currentRowWidgets: []
|
|
||||||
property real currentRowWidth: 0
|
|
||||||
property int expandedRowIndex: -1
|
|
||||||
property var colorPickerModal: null
|
|
||||||
|
|
||||||
function calculateRowsAndWidgets() {
|
|
||||||
return LayoutUtils.calculateRowsAndWidgets(root, expandedSection, expandedWidgetIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
property var layoutResult: {
|
|
||||||
const dummy = [expandedSection, expandedWidgetIndex, model?.controlCenterWidgets]
|
|
||||||
return calculateRowsAndWidgets()
|
|
||||||
}
|
|
||||||
|
|
||||||
onLayoutResultChanged: {
|
|
||||||
expandedRowIndex = layoutResult.expandedRowIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveToTop(item) {
|
|
||||||
const children = root.children
|
|
||||||
for (var i = 0; i < children.length; i++) {
|
|
||||||
if (children[i] === item)
|
|
||||||
continue
|
|
||||||
if (children[i].z)
|
|
||||||
children[i].z = Math.min(children[i].z, 999)
|
|
||||||
}
|
|
||||||
item.z = 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: root.layoutResult.rows
|
|
||||||
|
|
||||||
Column {
|
|
||||||
width: root.width
|
|
||||||
spacing: 0
|
|
||||||
property int rowIndex: index
|
|
||||||
property var rowWidgets: modelData
|
|
||||||
property bool isSliderOnlyRow: {
|
|
||||||
const widgets = rowWidgets || []
|
|
||||||
if (widgets.length === 0)
|
|
||||||
return false
|
|
||||||
return widgets.every(w => w.id === "volumeSlider" || w.id === "brightnessSlider" || w.id === "inputVolumeSlider")
|
|
||||||
}
|
|
||||||
topPadding: isSliderOnlyRow ? (root.editMode ? 4 : -6) : 0
|
|
||||||
bottomPadding: isSliderOnlyRow ? (root.editMode ? 4 : -6) : 0
|
|
||||||
|
|
||||||
Flow {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: rowWidgets || []
|
|
||||||
|
|
||||||
DragDropWidgetWrapper {
|
|
||||||
widgetData: modelData
|
|
||||||
property int globalWidgetIndex: {
|
|
||||||
const widgets = SettingsData.controlCenterWidgets || []
|
|
||||||
for (var i = 0; i < widgets.length; i++) {
|
|
||||||
if (widgets[i].id === modelData.id) {
|
|
||||||
if (modelData.id === "diskUsage") {
|
|
||||||
if (widgets[i].instanceId === modelData.instanceId) {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
property int widgetWidth: modelData.width || 50
|
|
||||||
width: {
|
|
||||||
const baseWidth = root.width
|
|
||||||
const spacing = Theme.spacingS
|
|
||||||
if (widgetWidth <= 25) {
|
|
||||||
return (baseWidth - spacing * 3) / 4
|
|
||||||
} else if (widgetWidth <= 50) {
|
|
||||||
return (baseWidth - spacing) / 2
|
|
||||||
} else if (widgetWidth <= 75) {
|
|
||||||
return (baseWidth - spacing * 2) * 0.75
|
|
||||||
} else {
|
|
||||||
return baseWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
height: isSliderOnlyRow ? 48 : 60
|
|
||||||
|
|
||||||
editMode: root.editMode
|
|
||||||
widgetIndex: globalWidgetIndex
|
|
||||||
gridCellWidth: width
|
|
||||||
gridCellHeight: height
|
|
||||||
gridColumns: 4
|
|
||||||
gridLayout: root
|
|
||||||
isSlider: {
|
|
||||||
const id = modelData.id || ""
|
|
||||||
return id === "volumeSlider" || id === "brightnessSlider" || id === "inputVolumeSlider"
|
|
||||||
}
|
|
||||||
|
|
||||||
widgetComponent: {
|
|
||||||
const id = modelData.id || ""
|
|
||||||
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
|
|
||||||
} else if (id === "volumeSlider") {
|
|
||||||
return audioSliderComponent
|
|
||||||
} else if (id === "brightnessSlider") {
|
|
||||||
return brightnessSliderComponent
|
|
||||||
} else if (id === "inputVolumeSlider") {
|
|
||||||
return inputAudioSliderComponent
|
|
||||||
} else if (id === "battery") {
|
|
||||||
return widgetWidth <= 25 ? smallBatteryComponent : batteryPillComponent
|
|
||||||
} else if (id === "diskUsage") {
|
|
||||||
return diskUsagePillComponent
|
|
||||||
} else if (id === "colorPicker") {
|
|
||||||
return colorPickerPillComponent
|
|
||||||
} else {
|
|
||||||
return widgetWidth <= 25 ? smallToggleComponent : toggleButtonComponent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onWidgetMoved: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
|
||||||
onRemoveWidget: index => root.removeWidget(index)
|
|
||||||
onToggleWidgetSize: index => root.toggleWidgetSize(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DetailHost {
|
|
||||||
width: parent.width
|
|
||||||
height: active ? (250 + Theme.spacingS) : 0
|
|
||||||
property bool active: {
|
|
||||||
if (root.expandedSection === "")
|
|
||||||
return false
|
|
||||||
|
|
||||||
if (root.expandedSection.startsWith("diskUsage_") && root.expandedWidgetData) {
|
|
||||||
const expandedInstanceId = root.expandedWidgetData.instanceId
|
|
||||||
return rowWidgets.some(w => w.id === "diskUsage" && w.instanceId === expandedInstanceId)
|
|
||||||
}
|
|
||||||
|
|
||||||
return rowIndex === root.expandedRowIndex
|
|
||||||
}
|
|
||||||
visible: active
|
|
||||||
expandedSection: root.expandedSection
|
|
||||||
expandedWidgetData: root.expandedWidgetData
|
|
||||||
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 {
|
|
||||||
id: compoundPillComponent
|
|
||||||
CompoundPill {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
|
|
||||||
width: parent.width
|
|
||||||
height: 60
|
|
||||||
iconName: {
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "wifi":
|
|
||||||
{
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
case "bluetooth":
|
|
||||||
{
|
|
||||||
if (!BluetoothService.available)
|
|
||||||
return "bluetooth_disabled"
|
|
||||||
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled)
|
|
||||||
return "bluetooth_disabled"
|
|
||||||
const primaryDevice = (() => {
|
|
||||||
if (!BluetoothService.adapter || !BluetoothService.adapter.devices)
|
|
||||||
return null
|
|
||||||
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
|
|
||||||
for (let device of devices) {
|
|
||||||
if (device && device.connected)
|
|
||||||
return device
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
})()
|
|
||||||
if (primaryDevice)
|
|
||||||
return BluetoothService.getDeviceIcon(primaryDevice)
|
|
||||||
return "bluetooth"
|
|
||||||
}
|
|
||||||
case "audioOutput":
|
|
||||||
{
|
|
||||||
if (!AudioService.sink)
|
|
||||||
return "volume_off"
|
|
||||||
let volume = AudioService.sink.audio.volume
|
|
||||||
let muted = AudioService.sink.audio.muted
|
|
||||||
if (muted || volume === 0.0)
|
|
||||||
return "volume_off"
|
|
||||||
if (volume <= 0.33)
|
|
||||||
return "volume_down"
|
|
||||||
if (volume <= 0.66)
|
|
||||||
return "volume_up"
|
|
||||||
return "volume_up"
|
|
||||||
}
|
|
||||||
case "audioInput":
|
|
||||||
{
|
|
||||||
if (!AudioService.source)
|
|
||||||
return "mic_off"
|
|
||||||
let muted = AudioService.source.audio.muted
|
|
||||||
return muted ? "mic_off" : "mic"
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return widgetDef?.icon || "help"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
primaryText: {
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "wifi":
|
|
||||||
{
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
case "bluetooth":
|
|
||||||
{
|
|
||||||
if (!BluetoothService.available)
|
|
||||||
return "Bluetooth"
|
|
||||||
if (!BluetoothService.adapter)
|
|
||||||
return "No adapter"
|
|
||||||
if (!BluetoothService.adapter.enabled)
|
|
||||||
return "Disabled"
|
|
||||||
return "Enabled"
|
|
||||||
}
|
|
||||||
case "audioOutput":
|
|
||||||
return AudioService.sink?.description || "No output device"
|
|
||||||
case "audioInput":
|
|
||||||
return AudioService.source?.description || "No input device"
|
|
||||||
default:
|
|
||||||
return widgetDef?.text || "Unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
secondaryText: {
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "wifi":
|
|
||||||
{
|
|
||||||
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 ""
|
|
||||||
}
|
|
||||||
case "bluetooth":
|
|
||||||
{
|
|
||||||
if (!BluetoothService.available)
|
|
||||||
return "No adapters"
|
|
||||||
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled)
|
|
||||||
return "Off"
|
|
||||||
const primaryDevice = (() => {
|
|
||||||
if (!BluetoothService.adapter || !BluetoothService.adapter.devices)
|
|
||||||
return null
|
|
||||||
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
|
|
||||||
for (let device of devices) {
|
|
||||||
if (device && device.connected)
|
|
||||||
return device
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
})()
|
|
||||||
if (primaryDevice)
|
|
||||||
return primaryDevice.name || primaryDevice.alias || primaryDevice.deviceName || "Connected Device"
|
|
||||||
return "No devices"
|
|
||||||
}
|
|
||||||
case "audioOutput":
|
|
||||||
{
|
|
||||||
if (!AudioService.sink)
|
|
||||||
return "Select device"
|
|
||||||
if (AudioService.sink.audio.muted)
|
|
||||||
return "Muted"
|
|
||||||
return Math.round(AudioService.sink.audio.volume * 100) + "%"
|
|
||||||
}
|
|
||||||
case "audioInput":
|
|
||||||
{
|
|
||||||
if (!AudioService.source)
|
|
||||||
return "Select device"
|
|
||||||
if (AudioService.source.audio.muted)
|
|
||||||
return "Muted"
|
|
||||||
return Math.round(AudioService.source.audio.volume * 100) + "%"
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return widgetDef?.description || ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
isActive: {
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "wifi":
|
|
||||||
{
|
|
||||||
if (NetworkService.wifiToggling)
|
|
||||||
return false
|
|
||||||
if (NetworkService.networkStatus === "ethernet")
|
|
||||||
return true
|
|
||||||
if (NetworkService.networkStatus === "wifi")
|
|
||||||
return true
|
|
||||||
return NetworkService.wifiEnabled
|
|
||||||
}
|
|
||||||
case "bluetooth":
|
|
||||||
return !!(BluetoothService.available && BluetoothService.adapter && BluetoothService.adapter.enabled)
|
|
||||||
case "audioOutput":
|
|
||||||
return !!(AudioService.sink && !AudioService.sink.audio.muted)
|
|
||||||
case "audioInput":
|
|
||||||
return !!(AudioService.source && !AudioService.source.audio.muted)
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enabled: widgetDef?.enabled ?? true
|
|
||||||
onToggled: {
|
|
||||||
if (root.editMode)
|
|
||||||
return
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "wifi":
|
|
||||||
{
|
|
||||||
if (NetworkService.networkStatus !== "ethernet" && !NetworkService.wifiToggling) {
|
|
||||||
NetworkService.toggleWifiRadio()
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case "bluetooth":
|
|
||||||
{
|
|
||||||
if (BluetoothService.available && BluetoothService.adapter) {
|
|
||||||
BluetoothService.adapter.enabled = !BluetoothService.adapter.enabled
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case "audioOutput":
|
|
||||||
{
|
|
||||||
if (AudioService.sink && AudioService.sink.audio) {
|
|
||||||
AudioService.sink.audio.muted = !AudioService.sink.audio.muted
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case "audioInput":
|
|
||||||
{
|
|
||||||
if (AudioService.source && AudioService.source.audio) {
|
|
||||||
AudioService.source.audio.muted = !AudioService.source.audio.muted
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onExpandClicked: {
|
|
||||||
if (root.editMode)
|
|
||||||
return
|
|
||||||
root.expandClicked(widgetData, widgetIndex)
|
|
||||||
}
|
|
||||||
onWheelEvent: function (wheelEvent) {
|
|
||||||
if (root.editMode)
|
|
||||||
return
|
|
||||||
const id = widgetData.id || ""
|
|
||||||
if (id === "audioOutput") {
|
|
||||||
if (!AudioService.sink || !AudioService.sink.audio)
|
|
||||||
return
|
|
||||||
let delta = wheelEvent.angleDelta.y
|
|
||||||
let currentVolume = AudioService.sink.audio.volume * 100
|
|
||||||
let newVolume
|
|
||||||
if (delta > 0)
|
|
||||||
newVolume = Math.min(100, currentVolume + 5)
|
|
||||||
else
|
|
||||||
newVolume = Math.max(0, currentVolume - 5)
|
|
||||||
AudioService.sink.audio.muted = false
|
|
||||||
AudioService.sink.audio.volume = newVolume / 100
|
|
||||||
wheelEvent.accepted = true
|
|
||||||
} else if (id === "audioInput") {
|
|
||||||
if (!AudioService.source || !AudioService.source.audio)
|
|
||||||
return
|
|
||||||
let delta = wheelEvent.angleDelta.y
|
|
||||||
let currentVolume = AudioService.source.audio.volume * 100
|
|
||||||
let newVolume
|
|
||||||
if (delta > 0)
|
|
||||||
newVolume = Math.min(100, currentVolume + 5)
|
|
||||||
else
|
|
||||||
newVolume = Math.max(0, currentVolume - 5)
|
|
||||||
AudioService.source.audio.muted = false
|
|
||||||
AudioService.source.audio.volume = newVolume / 100
|
|
||||||
wheelEvent.accepted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: audioSliderComponent
|
|
||||||
Item {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
width: parent.width
|
|
||||||
height: 16
|
|
||||||
|
|
||||||
AudioSliderRow {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: parent.width
|
|
||||||
height: 14
|
|
||||||
property color sliderTrackColor: Theme.surfaceContainerHigh
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: brightnessSliderComponent
|
|
||||||
Item {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
width: parent.width
|
|
||||||
height: 16
|
|
||||||
|
|
||||||
BrightnessSliderRow {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: parent.width
|
|
||||||
height: 14
|
|
||||||
property color sliderTrackColor: Theme.surfaceContainerHigh
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: inputAudioSliderComponent
|
|
||||||
Item {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
width: parent.width
|
|
||||||
height: 16
|
|
||||||
|
|
||||||
InputAudioSliderRow {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: parent.width
|
|
||||||
height: 14
|
|
||||||
property color sliderTrackColor: Theme.surfaceContainerHigh
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: batteryPillComponent
|
|
||||||
BatteryPill {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
width: parent.width
|
|
||||||
height: 60
|
|
||||||
|
|
||||||
onExpandClicked: {
|
|
||||||
if (!root.editMode) {
|
|
||||||
root.expandClicked(widgetData, widgetIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: smallBatteryComponent
|
|
||||||
SmallBatteryButton {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
width: parent.width
|
|
||||||
height: 48
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (!root.editMode) {
|
|
||||||
root.expandClicked(widgetData, widgetIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: toggleButtonComponent
|
|
||||||
ToggleButton {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
width: parent.width
|
|
||||||
height: 60
|
|
||||||
|
|
||||||
iconName: {
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "nightMode":
|
|
||||||
return DisplayService.nightModeEnabled ? "nightlight" : "dark_mode"
|
|
||||||
case "darkMode":
|
|
||||||
return "contrast"
|
|
||||||
case "doNotDisturb":
|
|
||||||
return SessionData.doNotDisturb ? "do_not_disturb_on" : "do_not_disturb_off"
|
|
||||||
case "idleInhibitor":
|
|
||||||
return SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
|
|
||||||
default:
|
|
||||||
return "help"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
text: {
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "nightMode":
|
|
||||||
return "Night Mode"
|
|
||||||
case "darkMode":
|
|
||||||
return SessionData.isLightMode ? "Light Mode" : "Dark Mode"
|
|
||||||
case "doNotDisturb":
|
|
||||||
return "Do Not Disturb"
|
|
||||||
case "idleInhibitor":
|
|
||||||
return SessionService.idleInhibited ? "Keeping Awake" : "Keep Awake"
|
|
||||||
default:
|
|
||||||
return "Unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iconRotation: {
|
|
||||||
if (widgetData.id !== "darkMode")
|
|
||||||
return 0
|
|
||||||
if (darkModeTransitionPending) {
|
|
||||||
return SessionData.isLightMode ? 180 : 0
|
|
||||||
}
|
|
||||||
return SessionData.isLightMode ? 180 : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
isActive: {
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "nightMode":
|
|
||||||
return DisplayService.nightModeEnabled || false
|
|
||||||
case "darkMode":
|
|
||||||
return SessionData.isLightMode
|
|
||||||
case "doNotDisturb":
|
|
||||||
return SessionData.doNotDisturb || false
|
|
||||||
case "idleInhibitor":
|
|
||||||
return SessionService.idleInhibited || false
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled: !root.editMode
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (root.editMode)
|
|
||||||
return
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "nightMode":
|
|
||||||
{
|
|
||||||
if (DisplayService.automationAvailable)
|
|
||||||
DisplayService.toggleNightMode()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case "darkMode":
|
|
||||||
{
|
|
||||||
Theme.screenTransition()
|
|
||||||
Theme.setLightMode(!SessionData.isLightMode)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case "doNotDisturb":
|
|
||||||
{
|
|
||||||
SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case "idleInhibitor":
|
|
||||||
{
|
|
||||||
SessionService.toggleIdleInhibit()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: smallToggleComponent
|
|
||||||
SmallToggleButton {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
width: parent.width
|
|
||||||
height: 48
|
|
||||||
|
|
||||||
iconName: {
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "nightMode":
|
|
||||||
return DisplayService.nightModeEnabled ? "nightlight" : "dark_mode"
|
|
||||||
case "darkMode":
|
|
||||||
return "contrast"
|
|
||||||
case "doNotDisturb":
|
|
||||||
return SessionData.doNotDisturb ? "do_not_disturb_on" : "do_not_disturb_off"
|
|
||||||
case "idleInhibitor":
|
|
||||||
return SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
|
|
||||||
default:
|
|
||||||
return "help"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iconRotation: {
|
|
||||||
if (widgetData.id !== "darkMode")
|
|
||||||
return 0
|
|
||||||
if (darkModeTransitionPending) {
|
|
||||||
return SessionData.isLightMode ? 180 : 0
|
|
||||||
}
|
|
||||||
return SessionData.isLightMode ? 180 : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
isActive: {
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "nightMode":
|
|
||||||
return DisplayService.nightModeEnabled || false
|
|
||||||
case "darkMode":
|
|
||||||
return SessionData.isLightMode
|
|
||||||
case "doNotDisturb":
|
|
||||||
return SessionData.doNotDisturb || false
|
|
||||||
case "idleInhibitor":
|
|
||||||
return SessionService.idleInhibited || false
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled: !root.editMode
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (root.editMode)
|
|
||||||
return
|
|
||||||
switch (widgetData.id || "") {
|
|
||||||
case "nightMode":
|
|
||||||
{
|
|
||||||
if (DisplayService.automationAvailable)
|
|
||||||
DisplayService.toggleNightMode()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case "darkMode":
|
|
||||||
{
|
|
||||||
Theme.screenTransition()
|
|
||||||
Theme.setLightMode(!SessionData.isLightMode)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case "doNotDisturb":
|
|
||||||
{
|
|
||||||
SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case "idleInhibitor":
|
|
||||||
{
|
|
||||||
SessionService.toggleIdleInhibit()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: diskUsagePillComponent
|
|
||||||
DiskUsagePill {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
width: parent.width
|
|
||||||
height: 60
|
|
||||||
|
|
||||||
mountPath: widgetData.mountPath || "/"
|
|
||||||
instanceId: widgetData.instanceId || ""
|
|
||||||
|
|
||||||
onExpandClicked: {
|
|
||||||
if (!root.editMode) {
|
|
||||||
root.expandClicked(widgetData, widgetIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: colorPickerPillComponent
|
|
||||||
ColorPickerPill {
|
|
||||||
property var widgetData: parent.widgetData || {}
|
|
||||||
property int widgetIndex: parent.widgetIndex || 0
|
|
||||||
width: parent.width
|
|
||||||
height: 60
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,289 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool editMode: false
|
|
||||||
property var widgetData: null
|
|
||||||
property int widgetIndex: -1
|
|
||||||
property bool isSlider: false
|
|
||||||
property Component widgetComponent: null
|
|
||||||
property real gridCellWidth: 100
|
|
||||||
property real gridCellHeight: 60
|
|
||||||
property int gridColumns: 4
|
|
||||||
property var gridLayout: null
|
|
||||||
|
|
||||||
z: dragArea.drag.active ? 10000 : 1
|
|
||||||
|
|
||||||
signal widgetMoved(int fromIndex, int toIndex)
|
|
||||||
signal removeWidget(int index)
|
|
||||||
signal toggleWidgetSize(int index)
|
|
||||||
|
|
||||||
width: {
|
|
||||||
const widgetWidth = widgetData?.width || 50
|
|
||||||
if (widgetWidth <= 25) return gridCellWidth
|
|
||||||
else if (widgetWidth <= 50) return gridCellWidth * 2
|
|
||||||
else if (widgetWidth <= 75) return gridCellWidth * 3
|
|
||||||
else return gridCellWidth * 4
|
|
||||||
}
|
|
||||||
height: isSlider ? 16 : gridCellHeight
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: dragIndicator
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "transparent"
|
|
||||||
border.color: Theme.primary
|
|
||||||
border.width: dragArea.drag.active ? 2 : 0
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
opacity: dragArea.drag.active ? 0.8 : 1.0
|
|
||||||
z: dragArea.drag.active ? 10000 : 1
|
|
||||||
|
|
||||||
Behavior on border.width {
|
|
||||||
NumberAnimation { duration: 150 }
|
|
||||||
}
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation { duration: 150 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: widgetLoader
|
|
||||||
anchors.fill: parent
|
|
||||||
sourceComponent: widgetComponent
|
|
||||||
property var widgetData: root.widgetData
|
|
||||||
property int widgetIndex: root.widgetIndex
|
|
||||||
property int globalWidgetIndex: root.widgetIndex
|
|
||||||
property int widgetWidth: root.widgetData?.width || 50
|
|
||||||
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: editModeBlocker
|
|
||||||
anchors.fill: parent
|
|
||||||
enabled: root.editMode
|
|
||||||
acceptedButtons: Qt.AllButtons
|
|
||||||
onPressed: function(mouse) { mouse.accepted = true }
|
|
||||||
onWheel: function(wheel) { wheel.accepted = true }
|
|
||||||
z: 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: dragArea
|
|
||||||
anchors.fill: parent
|
|
||||||
enabled: editMode
|
|
||||||
cursorShape: editMode ? Qt.OpenHandCursor : Qt.PointingHandCursor
|
|
||||||
drag.target: editMode ? root : null
|
|
||||||
drag.axis: Drag.XAndYAxis
|
|
||||||
drag.smoothed: true
|
|
||||||
|
|
||||||
onPressed: function(mouse) {
|
|
||||||
if (editMode) {
|
|
||||||
cursorShape = Qt.ClosedHandCursor
|
|
||||||
if (root.gridLayout && root.gridLayout.moveToTop) {
|
|
||||||
root.gridLayout.moveToTop(root)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onReleased: function(mouse) {
|
|
||||||
if (editMode) {
|
|
||||||
cursorShape = Qt.OpenHandCursor
|
|
||||||
root.snapToGrid()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Drag.active: dragArea.drag.active
|
|
||||||
Drag.hotSpot.x: width / 2
|
|
||||||
Drag.hotSpot.y: height / 2
|
|
||||||
|
|
||||||
function swapIndices(i, j) {
|
|
||||||
if (i === j) return;
|
|
||||||
const arr = SettingsData.controlCenterWidgets;
|
|
||||||
if (!arr || i < 0 || j < 0 || i >= arr.length || j >= arr.length) return;
|
|
||||||
|
|
||||||
const copy = arr.slice();
|
|
||||||
const tmp = copy[i];
|
|
||||||
copy[i] = copy[j];
|
|
||||||
copy[j] = tmp;
|
|
||||||
|
|
||||||
SettingsData.setControlCenterWidgets(copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
function snapToGrid() {
|
|
||||||
if (!editMode || !gridLayout) return
|
|
||||||
|
|
||||||
const globalPos = root.mapToItem(gridLayout, 0, 0)
|
|
||||||
const cellWidth = gridLayout.width / gridColumns
|
|
||||||
const cellHeight = gridCellHeight + Theme.spacingS
|
|
||||||
|
|
||||||
const centerX = globalPos.x + (root.width / 2)
|
|
||||||
const centerY = globalPos.y + (root.height / 2)
|
|
||||||
|
|
||||||
let targetCol = Math.max(0, Math.floor(centerX / cellWidth))
|
|
||||||
let targetRow = Math.max(0, Math.floor(centerY / cellHeight))
|
|
||||||
|
|
||||||
targetCol = Math.min(targetCol, gridColumns - 1)
|
|
||||||
|
|
||||||
const newIndex = findBestInsertionIndex(targetRow, targetCol)
|
|
||||||
|
|
||||||
if (newIndex !== widgetIndex && newIndex >= 0 && newIndex < (SettingsData.controlCenterWidgets?.length || 0)) {
|
|
||||||
swapIndices(widgetIndex, newIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function findBestInsertionIndex(targetRow, targetCol) {
|
|
||||||
const widgets = SettingsData.controlCenterWidgets || [];
|
|
||||||
const n = widgets.length;
|
|
||||||
if (!n || widgetIndex < 0 || widgetIndex >= n) return -1;
|
|
||||||
|
|
||||||
function spanFor(width) {
|
|
||||||
const w = width ?? 50;
|
|
||||||
if (w <= 25) return 1;
|
|
||||||
if (w <= 50) return 2;
|
|
||||||
if (w <= 75) return 3;
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cols = gridColumns || 4;
|
|
||||||
|
|
||||||
let row = 0, col = 0;
|
|
||||||
let draggedOrigKey = null;
|
|
||||||
|
|
||||||
const pos = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < n; i++) {
|
|
||||||
const span = Math.min(spanFor(widgets[i].width), cols);
|
|
||||||
|
|
||||||
if (col + span > cols) {
|
|
||||||
row++;
|
|
||||||
col = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const startCol = col;
|
|
||||||
const centerKey = row * cols + (startCol + (span - 1) / 2);
|
|
||||||
|
|
||||||
if (i === widgetIndex) {
|
|
||||||
draggedOrigKey = centerKey;
|
|
||||||
} else {
|
|
||||||
pos.push({ index: i, row, startCol, span, centerKey });
|
|
||||||
}
|
|
||||||
|
|
||||||
col += span;
|
|
||||||
if (col >= cols) {
|
|
||||||
row++;
|
|
||||||
col = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos.length === 0) return -1;
|
|
||||||
|
|
||||||
const centerColCoord = targetCol + 0.5;
|
|
||||||
const targetKey = targetRow * cols + centerColCoord;
|
|
||||||
|
|
||||||
for (let k = 0; k < pos.length; k++) {
|
|
||||||
const p = pos[k];
|
|
||||||
if (p.row === targetRow && centerColCoord >= p.startCol && centerColCoord < (p.startCol + p.span)) {
|
|
||||||
return p.index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let lo = 0, hi = pos.length - 1;
|
|
||||||
if (targetKey <= pos[0].centerKey) return pos[0].index;
|
|
||||||
if (targetKey >= pos[hi].centerKey) return pos[hi].index;
|
|
||||||
|
|
||||||
while (lo <= hi) {
|
|
||||||
const mid = (lo + hi) >> 1;
|
|
||||||
const mk = pos[mid].centerKey;
|
|
||||||
if (targetKey < mk) hi = mid - 1;
|
|
||||||
else if (targetKey > mk) lo = mid + 1;
|
|
||||||
else return pos[mid].index;
|
|
||||||
}
|
|
||||||
const movingUp = (draggedOrigKey != null) ? (targetKey < draggedOrigKey) : false;
|
|
||||||
return (movingUp ? pos[lo].index : pos[hi].index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 16
|
|
||||||
height: 16
|
|
||||||
radius: 8
|
|
||||||
color: Theme.error
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.margins: -4
|
|
||||||
visible: editMode
|
|
||||||
z: 10
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "close"
|
|
||||||
size: 12
|
|
||||||
color: Theme.primaryText
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: removeWidget(widgetIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SizeControls {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.margins: -6
|
|
||||||
visible: editMode
|
|
||||||
z: 10
|
|
||||||
currentSize: root.widgetData?.width || 50
|
|
||||||
isSlider: root.isSlider
|
|
||||||
widgetIndex: root.widgetIndex
|
|
||||||
onSizeChanged: (newSize) => {
|
|
||||||
var widgets = SettingsData.controlCenterWidgets.slice()
|
|
||||||
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
|
||||||
widgets[widgetIndex].width = newSize
|
|
||||||
SettingsData.setControlCenterWidgets(widgets)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: dragHandle
|
|
||||||
width: 16
|
|
||||||
height: 12
|
|
||||||
radius: 2
|
|
||||||
color: Theme.primary
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.margins: 4
|
|
||||||
visible: editMode
|
|
||||||
z: 15
|
|
||||||
opacity: dragArea.drag.active ? 1.0 : 0.7
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "drag_indicator"
|
|
||||||
size: 10
|
|
||||||
color: Theme.primaryText
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation { duration: 150 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: editMode ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
border.color: "transparent"
|
|
||||||
border.width: 0
|
|
||||||
z: -1
|
|
||||||
|
|
||||||
Behavior on color {
|
|
||||||
ColorAnimation { duration: Theme.shortDuration }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ Row {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var availableWidgets: []
|
property var availableWidgets: []
|
||||||
property Item popoutContent: null
|
|
||||||
|
|
||||||
signal addWidget(string widgetId)
|
signal addWidget(string widgetId)
|
||||||
signal resetToDefault()
|
signal resetToDefault()
|
||||||
@@ -20,9 +19,7 @@ Row {
|
|||||||
|
|
||||||
Popup {
|
Popup {
|
||||||
id: addWidgetPopup
|
id: addWidgetPopup
|
||||||
parent: popoutContent
|
anchors.centerIn: parent
|
||||||
x: parent ? Math.round((parent.width - width) / 2) : 0
|
|
||||||
y: parent ? Math.round((parent.height - height) / 2) : 0
|
|
||||||
width: 400
|
width: 400
|
||||||
height: 300
|
height: 300
|
||||||
modal: true
|
modal: true
|
||||||
@@ -32,7 +29,7 @@ Row {
|
|||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: Theme.surfaceContainer
|
color: Theme.surfaceContainer
|
||||||
border.color: Theme.primarySelected
|
border.color: Theme.primarySelected
|
||||||
border.width: 0
|
border.width: 1
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +52,7 @@ Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: I18n.tr("Add Widget")
|
text: "Add Widget"
|
||||||
style: Typography.Style.Subtitle
|
style: Typography.Style.Subtitle
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -77,7 +74,7 @@ Row {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: widgetMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceContainerHigh
|
color: widgetMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceContainerHigh
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||||
border.width: 0
|
border.width: 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -141,7 +138,7 @@ Row {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
||||||
border.color: Theme.primary
|
border.color: Theme.primary
|
||||||
border.width: 0
|
border.width: 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -155,7 +152,7 @@ Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: I18n.tr("Add Widget")
|
text: "Add Widget"
|
||||||
style: Typography.Style.Button
|
style: Typography.Style.Button
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -175,7 +172,7 @@ Row {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12)
|
color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12)
|
||||||
border.color: Theme.warning
|
border.color: Theme.warning
|
||||||
border.width: 0
|
border.width: 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -189,7 +186,7 @@ Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: I18n.tr("Defaults")
|
text: "Defaults"
|
||||||
style: Typography.Style.Button
|
style: Typography.Style.Button
|
||||||
color: Theme.warning
|
color: Theme.warning
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -209,7 +206,7 @@ Row {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
||||||
border.color: Theme.error
|
border.color: Theme.error
|
||||||
border.width: 0
|
border.width: 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -223,7 +220,7 @@ Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: I18n.tr("Reset")
|
text: "Reset"
|
||||||
style: Typography.Style.Button
|
style: Typography.Style.Button
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|||||||
241
Modules/ControlCenter/Components/EditModeOverlay.qml
Normal file
241
Modules/ControlCenter/Components/EditModeOverlay.qml
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool editMode: false
|
||||||
|
property var widgetData: null
|
||||||
|
property int widgetIndex: -1
|
||||||
|
property bool showSizeControls: true
|
||||||
|
property bool isSlider: false
|
||||||
|
|
||||||
|
signal removeWidget(int index)
|
||||||
|
signal toggleWidgetSize(int index)
|
||||||
|
signal moveWidget(int fromIndex, int toIndex)
|
||||||
|
|
||||||
|
// Delete button in top-right
|
||||||
|
Rectangle {
|
||||||
|
width: 16
|
||||||
|
height: 16
|
||||||
|
radius: 8
|
||||||
|
color: Theme.error
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.margins: -4
|
||||||
|
visible: editMode
|
||||||
|
z: 10
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "close"
|
||||||
|
size: 12
|
||||||
|
color: Theme.primaryText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: root.removeWidget(widgetIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size control buttons in bottom-right
|
||||||
|
Row {
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.margins: -8
|
||||||
|
spacing: 4
|
||||||
|
visible: editMode && showSizeControls
|
||||||
|
z: 10
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
radius: 12
|
||||||
|
color: (widgetData?.width || 50) === 25 ? Theme.primary : Theme.primaryContainer
|
||||||
|
border.color: Theme.primary
|
||||||
|
border.width: 1
|
||||||
|
visible: !isSlider
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "25"
|
||||||
|
font.pixelSize: 10
|
||||||
|
font.weight: Font.Medium
|
||||||
|
color: (widgetData?.width || 50) === 25 ? Theme.primaryText : Theme.primary
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
var widgets = SettingsData.controlCenterWidgets.slice()
|
||||||
|
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||||
|
widgets[widgetIndex].width = 25
|
||||||
|
SettingsData.setControlCenterWidgets(widgets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
radius: 12
|
||||||
|
color: (widgetData?.width || 50) === 50 ? Theme.primary : Theme.primaryContainer
|
||||||
|
border.color: Theme.primary
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "50"
|
||||||
|
font.pixelSize: 10
|
||||||
|
font.weight: Font.Medium
|
||||||
|
color: (widgetData?.width || 50) === 50 ? Theme.primaryText : Theme.primary
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
var widgets = SettingsData.controlCenterWidgets.slice()
|
||||||
|
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||||
|
widgets[widgetIndex].width = 50
|
||||||
|
SettingsData.setControlCenterWidgets(widgets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
radius: 12
|
||||||
|
color: (widgetData?.width || 50) === 75 ? Theme.primary : Theme.primaryContainer
|
||||||
|
border.color: Theme.primary
|
||||||
|
border.width: 1
|
||||||
|
visible: !isSlider
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "75"
|
||||||
|
font.pixelSize: 10
|
||||||
|
font.weight: Font.Medium
|
||||||
|
color: (widgetData?.width || 50) === 75 ? Theme.primaryText : Theme.primary
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
var widgets = SettingsData.controlCenterWidgets.slice()
|
||||||
|
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||||
|
widgets[widgetIndex].width = 75
|
||||||
|
SettingsData.setControlCenterWidgets(widgets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
radius: 12
|
||||||
|
color: (widgetData?.width || 50) === 100 ? Theme.primary : Theme.primaryContainer
|
||||||
|
border.color: Theme.primary
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "100"
|
||||||
|
font.pixelSize: 9
|
||||||
|
font.weight: Font.Medium
|
||||||
|
color: (widgetData?.width || 50) === 100 ? Theme.primaryText : Theme.primary
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
var widgets = SettingsData.controlCenterWidgets.slice()
|
||||||
|
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||||
|
widgets[widgetIndex].width = 100
|
||||||
|
SettingsData.setControlCenterWidgets(widgets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arrow buttons for reordering in top-left
|
||||||
|
Row {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: 4
|
||||||
|
spacing: 2
|
||||||
|
visible: editMode
|
||||||
|
z: 20
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 16
|
||||||
|
height: 16
|
||||||
|
radius: 8
|
||||||
|
color: Theme.surfaceContainer
|
||||||
|
border.color: Theme.outline
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "keyboard_arrow_left"
|
||||||
|
size: 12
|
||||||
|
color: Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
enabled: widgetIndex > 0
|
||||||
|
opacity: enabled ? 1.0 : 0.5
|
||||||
|
onClicked: root.moveWidget(widgetIndex, widgetIndex - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 16
|
||||||
|
height: 16
|
||||||
|
radius: 8
|
||||||
|
color: Theme.surfaceContainer
|
||||||
|
border.color: Theme.outline
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "keyboard_arrow_right"
|
||||||
|
size: 12
|
||||||
|
color: Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
enabled: widgetIndex < ((SettingsData.controlCenterWidgets?.length ?? 0) - 1)
|
||||||
|
opacity: enabled ? 1.0 : 0.5
|
||||||
|
onClicked: root.moveWidget(widgetIndex, widgetIndex + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Border highlight
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1)
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
border.color: Theme.primary
|
||||||
|
border.width: editMode ? 1 : 0
|
||||||
|
visible: editMode
|
||||||
|
z: -1
|
||||||
|
|
||||||
|
Behavior on border.width {
|
||||||
|
NumberAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,9 +6,10 @@ import qs.Widgets
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property bool powerOptionsExpanded: false
|
||||||
property bool editMode: false
|
property bool editMode: false
|
||||||
|
|
||||||
signal powerButtonClicked()
|
signal powerActionRequested(string action, string title, string message)
|
||||||
signal lockRequested()
|
signal lockRequested()
|
||||||
signal editModeToggled()
|
signal editModeToggled()
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ Rectangle {
|
|||||||
color: Theme.surfaceContainerHigh
|
color: Theme.surfaceContainerHigh
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
||||||
Theme.outline.b, 0.08)
|
Theme.outline.b, 0.08)
|
||||||
border.width: 0
|
border.width: 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -82,11 +83,13 @@ Rectangle {
|
|||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
buttonSize: 36
|
buttonSize: 36
|
||||||
iconName: "power_settings_new"
|
iconName: root.powerOptionsExpanded ? "expand_less" : "power_settings_new"
|
||||||
iconSize: Theme.iconSize - 4
|
iconSize: Theme.iconSize - 4
|
||||||
iconColor: Theme.surfaceText
|
iconColor: root.powerOptionsExpanded ? Theme.primary : Theme.surfaceText
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
onClicked: root.powerButtonClicked()
|
onClicked: {
|
||||||
|
root.powerOptionsExpanded = !root.powerOptionsExpanded
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
|
|||||||
70
Modules/ControlCenter/Components/PowerOptionsPane.qml
Normal file
70
Modules/ControlCenter/Components/PowerOptionsPane.qml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
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?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import qs.Common
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property int currentSize: 50
|
|
||||||
property bool isSlider: false
|
|
||||||
property int widgetIndex: -1
|
|
||||||
|
|
||||||
signal sizeChanged(int newSize)
|
|
||||||
|
|
||||||
readonly property var availableSizes: isSlider ? [50, 100] : [25, 50, 75, 100]
|
|
||||||
|
|
||||||
spacing: 2
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: root.availableSizes
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 16
|
|
||||||
height: 16
|
|
||||||
radius: 3
|
|
||||||
color: modelData === root.currentSize ? Theme.primary : Theme.surfaceContainer
|
|
||||||
border.color: modelData === root.currentSize ? Theme.primary : Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: modelData.toString()
|
|
||||||
font.pixelSize: 8
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: modelData === root.currentSize ? Theme.primaryText : Theme.surfaceText
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
root.currentSize = modelData
|
|
||||||
root.sizeChanged(modelData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on color {
|
|
||||||
ColorAnimation { duration: Theme.shortDuration }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
734
Modules/ControlCenter/Components/WidgetGrid.qml
Normal file
734
Modules/ControlCenter/Components/WidgetGrid.qml
Normal file
@@ -0,0 +1,734 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
import qs.Modules.ControlCenter.Widgets
|
||||||
|
import qs.Modules.ControlCenter.Components
|
||||||
|
import "../utils/layout.js" as LayoutUtils
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool editMode: false
|
||||||
|
property string expandedSection: ""
|
||||||
|
property int expandedWidgetIndex: -1
|
||||||
|
property var model: null
|
||||||
|
property var expandedWidgetData: null
|
||||||
|
|
||||||
|
signal expandClicked(var widgetData, int globalIndex)
|
||||||
|
signal removeWidget(int index)
|
||||||
|
signal moveWidget(int fromIndex, int toIndex)
|
||||||
|
signal toggleWidgetSize(int index)
|
||||||
|
|
||||||
|
spacing: editMode ? Theme.spacingL : Theme.spacingS
|
||||||
|
|
||||||
|
property var currentRowWidgets: []
|
||||||
|
property real currentRowWidth: 0
|
||||||
|
property int expandedRowIndex: -1
|
||||||
|
|
||||||
|
function calculateRowsAndWidgets() {
|
||||||
|
return LayoutUtils.calculateRowsAndWidgets(root, expandedSection, expandedWidgetIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
property var layoutResult: {
|
||||||
|
const dummy = [expandedSection, expandedWidgetIndex, model?.controlCenterWidgets]
|
||||||
|
return calculateRowsAndWidgets()
|
||||||
|
}
|
||||||
|
|
||||||
|
onLayoutResultChanged: {
|
||||||
|
expandedRowIndex = layoutResult.expandedRowIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: root.layoutResult.rows
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: root.width
|
||||||
|
spacing: 0
|
||||||
|
property int rowIndex: index
|
||||||
|
property var rowWidgets: modelData
|
||||||
|
property bool isSliderOnlyRow: {
|
||||||
|
const widgets = rowWidgets || []
|
||||||
|
if (widgets.length === 0) return false
|
||||||
|
return widgets.every(w => w.id === "volumeSlider" || w.id === "brightnessSlider" || w.id === "inputVolumeSlider")
|
||||||
|
}
|
||||||
|
topPadding: isSliderOnlyRow ? (root.editMode ? 4 : -12) : 0
|
||||||
|
bottomPadding: isSliderOnlyRow ? (root.editMode ? 4 : -12) : 0
|
||||||
|
|
||||||
|
Flow {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: rowWidgets || []
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property var widgetData: modelData
|
||||||
|
property int globalWidgetIndex: {
|
||||||
|
const widgets = SettingsData.controlCenterWidgets || []
|
||||||
|
for (var i = 0; i < widgets.length; i++) {
|
||||||
|
if (widgets[i].id === modelData.id) {
|
||||||
|
if (modelData.id === "diskUsage") {
|
||||||
|
if (widgets[i].instanceId === modelData.instanceId) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
property int widgetWidth: modelData.width || 50
|
||||||
|
width: {
|
||||||
|
const baseWidth = root.width
|
||||||
|
const spacing = Theme.spacingS
|
||||||
|
if (widgetWidth <= 25) {
|
||||||
|
return (baseWidth - spacing * 3) / 4
|
||||||
|
} else if (widgetWidth <= 50) {
|
||||||
|
return (baseWidth - spacing) / 2
|
||||||
|
} else if (widgetWidth <= 75) {
|
||||||
|
return (baseWidth - spacing * 2) * 0.75
|
||||||
|
} else {
|
||||||
|
return baseWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
height: 60
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: widgetLoader
|
||||||
|
anchors.fill: parent
|
||||||
|
property var widgetData: parent.widgetData
|
||||||
|
property int widgetIndex: parent.globalWidgetIndex
|
||||||
|
property int globalWidgetIndex: parent.globalWidgetIndex
|
||||||
|
property int widgetWidth: parent.widgetWidth
|
||||||
|
|
||||||
|
sourceComponent: {
|
||||||
|
const id = modelData.id || ""
|
||||||
|
if (id === "wifi" || id === "bluetooth" || id === "audioOutput" || id === "audioInput") {
|
||||||
|
return compoundPillComponent
|
||||||
|
} else if (id === "volumeSlider") {
|
||||||
|
return audioSliderComponent
|
||||||
|
} else if (id === "brightnessSlider") {
|
||||||
|
return brightnessSliderComponent
|
||||||
|
} else if (id === "inputVolumeSlider") {
|
||||||
|
return inputAudioSliderComponent
|
||||||
|
} else if (id === "battery") {
|
||||||
|
return widgetWidth <= 25 ? smallBatteryComponent : batteryPillComponent
|
||||||
|
} else if (id === "diskUsage") {
|
||||||
|
return diskUsagePillComponent
|
||||||
|
} else {
|
||||||
|
return widgetWidth <= 25 ? smallToggleComponent : toggleButtonComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DetailHost {
|
||||||
|
width: parent.width
|
||||||
|
height: active ? (250 + Theme.spacingS) : 0
|
||||||
|
property bool active: {
|
||||||
|
if (root.expandedSection === "") return false
|
||||||
|
|
||||||
|
if (root.expandedSection.startsWith("diskUsage_") && root.expandedWidgetData) {
|
||||||
|
const expandedInstanceId = root.expandedWidgetData.instanceId
|
||||||
|
return rowWidgets.some(w => w.id === "diskUsage" && w.instanceId === expandedInstanceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rowIndex === root.expandedRowIndex
|
||||||
|
}
|
||||||
|
visible: active
|
||||||
|
expandedSection: root.expandedSection
|
||||||
|
expandedWidgetData: root.expandedWidgetData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: compoundPillComponent
|
||||||
|
CompoundPill {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
|
||||||
|
width: parent.width
|
||||||
|
height: 60
|
||||||
|
iconName: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "wifi": {
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
case "bluetooth": {
|
||||||
|
if (!BluetoothService.available) {
|
||||||
|
return "bluetooth_disabled"
|
||||||
|
}
|
||||||
|
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled) {
|
||||||
|
return "bluetooth_disabled"
|
||||||
|
}
|
||||||
|
const primaryDevice = (() => {
|
||||||
|
if (!BluetoothService.adapter || !BluetoothService.adapter.devices) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
|
||||||
|
for (let device of devices) {
|
||||||
|
if (device && device.connected) {
|
||||||
|
return device
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
})()
|
||||||
|
if (primaryDevice) {
|
||||||
|
return BluetoothService.getDeviceIcon(primaryDevice)
|
||||||
|
}
|
||||||
|
return "bluetooth"
|
||||||
|
}
|
||||||
|
case "audioOutput": {
|
||||||
|
if (!AudioService.sink) return "volume_off"
|
||||||
|
let volume = AudioService.sink.audio.volume
|
||||||
|
let muted = AudioService.sink.audio.muted
|
||||||
|
if (muted || volume === 0.0) return "volume_off"
|
||||||
|
if (volume <= 0.33) return "volume_down"
|
||||||
|
if (volume <= 0.66) return "volume_up"
|
||||||
|
return "volume_up"
|
||||||
|
}
|
||||||
|
case "audioInput": {
|
||||||
|
if (!AudioService.source) return "mic_off"
|
||||||
|
let muted = AudioService.source.audio.muted
|
||||||
|
return muted ? "mic_off" : "mic"
|
||||||
|
}
|
||||||
|
default: return widgetDef?.icon || "help"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
primaryText: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "wifi": {
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
case "bluetooth": {
|
||||||
|
if (!BluetoothService.available) {
|
||||||
|
return "Bluetooth"
|
||||||
|
}
|
||||||
|
if (!BluetoothService.adapter) {
|
||||||
|
return "No adapter"
|
||||||
|
}
|
||||||
|
if (!BluetoothService.adapter.enabled) {
|
||||||
|
return "Disabled"
|
||||||
|
}
|
||||||
|
return "Enabled"
|
||||||
|
}
|
||||||
|
case "audioOutput": return AudioService.sink?.description || "No output device"
|
||||||
|
case "audioInput": return AudioService.source?.description || "No input device"
|
||||||
|
default: return widgetDef?.text || "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
secondaryText: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "wifi": {
|
||||||
|
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 ""
|
||||||
|
}
|
||||||
|
case "bluetooth": {
|
||||||
|
if (!BluetoothService.available) {
|
||||||
|
return "No adapters"
|
||||||
|
}
|
||||||
|
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled) {
|
||||||
|
return "Off"
|
||||||
|
}
|
||||||
|
const primaryDevice = (() => {
|
||||||
|
if (!BluetoothService.adapter || !BluetoothService.adapter.devices) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
|
||||||
|
for (let device of devices) {
|
||||||
|
if (device && device.connected) {
|
||||||
|
return device
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
})()
|
||||||
|
if (primaryDevice) {
|
||||||
|
return primaryDevice.name || primaryDevice.alias || primaryDevice.deviceName || "Connected Device"
|
||||||
|
}
|
||||||
|
return "No devices"
|
||||||
|
}
|
||||||
|
case "audioOutput": {
|
||||||
|
if (!AudioService.sink) {
|
||||||
|
return "Select device"
|
||||||
|
}
|
||||||
|
if (AudioService.sink.audio.muted) {
|
||||||
|
return "Muted"
|
||||||
|
}
|
||||||
|
return Math.round(AudioService.sink.audio.volume * 100) + "%"
|
||||||
|
}
|
||||||
|
case "audioInput": {
|
||||||
|
if (!AudioService.source) {
|
||||||
|
return "Select device"
|
||||||
|
}
|
||||||
|
if (AudioService.source.audio.muted) {
|
||||||
|
return "Muted"
|
||||||
|
}
|
||||||
|
return Math.round(AudioService.source.audio.volume * 100) + "%"
|
||||||
|
}
|
||||||
|
default: return widgetDef?.description || ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isActive: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "wifi": {
|
||||||
|
if (NetworkService.wifiToggling) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (NetworkService.networkStatus === "ethernet") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (NetworkService.networkStatus === "wifi") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return NetworkService.wifiEnabled
|
||||||
|
}
|
||||||
|
case "bluetooth": return !!(BluetoothService.available && BluetoothService.adapter && BluetoothService.adapter.enabled)
|
||||||
|
case "audioOutput": return !!(AudioService.sink && !AudioService.sink.audio.muted)
|
||||||
|
case "audioInput": return !!(AudioService.source && !AudioService.source.audio.muted)
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enabled: (widgetDef?.enabled ?? true)
|
||||||
|
onToggled: {
|
||||||
|
if (root.editMode) return
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "wifi": {
|
||||||
|
if (NetworkService.networkStatus !== "ethernet" && !NetworkService.wifiToggling) {
|
||||||
|
NetworkService.toggleWifiRadio()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "bluetooth": {
|
||||||
|
if (BluetoothService.available && BluetoothService.adapter) {
|
||||||
|
BluetoothService.adapter.enabled = !BluetoothService.adapter.enabled
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "audioOutput": {
|
||||||
|
if (AudioService.sink && AudioService.sink.audio) {
|
||||||
|
AudioService.sink.audio.muted = !AudioService.sink.audio.muted
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "audioInput": {
|
||||||
|
if (AudioService.source && AudioService.source.audio) {
|
||||||
|
AudioService.source.audio.muted = !AudioService.source.audio.muted
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onExpandClicked: {
|
||||||
|
if (root.editMode) return
|
||||||
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
|
}
|
||||||
|
onWheelEvent: function (wheelEvent) {
|
||||||
|
const id = widgetData.id || ""
|
||||||
|
if (id === "audioOutput") {
|
||||||
|
if (!AudioService.sink || !AudioService.sink.audio) return
|
||||||
|
let delta = wheelEvent.angleDelta.y
|
||||||
|
let currentVolume = AudioService.sink.audio.volume * 100
|
||||||
|
let newVolume
|
||||||
|
if (delta > 0)
|
||||||
|
newVolume = Math.min(100, currentVolume + 5)
|
||||||
|
else
|
||||||
|
newVolume = Math.max(0, currentVolume - 5)
|
||||||
|
AudioService.sink.audio.muted = false
|
||||||
|
AudioService.sink.audio.volume = newVolume / 100
|
||||||
|
wheelEvent.accepted = true
|
||||||
|
} else if (id === "audioInput") {
|
||||||
|
if (!AudioService.source || !AudioService.source.audio) return
|
||||||
|
let delta = wheelEvent.angleDelta.y
|
||||||
|
let currentVolume = AudioService.source.audio.volume * 100
|
||||||
|
let newVolume
|
||||||
|
if (delta > 0)
|
||||||
|
newVolume = Math.min(100, currentVolume + 5)
|
||||||
|
else
|
||||||
|
newVolume = Math.max(0, currentVolume - 5)
|
||||||
|
AudioService.source.audio.muted = false
|
||||||
|
AudioService.source.audio.volume = newVolume / 100
|
||||||
|
wheelEvent.accepted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditModeOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
editMode: root.editMode
|
||||||
|
widgetData: parent.widgetData
|
||||||
|
widgetIndex: parent.widgetIndex
|
||||||
|
showSizeControls: true
|
||||||
|
isSlider: false
|
||||||
|
onRemoveWidget: (index) => root.removeWidget(index)
|
||||||
|
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
|
||||||
|
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: audioSliderComponent
|
||||||
|
Item {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
|
||||||
|
width: parent.width
|
||||||
|
height: 16
|
||||||
|
|
||||||
|
AudioSliderRow {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width
|
||||||
|
height: 14
|
||||||
|
property color sliderTrackColor: Theme.surfaceContainerHigh
|
||||||
|
}
|
||||||
|
|
||||||
|
EditModeOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
editMode: root.editMode
|
||||||
|
widgetData: parent.widgetData
|
||||||
|
widgetIndex: parent.widgetIndex
|
||||||
|
showSizeControls: true
|
||||||
|
isSlider: true
|
||||||
|
onRemoveWidget: (index) => root.removeWidget(index)
|
||||||
|
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
|
||||||
|
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: brightnessSliderComponent
|
||||||
|
Item {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
width: parent.width
|
||||||
|
height: 16
|
||||||
|
|
||||||
|
BrightnessSliderRow {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width
|
||||||
|
height: 14
|
||||||
|
property color sliderTrackColor: Theme.surfaceContainerHigh
|
||||||
|
}
|
||||||
|
|
||||||
|
EditModeOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
editMode: root.editMode
|
||||||
|
widgetData: parent.widgetData
|
||||||
|
widgetIndex: parent.widgetIndex
|
||||||
|
showSizeControls: true
|
||||||
|
isSlider: true
|
||||||
|
onRemoveWidget: (index) => root.removeWidget(index)
|
||||||
|
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
|
||||||
|
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: inputAudioSliderComponent
|
||||||
|
Item {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
width: parent.width
|
||||||
|
height: 16
|
||||||
|
|
||||||
|
InputAudioSliderRow {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width
|
||||||
|
height: 14
|
||||||
|
property color sliderTrackColor: Theme.surfaceContainerHigh
|
||||||
|
}
|
||||||
|
|
||||||
|
EditModeOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
editMode: root.editMode
|
||||||
|
widgetData: parent.widgetData
|
||||||
|
widgetIndex: parent.widgetIndex
|
||||||
|
showSizeControls: true
|
||||||
|
isSlider: true
|
||||||
|
onRemoveWidget: (index) => root.removeWidget(index)
|
||||||
|
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
|
||||||
|
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: batteryPillComponent
|
||||||
|
BatteryPill {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
width: parent.width
|
||||||
|
height: 60
|
||||||
|
|
||||||
|
onExpandClicked: {
|
||||||
|
if (!root.editMode) {
|
||||||
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditModeOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
editMode: root.editMode
|
||||||
|
widgetData: parent.widgetData
|
||||||
|
widgetIndex: parent.widgetIndex
|
||||||
|
showSizeControls: true
|
||||||
|
isSlider: false
|
||||||
|
onRemoveWidget: (index) => root.removeWidget(index)
|
||||||
|
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
|
||||||
|
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: smallBatteryComponent
|
||||||
|
SmallBatteryButton {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
width: parent.width
|
||||||
|
height: 48
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (!root.editMode) {
|
||||||
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditModeOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
editMode: root.editMode
|
||||||
|
widgetData: parent.widgetData
|
||||||
|
widgetIndex: parent.widgetIndex
|
||||||
|
showSizeControls: true
|
||||||
|
isSlider: false
|
||||||
|
onRemoveWidget: (index) => root.removeWidget(index)
|
||||||
|
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
|
||||||
|
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: toggleButtonComponent
|
||||||
|
ToggleButton {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
|
||||||
|
width: parent.width
|
||||||
|
height: 60
|
||||||
|
|
||||||
|
iconName: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "nightMode": return DisplayService.nightModeEnabled ? "nightlight" : "dark_mode"
|
||||||
|
case "darkMode": return "contrast"
|
||||||
|
case "doNotDisturb": return SessionData.doNotDisturb ? "do_not_disturb_on" : "do_not_disturb_off"
|
||||||
|
case "idleInhibitor": return SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
|
||||||
|
default: return widgetDef?.icon || "help"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "nightMode": return "Night Mode"
|
||||||
|
case "darkMode": return SessionData.isLightMode ? "Light Mode" : "Dark Mode"
|
||||||
|
case "doNotDisturb": return "Do Not Disturb"
|
||||||
|
case "idleInhibitor": return SessionService.idleInhibited ? "Keeping Awake" : "Keep Awake"
|
||||||
|
default: return widgetDef?.text || "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
secondaryText: ""
|
||||||
|
|
||||||
|
iconRotation: widgetData.id === "darkMode" && SessionData.isLightMode ? 180 : 0
|
||||||
|
|
||||||
|
isActive: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "nightMode": return DisplayService.nightModeEnabled || false
|
||||||
|
case "darkMode": return !SessionData.isLightMode
|
||||||
|
case "doNotDisturb": return SessionData.doNotDisturb || false
|
||||||
|
case "idleInhibitor": return SessionService.idleInhibited || false
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled: (widgetDef?.enabled ?? true) && !root.editMode
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "nightMode": {
|
||||||
|
if (DisplayService.automationAvailable) {
|
||||||
|
DisplayService.toggleNightMode()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "darkMode": {
|
||||||
|
Theme.toggleLightMode()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "doNotDisturb": {
|
||||||
|
SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "idleInhibitor": {
|
||||||
|
SessionService.toggleIdleInhibit()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditModeOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
editMode: root.editMode
|
||||||
|
widgetData: parent.widgetData
|
||||||
|
widgetIndex: parent.widgetIndex
|
||||||
|
showSizeControls: true
|
||||||
|
isSlider: false
|
||||||
|
onRemoveWidget: (index) => root.removeWidget(index)
|
||||||
|
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
|
||||||
|
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: smallToggleComponent
|
||||||
|
SmallToggleButton {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
|
||||||
|
width: parent.width
|
||||||
|
height: 48
|
||||||
|
|
||||||
|
iconName: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "nightMode": return DisplayService.nightModeEnabled ? "nightlight" : "dark_mode"
|
||||||
|
case "darkMode": return "contrast"
|
||||||
|
case "doNotDisturb": return SessionData.doNotDisturb ? "do_not_disturb_on" : "do_not_disturb_off"
|
||||||
|
case "idleInhibitor": return SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
|
||||||
|
default: return widgetDef?.icon || "help"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iconRotation: widgetData.id === "darkMode" && SessionData.isLightMode ? 180 : 0
|
||||||
|
|
||||||
|
isActive: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "nightMode": return DisplayService.nightModeEnabled || false
|
||||||
|
case "darkMode": return !SessionData.isLightMode
|
||||||
|
case "doNotDisturb": return SessionData.doNotDisturb || false
|
||||||
|
case "idleInhibitor": return SessionService.idleInhibited || false
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled: (widgetDef?.enabled ?? true) && !root.editMode
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
switch (widgetData.id || "") {
|
||||||
|
case "nightMode": {
|
||||||
|
if (DisplayService.automationAvailable) {
|
||||||
|
DisplayService.toggleNightMode()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "darkMode": {
|
||||||
|
Theme.toggleLightMode()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "doNotDisturb": {
|
||||||
|
SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "idleInhibitor": {
|
||||||
|
SessionService.toggleIdleInhibit()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditModeOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
editMode: root.editMode
|
||||||
|
widgetData: parent.widgetData
|
||||||
|
widgetIndex: parent.widgetIndex
|
||||||
|
showSizeControls: true
|
||||||
|
isSlider: false
|
||||||
|
onRemoveWidget: (index) => root.removeWidget(index)
|
||||||
|
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
|
||||||
|
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: diskUsagePillComponent
|
||||||
|
DiskUsagePill {
|
||||||
|
property var widgetData: parent.widgetData || {}
|
||||||
|
property int widgetIndex: parent.widgetIndex || 0
|
||||||
|
width: parent.width
|
||||||
|
height: 60
|
||||||
|
|
||||||
|
mountPath: widgetData.mountPath || "/"
|
||||||
|
instanceId: widgetData.instanceId || ""
|
||||||
|
|
||||||
|
onExpandClicked: {
|
||||||
|
if (!root.editMode) {
|
||||||
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditModeOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
editMode: root.editMode
|
||||||
|
widgetData: parent.widgetData
|
||||||
|
widgetIndex: parent.widgetIndex
|
||||||
|
showSizeControls: true
|
||||||
|
isSlider: false
|
||||||
|
onRemoveWidget: (index) => root.removeWidget(index)
|
||||||
|
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
|
||||||
|
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import qs.Common
|
|||||||
import qs.Modules.ControlCenter
|
import qs.Modules.ControlCenter
|
||||||
import qs.Modules.ControlCenter.Widgets
|
import qs.Modules.ControlCenter.Widgets
|
||||||
import qs.Modules.ControlCenter.Details
|
import qs.Modules.ControlCenter.Details
|
||||||
import qs.Modules.DankBar
|
import qs.Modules.TopBar
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
import qs.Modules.ControlCenter.Components
|
import qs.Modules.ControlCenter.Components
|
||||||
@@ -21,11 +21,14 @@ DankPopout {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string expandedSection: ""
|
property string expandedSection: ""
|
||||||
|
property bool powerOptionsExpanded: false
|
||||||
|
property string triggerSection: "right"
|
||||||
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() {
|
||||||
@@ -63,9 +66,9 @@ DankPopout {
|
|||||||
popupWidth: 550
|
popupWidth: 550
|
||||||
popupHeight: Math.min((triggerScreen?.height ?? 1080) - 100, contentLoader.item && contentLoader.item.implicitHeight > 0 ? contentLoader.item.implicitHeight + 20 : 400)
|
popupHeight: Math.min((triggerScreen?.height ?? 1080) - 100, contentLoader.item && contentLoader.item.implicitHeight > 0 ? contentLoader.item.implicitHeight + 20 : 400)
|
||||||
triggerX: (triggerScreen?.width ?? 1920) - 600 - Theme.spacingL
|
triggerX: (triggerScreen?.width ?? 1920) - 600 - Theme.spacingL
|
||||||
triggerY: Theme.barHeight - 4 + SettingsData.dankBarSpacing
|
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingXS
|
||||||
triggerWidth: 80
|
triggerWidth: 80
|
||||||
positioning: ""
|
positioning: "center"
|
||||||
screen: triggerScreen
|
screen: triggerScreen
|
||||||
shouldBeVisible: false
|
shouldBeVisible: false
|
||||||
visible: shouldBeVisible
|
visible: shouldBeVisible
|
||||||
@@ -73,17 +76,13 @@ DankPopout {
|
|||||||
onShouldBeVisibleChanged: {
|
onShouldBeVisibleChanged: {
|
||||||
if (shouldBeVisible) {
|
if (shouldBeVisible) {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (NetworkService.activeService) {
|
NetworkService.autoRefreshEnabled = NetworkService.wifiEnabled
|
||||||
NetworkService.activeService.autoRefreshEnabled = NetworkService.wifiEnabled
|
|
||||||
}
|
|
||||||
if (UserInfoService)
|
if (UserInfoService)
|
||||||
UserInfoService.getUptime()
|
UserInfoService.getUptime()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (NetworkService.activeService) {
|
NetworkService.autoRefreshEnabled = false
|
||||||
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
|
||||||
@@ -103,14 +102,14 @@ DankPopout {
|
|||||||
property alias bluetoothCodecSelector: bluetoothCodecSelector
|
property alias bluetoothCodecSelector: bluetoothCodecSelector
|
||||||
|
|
||||||
color: {
|
color: {
|
||||||
const transparency = Theme.popupTransparency
|
const transparency = Theme.popupTransparency || 0.92
|
||||||
const surface = Theme.surfaceContainer || Qt.rgba(0.1, 0.1, 0.1, 1)
|
const surface = Theme.surfaceContainer || Qt.rgba(0.1, 0.1, 0.1, 1)
|
||||||
return Qt.rgba(surface.r, surface.g, surface.b, transparency)
|
return Qt.rgba(surface.r, surface.g, surface.b, transparency)
|
||||||
}
|
}
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
||||||
Theme.outline.b, 0.08)
|
Theme.outline.b, 0.08)
|
||||||
border.width: 0
|
border.width: 1
|
||||||
antialiasing: true
|
antialiasing: true
|
||||||
smooth: true
|
smooth: true
|
||||||
|
|
||||||
@@ -124,25 +123,29 @@ 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
|
||||||
onPowerButtonClicked: {
|
onPowerActionRequested: (action, title, message) => root.powerActionRequested(action, title, message)
|
||||||
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DragDropGrid {
|
PowerOptionsPane {
|
||||||
|
id: powerOptionsPane
|
||||||
|
width: parent.width
|
||||||
|
expanded: root.powerOptionsExpanded
|
||||||
|
onPowerActionRequested: (action, title, message) => {
|
||||||
|
root.powerOptionsExpanded = false
|
||||||
|
root.close()
|
||||||
|
root.powerActionRequested(action, title, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetGrid {
|
||||||
id: widgetGrid
|
id: widgetGrid
|
||||||
width: parent.width
|
width: parent.width
|
||||||
editMode: root.editMode
|
editMode: root.editMode
|
||||||
@@ -150,8 +153,6 @@ DankPopout {
|
|||||||
expandedWidgetIndex: root.expandedWidgetIndex
|
expandedWidgetIndex: root.expandedWidgetIndex
|
||||||
expandedWidgetData: root.expandedWidgetData
|
expandedWidgetData: root.expandedWidgetData
|
||||||
model: widgetModel
|
model: widgetModel
|
||||||
bluetoothCodecSelector: bluetoothCodecSelector
|
|
||||||
colorPickerModal: root.colorPickerModal
|
|
||||||
onExpandClicked: (widgetData, globalIndex) => {
|
onExpandClicked: (widgetData, globalIndex) => {
|
||||||
root.expandedWidgetIndex = globalIndex
|
root.expandedWidgetIndex = globalIndex
|
||||||
root.expandedWidgetData = widgetData
|
root.expandedWidgetData = widgetData
|
||||||
@@ -169,12 +170,9 @@ DankPopout {
|
|||||||
EditControls {
|
EditControls {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
visible: editMode
|
visible: editMode
|
||||||
popoutContent: controlContent
|
|
||||||
availableWidgets: {
|
availableWidgets: {
|
||||||
if (!editMode) return []
|
|
||||||
const existingIds = (SettingsData.controlCenterWidgets || []).map(w => w.id)
|
const existingIds = (SettingsData.controlCenterWidgets || []).map(w => w.id)
|
||||||
const allWidgets = widgetModel.baseWidgetDefinitions.concat(widgetModel.getPluginWidgets())
|
return widgetModel.baseWidgetDefinitions.filter(w => w.allowMultiple || !existingIds.includes(w.id))
|
||||||
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()
|
||||||
@@ -224,7 +222,4 @@ DankPopout {
|
|||||||
id: batteryDetailComponent
|
id: batteryDetailComponent
|
||||||
BatteryDetail {}
|
BatteryDetail {}
|
||||||
}
|
}
|
||||||
|
|
||||||
property var colorPickerModal: null
|
|
||||||
property var powerMenuModalLoader: null
|
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ Rectangle {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
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: 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: headerRow
|
id: headerRow
|
||||||
@@ -30,7 +30,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: headerText
|
id: headerText
|
||||||
text: I18n.tr("Input Devices")
|
text: "Input Devices"
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -57,6 +57,10 @@ Rectangle {
|
|||||||
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
||||||
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: iconArea
|
id: iconArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -134,9 +138,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
|
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHigh
|
||||||
border.color: modelData === AudioService.source ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
border.color: modelData === AudioService.source ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: 0
|
border.width: modelData === AudioService.source ? 2 : 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -194,6 +198,14 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ Rectangle {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
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: 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: headerRow
|
id: headerRow
|
||||||
@@ -30,7 +30,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: headerText
|
id: headerText
|
||||||
text: I18n.tr("Audio Devices")
|
text: "Audio Devices"
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -57,6 +57,10 @@ Rectangle {
|
|||||||
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
||||||
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: iconArea
|
id: iconArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -139,9 +143,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
|
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHigh
|
||||||
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: 0
|
border.width: modelData === AudioService.sink ? 2 : 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -201,6 +205,14 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Rectangle {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
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: 1
|
||||||
|
|
||||||
function isActiveProfile(profile) {
|
function isActiveProfile(profile) {
|
||||||
if (typeof PowerProfiles === "undefined") {
|
if (typeof PowerProfiles === "undefined") {
|
||||||
@@ -133,7 +133,7 @@ Rectangle {
|
|||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Health")
|
text: "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: I18n.tr("Capacity")
|
text: "Capacity"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -209,7 +209,7 @@ Rectangle {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
||||||
border.color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3)
|
border.color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3)
|
||||||
border.width: 0
|
border.width: 1
|
||||||
visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None
|
visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -237,7 +237,7 @@ Rectangle {
|
|||||||
width: parent.width - Theme.iconSize - Theme.spacingM
|
width: parent.width - Theme.iconSize - Theme.spacingM
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Power Profile Degradation")
|
text: "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
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ Item {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceContainer
|
color: Theme.surfaceContainer
|
||||||
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: 1
|
||||||
opacity: modalVisible ? 1 : 0
|
opacity: modalVisible ? 1 : 0
|
||||||
scale: modalVisible ? 1 : 0.9
|
scale: modalVisible ? 1 : 0.9
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("Audio Codec Selection")
|
text: "Audio Codec Selection"
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceTextMedium
|
color: Theme.surfaceTextMedium
|
||||||
}
|
}
|
||||||
@@ -206,14 +206,14 @@ Item {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: {
|
color: {
|
||||||
if (modelData.name === currentCodec)
|
if (modelData.name === currentCodec)
|
||||||
return Theme.surfaceContainerHighest;
|
return Theme.surfaceContainerHigh;
|
||||||
else if (codecMouseArea.containsMouse)
|
else if (codecMouseArea.containsMouse)
|
||||||
return Theme.surfaceHover;
|
return Theme.surfaceHover;
|
||||||
else
|
else
|
||||||
return "transparent";
|
return "transparent";
|
||||||
}
|
}
|
||||||
border.color: "transparent"
|
border.color: "transparent"
|
||||||
border.width: 0
|
border.width: 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -272,6 +272,12 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Rectangle {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
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: 1
|
||||||
|
|
||||||
property var bluetoothCodecModalRef: null
|
property var bluetoothCodecModalRef: null
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: headerText
|
id: headerText
|
||||||
text: I18n.tr("Bluetooth Settings")
|
text: "Bluetooth Settings"
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -62,7 +62,7 @@ Rectangle {
|
|||||||
return scanMouseArea.containsMouse ? Theme.surfaceContainerHigh : "transparent"
|
return scanMouseArea.containsMouse ? Theme.surfaceContainerHigh : "transparent"
|
||||||
}
|
}
|
||||||
border.color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
border.color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: 0
|
border.width: 1
|
||||||
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
|
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
@@ -96,6 +96,13 @@ Rectangle {
|
|||||||
BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering
|
BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +159,7 @@ Rectangle {
|
|||||||
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12)
|
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12)
|
||||||
if (deviceMouseArea.containsMouse)
|
if (deviceMouseArea.containsMouse)
|
||||||
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
|
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
|
||||||
return Theme.surfaceContainerHighest
|
return Theme.surfaceContainerHigh
|
||||||
}
|
}
|
||||||
border.color: {
|
border.color: {
|
||||||
if (modelData.state === BluetoothDeviceState.Connecting)
|
if (modelData.state === BluetoothDeviceState.Connecting)
|
||||||
@@ -161,7 +168,7 @@ Rectangle {
|
|||||||
return Theme.primary
|
return Theme.primary
|
||||||
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
}
|
}
|
||||||
border.width: 0
|
border.width: (modelData.connected || modelData.state === BluetoothDeviceState.Connecting) ? 2 : 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -277,6 +284,14 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,9 +347,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: availableMouseArea.containsMouse && !isBusy ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
|
color: availableMouseArea.containsMouse && !isBusy ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHigh
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: 0
|
border.width: 1
|
||||||
opacity: canConnect ? 1 : 0.6
|
opacity: canConnect ? 1 : 0.6
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
@@ -412,6 +427,9 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +440,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: I18n.tr("No Bluetooth adapter found")
|
text: "No Bluetooth adapter found"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
}
|
}
|
||||||
@@ -440,7 +458,7 @@ Rectangle {
|
|||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: Theme.popupBackground()
|
color: Theme.popupBackground()
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.width: 0
|
border.width: 1
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,7 +491,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: I18n.tr("Audio Codec")
|
text: "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 +516,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: I18n.tr("Forget Device")
|
text: "Forget Device"
|
||||||
height: 32
|
height: 32
|
||||||
|
|
||||||
contentItem: StyledText {
|
contentItem: StyledText {
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import qs.Services
|
|||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
|
||||||
|
|
||||||
property string currentMountPath: "/"
|
property string currentMountPath: "/"
|
||||||
property string instanceId: ""
|
property string instanceId: ""
|
||||||
|
|
||||||
@@ -17,7 +15,7 @@ Rectangle {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
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: 1
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
DgopService.addRef(["diskmounts"])
|
DgopService.addRef(["diskmounts"])
|
||||||
@@ -78,9 +76,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 80
|
height: 80
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceContainerHighest
|
color: Theme.surfaceContainerHigh
|
||||||
border.color: modelData.mount === currentMountPath ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
border.color: modelData.mount === currentMountPath ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: modelData.mount === currentMountPath ? 2 : 0
|
border.width: modelData.mount === currentMountPath ? 2 : 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -154,11 +152,16 @@ Rectangle {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
currentMountPath = modelData.mount
|
if (modelData.mount !== currentMountPath) {
|
||||||
mountPathChanged(modelData.mount)
|
currentMountPath = modelData.mount
|
||||||
|
mountPathChanged(modelData.mount)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,16 +19,28 @@ Rectangle {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
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: 1
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
NetworkService.addRef()
|
NetworkService.addRef()
|
||||||
|
if (NetworkService.wifiEnabled) {
|
||||||
|
NetworkService.scanWifi()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
NetworkService.removeRef()
|
NetworkService.removeRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property var wifiPasswordModalRef: {
|
||||||
|
wifiPasswordModalLoader.active = true
|
||||||
|
return wifiPasswordModalLoader.item
|
||||||
|
}
|
||||||
|
property var networkInfoModalRef: {
|
||||||
|
networkInfoModalLoader.active = true
|
||||||
|
return networkInfoModalLoader.item
|
||||||
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: headerRow
|
id: headerRow
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -41,7 +53,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: headerText
|
id: headerText
|
||||||
text: I18n.tr("Network Settings")
|
text: "Network Settings"
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -56,30 +68,15 @@ Rectangle {
|
|||||||
DankButtonGroup {
|
DankButtonGroup {
|
||||||
id: preferenceControls
|
id: preferenceControls
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: NetworkService.ethernetConnected
|
visible: NetworkService.ethernetConnected && NetworkService.wifiConnected
|
||||||
|
|
||||||
property int currentPreferenceIndex: {
|
property int currentPreferenceIndex: NetworkService.userPreference === "ethernet" ? 0 : 1
|
||||||
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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,17 +91,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
|
||||||
@@ -113,7 +110,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..."
|
||||||
@@ -148,7 +145,7 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
text: I18n.tr("WiFi is off")
|
text: "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
|
||||||
@@ -161,12 +158,12 @@ Rectangle {
|
|||||||
height: 36
|
height: 36
|
||||||
radius: 18
|
radius: 18
|
||||||
color: enableWifiButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
|
color: enableWifiButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
|
||||||
border.width: 0
|
border.width: 1
|
||||||
border.color: Theme.primary
|
border.color: Theme.primary
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: I18n.tr("Enable WiFi")
|
text: "Enable WiFi"
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -180,6 +177,12 @@ Rectangle {
|
|||||||
onClicked: NetworkService.toggleWifiRadio()
|
onClicked: NetworkService.toggleWifiRadio()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,16 +207,16 @@ Rectangle {
|
|||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 200
|
height: 200
|
||||||
visible: NetworkService.wifiInterface && NetworkService.wifiNetworks?.length < 1 && !NetworkService.wifiToggling && NetworkService.isScanning
|
visible: NetworkService.wifiInterface && NetworkService.wifiNetworks?.length < 1 && !NetworkService.wifiToggling
|
||||||
|
|
||||||
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: NetworkService.isScanning
|
running: true
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
from: 0
|
from: 0
|
||||||
to: 360
|
to: 360
|
||||||
@@ -223,18 +226,14 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: sortedNetworks
|
model: {
|
||||||
|
let networks = [...NetworkService.wifiNetworks]
|
||||||
property var sortedNetworks: {
|
networks.sort((a, b) => {
|
||||||
const ssid = NetworkService.currentWifiSSID
|
if (a.ssid === NetworkService.currentWifiSSID) return -1
|
||||||
const networks = NetworkService.wifiNetworks
|
if (b.ssid === NetworkService.currentWifiSSID) return 1
|
||||||
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 sorted
|
return networks
|
||||||
}
|
}
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
required property var modelData
|
required property var modelData
|
||||||
@@ -243,9 +242,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: networkMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
|
color: networkMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHigh
|
||||||
border.color: modelData.ssid === NetworkService.currentWifiSSID ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
border.color: modelData.ssid === NetworkService.currentWifiSSID ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: 0
|
border.width: modelData.ssid === NetworkService.currentWifiSSID ? 2 : 1
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -277,10 +276,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
|
||||||
@@ -333,7 +332,9 @@ Rectangle {
|
|||||||
onClicked: function(event) {
|
onClicked: function(event) {
|
||||||
if (modelData.ssid !== NetworkService.currentWifiSSID) {
|
if (modelData.ssid !== NetworkService.currentWifiSSID) {
|
||||||
if (modelData.secured && !modelData.saved) {
|
if (modelData.secured && !modelData.saved) {
|
||||||
wifiPasswordModal.show(modelData.ssid)
|
if (wifiPasswordModalRef) {
|
||||||
|
wifiPasswordModalRef.show(modelData.ssid)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
NetworkService.connectToWifi(modelData.ssid)
|
NetworkService.connectToWifi(modelData.ssid)
|
||||||
}
|
}
|
||||||
@@ -342,6 +343,13 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,7 +369,7 @@ Rectangle {
|
|||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: Theme.popupBackground()
|
color: Theme.popupBackground()
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.width: 0
|
border.width: 1
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +395,9 @@ Rectangle {
|
|||||||
NetworkService.disconnectWifi()
|
NetworkService.disconnectWifi()
|
||||||
} else {
|
} else {
|
||||||
if (networkContextMenu.currentSecured && !networkContextMenu.currentSaved) {
|
if (networkContextMenu.currentSecured && !networkContextMenu.currentSaved) {
|
||||||
wifiPasswordModal.show(networkContextMenu.currentSSID)
|
if (wifiPasswordModalRef) {
|
||||||
|
wifiPasswordModalRef.show(networkContextMenu.currentSSID)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
NetworkService.connectToWifi(networkContextMenu.currentSSID)
|
NetworkService.connectToWifi(networkContextMenu.currentSSID)
|
||||||
}
|
}
|
||||||
@@ -396,7 +406,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: I18n.tr("Network Info")
|
text: "Network Info"
|
||||||
height: 32
|
height: 32
|
||||||
|
|
||||||
contentItem: StyledText {
|
contentItem: StyledText {
|
||||||
@@ -413,13 +423,15 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
let networkData = NetworkService.getNetworkInfo(networkContextMenu.currentSSID)
|
if (networkInfoModalRef) {
|
||||||
networkInfoModal.showNetworkInfo(networkContextMenu.currentSSID, networkData)
|
let networkData = NetworkService.getNetworkInfo(networkContextMenu.currentSSID)
|
||||||
|
networkInfoModalRef.showNetworkInfo(networkContextMenu.currentSSID, networkData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: I18n.tr("Forget Network")
|
text: "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
|
||||||
|
|
||||||
@@ -442,12 +454,22 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WifiPasswordModal {
|
LazyLoader {
|
||||||
id: wifiPasswordModal
|
id: wifiPasswordModalLoader
|
||||||
|
active: false
|
||||||
|
|
||||||
|
WifiPasswordModal {
|
||||||
|
id: wifiPasswordModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkInfoModal {
|
LazyLoader {
|
||||||
id: networkInfoModal
|
id: networkInfoModalLoader
|
||||||
|
active: false
|
||||||
|
|
||||||
|
NetworkInfoModal {
|
||||||
|
id: networkInfoModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +1,13 @@
|
|||||||
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
|
||||||
|
|
||||||
property var vpnBuiltinInstance: null
|
readonly property var baseWidgetDefinitions: [
|
||||||
|
{
|
||||||
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",
|
||||||
@@ -40,28 +15,32 @@ 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",
|
||||||
@@ -69,7 +48,8 @@ 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",
|
||||||
@@ -77,28 +57,32 @@ 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",
|
||||||
@@ -106,21 +90,24 @@ 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",
|
||||||
@@ -129,68 +116,8 @@ 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",
|
|
||||||
"text": "Color Picker",
|
|
||||||
"description": "Choose colors from palette",
|
|
||||||
"icon": "palette",
|
|
||||||
"type": "action",
|
|
||||||
"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)
|
||||||
@@ -219,4 +146,4 @@ QtObject {
|
|||||||
function clearAll() {
|
function clearAll() {
|
||||||
WidgetUtils.clearAll()
|
WidgetUtils.clearAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,12 +10,6 @@ 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)
|
||||||
|
|
||||||
@@ -50,7 +44,7 @@ PanelWindow {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
||||||
Theme.outline.b, 0.08)
|
Theme.outline.b, 0.08)
|
||||||
border.width: 0
|
border.width: 1
|
||||||
opacity: powerMenuVisible ? 1 : 0
|
opacity: powerMenuVisible ? 1 : 0
|
||||||
scale: powerMenuVisible ? 1 : 0.85
|
scale: powerMenuVisible ? 1 : 0.85
|
||||||
|
|
||||||
@@ -71,7 +65,7 @@ PanelWindow {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: root.powerOptionsText
|
text: "Power Options"
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -124,7 +118,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: root.logOutText
|
text: "Log Out"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -174,7 +168,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: root.suspendText
|
text: "Suspend"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
@@ -224,7 +218,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: root.rebootText
|
text: "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
|
||||||
@@ -274,7 +268,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: root.powerOffText
|
text: "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
|
||||||
|
|||||||
@@ -20,7 +20,11 @@ Row {
|
|||||||
height: Theme.iconSize + Theme.spacingS * 2
|
height: Theme.iconSize + Theme.spacingS * 2
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
||||||
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0)
|
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: iconArea
|
id: iconArea
|
||||||
@@ -30,9 +34,7 @@ Row {
|
|||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (defaultSink) {
|
if (defaultSink) {
|
||||||
AudioService.suppressOSD = true
|
|
||||||
defaultSink.audio.muted = !defaultSink.audio.muted
|
defaultSink.audio.muted = !defaultSink.audio.muted
|
||||||
AudioService.suppressOSD = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ CompoundPill {
|
|||||||
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled) {
|
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled) {
|
||||||
return "bluetooth_disabled"
|
return "bluetooth_disabled"
|
||||||
}
|
}
|
||||||
|
if (primaryDevice) {
|
||||||
|
return BluetoothService.getDeviceIcon(primaryDevice)
|
||||||
|
}
|
||||||
return "bluetooth"
|
return "bluetooth"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,13 +18,17 @@ Row {
|
|||||||
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
||||||
color: iconArea.containsMouse
|
color: iconArea.containsMouse
|
||||||
? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
||||||
: Theme.withAlpha(Theme.primary, 0)
|
: "transparent"
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: iconArea
|
id: iconArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: DisplayService.devices.length > 1 ? Qt.PointingHandCursor : Qt.ArrowCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
|
||||||
onClicked: function(event) {
|
onClicked: function(event) {
|
||||||
if (DisplayService.devices.length > 1) {
|
if (DisplayService.devices.length > 1) {
|
||||||
@@ -37,22 +41,6 @@ Row {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onEntered: {
|
|
||||||
tooltipLoader.active = true
|
|
||||||
if (tooltipLoader.item) {
|
|
||||||
const tooltipText = DisplayService.currentDevice ? "bl device: " + DisplayService.currentDevice : "Backlight Control"
|
|
||||||
const p = iconArea.mapToItem(null, iconArea.width / 2, 0)
|
|
||||||
tooltipLoader.item.show(tooltipText, p.x, p.y - 40, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onExited: {
|
|
||||||
if (tooltipLoader.item) {
|
|
||||||
tooltipLoader.item.hide()
|
|
||||||
}
|
|
||||||
tooltipLoader.active = false
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
name: {
|
name: {
|
||||||
@@ -103,7 +91,7 @@ Row {
|
|||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: Theme.popupBackground()
|
color: Theme.popupBackground()
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.width: 0
|
border.width: 1
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,10 +141,4 @@ Row {
|
|||||||
onObjectRemoved: (index, object) => deviceMenu.removeItem(object)
|
onObjectRemoved: (index, object) => deviceMenu.removeItem(object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: tooltipLoader
|
|
||||||
active: false
|
|
||||||
sourceComponent: DankTooltip {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,33 +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
|
|
||||||
|
|
||||||
property var colorPickerModal: null
|
|
||||||
|
|
||||||
isActive: true
|
|
||||||
iconName: "palette"
|
|
||||||
iconColor: Theme.primary
|
|
||||||
primaryText: "Color Picker"
|
|
||||||
secondaryText: "Choose a color"
|
|
||||||
|
|
||||||
onToggled: {
|
|
||||||
console.log("ColorPickerPill toggled, modal:", colorPickerModal)
|
|
||||||
if (colorPickerModal) {
|
|
||||||
colorPickerModal.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onExpandClicked: {
|
|
||||||
console.log("ColorPickerPill expandClicked, modal:", colorPickerModal)
|
|
||||||
if (colorPickerModal) {
|
|
||||||
colorPickerModal.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,7 @@ Rectangle {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
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: 1
|
||||||
opacity: enabled ? 1.0 : 0.6
|
opacity: enabled ? 1.0 : 0.6
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
|||||||
@@ -29,19 +29,16 @@ Rectangle {
|
|||||||
|
|
||||||
readonly property color _containerBg: Theme.surfaceContainerHigh
|
readonly property color _containerBg: Theme.surfaceContainerHigh
|
||||||
|
|
||||||
color: {
|
color: _containerBg
|
||||||
const baseColor = bodyMouse.containsMouse ? Theme.widgetBaseHoverColor : _containerBg
|
|
||||||
return baseColor
|
|
||||||
}
|
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.10)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.10)
|
||||||
border.width: 0
|
border.width: 1
|
||||||
antialiasing: true
|
antialiasing: true
|
||||||
|
|
||||||
readonly property color _labelPrimary: Theme.surfaceText
|
readonly property color _labelPrimary: Theme.surfaceText
|
||||||
readonly property color _labelSecondary: Theme.surfaceVariantText
|
readonly property color _labelSecondary: Theme.surfaceVariantText
|
||||||
readonly property color _tileBgActive: Theme.primary
|
readonly property color _tileBgActive: Theme.primary
|
||||||
readonly property color _tileBgInactive: {
|
readonly property color _tileBgInactive: {
|
||||||
const transparency = Theme.popupTransparency
|
const transparency = Theme.popupTransparency || 0.92
|
||||||
const surface = Theme.surfaceContainer || Qt.rgba(0.1, 0.1, 0.1, 1)
|
const surface = Theme.surfaceContainer || Qt.rgba(0.1, 0.1, 0.1, 1)
|
||||||
return Qt.rgba(surface.r, surface.g, surface.b, transparency)
|
return Qt.rgba(surface.r, surface.g, surface.b, transparency)
|
||||||
}
|
}
|
||||||
@@ -49,7 +46,7 @@ Rectangle {
|
|||||||
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
|
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
|
||||||
readonly property color _tileRingInactive:
|
readonly property color _tileRingInactive:
|
||||||
Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.18)
|
Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.18)
|
||||||
readonly property color _tileIconActive: Theme.primaryText
|
readonly property color _tileIconActive: Theme.primaryContainer
|
||||||
readonly property color _tileIconInactive: Theme.primary
|
readonly property color _tileIconInactive: Theme.primary
|
||||||
|
|
||||||
property int _padH: Theme.spacingS
|
property int _padH: Theme.spacingS
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,11 @@ Row {
|
|||||||
height: Theme.iconSize + Theme.spacingS * 2
|
height: Theme.iconSize + Theme.spacingS * 2
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
radius: (Theme.iconSize + Theme.spacingS * 2) / 2
|
||||||
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0)
|
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.shortDuration }
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: iconArea
|
id: iconArea
|
||||||
@@ -30,9 +34,7 @@ Row {
|
|||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (defaultSource) {
|
if (defaultSource) {
|
||||||
AudioService.suppressOSD = true
|
|
||||||
defaultSource.audio.muted = !defaultSource.audio.muted
|
defaultSource.audio.muted = !defaultSource.audio.muted
|
||||||
AudioService.suppressOSD = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,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 (defaultSource) {
|
if (defaultSource) {
|
||||||
defaultSource.audio.volume = newValue / 100.0
|
defaultSource.audio.volume = newValue / 100.0
|
||||||
|
|||||||
78
Modules/ControlCenter/Widgets/NetworkPill.qml
Normal file
78
Modules/ControlCenter/Widgets/NetworkPill.qml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,14 +28,10 @@ Rectangle {
|
|||||||
readonly property color _tileBgInactive: Theme.surfaceContainerHigh
|
readonly property color _tileBgInactive: Theme.surfaceContainerHigh
|
||||||
readonly property color _tileRingActive:
|
readonly property color _tileRingActive:
|
||||||
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
|
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
|
||||||
readonly property color _tileIconActive: Theme.primaryText
|
readonly property color _tileIconActive: Theme.primaryContainer
|
||||||
readonly property color _tileIconInactive: Theme.primary
|
readonly property color _tileIconInactive: Theme.primary
|
||||||
|
|
||||||
color: {
|
color: isActive ? _tileBgActive : _tileBgInactive
|
||||||
if (isActive) return _tileBgActive
|
|
||||||
const baseColor = mouseArea.containsMouse ? Theme.widgetBaseHoverColor : _tileBgInactive
|
|
||||||
return baseColor
|
|
||||||
}
|
|
||||||
border.color: isActive ? _tileRingActive : "transparent"
|
border.color: isActive ? _tileRingActive : "transparent"
|
||||||
border.width: isActive ? 1 : 0
|
border.width: isActive ? 1 : 0
|
||||||
antialiasing: true
|
antialiasing: true
|
||||||
@@ -91,6 +87,13 @@ Rectangle {
|
|||||||
onClicked: root.clicked()
|
onClicked: root.clicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Behavior on radius {
|
Behavior on radius {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ Rectangle {
|
|||||||
property real iconRotation: 0
|
property real iconRotation: 0
|
||||||
|
|
||||||
signal clicked()
|
signal clicked()
|
||||||
signal iconRotationCompleted()
|
|
||||||
|
|
||||||
width: parent ? ((parent.width - parent.spacing * 3) / 4) : 48
|
width: parent ? ((parent.width - parent.spacing * 3) / 4) : 48
|
||||||
height: 48
|
height: 48
|
||||||
@@ -30,14 +29,10 @@ Rectangle {
|
|||||||
readonly property color _tileBgInactive: Theme.surfaceContainerHigh
|
readonly property color _tileBgInactive: Theme.surfaceContainerHigh
|
||||||
readonly property color _tileRingActive:
|
readonly property color _tileRingActive:
|
||||||
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
|
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
|
||||||
readonly property color _tileIconActive: Theme.primaryText
|
readonly property color _tileIconActive: Theme.primaryContainer
|
||||||
readonly property color _tileIconInactive: Theme.primary
|
readonly property color _tileIconInactive: Theme.primary
|
||||||
|
|
||||||
color: {
|
color: isActive ? _tileBgActive : _tileBgInactive
|
||||||
if (isActive) return _tileBgActive
|
|
||||||
const baseColor = mouseArea.containsMouse ? Theme.widgetBaseHoverColor : _tileBgInactive
|
|
||||||
return baseColor
|
|
||||||
}
|
|
||||||
border.color: isActive ? _tileRingActive : "transparent"
|
border.color: isActive ? _tileRingActive : "transparent"
|
||||||
border.width: isActive ? 1 : 0
|
border.width: isActive ? 1 : 0
|
||||||
antialiasing: true
|
antialiasing: true
|
||||||
@@ -59,7 +54,6 @@ Rectangle {
|
|||||||
size: Theme.iconSize
|
size: Theme.iconSize
|
||||||
color: isActive ? _tileIconActive : _tileIconInactive
|
color: isActive ? _tileIconActive : _tileIconInactive
|
||||||
rotation: iconRotation
|
rotation: iconRotation
|
||||||
onRotationCompleted: root.iconRotationCompleted()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -71,6 +65,13 @@ Rectangle {
|
|||||||
onClicked: root.clicked()
|
onClicked: root.clicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Behavior on radius {
|
Behavior on radius {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ Rectangle {
|
|||||||
property bool enabled: true
|
property bool enabled: true
|
||||||
property string secondaryText: ""
|
property string secondaryText: ""
|
||||||
property real iconRotation: 0
|
property real iconRotation: 0
|
||||||
|
|
||||||
signal clicked()
|
signal clicked()
|
||||||
signal iconRotationCompleted()
|
|
||||||
|
|
||||||
width: parent ? parent.width : 200
|
width: parent ? parent.width : 200
|
||||||
height: 60
|
height: 60
|
||||||
@@ -28,13 +27,9 @@ Rectangle {
|
|||||||
readonly property color _tileRingActive:
|
readonly property color _tileRingActive:
|
||||||
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
|
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
|
||||||
|
|
||||||
color: {
|
color: isActive ? _tileBgActive : _tileBgInactive
|
||||||
if (isActive) return _tileBgActive
|
|
||||||
const baseColor = mouseArea.containsMouse ? Theme.widgetBaseHoverColor : _tileBgInactive
|
|
||||||
return baseColor
|
|
||||||
}
|
|
||||||
border.color: isActive ? _tileRingActive : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
border.color: isActive ? _tileRingActive : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
border.width: 0
|
border.width: isActive ? 1 : 1
|
||||||
opacity: enabled ? 1.0 : 0.6
|
opacity: enabled ? 1.0 : 0.6
|
||||||
|
|
||||||
function hoverTint(base) {
|
function hoverTint(base) {
|
||||||
@@ -47,7 +42,7 @@ Rectangle {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: mouseArea.containsMouse ? hoverTint(_containerBg) : Theme.withAlpha(_containerBg, 0)
|
color: mouseArea.containsMouse ? hoverTint(_containerBg) : "transparent"
|
||||||
opacity: mouseArea.containsMouse ? 0.08 : 0.0
|
opacity: mouseArea.containsMouse ? 0.08 : 0.0
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
@@ -64,10 +59,9 @@ Rectangle {
|
|||||||
DankIcon {
|
DankIcon {
|
||||||
name: root.iconName
|
name: root.iconName
|
||||||
size: Theme.iconSize
|
size: Theme.iconSize
|
||||||
color: isActive ? Theme.primaryText : Theme.primary
|
color: isActive ? Theme.primaryContainer : Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
rotation: root.iconRotation
|
rotation: root.iconRotation
|
||||||
onRotationCompleted: root.iconRotationCompleted()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -84,7 +78,7 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
text: root.text
|
text: root.text
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: isActive ? Theme.primaryText : Theme.surfaceText
|
color: isActive ? Theme.primaryContainer : Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
@@ -94,7 +88,7 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
text: root.secondaryText
|
text: root.secondaryText
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: isActive ? Theme.primaryText : Theme.surfaceVariantText
|
color: isActive ? Theme.primaryContainer : Theme.surfaceVariantText
|
||||||
visible: text.length > 0
|
visible: text.length > 0
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
@@ -112,6 +106,13 @@ Rectangle {
|
|||||||
onClicked: root.clicked()
|
onClicked: root.clicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Behavior on radius {
|
Behavior on radius {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
|
|||||||
@@ -1,179 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Wayland
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
required property var barWindow
|
|
||||||
required property var axis
|
|
||||||
required property var appDrawerLoader
|
|
||||||
required property var dankDashPopoutLoader
|
|
||||||
required property var processListPopoutLoader
|
|
||||||
required property var notificationCenterLoader
|
|
||||||
required property var batteryPopoutLoader
|
|
||||||
required property var vpnPopoutLoader
|
|
||||||
required property var controlCenterLoader
|
|
||||||
required property var clipboardHistoryModalPopup
|
|
||||||
required property var systemUpdateLoader
|
|
||||||
required property var notepadInstance
|
|
||||||
|
|
||||||
property alias reveal: core.reveal
|
|
||||||
property alias autoHide: core.autoHide
|
|
||||||
property alias backgroundTransparency: core.backgroundTransparency
|
|
||||||
property alias hasActivePopout: core.hasActivePopout
|
|
||||||
property alias mouseArea: topBarMouseArea
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: inputMask
|
|
||||||
|
|
||||||
readonly property int barThickness: barWindow.px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing)
|
|
||||||
|
|
||||||
readonly property bool showing: SettingsData.dankBarVisible && (core.reveal
|
|
||||||
|| (CompositorService.isNiri && NiriService.inOverview && SettingsData.dankBarOpenOnOverview)
|
|
||||||
|| !core.autoHide)
|
|
||||||
|
|
||||||
readonly property int maskThickness: showing ? barThickness : 1
|
|
||||||
|
|
||||||
x: {
|
|
||||||
if (!axis.isVertical) {
|
|
||||||
return 0
|
|
||||||
} else {
|
|
||||||
switch (SettingsData.dankBarPosition) {
|
|
||||||
case SettingsData.Position.Left: return 0
|
|
||||||
case SettingsData.Position.Right: return parent.width - maskThickness
|
|
||||||
default: return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
y: {
|
|
||||||
if (axis.isVertical) {
|
|
||||||
return 0
|
|
||||||
} else {
|
|
||||||
switch (SettingsData.dankBarPosition) {
|
|
||||||
case SettingsData.Position.Top: return 0
|
|
||||||
case SettingsData.Position.Bottom: return parent.height - maskThickness
|
|
||||||
default: return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
width: axis.isVertical ? maskThickness : parent.width
|
|
||||||
height: axis.isVertical ? parent.height : maskThickness
|
|
||||||
}
|
|
||||||
|
|
||||||
Region {
|
|
||||||
id: mask
|
|
||||||
item: inputMask
|
|
||||||
}
|
|
||||||
|
|
||||||
property alias maskRegion: mask
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: core
|
|
||||||
|
|
||||||
property real backgroundTransparency: SettingsData.dankBarTransparency
|
|
||||||
property bool autoHide: SettingsData.dankBarAutoHide
|
|
||||||
property bool revealSticky: false
|
|
||||||
|
|
||||||
property bool notepadInstanceVisible: notepadInstance?.isVisible ?? false
|
|
||||||
|
|
||||||
readonly property bool hasActivePopout: {
|
|
||||||
const loaders = [{
|
|
||||||
"loader": appDrawerLoader,
|
|
||||||
"prop": "shouldBeVisible"
|
|
||||||
}, {
|
|
||||||
"loader": dankDashPopoutLoader,
|
|
||||||
"prop": "shouldBeVisible"
|
|
||||||
}, {
|
|
||||||
"loader": processListPopoutLoader,
|
|
||||||
"prop": "shouldBeVisible"
|
|
||||||
}, {
|
|
||||||
"loader": notificationCenterLoader,
|
|
||||||
"prop": "shouldBeVisible"
|
|
||||||
}, {
|
|
||||||
"loader": batteryPopoutLoader,
|
|
||||||
"prop": "shouldBeVisible"
|
|
||||||
}, {
|
|
||||||
"loader": vpnPopoutLoader,
|
|
||||||
"prop": "shouldBeVisible"
|
|
||||||
}, {
|
|
||||||
"loader": controlCenterLoader,
|
|
||||||
"prop": "shouldBeVisible"
|
|
||||||
}, {
|
|
||||||
"loader": clipboardHistoryModalPopup,
|
|
||||||
"prop": "visible"
|
|
||||||
}, {
|
|
||||||
"loader": systemUpdateLoader,
|
|
||||||
"prop": "shouldBeVisible"
|
|
||||||
}]
|
|
||||||
return notepadInstanceVisible || loaders.some(item => {
|
|
||||||
if (item.loader) {
|
|
||||||
return item.loader?.item?.[item.prop]
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
property bool reveal: {
|
|
||||||
if (CompositorService.isNiri && NiriService.inOverview) {
|
|
||||||
return SettingsData.dankBarOpenOnOverview
|
|
||||||
}
|
|
||||||
return SettingsData.dankBarVisible && (!autoHide || topBarMouseArea.containsMouse || hasActivePopout || revealSticky)
|
|
||||||
}
|
|
||||||
|
|
||||||
onHasActivePopoutChanged: {
|
|
||||||
if (!hasActivePopout && autoHide && !topBarMouseArea.containsMouse) {
|
|
||||||
revealSticky = true
|
|
||||||
revealHold.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: revealHold
|
|
||||||
interval: 250
|
|
||||||
repeat: false
|
|
||||||
onTriggered: core.revealSticky = false
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
function onDankBarTransparencyChanged() {
|
|
||||||
core.backgroundTransparency = SettingsData.dankBarTransparency
|
|
||||||
}
|
|
||||||
|
|
||||||
target: SettingsData
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: topBarMouseArea
|
|
||||||
function onContainsMouseChanged() {
|
|
||||||
if (topBarMouseArea.containsMouse) {
|
|
||||||
core.revealSticky = true
|
|
||||||
revealHold.stop()
|
|
||||||
} else {
|
|
||||||
if (core.autoHide && !core.hasActivePopout) {
|
|
||||||
revealHold.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: topBarMouseArea
|
|
||||||
y: !barWindow.isVertical ? (SettingsData.dankBarPosition === SettingsData.Position.Bottom ? parent.height - height : 0) : 0
|
|
||||||
x: barWindow.isVertical ? (SettingsData.dankBarPosition === SettingsData.Position.Right ? parent.width - width : 0) : 0
|
|
||||||
height: !barWindow.isVertical ? barWindow.px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing) : undefined
|
|
||||||
width: barWindow.isVertical ? barWindow.px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing) : undefined
|
|
||||||
anchors {
|
|
||||||
left: !barWindow.isVertical ? parent.left : (SettingsData.dankBarPosition === SettingsData.Position.Left ? parent.left : undefined)
|
|
||||||
right: !barWindow.isVertical ? parent.right : (SettingsData.dankBarPosition === SettingsData.Position.Right ? parent.right : undefined)
|
|
||||||
top: barWindow.isVertical ? parent.top : undefined
|
|
||||||
bottom: barWindow.isVertical ? parent.bottom : undefined
|
|
||||||
}
|
|
||||||
hoverEnabled: SettingsData.dankBarAutoHide && !core.reveal
|
|
||||||
acceptedButtons: Qt.NoButton
|
|
||||||
enabled: SettingsData.dankBarAutoHide && !core.reveal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property string edge: "top"
|
|
||||||
|
|
||||||
readonly property string orientation: isVertical ? "vertical" : "horizontal"
|
|
||||||
readonly property bool isVertical: edge === "left" || edge === "right"
|
|
||||||
readonly property bool isHorizontal: !isVertical
|
|
||||||
|
|
||||||
function primarySize(item) {
|
|
||||||
return isVertical ? item.height : item.width
|
|
||||||
}
|
|
||||||
|
|
||||||
function crossSize(item) {
|
|
||||||
return isVertical ? item.width : item.height
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPrimaryPos(item, value) {
|
|
||||||
if (isVertical) {
|
|
||||||
item.y = value
|
|
||||||
} else {
|
|
||||||
item.x = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPrimaryPos(item) {
|
|
||||||
return isVertical ? item.y : item.x
|
|
||||||
}
|
|
||||||
|
|
||||||
function primaryAnchor(anchors) {
|
|
||||||
return isVertical ? anchors.verticalCenter : anchors.horizontalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
function crossAnchor(anchors) {
|
|
||||||
return isVertical ? anchors.horizontalCenter : anchors.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
function outerVisualEdge() {
|
|
||||||
if (edge === "bottom") return "bottom"
|
|
||||||
if (edge === "left") return "right"
|
|
||||||
if (edge === "right") return "left"
|
|
||||||
if (edge === "top") return "top"
|
|
||||||
return "bottom"
|
|
||||||
}
|
|
||||||
|
|
||||||
signal axisEdgeChanged()
|
|
||||||
signal axisOrientationChanged()
|
|
||||||
signal changed() // Single coalesced signal
|
|
||||||
|
|
||||||
onEdgeChanged: {
|
|
||||||
axisEdgeChanged()
|
|
||||||
axisOrientationChanged()
|
|
||||||
changed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
required property var barWindow
|
|
||||||
required property var axis
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.leftMargin: -(SettingsData.dankBarGothCornersEnabled && axis.isVertical && axis.edge === "right" ? barWindow._wingR : 0)
|
|
||||||
anchors.rightMargin: -(SettingsData.dankBarGothCornersEnabled && axis.isVertical && axis.edge === "left" ? barWindow._wingR : 0)
|
|
||||||
anchors.topMargin: -(SettingsData.dankBarGothCornersEnabled && !axis.isVertical && axis.edge === "bottom" ? barWindow._wingR : 0)
|
|
||||||
anchors.bottomMargin: -(SettingsData.dankBarGothCornersEnabled && !axis.isVertical && axis.edge === "top" ? barWindow._wingR : 0)
|
|
||||||
|
|
||||||
Canvas {
|
|
||||||
id: barShape
|
|
||||||
anchors.fill: parent
|
|
||||||
antialiasing: true
|
|
||||||
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
|
|
||||||
|
|
||||||
onWingChanged: requestPaint()
|
|
||||||
onRtChanged: requestPaint()
|
|
||||||
onCorrectWidthChanged: requestPaint()
|
|
||||||
onCorrectHeightChanged: requestPaint()
|
|
||||||
onVisibleChanged: if (visible) requestPaint()
|
|
||||||
Component.onCompleted: requestPaint()
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: barWindow
|
|
||||||
function on_BgColorChanged() { barShape.requestPaint() }
|
|
||||||
function on_DprChanged() { barShape.requestPaint() }
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: Theme
|
|
||||||
function onIsLightModeChanged() { barShape.requestPaint() }
|
|
||||||
}
|
|
||||||
|
|
||||||
onPaint: {
|
|
||||||
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
|
|
||||||
|
|
||||||
ctx.scale(scale, scale)
|
|
||||||
|
|
||||||
function drawTopPath() {
|
|
||||||
ctx.beginPath()
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
drawTopPath()
|
|
||||||
ctx.restore()
|
|
||||||
|
|
||||||
ctx.fillStyle = barWindow._bgColor
|
|
||||||
ctx.fill()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Canvas {
|
|
||||||
id: barTint
|
|
||||||
anchors.fill: parent
|
|
||||||
antialiasing: true
|
|
||||||
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 real alphaTint: (barWindow._bgColor?.a ?? 1) < 0.99 ? (Theme.stateLayerOpacity ?? 0) : 0
|
|
||||||
|
|
||||||
onWingChanged: requestPaint()
|
|
||||||
onRtChanged: requestPaint()
|
|
||||||
onAlphaTintChanged: requestPaint()
|
|
||||||
onCorrectWidthChanged: requestPaint()
|
|
||||||
onCorrectHeightChanged: requestPaint()
|
|
||||||
onVisibleChanged: if (visible) requestPaint()
|
|
||||||
Component.onCompleted: requestPaint()
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: barWindow
|
|
||||||
function on_BgColorChanged() { barTint.requestPaint() }
|
|
||||||
function on_DprChanged() { barTint.requestPaint() }
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: Theme
|
|
||||||
function onIsLightModeChanged() { barTint.requestPaint() }
|
|
||||||
}
|
|
||||||
|
|
||||||
onPaint: {
|
|
||||||
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
|
|
||||||
|
|
||||||
ctx.scale(scale, scale)
|
|
||||||
|
|
||||||
function drawTopPath() {
|
|
||||||
ctx.beginPath()
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
drawTopPath()
|
|
||||||
ctx.restore()
|
|
||||||
|
|
||||||
ctx.fillStyle = Qt.rgba(Theme.surface.r, Theme.surface.g, Theme.surface.b, alphaTint)
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,460 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property var widgetsModel: null
|
|
||||||
property var components: null
|
|
||||||
property bool noBackground: false
|
|
||||||
required property var axis
|
|
||||||
property string section: "center"
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
|
|
||||||
readonly property bool isVertical: axis?.isVertical ?? false
|
|
||||||
readonly property real spacing: noBackground ? 2 : Theme.spacingXS
|
|
||||||
|
|
||||||
property var centerWidgets: []
|
|
||||||
property int totalWidgets: 0
|
|
||||||
property real totalSize: 0
|
|
||||||
|
|
||||||
function updateLayout() {
|
|
||||||
const containerSize = isVertical ? height : width
|
|
||||||
if (containerSize <= 0 || !visible) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
centerWidgets = []
|
|
||||||
totalWidgets = 0
|
|
||||||
totalSize = 0
|
|
||||||
|
|
||||||
let configuredWidgets = 0
|
|
||||||
for (var i = 0; i < centerRepeater.count; i++) {
|
|
||||||
const item = centerRepeater.itemAt(i)
|
|
||||||
if (item && getWidgetVisible(item.widgetId)) {
|
|
||||||
configuredWidgets++
|
|
||||||
if (item.active && item.item) {
|
|
||||||
centerWidgets.push(item.item)
|
|
||||||
totalWidgets++
|
|
||||||
totalSize += isVertical ? item.item.height : item.item.width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (totalWidgets > 1) {
|
|
||||||
totalSize += spacing * (totalWidgets - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
positionWidgets(configuredWidgets)
|
|
||||||
}
|
|
||||||
|
|
||||||
function positionWidgets(configuredWidgets) {
|
|
||||||
if (totalWidgets === 0 || (isVertical ? height : width) <= 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const parentCenter = (isVertical ? height : width) / 2
|
|
||||||
const isOdd = configuredWidgets % 2 === 1
|
|
||||||
|
|
||||||
centerWidgets.forEach(widget => {
|
|
||||||
if (isVertical) {
|
|
||||||
widget.anchors.verticalCenter = undefined
|
|
||||||
} else {
|
|
||||||
widget.anchors.horizontalCenter = undefined
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (isOdd) {
|
|
||||||
const middleIndex = Math.floor(configuredWidgets / 2)
|
|
||||||
let currentActiveIndex = 0
|
|
||||||
let middleWidget = null
|
|
||||||
|
|
||||||
for (var i = 0; i < centerRepeater.count; i++) {
|
|
||||||
const item = centerRepeater.itemAt(i)
|
|
||||||
if (item && getWidgetVisible(item.widgetId)) {
|
|
||||||
if (currentActiveIndex === middleIndex && item.active && item.item) {
|
|
||||||
middleWidget = item.item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
currentActiveIndex++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (middleWidget) {
|
|
||||||
const middleSize = isVertical ? middleWidget.height : middleWidget.width
|
|
||||||
if (isVertical) {
|
|
||||||
middleWidget.y = parentCenter - (middleSize / 2)
|
|
||||||
} else {
|
|
||||||
middleWidget.x = parentCenter - (middleSize / 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
let leftWidgets = []
|
|
||||||
let rightWidgets = []
|
|
||||||
let foundMiddle = false
|
|
||||||
|
|
||||||
for (var i = 0; i < centerWidgets.length; i++) {
|
|
||||||
if (centerWidgets[i] === middleWidget) {
|
|
||||||
foundMiddle = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (!foundMiddle) {
|
|
||||||
leftWidgets.push(centerWidgets[i])
|
|
||||||
} else {
|
|
||||||
rightWidgets.push(centerWidgets[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentPos = isVertical ? middleWidget.y : middleWidget.x
|
|
||||||
for (var i = leftWidgets.length - 1; i >= 0; i--) {
|
|
||||||
const size = isVertical ? leftWidgets[i].height : leftWidgets[i].width
|
|
||||||
currentPos -= (spacing + size)
|
|
||||||
if (isVertical) {
|
|
||||||
leftWidgets[i].y = currentPos
|
|
||||||
} else {
|
|
||||||
leftWidgets[i].x = currentPos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPos = (isVertical ? middleWidget.y : middleWidget.x) + middleSize
|
|
||||||
for (var i = 0; i < rightWidgets.length; i++) {
|
|
||||||
currentPos += spacing
|
|
||||||
if (isVertical) {
|
|
||||||
rightWidgets[i].y = currentPos
|
|
||||||
} else {
|
|
||||||
rightWidgets[i].x = currentPos
|
|
||||||
}
|
|
||||||
currentPos += isVertical ? rightWidgets[i].height : rightWidgets[i].width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let configuredLeftIndex = (configuredWidgets / 2) - 1
|
|
||||||
let configuredRightIndex = configuredWidgets / 2
|
|
||||||
const halfSpacing = spacing / 2
|
|
||||||
|
|
||||||
let leftWidget = null
|
|
||||||
let rightWidget = null
|
|
||||||
let leftWidgets = []
|
|
||||||
let rightWidgets = []
|
|
||||||
|
|
||||||
let currentConfigIndex = 0
|
|
||||||
for (var i = 0; i < centerRepeater.count; i++) {
|
|
||||||
const item = centerRepeater.itemAt(i)
|
|
||||||
if (item && getWidgetVisible(item.widgetId)) {
|
|
||||||
if (item.active && item.item) {
|
|
||||||
if (currentConfigIndex < configuredLeftIndex) {
|
|
||||||
leftWidgets.push(item.item)
|
|
||||||
} else if (currentConfigIndex === configuredLeftIndex) {
|
|
||||||
leftWidget = item.item
|
|
||||||
} else if (currentConfigIndex === configuredRightIndex) {
|
|
||||||
rightWidget = item.item
|
|
||||||
} else {
|
|
||||||
rightWidgets.push(item.item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentConfigIndex++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (leftWidget && rightWidget) {
|
|
||||||
const leftSize = isVertical ? leftWidget.height : leftWidget.width
|
|
||||||
if (isVertical) {
|
|
||||||
leftWidget.y = parentCenter - halfSpacing - leftSize
|
|
||||||
rightWidget.y = parentCenter + halfSpacing
|
|
||||||
} else {
|
|
||||||
leftWidget.x = parentCenter - halfSpacing - leftSize
|
|
||||||
rightWidget.x = parentCenter + halfSpacing
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentPos = isVertical ? leftWidget.y : leftWidget.x
|
|
||||||
for (var i = leftWidgets.length - 1; i >= 0; i--) {
|
|
||||||
const size = isVertical ? leftWidgets[i].height : leftWidgets[i].width
|
|
||||||
currentPos -= (spacing + size)
|
|
||||||
if (isVertical) {
|
|
||||||
leftWidgets[i].y = currentPos
|
|
||||||
} else {
|
|
||||||
leftWidgets[i].x = currentPos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPos = (isVertical ? rightWidget.y + rightWidget.height : rightWidget.x + rightWidget.width)
|
|
||||||
for (var i = 0; i < rightWidgets.length; i++) {
|
|
||||||
currentPos += spacing
|
|
||||||
if (isVertical) {
|
|
||||||
rightWidgets[i].y = currentPos
|
|
||||||
} else {
|
|
||||||
rightWidgets[i].x = currentPos
|
|
||||||
}
|
|
||||||
currentPos += isVertical ? rightWidgets[i].height : rightWidgets[i].width
|
|
||||||
}
|
|
||||||
} else if (leftWidget && !rightWidget) {
|
|
||||||
const leftSize = isVertical ? leftWidget.height : leftWidget.width
|
|
||||||
if (isVertical) {
|
|
||||||
leftWidget.y = parentCenter - halfSpacing - leftSize
|
|
||||||
} else {
|
|
||||||
leftWidget.x = parentCenter - halfSpacing - leftSize
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentPos = isVertical ? leftWidget.y : leftWidget.x
|
|
||||||
for (var i = leftWidgets.length - 1; i >= 0; i--) {
|
|
||||||
const size = isVertical ? leftWidgets[i].height : leftWidgets[i].width
|
|
||||||
currentPos -= (spacing + size)
|
|
||||||
if (isVertical) {
|
|
||||||
leftWidgets[i].y = currentPos
|
|
||||||
} else {
|
|
||||||
leftWidgets[i].x = currentPos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPos = (isVertical ? leftWidget.y + leftWidget.height : leftWidget.x + leftWidget.width) + spacing
|
|
||||||
for (var i = 0; i < rightWidgets.length; i++) {
|
|
||||||
currentPos += spacing
|
|
||||||
if (isVertical) {
|
|
||||||
rightWidgets[i].y = currentPos
|
|
||||||
} else {
|
|
||||||
rightWidgets[i].x = currentPos
|
|
||||||
}
|
|
||||||
currentPos += isVertical ? rightWidgets[i].height : rightWidgets[i].width
|
|
||||||
}
|
|
||||||
} else if (!leftWidget && rightWidget) {
|
|
||||||
if (isVertical) {
|
|
||||||
rightWidget.y = parentCenter + halfSpacing
|
|
||||||
} else {
|
|
||||||
rightWidget.x = parentCenter + halfSpacing
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentPos = (isVertical ? rightWidget.y : rightWidget.x) - spacing
|
|
||||||
for (var i = leftWidgets.length - 1; i >= 0; i--) {
|
|
||||||
const size = isVertical ? leftWidgets[i].height : leftWidgets[i].width
|
|
||||||
currentPos -= size
|
|
||||||
if (isVertical) {
|
|
||||||
leftWidgets[i].y = currentPos
|
|
||||||
} else {
|
|
||||||
leftWidgets[i].x = currentPos
|
|
||||||
}
|
|
||||||
currentPos -= spacing
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPos = (isVertical ? rightWidget.y + rightWidget.height : rightWidget.x + rightWidget.width)
|
|
||||||
for (var i = 0; i < rightWidgets.length; i++) {
|
|
||||||
currentPos += spacing
|
|
||||||
if (isVertical) {
|
|
||||||
rightWidgets[i].y = currentPos
|
|
||||||
} else {
|
|
||||||
rightWidgets[i].x = currentPos
|
|
||||||
}
|
|
||||||
currentPos += isVertical ? rightWidgets[i].height : rightWidgets[i].width
|
|
||||||
}
|
|
||||||
} else if (totalWidgets === 1 && centerWidgets[0]) {
|
|
||||||
const size = isVertical ? centerWidgets[0].height : centerWidgets[0].width
|
|
||||||
if (isVertical) {
|
|
||||||
centerWidgets[0].y = parentCenter - (size / 2)
|
|
||||||
} else {
|
|
||||||
centerWidgets[0].x = parentCenter - (size / 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWidgetVisible(widgetId) {
|
|
||||||
const widgetVisibility = {
|
|
||||||
"cpuUsage": DgopService.dgopAvailable,
|
|
||||||
"memUsage": DgopService.dgopAvailable,
|
|
||||||
"cpuTemp": DgopService.dgopAvailable,
|
|
||||||
"gpuTemp": DgopService.dgopAvailable,
|
|
||||||
"network_speed_monitor": DgopService.dgopAvailable
|
|
||||||
}
|
|
||||||
return widgetVisibility[widgetId] ?? true
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWidgetComponent(widgetId) {
|
|
||||||
// Build dynamic component map including plugins
|
|
||||||
let baseMap = {
|
|
||||||
"launcherButton": "launcherButtonComponent",
|
|
||||||
"workspaceSwitcher": "workspaceSwitcherComponent",
|
|
||||||
"focusedWindow": "focusedWindowComponent",
|
|
||||||
"runningApps": "runningAppsComponent",
|
|
||||||
"clock": "clockComponent",
|
|
||||||
"music": "mediaComponent",
|
|
||||||
"weather": "weatherComponent",
|
|
||||||
"systemTray": "systemTrayComponent",
|
|
||||||
"privacyIndicator": "privacyIndicatorComponent",
|
|
||||||
"clipboard": "clipboardComponent",
|
|
||||||
"cpuUsage": "cpuUsageComponent",
|
|
||||||
"memUsage": "memUsageComponent",
|
|
||||||
"diskUsage": "diskUsageComponent",
|
|
||||||
"cpuTemp": "cpuTempComponent",
|
|
||||||
"gpuTemp": "gpuTempComponent",
|
|
||||||
"notificationButton": "notificationButtonComponent",
|
|
||||||
"battery": "batteryComponent",
|
|
||||||
"controlCenterButton": "controlCenterButtonComponent",
|
|
||||||
"idleInhibitor": "idleInhibitorComponent",
|
|
||||||
"spacer": "spacerComponent",
|
|
||||||
"separator": "separatorComponent",
|
|
||||||
"network_speed_monitor": "networkComponent",
|
|
||||||
"keyboard_layout_name": "keyboardLayoutNameComponent",
|
|
||||||
"vpn": "vpnComponent",
|
|
||||||
"notepadButton": "notepadButtonComponent",
|
|
||||||
"colorPicker": "colorPickerComponent",
|
|
||||||
"systemUpdate": "systemUpdateComponent"
|
|
||||||
}
|
|
||||||
|
|
||||||
// For built-in components, get from components property
|
|
||||||
const componentKey = baseMap[widgetId]
|
|
||||||
if (componentKey && root.components[componentKey]) {
|
|
||||||
return root.components[componentKey]
|
|
||||||
}
|
|
||||||
|
|
||||||
// For plugin components, get from PluginService
|
|
||||||
var parts = widgetId.split(":")
|
|
||||||
var pluginId = parts[0]
|
|
||||||
let pluginComponents = PluginService.getWidgetComponents()
|
|
||||||
return pluginComponents[pluginId] || null
|
|
||||||
}
|
|
||||||
|
|
||||||
height: parent.height
|
|
||||||
width: parent.width
|
|
||||||
anchors.centerIn: parent
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: layoutTimer
|
|
||||||
interval: 0
|
|
||||||
repeat: false
|
|
||||||
onTriggered: root.updateLayout()
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
layoutTimer.restart()
|
|
||||||
}
|
|
||||||
|
|
||||||
onWidthChanged: {
|
|
||||||
if (width > 0) {
|
|
||||||
layoutTimer.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onHeightChanged: {
|
|
||||||
if (height > 0) {
|
|
||||||
layoutTimer.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (visible && (isVertical ? height : width) > 0) {
|
|
||||||
layoutTimer.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
id: centerRepeater
|
|
||||||
model: root.widgetsModel
|
|
||||||
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
property string widgetId: model.widgetId
|
|
||||||
property var widgetData: model
|
|
||||||
property int spacerSize: model.size || 20
|
|
||||||
|
|
||||||
anchors.verticalCenter: !root.isVertical ? parent.verticalCenter : undefined
|
|
||||||
anchors.horizontalCenter: root.isVertical ? parent.horizontalCenter : undefined
|
|
||||||
active: root.getWidgetVisible(model.widgetId) && (model.widgetId !== "music" || MprisController.activePlayer !== null)
|
|
||||||
sourceComponent: root.getWidgetComponent(model.widgetId)
|
|
||||||
opacity: (model.enabled !== false) ? 1 : 0
|
|
||||||
asynchronous: false
|
|
||||||
|
|
||||||
onLoaded: {
|
|
||||||
if (!item) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
item.widthChanged.connect(() => layoutTimer.restart())
|
|
||||||
item.heightChanged.connect(() => layoutTimer.restart())
|
|
||||||
if (model.widgetId === "spacer") {
|
|
||||||
item.spacerSize = Qt.binding(() => model.size || 20)
|
|
||||||
}
|
|
||||||
if (root.axis && "axis" in item) {
|
|
||||||
item.axis = Qt.binding(() => root.axis)
|
|
||||||
}
|
|
||||||
if (root.axis && "isVertical" in item) {
|
|
||||||
try {
|
|
||||||
item.isVertical = Qt.binding(() => root.axis.isVertical)
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inject properties for plugin widgets
|
|
||||||
if ("section" in item) {
|
|
||||||
item.section = root.section
|
|
||||||
}
|
|
||||||
if ("parentScreen" in item) {
|
|
||||||
item.parentScreen = Qt.binding(() => root.parentScreen)
|
|
||||||
}
|
|
||||||
if ("widgetThickness" in item) {
|
|
||||||
item.widgetThickness = Qt.binding(() => root.widgetThickness)
|
|
||||||
}
|
|
||||||
if ("barThickness" in item) {
|
|
||||||
item.barThickness = Qt.binding(() => root.barThickness)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inject PluginService for plugin widgets
|
|
||||||
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) {
|
|
||||||
item.pluginId = pluginId
|
|
||||||
}
|
|
||||||
if (item.variantId !== undefined) {
|
|
||||||
item.variantId = variantId
|
|
||||||
}
|
|
||||||
if (item.variantData !== undefined && variantId) {
|
|
||||||
item.variantData = PluginService.getPluginVariantData(pluginId, variantId)
|
|
||||||
}
|
|
||||||
item.pluginService = PluginService
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.popoutService !== undefined) {
|
|
||||||
item.popoutService = PopoutService
|
|
||||||
}
|
|
||||||
|
|
||||||
layoutTimer.restart()
|
|
||||||
}
|
|
||||||
|
|
||||||
onActiveChanged: {
|
|
||||||
layoutTimer.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: widgetsModel
|
|
||||||
function onCountChanged() {
|
|
||||||
layoutTimer.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listen for plugin changes and refresh components
|
|
||||||
Connections {
|
|
||||||
target: PluginService
|
|
||||||
function onPluginLoaded(pluginId) {
|
|
||||||
// Force refresh of component lookups
|
|
||||||
for (var i = 0; i < centerRepeater.count; i++) {
|
|
||||||
var item = centerRepeater.itemAt(i)
|
|
||||||
if (item && item.widgetId.startsWith(pluginId)) {
|
|
||||||
item.sourceComponent = root.getWidgetComponent(item.widgetId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function onPluginUnloaded(pluginId) {
|
|
||||||
// Force refresh of component lookups
|
|
||||||
for (var i = 0; i < centerRepeater.count; i++) {
|
|
||||||
var item = centerRepeater.itemAt(i)
|
|
||||||
if (item && item.widgetId.startsWith(pluginId)) {
|
|
||||||
item.sourceComponent = root.getWidgetComponent(item.widgetId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,82 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property var widgetsModel: null
|
|
||||||
property var components: null
|
|
||||||
property bool noBackground: false
|
|
||||||
required property var axis
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
|
|
||||||
readonly property bool isVertical: axis?.isVertical ?? false
|
|
||||||
|
|
||||||
implicitHeight: layoutLoader.item ? (layoutLoader.item.implicitHeight || layoutLoader.item.height) : 0
|
|
||||||
implicitWidth: layoutLoader.item ? (layoutLoader.item.implicitWidth || layoutLoader.item.width) : 0
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: layoutLoader
|
|
||||||
anchors.fill: parent
|
|
||||||
sourceComponent: root.isVertical ? columnComp : rowComp
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: rowComp
|
|
||||||
Row {
|
|
||||||
spacing: noBackground ? 2 : Theme.spacingXS
|
|
||||||
Repeater {
|
|
||||||
model: root.widgetsModel
|
|
||||||
Item {
|
|
||||||
width: widgetLoader.item ? widgetLoader.item.width : 0
|
|
||||||
height: widgetLoader.item ? widgetLoader.item.height : 0
|
|
||||||
WidgetHost {
|
|
||||||
id: widgetLoader
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
widgetId: model.widgetId
|
|
||||||
widgetData: model
|
|
||||||
spacerSize: model.size || 20
|
|
||||||
components: root.components
|
|
||||||
isInColumn: false
|
|
||||||
axis: root.axis
|
|
||||||
section: "left"
|
|
||||||
parentScreen: root.parentScreen
|
|
||||||
widgetThickness: root.widgetThickness
|
|
||||||
barThickness: root.barThickness
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: columnComp
|
|
||||||
Column {
|
|
||||||
width: Math.max(parent.width, 200)
|
|
||||||
spacing: noBackground ? 2 : Theme.spacingXS
|
|
||||||
Repeater {
|
|
||||||
model: root.widgetsModel
|
|
||||||
Item {
|
|
||||||
width: parent.width
|
|
||||||
height: widgetLoader.item ? widgetLoader.item.height : 0
|
|
||||||
WidgetHost {
|
|
||||||
id: widgetLoader
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
widgetId: model.widgetId
|
|
||||||
widgetData: model
|
|
||||||
spacerSize: model.size || 20
|
|
||||||
components: root.components
|
|
||||||
isInColumn: true
|
|
||||||
axis: root.axis
|
|
||||||
section: "left"
|
|
||||||
parentScreen: root.parentScreen
|
|
||||||
widgetThickness: root.widgetThickness
|
|
||||||
barThickness: root.barThickness
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property var widgetsModel: null
|
|
||||||
property var components: null
|
|
||||||
property bool noBackground: false
|
|
||||||
required property var axis
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
|
|
||||||
readonly property bool isVertical: axis?.isVertical ?? false
|
|
||||||
|
|
||||||
implicitHeight: layoutLoader.item ? layoutLoader.item.implicitHeight : 0
|
|
||||||
implicitWidth: layoutLoader.item ? layoutLoader.item.implicitWidth : 0
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: layoutLoader
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
sourceComponent: root.isVertical ? columnComp : rowComp
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: rowComp
|
|
||||||
Row {
|
|
||||||
spacing: noBackground ? 2 : Theme.spacingXS
|
|
||||||
anchors.right: parent ? parent.right : undefined
|
|
||||||
Repeater {
|
|
||||||
model: root.widgetsModel
|
|
||||||
Item {
|
|
||||||
width: widgetLoader.item ? widgetLoader.item.width : 0
|
|
||||||
height: widgetLoader.item ? widgetLoader.item.height : 0
|
|
||||||
WidgetHost {
|
|
||||||
id: widgetLoader
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
widgetId: model.widgetId
|
|
||||||
widgetData: model
|
|
||||||
spacerSize: model.size || 20
|
|
||||||
components: root.components
|
|
||||||
isInColumn: false
|
|
||||||
axis: root.axis
|
|
||||||
section: "right"
|
|
||||||
parentScreen: root.parentScreen
|
|
||||||
widgetThickness: root.widgetThickness
|
|
||||||
barThickness: root.barThickness
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: columnComp
|
|
||||||
Column {
|
|
||||||
width: parent ? parent.width : 0
|
|
||||||
spacing: noBackground ? 2 : Theme.spacingXS
|
|
||||||
Repeater {
|
|
||||||
model: root.widgetsModel
|
|
||||||
Item {
|
|
||||||
width: parent.width
|
|
||||||
height: widgetLoader.item ? widgetLoader.item.height : 0
|
|
||||||
WidgetHost {
|
|
||||||
id: widgetLoader
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
widgetId: model.widgetId
|
|
||||||
widgetData: model
|
|
||||||
spacerSize: model.size || 20
|
|
||||||
components: root.components
|
|
||||||
isInColumn: true
|
|
||||||
axis: root.axis
|
|
||||||
section: "right"
|
|
||||||
parentScreen: root.parentScreen
|
|
||||||
widgetThickness: root.widgetThickness
|
|
||||||
barThickness: root.barThickness
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell.Services.Mpris
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property string widgetId: ""
|
|
||||||
property var widgetData: null
|
|
||||||
property int spacerSize: 20
|
|
||||||
property var components: null
|
|
||||||
property bool isInColumn: false
|
|
||||||
property var axis: null
|
|
||||||
property string section: "center"
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
|
|
||||||
asynchronous: false
|
|
||||||
|
|
||||||
active: getWidgetVisible(widgetId, DgopService.dgopAvailable) &&
|
|
||||||
(widgetId !== "music" || MprisController.activePlayer !== null)
|
|
||||||
sourceComponent: getWidgetComponent(widgetId, components)
|
|
||||||
opacity: getWidgetEnabled(widgetData?.enabled) ? 1 : 0
|
|
||||||
|
|
||||||
signal contentItemReady(var item)
|
|
||||||
|
|
||||||
Binding {
|
|
||||||
target: root.item
|
|
||||||
when: root.item && "parentScreen" in root.item
|
|
||||||
property: "parentScreen"
|
|
||||||
value: root.parentScreen
|
|
||||||
restoreMode: Binding.RestoreNone
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding {
|
|
||||||
target: root.item
|
|
||||||
when: root.item && "section" in root.item
|
|
||||||
property: "section"
|
|
||||||
value: root.section
|
|
||||||
restoreMode: Binding.RestoreNone
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding {
|
|
||||||
target: root.item
|
|
||||||
when: root.item && "widgetThickness" in root.item
|
|
||||||
property: "widgetThickness"
|
|
||||||
value: root.widgetThickness
|
|
||||||
restoreMode: Binding.RestoreNone
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding {
|
|
||||||
target: root.item
|
|
||||||
when: root.item && "barThickness" in root.item
|
|
||||||
property: "barThickness"
|
|
||||||
value: root.barThickness
|
|
||||||
restoreMode: Binding.RestoreNone
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding {
|
|
||||||
target: root.item
|
|
||||||
when: root.item && "axis" in root.item
|
|
||||||
property: "axis"
|
|
||||||
value: root.axis
|
|
||||||
restoreMode: Binding.RestoreNone
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding {
|
|
||||||
target: root.item
|
|
||||||
when: root.item && "widgetData" in root.item
|
|
||||||
property: "widgetData"
|
|
||||||
value: root.widgetData
|
|
||||||
restoreMode: Binding.RestoreNone
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoaded: {
|
|
||||||
if (item) {
|
|
||||||
contentItemReady(item)
|
|
||||||
if (widgetId === "spacer") {
|
|
||||||
item.spacerSize = Qt.binding(() => spacerSize)
|
|
||||||
}
|
|
||||||
if (axis && "isVertical" in item) {
|
|
||||||
try {
|
|
||||||
item.isVertical = axis.isVertical
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.pluginService !== undefined) {
|
|
||||||
var parts = widgetId.split(":")
|
|
||||||
var pluginId = parts[0]
|
|
||||||
var variantId = parts.length > 1 ? parts[1] : null
|
|
||||||
|
|
||||||
if (item.pluginId !== undefined) {
|
|
||||||
item.pluginId = pluginId
|
|
||||||
}
|
|
||||||
if (item.variantId !== undefined) {
|
|
||||||
item.variantId = variantId
|
|
||||||
}
|
|
||||||
if (item.variantData !== undefined && variantId) {
|
|
||||||
item.variantData = PluginService.getPluginVariantData(pluginId, variantId)
|
|
||||||
}
|
|
||||||
item.pluginService = PluginService
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.popoutService !== undefined) {
|
|
||||||
item.popoutService = PopoutService
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWidgetComponent(widgetId, components) {
|
|
||||||
const componentMap = {
|
|
||||||
"launcherButton": components.launcherButtonComponent,
|
|
||||||
"workspaceSwitcher": components.workspaceSwitcherComponent,
|
|
||||||
"focusedWindow": components.focusedWindowComponent,
|
|
||||||
"runningApps": components.runningAppsComponent,
|
|
||||||
"clock": components.clockComponent,
|
|
||||||
"music": components.mediaComponent,
|
|
||||||
"weather": components.weatherComponent,
|
|
||||||
"systemTray": components.systemTrayComponent,
|
|
||||||
"privacyIndicator": components.privacyIndicatorComponent,
|
|
||||||
"clipboard": components.clipboardComponent,
|
|
||||||
"cpuUsage": components.cpuUsageComponent,
|
|
||||||
"memUsage": components.memUsageComponent,
|
|
||||||
"diskUsage": components.diskUsageComponent,
|
|
||||||
"cpuTemp": components.cpuTempComponent,
|
|
||||||
"gpuTemp": components.gpuTempComponent,
|
|
||||||
"notificationButton": components.notificationButtonComponent,
|
|
||||||
"battery": components.batteryComponent,
|
|
||||||
"controlCenterButton": components.controlCenterButtonComponent,
|
|
||||||
"idleInhibitor": components.idleInhibitorComponent,
|
|
||||||
"spacer": components.spacerComponent,
|
|
||||||
"separator": components.separatorComponent,
|
|
||||||
"network_speed_monitor": components.networkComponent,
|
|
||||||
"keyboard_layout_name": components.keyboardLayoutNameComponent,
|
|
||||||
"vpn": components.vpnComponent,
|
|
||||||
"notepadButton": components.notepadButtonComponent,
|
|
||||||
"colorPicker": components.colorPickerComponent,
|
|
||||||
"systemUpdate": components.systemUpdateComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
if (componentMap[widgetId]) {
|
|
||||||
return componentMap[widgetId]
|
|
||||||
}
|
|
||||||
|
|
||||||
var parts = widgetId.split(":")
|
|
||||||
var pluginId = parts[0]
|
|
||||||
|
|
||||||
let pluginMap = PluginService.getWidgetComponents()
|
|
||||||
return pluginMap[pluginId] || null
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWidgetVisible(widgetId, dgopAvailable) {
|
|
||||||
const widgetVisibility = {
|
|
||||||
"cpuUsage": dgopAvailable,
|
|
||||||
"memUsage": dgopAvailable,
|
|
||||||
"cpuTemp": dgopAvailable,
|
|
||||||
"gpuTemp": dgopAvailable,
|
|
||||||
"network_speed_monitor": dgopAvailable
|
|
||||||
}
|
|
||||||
|
|
||||||
return widgetVisibility[widgetId] ?? true
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWidgetEnabled(enabled) {
|
|
||||||
return enabled !== false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell.Services.UPower
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: battery
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property bool batteryPopupVisible: false
|
|
||||||
property string section: "right"
|
|
||||||
property var popupTarget: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
|
||||||
|
|
||||||
signal toggleBatteryPopup()
|
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (batteryContent.implicitWidth + horizontalPadding * 2)
|
|
||||||
height: isVertical ? (batteryColumn.implicitHeight + horizontalPadding * 2) : widgetThickness
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = batteryArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
visible: true
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: batteryColumn
|
|
||||||
visible: battery.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 1
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: BatteryService.getBatteryIcon()
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: {
|
|
||||||
if (!BatteryService.batteryAvailable) {
|
|
||||||
return Theme.surfaceText
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BatteryService.isLowBattery && !BatteryService.isCharging) {
|
|
||||||
return Theme.error
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BatteryService.isCharging || BatteryService.isPluggedIn) {
|
|
||||||
return Theme.primary
|
|
||||||
}
|
|
||||||
|
|
||||||
return Theme.surfaceText
|
|
||||||
}
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: BatteryService.batteryLevel.toString()
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: BatteryService.batteryAvailable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: batteryContent
|
|
||||||
visible: !battery.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: SettingsData.dankBarNoBackground ? 1 : 2
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: BatteryService.getBatteryIcon()
|
|
||||||
size: Theme.barIconSize(barThickness, -4)
|
|
||||||
color: {
|
|
||||||
if (!BatteryService.batteryAvailable) {
|
|
||||||
return Theme.surfaceText;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BatteryService.isLowBattery && !BatteryService.isCharging) {
|
|
||||||
return Theme.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BatteryService.isCharging || BatteryService.isPluggedIn) {
|
|
||||||
return Theme.primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Theme.surfaceText;
|
|
||||||
}
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: `${BatteryService.batteryLevel}%`
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: BatteryService.batteryAvailable
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: batteryArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
|
||||||
const globalPos = mapToGlobal(0, 0)
|
|
||||||
const currentScreen = parentScreen || Screen
|
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
|
||||||
popupTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
|
||||||
}
|
|
||||||
toggleBatteryPopup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isActive: false
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property string section: "right"
|
|
||||||
property var clipboardHistoryModal: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
|
||||||
|
|
||||||
signal clicked()
|
|
||||||
|
|
||||||
width: widgetThickness
|
|
||||||
height: widgetThickness
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: clipboardArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
onPressed: {
|
|
||||||
root.clicked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: clipboardContent
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent"
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = clipboardArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency)
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
name: "content_paste"
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import qs.Common
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property bool compactMode: false
|
|
||||||
property string section: "center"
|
|
||||||
property var popupTarget: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property real barThickness: 48
|
|
||||||
property real widgetThickness: 30
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
|
||||||
|
|
||||||
signal clockClicked
|
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (clockRow.implicitWidth + horizontalPadding * 2)
|
|
||||||
height: isVertical ? (clockColumn.implicitHeight + horizontalPadding * 2) : widgetThickness
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = clockMouseArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: clockColumn
|
|
||||||
visible: root.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: -2
|
|
||||||
|
|
||||||
Row {
|
|
||||||
spacing: 0
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
if (SettingsData.use24HourClock) {
|
|
||||||
return String(systemClock?.date?.getHours()).padStart(2, '0').charAt(0)
|
|
||||||
} else {
|
|
||||||
const hours = systemClock?.date?.getHours()
|
|
||||||
const display = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours
|
|
||||||
return String(display).padStart(2, '0').charAt(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Normal
|
|
||||||
width: 9
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
if (SettingsData.use24HourClock) {
|
|
||||||
return String(systemClock?.date?.getHours()).padStart(2, '0').charAt(1)
|
|
||||||
} else {
|
|
||||||
const hours = systemClock?.date?.getHours()
|
|
||||||
const display = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours
|
|
||||||
return String(display).padStart(2, '0').charAt(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Normal
|
|
||||||
width: 9
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
spacing: 0
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(0)
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Normal
|
|
||||||
width: 9
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(1)
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Normal
|
|
||||||
width: 9
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: 12
|
|
||||||
height: Theme.spacingM
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 12
|
|
||||||
height: 1
|
|
||||||
color: Theme.outlineButton
|
|
||||||
anchors.centerIn: parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
spacing: 0
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
const locale = Qt.locale()
|
|
||||||
const dateFormatShort = locale.dateFormat(Locale.ShortFormat)
|
|
||||||
const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M')
|
|
||||||
const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0')
|
|
||||||
return value.charAt(0)
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.primary
|
|
||||||
font.weight: Font.Light
|
|
||||||
width: 9
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
const locale = Qt.locale()
|
|
||||||
const dateFormatShort = locale.dateFormat(Locale.ShortFormat)
|
|
||||||
const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M')
|
|
||||||
const value = dayFirst ? String(systemClock?.date?.getDate()).padStart(2, '0') : String(systemClock?.date?.getMonth() + 1).padStart(2, '0')
|
|
||||||
return value.charAt(1)
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.primary
|
|
||||||
font.weight: Font.Light
|
|
||||||
width: 9
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
spacing: 0
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
const locale = Qt.locale()
|
|
||||||
const dateFormatShort = locale.dateFormat(Locale.ShortFormat)
|
|
||||||
const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M')
|
|
||||||
const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0')
|
|
||||||
return value.charAt(0)
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.primary
|
|
||||||
font.weight: Font.Light
|
|
||||||
width: 9
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
const locale = Qt.locale()
|
|
||||||
const dateFormatShort = locale.dateFormat(Locale.ShortFormat)
|
|
||||||
const dayFirst = dateFormatShort.indexOf('d') < dateFormatShort.indexOf('M')
|
|
||||||
const value = dayFirst ? String(systemClock?.date?.getMonth() + 1).padStart(2, '0') : String(systemClock?.date?.getDate()).padStart(2, '0')
|
|
||||||
return value.charAt(1)
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.primary
|
|
||||||
font.weight: Font.Light
|
|
||||||
width: 9
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: clockRow
|
|
||||||
|
|
||||||
visible: !root.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP"
|
|
||||||
return systemClock?.date?.toLocaleTimeString(Qt.locale(), format)
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: "•"
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.outlineButton
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: !SettingsData.clockCompactMode
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0) {
|
|
||||||
return systemClock?.date?.toLocaleDateString(Qt.locale(), SettingsData.clockDateFormat)
|
|
||||||
}
|
|
||||||
|
|
||||||
return systemClock?.date?.toLocaleDateString(Qt.locale(), "ddd d")
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: !SettingsData.clockCompactMode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SystemClock {
|
|
||||||
id: systemClock
|
|
||||||
precision: SystemClock.Seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: clockMouseArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
|
||||||
const globalPos = mapToGlobal(0, 0)
|
|
||||||
const currentScreen = parentScreen || Screen
|
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
|
||||||
popupTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
|
||||||
}
|
|
||||||
root.clockClicked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,268 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property bool isActive: false
|
|
||||||
property string section: "right"
|
|
||||||
property var popupTarget: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property var widgetData: null
|
|
||||||
property bool showNetworkIcon: SettingsData.controlCenterShowNetworkIcon
|
|
||||||
property bool showBluetoothIcon: SettingsData.controlCenterShowBluetoothIcon
|
|
||||||
property bool showAudioIcon: SettingsData.controlCenterShowAudioIcon
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
|
||||||
|
|
||||||
signal clicked()
|
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (controlIndicators.implicitWidth + horizontalPadding * 2)
|
|
||||||
height: isVertical ? (controlColumn.implicitHeight + horizontalPadding * 2) : widgetThickness
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = controlCenterArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: controlColumn
|
|
||||||
visible: root.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: {
|
|
||||||
if (NetworkService.wifiToggling) {
|
|
||||||
return "sync"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NetworkService.networkStatus === "ethernet") {
|
|
||||||
return "lan"
|
|
||||||
}
|
|
||||||
|
|
||||||
return NetworkService.wifiSignalIcon
|
|
||||||
}
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: {
|
|
||||||
if (NetworkService.wifiToggling) {
|
|
||||||
return Theme.primary
|
|
||||||
}
|
|
||||||
|
|
||||||
return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton
|
|
||||||
}
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showNetworkIcon && NetworkService.networkAvailable
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: "bluetooth"
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: audioIconV.implicitWidth + 4
|
|
||||||
height: audioIconV.implicitHeight + 4
|
|
||||||
color: "transparent"
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showAudioIcon
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
id: audioIconV
|
|
||||||
|
|
||||||
name: {
|
|
||||||
if (AudioService.sink && AudioService.sink.audio) {
|
|
||||||
if (AudioService.sink.audio.muted || AudioService.sink.audio.volume === 0) {
|
|
||||||
return "volume_off"
|
|
||||||
} else if (AudioService.sink.audio.volume * 100 < 33) {
|
|
||||||
return "volume_down"
|
|
||||||
} else {
|
|
||||||
return "volume_up"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "volume_up"
|
|
||||||
}
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.centerIn: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
acceptedButtons: Qt.NoButton
|
|
||||||
onWheel: function(wheelEvent) {
|
|
||||||
let delta = wheelEvent.angleDelta.y
|
|
||||||
let currentVolume = (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) || 0
|
|
||||||
let newVolume
|
|
||||||
if (delta > 0) {
|
|
||||||
newVolume = Math.min(100, currentVolume + 5)
|
|
||||||
} else {
|
|
||||||
newVolume = Math.max(0, currentVolume - 5)
|
|
||||||
}
|
|
||||||
if (AudioService.sink && AudioService.sink.audio) {
|
|
||||||
AudioService.sink.audio.muted = false
|
|
||||||
AudioService.sink.audio.volume = newVolume / 100
|
|
||||||
AudioService.volumeChanged()
|
|
||||||
}
|
|
||||||
wheelEvent.accepted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: "settings"
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: controlCenterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: controlIndicators
|
|
||||||
visible: !root.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
id: networkIcon
|
|
||||||
|
|
||||||
name: {
|
|
||||||
if (NetworkService.wifiToggling) {
|
|
||||||
return "sync";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NetworkService.networkStatus === "ethernet") {
|
|
||||||
return "lan";
|
|
||||||
}
|
|
||||||
|
|
||||||
return NetworkService.wifiSignalIcon;
|
|
||||||
}
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: {
|
|
||||||
if (NetworkService.wifiToggling) {
|
|
||||||
return Theme.primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton;
|
|
||||||
}
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: root.showNetworkIcon && NetworkService.networkAvailable
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
id: bluetoothIcon
|
|
||||||
|
|
||||||
name: "bluetooth"
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: audioIcon.implicitWidth + 4
|
|
||||||
height: audioIcon.implicitHeight + 4
|
|
||||||
color: "transparent"
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: root.showAudioIcon
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
id: audioIcon
|
|
||||||
|
|
||||||
name: {
|
|
||||||
if (AudioService.sink && AudioService.sink.audio) {
|
|
||||||
if (AudioService.sink.audio.muted || AudioService.sink.audio.volume === 0) {
|
|
||||||
return "volume_off";
|
|
||||||
} else if (AudioService.sink.audio.volume * 100 < 33) {
|
|
||||||
return "volume_down";
|
|
||||||
} else {
|
|
||||||
return "volume_up";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "volume_up";
|
|
||||||
}
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.centerIn: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: audioWheelArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
acceptedButtons: Qt.NoButton
|
|
||||||
onWheel: function(wheelEvent) {
|
|
||||||
let delta = wheelEvent.angleDelta.y;
|
|
||||||
let currentVolume = (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) || 0;
|
|
||||||
let newVolume;
|
|
||||||
if (delta > 0) {
|
|
||||||
newVolume = Math.min(100, currentVolume + 5);
|
|
||||||
} else {
|
|
||||||
newVolume = Math.max(0, currentVolume - 5);
|
|
||||||
}
|
|
||||||
if (AudioService.sink && AudioService.sink.audio) {
|
|
||||||
AudioService.sink.audio.muted = false;
|
|
||||||
AudioService.sink.audio.volume = newVolume / 100;
|
|
||||||
AudioService.volumeChanged();
|
|
||||||
}
|
|
||||||
wheelEvent.accepted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: "mic"
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: Theme.primary
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: false // TODO: Add mic detection
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback settings icon when all other icons are hidden
|
|
||||||
DankIcon {
|
|
||||||
name: "settings"
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: controlCenterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: controlCenterArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
|
||||||
const globalPos = mapToGlobal(0, 0)
|
|
||||||
const currentScreen = parentScreen || Screen
|
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
|
||||||
popupTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
|
||||||
}
|
|
||||||
root.clicked();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property bool showPercentage: true
|
|
||||||
property bool showIcon: true
|
|
||||||
property var toggleProcessList
|
|
||||||
property string section: "right"
|
|
||||||
property var popupTarget: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property real barThickness: 48
|
|
||||||
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))
|
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (cpuTempContent.implicitWidth + horizontalPadding * 2)
|
|
||||||
height: isVertical ? (cpuTempColumn.implicitHeight + horizontalPadding * 2) : widgetThickness
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = cpuTempArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
Component.onCompleted: {
|
|
||||||
DgopService.addRef(["cpu"]);
|
|
||||||
}
|
|
||||||
Component.onDestruction: {
|
|
||||||
DgopService.removeRef(["cpu"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: cpuTempArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
|
||||||
const globalPos = mapToGlobal(0, 0)
|
|
||||||
const currentScreen = parentScreen || Screen
|
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
|
||||||
popupTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
|
||||||
}
|
|
||||||
DgopService.setSortBy("cpu");
|
|
||||||
if (root.toggleProcessList) {
|
|
||||||
root.toggleProcessList();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: cpuTempColumn
|
|
||||||
visible: root.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 1
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: "device_thermostat"
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: {
|
|
||||||
if (DgopService.cpuTemperature > 85) {
|
|
||||||
return Theme.tempDanger;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DgopService.cpuTemperature > 69) {
|
|
||||||
return Theme.tempWarning;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Theme.surfaceText;
|
|
||||||
}
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
if (DgopService.cpuTemperature === undefined || DgopService.cpuTemperature === null || DgopService.cpuTemperature < 0) {
|
|
||||||
return "--";
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.round(DgopService.cpuTemperature).toString();
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: cpuTempContent
|
|
||||||
visible: !root.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 3
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: "device_thermostat"
|
|
||||||
size: Theme.barIconSize(barThickness)
|
|
||||||
color: {
|
|
||||||
if (DgopService.cpuTemperature > 85) {
|
|
||||||
return Theme.tempDanger;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DgopService.cpuTemperature > 69) {
|
|
||||||
return Theme.tempWarning;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Theme.surfaceText;
|
|
||||||
}
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
if (DgopService.cpuTemperature === undefined || DgopService.cpuTemperature === null || DgopService.cpuTemperature < 0) {
|
|
||||||
return "--°";
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.round(DgopService.cpuTemperature) + "°";
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
elide: Text.ElideNone
|
|
||||||
|
|
||||||
StyledTextMetrics {
|
|
||||||
id: tempBaseline
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
text: "100°"
|
|
||||||
}
|
|
||||||
|
|
||||||
width: root.minimumWidth ? Math.max(tempBaseline.width, paintedWidth) : paintedWidth
|
|
||||||
|
|
||||||
Behavior on width {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 120
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,273 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Wayland
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import Quickshell.Hyprland
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property var parentScreen
|
|
||||||
property bool compactMode: SettingsData.focusedWindowCompactMode
|
|
||||||
property int availableWidth: 400
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
|
||||||
readonly property int baseWidth: contentRow.implicitWidth + horizontalPadding * 2
|
|
||||||
readonly property int maxNormalWidth: 456
|
|
||||||
readonly property int maxCompactWidth: 288
|
|
||||||
readonly property Toplevel activeWindow: ToplevelManager.activeToplevel
|
|
||||||
property var activeDesktopEntry: null
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
updateDesktopEntry()
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: DesktopEntries
|
|
||||||
function onApplicationsChanged() {
|
|
||||||
root.updateDesktopEntry()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: root
|
|
||||||
function onActiveWindowChanged() {
|
|
||||||
root.updateDesktopEntry()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateDesktopEntry() {
|
|
||||||
if (activeWindow && activeWindow.appId) {
|
|
||||||
const moddedId = Paths.moddedAppId(activeWindow.appId)
|
|
||||||
activeDesktopEntry = DesktopEntries.heuristicLookup(moddedId)
|
|
||||||
} else {
|
|
||||||
activeDesktopEntry = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
readonly property bool hasWindowsOnCurrentWorkspace: {
|
|
||||||
if (CompositorService.isNiri) {
|
|
||||||
let currentWorkspaceId = null
|
|
||||||
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
|
|
||||||
const ws = NiriService.allWorkspaces[i]
|
|
||||||
if (ws.is_focused) {
|
|
||||||
currentWorkspaceId = ws.id
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentWorkspaceId) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const workspaceWindows = NiriService.windows.filter(w => w.workspace_id === currentWorkspaceId)
|
|
||||||
return workspaceWindows.length > 0 && activeWindow && activeWindow.title
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CompositorService.isHyprland) {
|
|
||||||
if (!Hyprland.focusedWorkspace || !activeWindow || !activeWindow.title) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const hyprlandToplevels = Array.from(Hyprland.toplevels.values)
|
|
||||||
const activeHyprToplevel = hyprlandToplevels.find(t => t.wayland === activeWindow)
|
|
||||||
|
|
||||||
if (!activeHyprToplevel || !activeHyprToplevel.workspace) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return activeHyprToplevel.workspace.id === Hyprland.focusedWorkspace.id
|
|
||||||
}
|
|
||||||
|
|
||||||
return activeWindow && activeWindow.title
|
|
||||||
}
|
|
||||||
|
|
||||||
width: !hasWindowsOnCurrentWorkspace ? 0 : (isVertical ? widgetThickness : (compactMode ? Math.min(baseWidth, maxCompactWidth) : Math.min(baseWidth, maxNormalWidth)))
|
|
||||||
height: !hasWindowsOnCurrentWorkspace ? 0 : (isVertical ? widgetThickness : widgetThickness)
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (!activeWindow || !activeWindow.title) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = mouseArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
clip: true
|
|
||||||
visible: hasWindowsOnCurrentWorkspace
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
id: appIcon
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: 18
|
|
||||||
height: 18
|
|
||||||
visible: root.isVertical && activeWindow && status === Image.Ready
|
|
||||||
source: {
|
|
||||||
if (!activeWindow || !activeWindow.appId) return ""
|
|
||||||
const moddedId = Paths.moddedAppId(activeWindow.appId)
|
|
||||||
if (moddedId.toLowerCase().includes("steam_app")) return ""
|
|
||||||
return Quickshell.iconPath(activeDesktopEntry?.icon, true)
|
|
||||||
}
|
|
||||||
smooth: true
|
|
||||||
mipmap: true
|
|
||||||
asynchronous: true
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
size: 18
|
|
||||||
name: "sports_esports"
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: {
|
|
||||||
if (!root.isVertical || !activeWindow || !activeWindow.appId) return false
|
|
||||||
const moddedId = Paths.moddedAppId(activeWindow.appId)
|
|
||||||
return moddedId.toLowerCase().includes("steam_app")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: {
|
|
||||||
if (!root.isVertical || !activeWindow || !activeWindow.appId) return false
|
|
||||||
if (appIcon.status === Image.Ready) return false
|
|
||||||
const moddedId = Paths.moddedAppId(activeWindow.appId)
|
|
||||||
return !moddedId.toLowerCase().includes("steam_app")
|
|
||||||
}
|
|
||||||
text: {
|
|
||||||
if (!activeWindow || !activeWindow.appId) return "?"
|
|
||||||
if (activeDesktopEntry && activeDesktopEntry.name) {
|
|
||||||
return activeDesktopEntry.name.charAt(0).toUpperCase()
|
|
||||||
}
|
|
||||||
return activeWindow.appId.charAt(0).toUpperCase()
|
|
||||||
}
|
|
||||||
font.pixelSize: 10
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: contentRow
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
visible: !root.isVertical
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: appText
|
|
||||||
|
|
||||||
text: {
|
|
||||||
if (!activeWindow || !activeWindow.appId) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const desktopEntry = DesktopEntries.heuristicLookup(activeWindow.appId);
|
|
||||||
return desktopEntry && desktopEntry.name ? desktopEntry.name : activeWindow.appId;
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
maximumLineCount: 1
|
|
||||||
width: Math.min(implicitWidth, compactMode ? 80 : 180)
|
|
||||||
visible: !compactMode && text.length > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: "•"
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.outlineButton
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: !compactMode && appText.text && titleText.text
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: titleText
|
|
||||||
|
|
||||||
text: {
|
|
||||||
const title = activeWindow && activeWindow.title ? activeWindow.title : "";
|
|
||||||
const appName = appText.text;
|
|
||||||
if (!title || !appName) {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (title.endsWith(" - " + appName)) {
|
|
||||||
return title.substring(0, title.length - (" - " + appName).length);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (title.endsWith(appName)) {
|
|
||||||
return title.substring(0, title.length - appName.length).replace(/ - $/, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
maximumLineCount: 1
|
|
||||||
width: Math.min(implicitWidth, compactMode ? 280 : 250)
|
|
||||||
visible: text.length > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: mouseArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: root.isVertical
|
|
||||||
onEntered: {
|
|
||||||
if (root.isVertical && activeWindow && activeWindow.appId && root.parentScreen) {
|
|
||||||
tooltipLoader.active = true
|
|
||||||
if (tooltipLoader.item) {
|
|
||||||
const globalPos = mapToGlobal(width / 2, height / 2)
|
|
||||||
const currentScreen = root.parentScreen
|
|
||||||
const screenX = currentScreen ? currentScreen.x : 0
|
|
||||||
const screenY = currentScreen ? currentScreen.y : 0
|
|
||||||
const relativeY = globalPos.y - screenY
|
|
||||||
const tooltipX = root.axis?.edge === "left" ? (Theme.barHeight + SettingsData.dankBarSpacing + Theme.spacingXS) : (currentScreen.width - Theme.barHeight - SettingsData.dankBarSpacing - Theme.spacingXS)
|
|
||||||
|
|
||||||
const appName = activeDesktopEntry && activeDesktopEntry.name ? activeDesktopEntry.name : activeWindow.appId
|
|
||||||
const title = activeWindow.title || ""
|
|
||||||
const tooltipText = appName + (title ? " • " + title : "")
|
|
||||||
|
|
||||||
const isLeft = root.axis?.edge === "left"
|
|
||||||
tooltipLoader.item.show(tooltipText, screenX + tooltipX, relativeY, currentScreen, isLeft, !isLeft)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
if (tooltipLoader.item) {
|
|
||||||
tooltipLoader.item.hide()
|
|
||||||
}
|
|
||||||
tooltipLoader.active = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: tooltipLoader
|
|
||||||
active: false
|
|
||||||
sourceComponent: DankTooltip {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Behavior on width {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.shortDuration
|
|
||||||
easing.type: Theme.standardEasing
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isActive: false
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property string section: "left"
|
|
||||||
property var popupTarget: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
|
||||||
|
|
||||||
signal clicked()
|
|
||||||
|
|
||||||
width: widgetThickness
|
|
||||||
height: widgetThickness
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: launcherArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
onPressed: {
|
|
||||||
root.clicked();
|
|
||||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
|
||||||
const globalPos = mapToGlobal(0, 0);
|
|
||||||
const currentScreen = parentScreen || Screen;
|
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width);
|
|
||||||
popupTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: launcherContent
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = launcherArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
visible: SettingsData.launcherLogoMode === "apps"
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "apps"
|
|
||||||
size: Theme.barIconSize(barThickness, -4)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell.Hyprland
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property string section: "right"
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
|
||||||
|
|
||||||
signal clicked()
|
|
||||||
|
|
||||||
readonly property string focusedScreenName: (
|
|
||||||
CompositorService.isHyprland && typeof Hyprland !== "undefined" && Hyprland.focusedWorkspace && Hyprland.focusedWorkspace.monitor ? (Hyprland.focusedWorkspace.monitor.name || "") :
|
|
||||||
CompositorService.isNiri && typeof NiriService !== "undefined" && NiriService.currentOutput ? NiriService.currentOutput : ""
|
|
||||||
)
|
|
||||||
|
|
||||||
function resolveNotepadInstance() {
|
|
||||||
if (typeof notepadSlideoutVariants === "undefined" || !notepadSlideoutVariants || !notepadSlideoutVariants.instances) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const targetScreen = focusedScreenName
|
|
||||||
if (targetScreen) {
|
|
||||||
for (var i = 0; i < notepadSlideoutVariants.instances.length; i++) {
|
|
||||||
var slideout = notepadSlideoutVariants.instances[i]
|
|
||||||
if (slideout.modelData && slideout.modelData.name === targetScreen) {
|
|
||||||
return slideout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return notepadSlideoutVariants.instances.length > 0 ? notepadSlideoutVariants.instances[0] : null
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property var notepadInstance: resolveNotepadInstance()
|
|
||||||
readonly property bool isActive: notepadInstance?.isVisible ?? false
|
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (notepadIcon.width + horizontalPadding * 2)
|
|
||||||
height: isVertical ? (notepadIcon.height + horizontalPadding * 2) : widgetThickness
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = notepadArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
id: notepadIcon
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "assignment"
|
|
||||||
size: Theme.barIconSize(barThickness, -4)
|
|
||||||
color: notepadArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 6
|
|
||||||
height: 6
|
|
||||||
radius: 3
|
|
||||||
color: Theme.primary
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.rightMargin: SettingsData.dankBarNoBackground ? 0 : 4
|
|
||||||
anchors.topMargin: SettingsData.dankBarNoBackground ? 0 : 4
|
|
||||||
visible: NotepadStorageService.tabs && NotepadStorageService.tabs.length > 0
|
|
||||||
opacity: 0.8
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: notepadArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
const inst = root.notepadInstance
|
|
||||||
if (inst) {
|
|
||||||
inst.toggle()
|
|
||||||
}
|
|
||||||
root.clicked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool hasUnread: false
|
|
||||||
property bool isActive: false
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property string section: "right"
|
|
||||||
property var popupTarget: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property real barThickness: 48
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
|
||||||
|
|
||||||
signal clicked()
|
|
||||||
|
|
||||||
width: widgetThickness
|
|
||||||
height: widgetThickness
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: notificationArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
onPressed: {
|
|
||||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
|
||||||
const globalPos = mapToGlobal(0, 0)
|
|
||||||
const currentScreen = parentScreen || Screen
|
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
|
||||||
popupTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
|
||||||
}
|
|
||||||
root.clicked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: notificationContent
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent"
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = notificationArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency)
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
|
|
||||||
size: Theme.barIconSize(barThickness, -4)
|
|
||||||
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText)
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 8
|
|
||||||
height: 8
|
|
||||||
radius: 4
|
|
||||||
color: Theme.error
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.rightMargin: SettingsData.dankBarNoBackground ? 0 : 6
|
|
||||||
anchors.topMargin: SettingsData.dankBarNoBackground ? 0 : 6
|
|
||||||
visible: root.hasUnread
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,633 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Services.SystemTray
|
|
||||||
import Quickshell.Wayland
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import qs.Common
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property var parentWindow: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property real widgetThickness: 30
|
|
||||||
property bool isAtBottom: false
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
|
||||||
readonly property int calculatedSize: SystemTray.items.values.length > 0 ? SystemTray.items.values.length * 24 + horizontalPadding * 2 : 0
|
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : calculatedSize
|
|
||||||
height: isVertical ? calculatedSize : widgetThickness
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SystemTray.items.values.length === 0) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
visible: SystemTray.items.values.length > 0
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: layoutLoader
|
|
||||||
anchors.centerIn: parent
|
|
||||||
sourceComponent: root.isVertical ? columnComp : rowComp
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: rowComp
|
|
||||||
Row {
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: SystemTray.items.values
|
|
||||||
|
|
||||||
delegate: Item {
|
|
||||||
property var trayItem: modelData
|
|
||||||
property string iconSource: {
|
|
||||||
let icon = trayItem && trayItem.icon;
|
|
||||||
if (typeof icon === 'string' || icon instanceof String) {
|
|
||||||
if (icon === "") {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (icon.includes("?path=")) {
|
|
||||||
const split = icon.split("?path=");
|
|
||||||
if (split.length !== 2) {
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
const name = split[0];
|
|
||||||
const path = split[1];
|
|
||||||
let fileName = name.substring(name.lastIndexOf("/") + 1);
|
|
||||||
if (fileName.startsWith("dropboxstatus")) {
|
|
||||||
fileName = `hicolor/16x16/status/${fileName}`;
|
|
||||||
}
|
|
||||||
return `file://${path}/${fileName}`;
|
|
||||||
}
|
|
||||||
if (icon.startsWith("/") && !icon.startsWith("file://")) {
|
|
||||||
return `file://${icon}`;
|
|
||||||
}
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
width: 24
|
|
||||||
height: 24
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: trayItemArea.containsMouse ? Theme.primaryHover : "transparent"
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: 16
|
|
||||||
height: 16
|
|
||||||
source: parent.iconSource
|
|
||||||
asynchronous: true
|
|
||||||
smooth: true
|
|
||||||
mipmap: true
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: trayItemArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: (mouse) => {
|
|
||||||
if (!trayItem) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mouse.button === Qt.LeftButton && !trayItem.onlyMenu) {
|
|
||||||
trayItem.activate();
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
if (trayItem.hasMenu) {
|
|
||||||
root.showForTrayItem(trayItem, parent, parentScreen, root.isAtBottom, root.isVertical, root.axis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: columnComp
|
|
||||||
Column {
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: SystemTray.items.values
|
|
||||||
|
|
||||||
delegate: Item {
|
|
||||||
property var trayItem: modelData
|
|
||||||
property string iconSource: {
|
|
||||||
let icon = trayItem && trayItem.icon;
|
|
||||||
if (typeof icon === 'string' || icon instanceof String) {
|
|
||||||
if (icon === "") {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (icon.includes("?path=")) {
|
|
||||||
const split = icon.split("?path=");
|
|
||||||
if (split.length !== 2) {
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
const name = split[0];
|
|
||||||
const path = split[1];
|
|
||||||
const fileName = name.substring(name.lastIndexOf("/") + 1);
|
|
||||||
return `file://${path}/${fileName}`;
|
|
||||||
}
|
|
||||||
if (icon.startsWith("/") && !icon.startsWith("file://")) {
|
|
||||||
return `file://${icon}`;
|
|
||||||
}
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
width: 24
|
|
||||||
height: 24
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: trayItemArea.containsMouse ? Theme.primaryHover : "transparent"
|
|
||||||
}
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: 16
|
|
||||||
height: 16
|
|
||||||
source: parent.iconSource
|
|
||||||
asynchronous: true
|
|
||||||
smooth: true
|
|
||||||
mipmap: true
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: trayItemArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: (mouse) => {
|
|
||||||
if (!trayItem) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mouse.button === Qt.LeftButton && !trayItem.onlyMenu) {
|
|
||||||
trayItem.activate();
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
if (trayItem.hasMenu) {
|
|
||||||
root.showForTrayItem(trayItem, parent, parentScreen, root.isAtBottom, root.isVertical, root.axis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: trayMenuComponent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: menuRoot
|
|
||||||
|
|
||||||
property var trayItem: null
|
|
||||||
property var anchorItem: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property bool isAtBottom: false
|
|
||||||
property bool isVertical: false
|
|
||||||
property var axis: null
|
|
||||||
property bool showMenu: false
|
|
||||||
property var menuHandle: null
|
|
||||||
|
|
||||||
ListModel { id: entryStack }
|
|
||||||
function topEntry() {
|
|
||||||
return entryStack.count ? entryStack.get(entryStack.count - 1).handle : null
|
|
||||||
}
|
|
||||||
|
|
||||||
function showForTrayItem(item, anchor, screen, atBottom, vertical, axisObj) {
|
|
||||||
trayItem = item
|
|
||||||
anchorItem = anchor
|
|
||||||
parentScreen = screen
|
|
||||||
isAtBottom = atBottom
|
|
||||||
isVertical = vertical
|
|
||||||
axis = axisObj
|
|
||||||
menuHandle = item?.menu
|
|
||||||
|
|
||||||
if (parentScreen) {
|
|
||||||
for (var i = 0; i < Quickshell.screens.length; i++) {
|
|
||||||
const s = Quickshell.screens[i]
|
|
||||||
if (s === parentScreen) {
|
|
||||||
menuWindow.screen = s
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showMenu = true
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
showMenu = false
|
|
||||||
}
|
|
||||||
|
|
||||||
function showSubMenu(entry) {
|
|
||||||
if (!entry || !entry.hasChildren) return;
|
|
||||||
|
|
||||||
entryStack.append({ handle: entry });
|
|
||||||
|
|
||||||
const h = entry.menu || entry;
|
|
||||||
if (h && typeof h.updateLayout === "function") h.updateLayout();
|
|
||||||
|
|
||||||
submenuHydrator.menu = h;
|
|
||||||
submenuHydrator.open();
|
|
||||||
Qt.callLater(() => submenuHydrator.close());
|
|
||||||
}
|
|
||||||
|
|
||||||
function goBack() {
|
|
||||||
if (!entryStack.count) return;
|
|
||||||
entryStack.remove(entryStack.count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
PanelWindow {
|
|
||||||
id: menuWindow
|
|
||||||
visible: menuRoot.showMenu && (menuRoot.trayItem?.hasMenu ?? false)
|
|
||||||
WlrLayershell.layer: WlrLayershell.Overlay
|
|
||||||
WlrLayershell.exclusiveZone: -1
|
|
||||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
anchors {
|
|
||||||
top: true
|
|
||||||
left: true
|
|
||||||
right: true
|
|
||||||
bottom: true
|
|
||||||
}
|
|
||||||
|
|
||||||
property point anchorPos: Qt.point(screen.width / 2, screen.height / 2)
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (visible) {
|
|
||||||
updatePosition()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updatePosition() {
|
|
||||||
if (!menuRoot.anchorItem || !menuRoot.trayItem) {
|
|
||||||
anchorPos = Qt.point(screen.width / 2, screen.height / 2)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const globalPos = menuRoot.anchorItem.mapToGlobal(0, 0)
|
|
||||||
const screenX = screen.x || 0
|
|
||||||
const screenY = screen.y || 0
|
|
||||||
const relativeX = globalPos.x - screenX
|
|
||||||
const relativeY = globalPos.y - screenY
|
|
||||||
|
|
||||||
const widgetThickness = Math.max(20, 26 + SettingsData.dankBarInnerPadding * 0.6)
|
|
||||||
const effectiveBarThickness = Math.max(widgetThickness + SettingsData.dankBarInnerPadding + 4, Theme.barHeight - 4 - (8 - SettingsData.dankBarInnerPadding))
|
|
||||||
|
|
||||||
if (menuRoot.isVertical) {
|
|
||||||
const edge = menuRoot.axis?.edge
|
|
||||||
let targetX
|
|
||||||
if (edge === "left") {
|
|
||||||
targetX = effectiveBarThickness + SettingsData.dankBarSpacing + Theme.popupDistance
|
|
||||||
} else {
|
|
||||||
const popupX = effectiveBarThickness + SettingsData.dankBarSpacing + Theme.popupDistance
|
|
||||||
targetX = screen.width - popupX
|
|
||||||
}
|
|
||||||
anchorPos = Qt.point(targetX, relativeY + menuRoot.anchorItem.height / 2)
|
|
||||||
} else {
|
|
||||||
let targetY
|
|
||||||
if (menuRoot.isAtBottom) {
|
|
||||||
const popupY = effectiveBarThickness + SettingsData.dankBarSpacing + SettingsData.dankBarBottomGap + Theme.popupDistance
|
|
||||||
targetY = screen.height - popupY
|
|
||||||
} else {
|
|
||||||
targetY = effectiveBarThickness + SettingsData.dankBarSpacing + SettingsData.dankBarBottomGap + Theme.popupDistance
|
|
||||||
}
|
|
||||||
anchorPos = Qt.point(relativeX + menuRoot.anchorItem.width / 2, targetY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: menuContainer
|
|
||||||
|
|
||||||
width: Math.min(500, Math.max(250, menuColumn.implicitWidth + Theme.spacingS * 2))
|
|
||||||
height: Math.max(40, menuColumn.implicitHeight + Theme.spacingS * 2)
|
|
||||||
|
|
||||||
x: {
|
|
||||||
if (menuRoot.isVertical) {
|
|
||||||
const edge = menuRoot.axis?.edge
|
|
||||||
if (edge === "left") {
|
|
||||||
const targetX = menuWindow.anchorPos.x
|
|
||||||
return Math.min(menuWindow.screen.width - width - 10, targetX)
|
|
||||||
} else {
|
|
||||||
const targetX = menuWindow.anchorPos.x - width
|
|
||||||
return Math.max(10, targetX)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const left = 10
|
|
||||||
const right = menuWindow.width - width - 10
|
|
||||||
const want = menuWindow.anchorPos.x - width / 2
|
|
||||||
return Math.max(left, Math.min(right, want))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
y: {
|
|
||||||
if (menuRoot.isVertical) {
|
|
||||||
const top = 10
|
|
||||||
const bottom = menuWindow.height - height - 10
|
|
||||||
const want = menuWindow.anchorPos.y - height / 2
|
|
||||||
return Math.max(top, Math.min(bottom, want))
|
|
||||||
} else {
|
|
||||||
if (menuRoot.isAtBottom) {
|
|
||||||
const targetY = menuWindow.anchorPos.y - height
|
|
||||||
return Math.max(10, targetY)
|
|
||||||
} else {
|
|
||||||
const targetY = menuWindow.anchorPos.y
|
|
||||||
return Math.min(menuWindow.screen.height - height - 10, targetY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
color: Theme.popupBackground()
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
opacity: menuRoot.showMenu ? 1 : 0
|
|
||||||
scale: menuRoot.showMenu ? 1 : 0.85
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.topMargin: 4
|
|
||||||
anchors.leftMargin: 2
|
|
||||||
anchors.rightMargin: -2
|
|
||||||
anchors.bottomMargin: -4
|
|
||||||
radius: parent.radius
|
|
||||||
color: Qt.rgba(0, 0, 0, 0.15)
|
|
||||||
z: parent.z - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
QsMenuAnchor {
|
|
||||||
id: submenuHydrator
|
|
||||||
anchor.window: menuWindow
|
|
||||||
}
|
|
||||||
|
|
||||||
QsMenuOpener {
|
|
||||||
id: rootOpener
|
|
||||||
menu: menuRoot.menuHandle
|
|
||||||
}
|
|
||||||
|
|
||||||
QsMenuOpener {
|
|
||||||
id: subOpener
|
|
||||||
menu: {
|
|
||||||
const e = menuRoot.topEntry();
|
|
||||||
return e ? (e.menu || e) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: menuColumn
|
|
||||||
|
|
||||||
width: parent.width - Theme.spacingS * 2
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: Theme.spacingS
|
|
||||||
spacing: 1
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
visible: entryStack.count > 0
|
|
||||||
width: parent.width
|
|
||||||
height: 28
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: backArea.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.spacingXS
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: "arrow_back"
|
|
||||||
size: 16
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Back")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: backArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: menuRoot.goBack()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
visible: entryStack.count > 0
|
|
||||||
width: parent.width
|
|
||||||
height: 1
|
|
||||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: entryStack.count
|
|
||||||
? (subOpener.children ? subOpener.children
|
|
||||||
: (menuRoot.topEntry()?.children || []))
|
|
||||||
: rootOpener.children
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
property var menuEntry: modelData
|
|
||||||
|
|
||||||
width: menuColumn.width
|
|
||||||
height: menuEntry?.isSeparator ? 1 : 28
|
|
||||||
radius: menuEntry?.isSeparator ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (menuEntry?.isSeparator) {
|
|
||||||
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
|
||||||
}
|
|
||||||
return itemArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: itemArea
|
|
||||||
anchors.fill: parent
|
|
||||||
enabled: !menuEntry?.isSeparator && (menuEntry?.enabled !== false)
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (!menuEntry || menuEntry.isSeparator) return;
|
|
||||||
|
|
||||||
if (menuEntry.hasChildren) {
|
|
||||||
menuRoot.showSubMenu(menuEntry);
|
|
||||||
} else {
|
|
||||||
if (typeof menuEntry.activate === "function") {
|
|
||||||
menuEntry.activate();
|
|
||||||
} else if (typeof menuEntry.triggered === "function") {
|
|
||||||
menuEntry.triggered();
|
|
||||||
}
|
|
||||||
Qt.createQmlObject('import QtQuick; Timer { interval: 80; running: true; repeat: false; onTriggered: menuRoot.close() }', menuRoot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
visible: !menuEntry?.isSeparator
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 16
|
|
||||||
height: 16
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: menuEntry?.buttonType !== undefined && menuEntry.buttonType !== 0
|
|
||||||
radius: menuEntry?.buttonType === 2 ? 8 : 2
|
|
||||||
border.width: 1
|
|
||||||
border.color: Theme.outline
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: parent.width - 6
|
|
||||||
height: parent.height - 6
|
|
||||||
radius: parent.radius - 3
|
|
||||||
color: Theme.primary
|
|
||||||
visible: menuEntry?.checkState === 2
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "check"
|
|
||||||
size: 10
|
|
||||||
color: Theme.primaryText
|
|
||||||
visible: menuEntry?.buttonType === 1 && menuEntry?.checkState === 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: 16
|
|
||||||
height: 16
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: menuEntry?.icon && menuEntry.icon !== ""
|
|
||||||
|
|
||||||
Image {
|
|
||||||
anchors.fill: parent
|
|
||||||
source: menuEntry?.icon || ""
|
|
||||||
sourceSize.width: 16
|
|
||||||
sourceSize.height: 16
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
smooth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: menuEntry?.text || ""
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: (menuEntry?.enabled !== false) ? Theme.surfaceText : Theme.surfaceTextMedium
|
|
||||||
elide: Text.ElideRight
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: Math.max(150, parent.width - 64)
|
|
||||||
wrapMode: Text.NoWrap
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: 16
|
|
||||||
height: 16
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "chevron_right"
|
|
||||||
size: 14
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: menuEntry?.hasChildren ?? false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.mediumDuration
|
|
||||||
easing.type: Theme.emphasizedEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on scale {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.mediumDuration
|
|
||||||
easing.type: Theme.emphasizedEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
z: -1
|
|
||||||
onClicked: menuRoot.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property var currentTrayMenu: null
|
|
||||||
|
|
||||||
function showForTrayItem(item, anchor, screen, atBottom, vertical, axisObj) {
|
|
||||||
if (currentTrayMenu) {
|
|
||||||
currentTrayMenu.destroy()
|
|
||||||
}
|
|
||||||
currentTrayMenu = trayMenuComponent.createObject(null)
|
|
||||||
if (currentTrayMenu) {
|
|
||||||
currentTrayMenu.showForTrayItem(item, anchor, screen, atBottom, vertical ?? false, axisObj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property bool isActive: false
|
|
||||||
property string section: "right"
|
|
||||||
property var popupTarget: null
|
|
||||||
property var parentScreen: null
|
|
||||||
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 bool hasUpdates: SystemUpdateService.updateCount > 0
|
|
||||||
readonly property bool isChecking: SystemUpdateService.isChecking
|
|
||||||
|
|
||||||
signal clicked()
|
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (updaterIcon.width + horizontalPadding * 2)
|
|
||||||
height: isVertical ? widgetThickness : widgetThickness
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = updaterArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
id: statusIcon
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: root.isVertical
|
|
||||||
name: {
|
|
||||||
if (isChecking) return "refresh";
|
|
||||||
if (SystemUpdateService.hasError) return "error";
|
|
||||||
if (hasUpdates) return "system_update_alt";
|
|
||||||
return "check_circle";
|
|
||||||
}
|
|
||||||
size: Theme.barIconSize(barThickness, -4)
|
|
||||||
color: {
|
|
||||||
if (SystemUpdateService.hasError) return Theme.error;
|
|
||||||
if (hasUpdates) return Theme.primary;
|
|
||||||
return (updaterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText);
|
|
||||||
}
|
|
||||||
|
|
||||||
RotationAnimation {
|
|
||||||
id: rotationAnimation
|
|
||||||
target: statusIcon
|
|
||||||
property: "rotation"
|
|
||||||
from: 0
|
|
||||||
to: 360
|
|
||||||
duration: 1000
|
|
||||||
running: isChecking
|
|
||||||
loops: Animation.Infinite
|
|
||||||
|
|
||||||
onRunningChanged: {
|
|
||||||
if (!running) {
|
|
||||||
statusIcon.rotation = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 8
|
|
||||||
height: 8
|
|
||||||
radius: 4
|
|
||||||
color: Theme.error
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.rightMargin: SettingsData.dankBarNoBackground ? 0 : 6
|
|
||||||
anchors.topMargin: SettingsData.dankBarNoBackground ? 0 : 6
|
|
||||||
visible: root.isVertical && root.hasUpdates && !root.isChecking
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: updaterIcon
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
visible: !root.isVertical
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
id: statusIconHorizontal
|
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
name: {
|
|
||||||
if (isChecking) return "refresh";
|
|
||||||
if (SystemUpdateService.hasError) return "error";
|
|
||||||
if (hasUpdates) return "system_update_alt";
|
|
||||||
return "check_circle";
|
|
||||||
}
|
|
||||||
size: Theme.barIconSize(barThickness, -4)
|
|
||||||
color: {
|
|
||||||
if (SystemUpdateService.hasError) return Theme.error;
|
|
||||||
if (hasUpdates) return Theme.primary;
|
|
||||||
return (updaterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText);
|
|
||||||
}
|
|
||||||
|
|
||||||
RotationAnimation {
|
|
||||||
id: rotationAnimationHorizontal
|
|
||||||
target: statusIconHorizontal
|
|
||||||
property: "rotation"
|
|
||||||
from: 0
|
|
||||||
to: 360
|
|
||||||
duration: 1000
|
|
||||||
running: isChecking
|
|
||||||
loops: Animation.Infinite
|
|
||||||
|
|
||||||
onRunningChanged: {
|
|
||||||
if (!running) {
|
|
||||||
statusIconHorizontal.rotation = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: countText
|
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: SystemUpdateService.updateCount.toString()
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
visible: hasUpdates && !isChecking
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: updaterArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
|
||||||
const globalPos = mapToGlobal(0, 0)
|
|
||||||
const currentScreen = parentScreen || Screen
|
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
|
||||||
popupTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
|
||||||
}
|
|
||||||
root.clicked();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
Ref {
|
|
||||||
service: VpnService
|
|
||||||
}
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property int widgetThickness: 28
|
|
||||||
property int barThickness: 32
|
|
||||||
property string section: "right"
|
|
||||||
property var popupTarget: null
|
|
||||||
property var parentScreen: null
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
|
||||||
|
|
||||||
signal toggleVpnPopup()
|
|
||||||
|
|
||||||
width: isVertical ? widgetThickness : (Theme.iconSize + horizontalPadding * 2)
|
|
||||||
height: isVertical ? (Theme.iconSize + horizontalPadding * 2) : widgetThickness
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = clickArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
id: icon
|
|
||||||
|
|
||||||
name: VpnService.isBusy ? "sync" : (VpnService.connected ? "vpn_lock" : "vpn_key_off")
|
|
||||||
size: Theme.barIconSize(barThickness, -4)
|
|
||||||
color: VpnService.connected ? Theme.primary : Theme.surfaceText
|
|
||||||
anchors.centerIn: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: tooltipLoader
|
|
||||||
active: false
|
|
||||||
sourceComponent: DankTooltip {}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: clickArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
|
||||||
const globalPos = mapToGlobal(0, 0)
|
|
||||||
const currentScreen = parentScreen || Screen
|
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
|
||||||
popupTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
|
||||||
}
|
|
||||||
root.toggleVpnPopup();
|
|
||||||
}
|
|
||||||
onEntered: {
|
|
||||||
if (root.parentScreen && !(popupTarget && popupTarget.shouldBeVisible)) {
|
|
||||||
tooltipLoader.active = true
|
|
||||||
if (tooltipLoader.item) {
|
|
||||||
let tooltipText = ""
|
|
||||||
if (!VpnService.connected) {
|
|
||||||
tooltipText = "VPN Disconnected"
|
|
||||||
} else {
|
|
||||||
const names = VpnService.activeNames || []
|
|
||||||
if (names.length <= 1) {
|
|
||||||
tooltipText = "VPN Connected • " + (names[0] || "")
|
|
||||||
} else {
|
|
||||||
tooltipText = "VPN Connected • " + names[0] + " +" + (names.length - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (root.isVertical) {
|
|
||||||
const globalPos = mapToGlobal(width / 2, height / 2)
|
|
||||||
const screenX = root.parentScreen ? root.parentScreen.x : 0
|
|
||||||
const screenY = root.parentScreen ? root.parentScreen.y : 0
|
|
||||||
const relativeY = globalPos.y - screenY
|
|
||||||
const tooltipX = root.axis?.edge === "left" ? (Theme.barHeight + SettingsData.dankBarSpacing + Theme.spacingXS) : (root.parentScreen.width - Theme.barHeight - SettingsData.dankBarSpacing - Theme.spacingXS)
|
|
||||||
const isLeft = root.axis?.edge === "left"
|
|
||||||
tooltipLoader.item.show(tooltipText, screenX + tooltipX, relativeY, root.parentScreen, isLeft, !isLeft)
|
|
||||||
} else {
|
|
||||||
const globalPos = mapToGlobal(width / 2, height)
|
|
||||||
const tooltipY = Theme.barHeight + SettingsData.dankBarSpacing + Theme.spacingXS
|
|
||||||
tooltipLoader.item.show(tooltipText, globalPos.x, tooltipY, root.parentScreen, false, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
if (tooltipLoader.item) {
|
|
||||||
tooltipLoader.item.hide()
|
|
||||||
}
|
|
||||||
tooltipLoader.active = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property bool isVertical: axis?.isVertical ?? false
|
|
||||||
property var axis: null
|
|
||||||
property string section: "center"
|
|
||||||
property var popupTarget: null
|
|
||||||
property var parentScreen: null
|
|
||||||
property real barThickness: 48
|
|
||||||
property real widgetThickness: 30
|
|
||||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
|
|
||||||
|
|
||||||
signal clicked()
|
|
||||||
|
|
||||||
visible: SettingsData.weatherEnabled
|
|
||||||
width: isVertical ? widgetThickness : (visible ? Math.min(100, weatherRow.implicitWidth + horizontalPadding * 2) : 0)
|
|
||||||
height: isVertical ? (weatherColumn.implicitHeight + horizontalPadding * 2) : widgetThickness
|
|
||||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
|
||||||
color: {
|
|
||||||
if (SettingsData.dankBarNoBackground) {
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColor = weatherArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
|
||||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref {
|
|
||||||
service: WeatherService
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: weatherColumn
|
|
||||||
visible: root.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 1
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
|
||||||
size: Theme.barIconSize(barThickness, -6)
|
|
||||||
color: Theme.primary
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
|
|
||||||
if (temp === undefined || temp === null || temp === 0) {
|
|
||||||
return "--";
|
|
||||||
}
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: weatherRow
|
|
||||||
|
|
||||||
visible: !root.isVertical
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
|
||||||
size: Theme.barIconSize(barThickness, -6)
|
|
||||||
color: Theme.primary
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: {
|
|
||||||
const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
|
|
||||||
if (temp === undefined || temp === null || temp === 0) {
|
|
||||||
return "--°" + (SettingsData.useFahrenheit ? "F" : "C");
|
|
||||||
}
|
|
||||||
|
|
||||||
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.barTextSize(barThickness)
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: weatherArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
|
||||||
const globalPos = mapToGlobal(0, 0)
|
|
||||||
const currentScreen = parentScreen || Screen
|
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
|
||||||
popupTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
|
||||||
}
|
|
||||||
root.clicked();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Behavior on width {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.shortDuration
|
|
||||||
easing.type: Theme.standardEasing
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -13,33 +13,30 @@ DankPopout {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool dashVisible: false
|
property bool dashVisible: false
|
||||||
|
property string triggerSection: "center"
|
||||||
property var triggerScreen: null
|
property var triggerScreen: null
|
||||||
property int currentTabIndex: 0
|
property int currentTabIndex: 0
|
||||||
|
|
||||||
function setTriggerPosition(x, y, width, section, screen) {
|
function setTriggerPosition(x, y, width, section, screen) {
|
||||||
triggerSection = section
|
if (section === "center") {
|
||||||
triggerScreen = screen
|
|
||||||
triggerY = y
|
|
||||||
|
|
||||||
if (section === "center" && (SettingsData.dankBarPosition === SettingsData.Position.Top || SettingsData.dankBarPosition === SettingsData.Position.Bottom)) {
|
|
||||||
const screenWidth = screen ? screen.width : Screen.width
|
const screenWidth = screen ? screen.width : Screen.width
|
||||||
triggerX = (screenWidth - popupWidth) / 2
|
triggerX = (screenWidth - popupWidth) / 2
|
||||||
triggerWidth = popupWidth
|
triggerWidth = popupWidth
|
||||||
} else if (section === "center" && (SettingsData.dankBarPosition === SettingsData.Position.Left || SettingsData.dankBarPosition === SettingsData.Position.Right)) {
|
|
||||||
const screenHeight = screen ? screen.height : Screen.height
|
|
||||||
triggerX = (screenHeight - popupHeight) / 2
|
|
||||||
triggerWidth = popupHeight
|
|
||||||
} else {
|
} else {
|
||||||
triggerX = x
|
triggerX = x
|
||||||
triggerWidth = width
|
triggerWidth = width
|
||||||
}
|
}
|
||||||
|
triggerY = y
|
||||||
|
triggerSection = section
|
||||||
|
triggerScreen = screen
|
||||||
}
|
}
|
||||||
|
|
||||||
popupWidth: 700
|
popupWidth: 700
|
||||||
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 500
|
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 500
|
||||||
triggerX: Screen.width - 620 - Theme.spacingL
|
triggerX: Screen.width - 620 - Theme.spacingL
|
||||||
triggerY: Math.max(26 + SettingsData.dankBarInnerPadding + 4, Theme.barHeight - 4 - (8 - SettingsData.dankBarInnerPadding)) + SettingsData.dankBarSpacing + SettingsData.dankBarBottomGap - 2
|
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingS
|
||||||
triggerWidth: 80
|
triggerWidth: 80
|
||||||
|
positioning: "center"
|
||||||
shouldBeVisible: dashVisible
|
shouldBeVisible: dashVisible
|
||||||
visible: shouldBeVisible
|
visible: shouldBeVisible
|
||||||
|
|
||||||
@@ -131,15 +128,15 @@ DankPopout {
|
|||||||
|
|
||||||
model: {
|
model: {
|
||||||
let tabs = [
|
let tabs = [
|
||||||
{ icon: "dashboard", text: I18n.tr("Overview") },
|
{ icon: "dashboard", text: "Overview" },
|
||||||
{ icon: "music_note", text: I18n.tr("Media") }
|
{ icon: "music_note", text: "Media" }
|
||||||
]
|
]
|
||||||
|
|
||||||
if (SettingsData.weatherEnabled) {
|
if (SettingsData.weatherEnabled) {
|
||||||
tabs.push({ icon: "wb_sunny", text: I18n.tr("Weather") })
|
tabs.push({ icon: "wb_sunny", text: "Weather" })
|
||||||
}
|
}
|
||||||
|
|
||||||
tabs.push({ icon: "settings", text: I18n.tr("Settings"), isAction: true })
|
tabs.push({ icon: "settings", text: "Settings", isAction: true })
|
||||||
return tabs
|
return tabs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user