mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-29 07:52:50 -05:00
plugins: add pillClickAction + PopoutService
This commit is contained in:
75
DMSShell.qml
75
DMSShell.qml
@@ -34,11 +34,8 @@ ShellRoot {
|
|||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
PortalService.init()
|
PortalService.init()
|
||||||
// Initialize DisplayService night mode functionality
|
|
||||||
DisplayService.nightModeEnabled
|
DisplayService.nightModeEnabled
|
||||||
// Initialize WallpaperCyclingService
|
|
||||||
WallpaperCyclingService.cyclingActive
|
WallpaperCyclingService.cyclingActive
|
||||||
// Initialize PluginService by accessing its properties
|
|
||||||
PluginService.pluginDirectory
|
PluginService.pluginDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +51,9 @@ ShellRoot {
|
|||||||
onLoaded: {
|
onLoaded: {
|
||||||
if (item) {
|
if (item) {
|
||||||
item.pluginService = PluginService
|
item.pluginService = PluginService
|
||||||
|
if (item.popoutService !== undefined) {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
item.pluginId = pluginId
|
item.pluginId = pluginId
|
||||||
console.log("Daemon plugin loaded:", pluginId)
|
console.log("Daemon plugin loaded:", pluginId)
|
||||||
}
|
}
|
||||||
@@ -124,6 +124,10 @@ ShellRoot {
|
|||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
DankDashPopout {
|
DankDashPopout {
|
||||||
id: dankDashPopout
|
id: dankDashPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.dankDashPopout = dankDashPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,6 +149,10 @@ ShellRoot {
|
|||||||
|
|
||||||
NotificationCenterPopout {
|
NotificationCenterPopout {
|
||||||
id: notificationCenter
|
id: notificationCenter
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.notificationCenterPopout = notificationCenter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,6 +180,10 @@ ShellRoot {
|
|||||||
onLockRequested: {
|
onLockRequested: {
|
||||||
lock.activate()
|
lock.activate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.controlCenterPopout = controlCenterPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,6 +194,10 @@ ShellRoot {
|
|||||||
|
|
||||||
WifiPasswordModal {
|
WifiPasswordModal {
|
||||||
id: wifiPasswordModal
|
id: wifiPasswordModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.wifiPasswordModal = wifiPasswordModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,6 +208,10 @@ ShellRoot {
|
|||||||
|
|
||||||
NetworkInfoModal {
|
NetworkInfoModal {
|
||||||
id: networkInfoModal
|
id: networkInfoModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.networkInfoModal = networkInfoModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +222,10 @@ ShellRoot {
|
|||||||
|
|
||||||
BatteryPopout {
|
BatteryPopout {
|
||||||
id: batteryPopout
|
id: batteryPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.batteryPopout = batteryPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,6 +236,10 @@ ShellRoot {
|
|||||||
|
|
||||||
VpnPopout {
|
VpnPopout {
|
||||||
id: vpnPopout
|
id: vpnPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.vpnPopout = vpnPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,11 +296,19 @@ ShellRoot {
|
|||||||
|
|
||||||
ProcessListPopout {
|
ProcessListPopout {
|
||||||
id: processListPopout
|
id: processListPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.processListPopout = processListPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsModal {
|
SettingsModal {
|
||||||
id: settingsModal
|
id: settingsModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.settingsModal = settingsModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
@@ -282,22 +318,43 @@ ShellRoot {
|
|||||||
|
|
||||||
AppDrawerPopout {
|
AppDrawerPopout {
|
||||||
id: appDrawerPopout
|
id: appDrawerPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.appDrawerPopout = appDrawerPopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpotlightModal {
|
SpotlightModal {
|
||||||
id: spotlightModal
|
id: spotlightModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.spotlightModal = spotlightModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipboardHistoryModal {
|
ClipboardHistoryModal {
|
||||||
id: clipboardHistoryModalPopup
|
id: clipboardHistoryModalPopup
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.clipboardHistoryModal = clipboardHistoryModalPopup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationModal {
|
NotificationModal {
|
||||||
id: notificationModal
|
id: notificationModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.notificationModal = notificationModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorPickerModal {
|
ColorPickerModal {
|
||||||
id: colorPickerModal
|
id: colorPickerModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.colorPickerModal = colorPickerModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
@@ -307,6 +364,10 @@ ShellRoot {
|
|||||||
|
|
||||||
ProcessListModal {
|
ProcessListModal {
|
||||||
id: processListModal
|
id: processListModal
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.processListModal = processListModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,6 +378,10 @@ ShellRoot {
|
|||||||
|
|
||||||
SystemUpdatePopout {
|
SystemUpdatePopout {
|
||||||
id: systemUpdatePopout
|
id: systemUpdatePopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.systemUpdatePopout = systemUpdatePopout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,6 +449,10 @@ ShellRoot {
|
|||||||
}, function () {})
|
}, function () {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.powerMenuModal = powerMenuModal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -403,6 +403,10 @@ Item {
|
|||||||
item.pluginService = PluginService
|
item.pluginService = PluginService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.popoutService !== undefined) {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
|
|
||||||
layoutTimer.restart()
|
layoutTimer.restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,10 @@ Loader {
|
|||||||
}
|
}
|
||||||
item.pluginService = PluginService
|
item.pluginService = PluginService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.popoutService !== undefined) {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ Variants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
property bool reveal: {
|
property bool reveal: {
|
||||||
if (CompositorService.isNiri && NiriService.inOverview) {
|
if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) {
|
||||||
return SettingsData.dockOpenOnOverview
|
return true
|
||||||
}
|
}
|
||||||
return (!autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky) && !windowIsFullscreen
|
return (!autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky) && !windowIsFullscreen
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ Variants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
screen: modelData
|
screen: modelData
|
||||||
visible: SettingsData.showDock
|
visible: SettingsData.showDock || (CompositorService.isNiri && SettingsData.dockOpenOnOverview && NiriService.inOverview)
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ Rectangle {
|
|||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: contentLoader
|
id: contentLoader
|
||||||
anchors.centerIn: parent
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ Item {
|
|||||||
property Component popoutContent: null
|
property Component popoutContent: null
|
||||||
property real popoutWidth: 400
|
property real popoutWidth: 400
|
||||||
property real popoutHeight: 400
|
property real popoutHeight: 400
|
||||||
|
property var pillClickAction: null
|
||||||
|
|
||||||
property var pluginData: ({})
|
property var pluginData: ({})
|
||||||
|
|
||||||
@@ -70,7 +71,16 @@ Item {
|
|||||||
barThickness: root.barThickness
|
barThickness: root.barThickness
|
||||||
content: root.horizontalBarPill
|
content: root.horizontalBarPill
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (hasPopout) {
|
if (pillClickAction) {
|
||||||
|
if (pillClickAction.length === 0) {
|
||||||
|
pillClickAction()
|
||||||
|
} else {
|
||||||
|
const globalPos = mapToGlobal(0, 0)
|
||||||
|
const currentScreen = parentScreen || Screen
|
||||||
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
||||||
|
pillClickAction(pos.x, pos.y, pos.width, section, currentScreen)
|
||||||
|
}
|
||||||
|
} else if (hasPopout) {
|
||||||
pluginPopout.toggle()
|
pluginPopout.toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,7 +98,16 @@ Item {
|
|||||||
content: root.verticalBarPill
|
content: root.verticalBarPill
|
||||||
isVerticalOrientation: true
|
isVerticalOrientation: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (hasPopout) {
|
if (pillClickAction) {
|
||||||
|
if (pillClickAction.length === 0) {
|
||||||
|
pillClickAction()
|
||||||
|
} else {
|
||||||
|
const globalPos = mapToGlobal(0, 0)
|
||||||
|
const currentScreen = parentScreen || Screen
|
||||||
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
||||||
|
pillClickAction(pos.x, pos.y, pos.width, section, currentScreen)
|
||||||
|
}
|
||||||
|
} else if (hasPopout) {
|
||||||
pluginPopout.toggle()
|
pluginPopout.toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -394,6 +394,9 @@ Item {
|
|||||||
if (item && typeof PluginService !== "undefined") {
|
if (item && typeof PluginService !== "undefined") {
|
||||||
item.pluginService = PluginService
|
item.pluginService = PluginService
|
||||||
}
|
}
|
||||||
|
if (item && typeof PopoutService !== "undefined") {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
285
PLUGINS/POPOUT_SERVICE.md
Normal file
285
PLUGINS/POPOUT_SERVICE.md
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
# PopoutService for Plugins
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The `PopoutService` singleton provides plugins with access to all DankMaterialShell popouts and modals. It's automatically injected into plugin widgets and daemons, enabling them to control shell UI elements.
|
||||||
|
|
||||||
|
## Automatic Injection
|
||||||
|
|
||||||
|
The `popoutService` property is automatically injected into:
|
||||||
|
- Widget plugins (loaded in DankBar)
|
||||||
|
- Daemon plugins (background services)
|
||||||
|
- Plugin settings components
|
||||||
|
|
||||||
|
**Required**: Declare the property in your plugin component:
|
||||||
|
|
||||||
|
```qml
|
||||||
|
property var popoutService: null
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: Without this declaration, the service cannot be injected and you'll see errors like `Cannot assign to non-existent property "popoutService"`
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### Popouts (DankPopout-based)
|
||||||
|
|
||||||
|
| Component | Open | Close | Toggle |
|
||||||
|
|-----------|------|-------|--------|
|
||||||
|
| Control Center | `openControlCenter()` | `closeControlCenter()` | `toggleControlCenter()` |
|
||||||
|
| Notification Center | `openNotificationCenter()` | `closeNotificationCenter()` | `toggleNotificationCenter()` |
|
||||||
|
| App Drawer | `openAppDrawer()` | `closeAppDrawer()` | `toggleAppDrawer()` |
|
||||||
|
| Process List | `openProcessList()` | `closeProcessList()` | `toggleProcessList()` |
|
||||||
|
| DankDash | `openDankDash(tab)` | `closeDankDash()` | `toggleDankDash(tab)` |
|
||||||
|
| Battery | `openBattery()` | `closeBattery()` | `toggleBattery()` |
|
||||||
|
| VPN | `openVpn()` | `closeVpn()` | `toggleVpn()` |
|
||||||
|
| System Update | `openSystemUpdate()` | `closeSystemUpdate()` | `toggleSystemUpdate()` |
|
||||||
|
|
||||||
|
### Modals (DankModal-based)
|
||||||
|
|
||||||
|
| Modal | Show | Hide | Notes |
|
||||||
|
|-------|------|------|-------|
|
||||||
|
| Settings | `openSettings()` | `closeSettings()` | Full settings interface |
|
||||||
|
| Clipboard History | `openClipboardHistory()` | `closeClipboardHistory()` | Cliphist integration |
|
||||||
|
| Spotlight | `openSpotlight()` | `closeSpotlight()` | Command launcher |
|
||||||
|
| Power Menu | `openPowerMenu()` | `closePowerMenu()` | Also has `togglePowerMenu()` |
|
||||||
|
| Process List Modal | `showProcessListModal()` | `hideProcessListModal()` | Fullscreen version, has `toggleProcessListModal()` |
|
||||||
|
| Color Picker | `showColorPicker()` | `hideColorPicker()` | Theme color selection |
|
||||||
|
| Notification | `showNotificationModal()` | `hideNotificationModal()` | Notification details |
|
||||||
|
| WiFi Password | `showWifiPasswordModal()` | `hideWifiPasswordModal()` | Network authentication |
|
||||||
|
| Network Info | `showNetworkInfoModal()` | `hideNetworkInfoModal()` | Network details |
|
||||||
|
|
||||||
|
### Slideouts
|
||||||
|
|
||||||
|
| Component | Open | Close | Toggle |
|
||||||
|
|-----------|------|-------|--------|
|
||||||
|
| Notepad | `openNotepad()` | `closeNotepad()` | `toggleNotepad()` |
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Simple Widget with Popout Control
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var popoutService: null
|
||||||
|
|
||||||
|
width: 100
|
||||||
|
height: 30
|
||||||
|
color: Theme.surfaceContainerHigh
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: popoutService?.toggleControlCenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Settings"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Daemon with Event-Driven Popouts
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var popoutService: null
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: NotificationService
|
||||||
|
|
||||||
|
function onNotificationReceived(notification) {
|
||||||
|
if (notification.urgency === "critical") {
|
||||||
|
popoutService?.openNotificationCenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: BatteryService
|
||||||
|
|
||||||
|
function onPercentageChanged() {
|
||||||
|
if (BatteryService.percentage < 10 && !BatteryService.isCharging) {
|
||||||
|
popoutService?.openBattery()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Widget with Multiple Popout Options
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import qs.Common
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
property var popoutService: null
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
|
||||||
|
onClicked: (mouse) => {
|
||||||
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
contextMenu.popup()
|
||||||
|
} else {
|
||||||
|
popoutService?.toggleControlCenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id: contextMenu
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: "Settings"
|
||||||
|
onClicked: popoutService?.openSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: "Notifications"
|
||||||
|
onClicked: popoutService?.toggleNotificationCenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: "Power Menu"
|
||||||
|
onClicked: popoutService?.openPowerMenu()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
### Service Architecture
|
||||||
|
|
||||||
|
`PopoutService` is a singleton that holds references to popout instances:
|
||||||
|
|
||||||
|
```qml
|
||||||
|
// Services/PopoutService.qml
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var controlCenterPopout: null
|
||||||
|
property var notificationCenterPopout: null
|
||||||
|
// ... other popout references
|
||||||
|
|
||||||
|
function toggleControlCenter() {
|
||||||
|
controlCenterPopout?.toggle()
|
||||||
|
}
|
||||||
|
// ... other control functions
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reference Assignment
|
||||||
|
|
||||||
|
References are assigned in `DMSShell.qml` when popouts are loaded:
|
||||||
|
|
||||||
|
```qml
|
||||||
|
LazyLoader {
|
||||||
|
ControlCenterPopout {
|
||||||
|
id: controlCenterPopout
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PopoutService.controlCenterPopout = controlCenterPopout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Plugin Injection
|
||||||
|
|
||||||
|
The service is injected in three locations:
|
||||||
|
|
||||||
|
1. **DMSShell.qml** (daemon plugins):
|
||||||
|
```qml
|
||||||
|
Instantiator {
|
||||||
|
delegate: Loader {
|
||||||
|
onLoaded: {
|
||||||
|
if (item) {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **WidgetHost.qml** (widget plugins):
|
||||||
|
```qml
|
||||||
|
onLoaded: {
|
||||||
|
if (item.popoutService !== undefined) {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **CenterSection.qml** (center widgets):
|
||||||
|
```qml
|
||||||
|
onLoaded: {
|
||||||
|
if (item.popoutService !== undefined) {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **PluginsTab.qml** (settings):
|
||||||
|
```qml
|
||||||
|
onLoaded: {
|
||||||
|
if (item && typeof PopoutService !== "undefined") {
|
||||||
|
item.popoutService = PopoutService
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Use Optional Chaining**: Always use `?.` to handle null cases
|
||||||
|
```qml
|
||||||
|
popoutService?.toggleControlCenter()
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check Availability**: Some popouts may not be available
|
||||||
|
```qml
|
||||||
|
if (popoutService && popoutService.controlCenterPopout) {
|
||||||
|
popoutService.toggleControlCenter()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Lazy Loading**: First access may activate lazy loaders - this is normal
|
||||||
|
|
||||||
|
4. **Feature Detection**: Some popouts require specific features
|
||||||
|
```qml
|
||||||
|
if (BatteryService.batteryAvailable) {
|
||||||
|
popoutService?.openBattery()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **User Intent**: Only trigger popouts based on user actions or critical events
|
||||||
|
|
||||||
|
## Example Plugin
|
||||||
|
|
||||||
|
See `PLUGINS/PopoutControlExample/` for a complete working example that demonstrates:
|
||||||
|
- Widget creation with popout controls
|
||||||
|
- Menu-based popout selection
|
||||||
|
- Proper service usage
|
||||||
|
- Error handling
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- Popouts are shared across all plugins - avoid conflicts
|
||||||
|
- Some popouts may be compositor or feature-dependent
|
||||||
|
- Lazy-loaded popouts need activation before use
|
||||||
|
- Multi-monitor considerations apply to positioned popouts
|
||||||
56
PLUGINS/PopoutControlExample/PopoutControlSettings.qml
Normal file
56
PLUGINS/PopoutControlExample/PopoutControlSettings.qml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
import qs.Modules.Plugins
|
||||||
|
|
||||||
|
PluginSettings {
|
||||||
|
id: root
|
||||||
|
pluginId: "popoutControlExample"
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
width: parent.width
|
||||||
|
text: "Popout Control Settings"
|
||||||
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
font.weight: Font.Bold
|
||||||
|
color: Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
width: parent.width
|
||||||
|
text: "Choose which popout/modal will open when clicking the widget"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectionSetting {
|
||||||
|
settingKey: "selectedPopout"
|
||||||
|
label: "Popout to Open"
|
||||||
|
description: "Select which popout or modal opens when you click the widget"
|
||||||
|
options: [
|
||||||
|
{label: "Control Center", value: "controlCenter"},
|
||||||
|
{label: "Notification Center", value: "notificationCenter"},
|
||||||
|
{label: "App Drawer", value: "appDrawer"},
|
||||||
|
{label: "Process List", value: "processList"},
|
||||||
|
{label: "DankDash", value: "dankDash"},
|
||||||
|
{label: "Battery Info", value: "battery"},
|
||||||
|
{label: "VPN", value: "vpn"},
|
||||||
|
{label: "System Update", value: "systemUpdate"},
|
||||||
|
{label: "Settings", value: "settings"},
|
||||||
|
{label: "Clipboard History", value: "clipboardHistory"},
|
||||||
|
{label: "Spotlight", value: "spotlight"},
|
||||||
|
{label: "Power Menu", value: "powerMenu"},
|
||||||
|
{label: "Color Picker", value: "colorPicker"},
|
||||||
|
{label: "Notepad", value: "notepad"}
|
||||||
|
]
|
||||||
|
defaultValue: "controlCenter"
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
width: parent.width
|
||||||
|
text: "💡 Tip: The widget displays the name of the selected popout and opens it when clicked!"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
}
|
||||||
95
PLUGINS/PopoutControlExample/PopoutControlWidget.qml
Normal file
95
PLUGINS/PopoutControlExample/PopoutControlWidget.qml
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
import qs.Modules.Plugins
|
||||||
|
|
||||||
|
PluginComponent {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var popoutService: null
|
||||||
|
|
||||||
|
property string selectedPopout: pluginData.selectedPopout || "controlCenter"
|
||||||
|
|
||||||
|
property var popoutActions: ({
|
||||||
|
"controlCenter": (x, y, w, s, scr) => popoutService?.toggleControlCenter(x, y, w, s, scr),
|
||||||
|
"notificationCenter": (x, y, w, s, scr) => popoutService?.toggleNotificationCenter(x, y, w, s, scr),
|
||||||
|
"appDrawer": (x, y, w, s, scr) => popoutService?.toggleAppDrawer(x, y, w, s, scr),
|
||||||
|
"processList": (x, y, w, s, scr) => popoutService?.toggleProcessList(x, y, w, s, scr),
|
||||||
|
"dankDash": (x, y, w, s, scr) => popoutService?.toggleDankDash(0, x, y, w, s, scr),
|
||||||
|
"battery": (x, y, w, s, scr) => popoutService?.toggleBattery(x, y, w, s, scr),
|
||||||
|
"vpn": (x, y, w, s, scr) => popoutService?.toggleVpn(x, y, w, s, scr),
|
||||||
|
"systemUpdate": (x, y, w, s, scr) => popoutService?.toggleSystemUpdate(x, y, w, s, scr),
|
||||||
|
"settings": () => popoutService?.openSettings(),
|
||||||
|
"clipboardHistory": () => popoutService?.openClipboardHistory(),
|
||||||
|
"spotlight": () => popoutService?.openSpotlight(),
|
||||||
|
"powerMenu": () => popoutService?.togglePowerMenu(),
|
||||||
|
"colorPicker": () => popoutService?.showColorPicker(),
|
||||||
|
"notepad": () => popoutService?.toggleNotepad()
|
||||||
|
})
|
||||||
|
|
||||||
|
property var popoutNames: ({
|
||||||
|
"controlCenter": "Control Center",
|
||||||
|
"notificationCenter": "Notification Center",
|
||||||
|
"appDrawer": "App Drawer",
|
||||||
|
"processList": "Process List",
|
||||||
|
"dankDash": "DankDash",
|
||||||
|
"battery": "Battery Info",
|
||||||
|
"vpn": "VPN",
|
||||||
|
"systemUpdate": "System Update",
|
||||||
|
"settings": "Settings",
|
||||||
|
"clipboardHistory": "Clipboard",
|
||||||
|
"spotlight": "Spotlight",
|
||||||
|
"powerMenu": "Power Menu",
|
||||||
|
"colorPicker": "Color Picker",
|
||||||
|
"notepad": "Notepad"
|
||||||
|
})
|
||||||
|
|
||||||
|
pillClickAction: (x, y, width, section, screen) => {
|
||||||
|
if (popoutActions[selectedPopout]) {
|
||||||
|
popoutActions[selectedPopout](x, y, width, section, screen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
horizontalBarPill: Component {
|
||||||
|
Row {
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "widgets"
|
||||||
|
color: Theme.primary
|
||||||
|
font.pixelSize: Theme.iconSize - 6
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: popoutNames[selectedPopout] || "Popouts"
|
||||||
|
color: Theme.primary
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verticalBarPill: Component {
|
||||||
|
Column {
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "widgets"
|
||||||
|
color: Theme.primary
|
||||||
|
font.pixelSize: Theme.iconSize - 6
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: popoutNames[selectedPopout] || "Popouts"
|
||||||
|
color: Theme.primary
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
207
PLUGINS/PopoutControlExample/README.md
Normal file
207
PLUGINS/PopoutControlExample/README.md
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
# Popout Control Example Plugin
|
||||||
|
|
||||||
|
This example plugin demonstrates:
|
||||||
|
- Using `PopoutService` to trigger positioned popouts and modals
|
||||||
|
- Using `pillClickAction` with position parameters
|
||||||
|
- Using `PluginSettings` with dropdown selection
|
||||||
|
- Dynamic widget text based on settings
|
||||||
|
|
||||||
|
The `pillClickAction` receives position parameters `(x, y, width, section, screen)` which are passed to PopoutService functions to properly position popouts relative to the widget.
|
||||||
|
|
||||||
|
## PopoutService API
|
||||||
|
|
||||||
|
The `PopoutService` is automatically injected into plugin widgets and daemons as `popoutService`. It provides access to all shell popouts and modals.
|
||||||
|
|
||||||
|
### Available Popouts
|
||||||
|
|
||||||
|
#### Control Center
|
||||||
|
```qml
|
||||||
|
popoutService.openControlCenter()
|
||||||
|
popoutService.closeControlCenter()
|
||||||
|
popoutService.toggleControlCenter()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Notification Center
|
||||||
|
```qml
|
||||||
|
popoutService.openNotificationCenter()
|
||||||
|
popoutService.closeNotificationCenter()
|
||||||
|
popoutService.toggleNotificationCenter()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### App Drawer
|
||||||
|
```qml
|
||||||
|
popoutService.openAppDrawer()
|
||||||
|
popoutService.closeAppDrawer()
|
||||||
|
popoutService.toggleAppDrawer()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Process List (Popout)
|
||||||
|
```qml
|
||||||
|
popoutService.openProcessList()
|
||||||
|
popoutService.closeProcessList()
|
||||||
|
popoutService.toggleProcessList()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### DankDash
|
||||||
|
```qml
|
||||||
|
popoutService.openDankDash(tabIndex) // tabIndex: 0=Calendar, 1=Media, 2=Weather
|
||||||
|
popoutService.closeDankDash()
|
||||||
|
popoutService.toggleDankDash(tabIndex)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Battery Popout
|
||||||
|
```qml
|
||||||
|
popoutService.openBattery()
|
||||||
|
popoutService.closeBattery()
|
||||||
|
popoutService.toggleBattery()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### VPN Popout
|
||||||
|
```qml
|
||||||
|
popoutService.openVpn()
|
||||||
|
popoutService.closeVpn()
|
||||||
|
popoutService.toggleVpn()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### System Update Popout
|
||||||
|
```qml
|
||||||
|
popoutService.openSystemUpdate()
|
||||||
|
popoutService.closeSystemUpdate()
|
||||||
|
popoutService.toggleSystemUpdate()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Modals
|
||||||
|
|
||||||
|
#### Settings Modal
|
||||||
|
```qml
|
||||||
|
popoutService.openSettings()
|
||||||
|
popoutService.closeSettings()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Clipboard History Modal
|
||||||
|
```qml
|
||||||
|
popoutService.openClipboardHistory()
|
||||||
|
popoutService.closeClipboardHistory()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Spotlight Modal
|
||||||
|
```qml
|
||||||
|
popoutService.openSpotlight()
|
||||||
|
popoutService.closeSpotlight()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Power Menu Modal
|
||||||
|
```qml
|
||||||
|
popoutService.openPowerMenu()
|
||||||
|
popoutService.closePowerMenu()
|
||||||
|
popoutService.togglePowerMenu()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Process List Modal (fullscreen)
|
||||||
|
```qml
|
||||||
|
popoutService.showProcessListModal()
|
||||||
|
popoutService.hideProcessListModal()
|
||||||
|
popoutService.toggleProcessListModal()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Color Picker Modal
|
||||||
|
```qml
|
||||||
|
popoutService.showColorPicker()
|
||||||
|
popoutService.hideColorPicker()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Notification Modal
|
||||||
|
```qml
|
||||||
|
popoutService.showNotificationModal()
|
||||||
|
popoutService.hideNotificationModal()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### WiFi Password Modal
|
||||||
|
```qml
|
||||||
|
popoutService.showWifiPasswordModal()
|
||||||
|
popoutService.hideWifiPasswordModal()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Network Info Modal
|
||||||
|
```qml
|
||||||
|
popoutService.showNetworkInfoModal()
|
||||||
|
popoutService.hideNetworkInfoModal()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Notepad Slideout
|
||||||
|
```qml
|
||||||
|
popoutService.openNotepad()
|
||||||
|
popoutService.closeNotepad()
|
||||||
|
popoutService.toggleNotepad()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage in Plugins
|
||||||
|
|
||||||
|
### Widget Plugins
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var popoutService: null // REQUIRED: Must declare for injection
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
popoutService?.toggleControlCenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Daemon Plugins
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var popoutService: null // REQUIRED: Must declare for injection
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: NotificationService
|
||||||
|
function onNotificationReceived() {
|
||||||
|
popoutService?.openNotificationCenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important**: The `popoutService` property **must** be declared in your plugin component. Without it, you'll get errors like:
|
||||||
|
```
|
||||||
|
Error: Cannot assign to non-existent property "popoutService"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example Use Cases
|
||||||
|
|
||||||
|
1. **Custom Launcher**: Create a widget that opens the app drawer
|
||||||
|
2. **Quick Settings**: Toggle control center from a custom button
|
||||||
|
3. **Notification Manager**: Open notification center on new notifications
|
||||||
|
4. **System Monitor**: Open process list on high CPU usage
|
||||||
|
5. **Power Management**: Trigger power menu from a custom widget
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Copy the plugin directory to `~/.config/DankMaterialShell/plugins/`
|
||||||
|
2. Open Settings → Plugins
|
||||||
|
3. Click "Scan for Plugins"
|
||||||
|
4. Enable "Popout Control Example"
|
||||||
|
5. Add `popoutControlExample` to your DankBar widget list
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The `popoutService` property is automatically injected - no manual setup required
|
||||||
|
- Always use optional chaining (`?.`) when calling methods to handle null cases
|
||||||
|
- Popouts are lazily loaded - first access may activate the loader
|
||||||
|
- Some popouts require specific system features to be available
|
||||||
12
PLUGINS/PopoutControlExample/plugin.json
Normal file
12
PLUGINS/PopoutControlExample/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"id": "popoutControlExample",
|
||||||
|
"name": "Popout Control Example",
|
||||||
|
"description": "Example widget demonstrating PopoutService usage with pillClickAction",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "DankMaterialShell",
|
||||||
|
"icon": "widgets",
|
||||||
|
"type": "widget",
|
||||||
|
"component": "./PopoutControlWidget.qml",
|
||||||
|
"settings": "./PopoutControlSettings.qml",
|
||||||
|
"permissions": ["settings_read", "settings_write"]
|
||||||
|
}
|
||||||
@@ -159,6 +159,29 @@ PluginComponent {
|
|||||||
- `popoutContent`: Optional popout window content
|
- `popoutContent`: Optional popout window content
|
||||||
- `popoutWidth`: Popout window width
|
- `popoutWidth`: Popout window width
|
||||||
- `popoutHeight`: Popout window height
|
- `popoutHeight`: Popout window height
|
||||||
|
- `pillClickAction`: Custom click handler function (overrides popout)
|
||||||
|
|
||||||
|
**Custom Click Actions:**
|
||||||
|
|
||||||
|
Override the default popout behavior with `pillClickAction`:
|
||||||
|
|
||||||
|
```qml
|
||||||
|
PluginComponent {
|
||||||
|
horizontalBarPill: Component {
|
||||||
|
StyledText { text: "Click Me" }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple 0-parameter function
|
||||||
|
pillClickAction: () => {
|
||||||
|
Process.exec("bash", ["-c", "notify-send 'Clicked!'"])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or with position parameters for popouts: (x, y, width, section, screen)
|
||||||
|
pillClickAction: (x, y, width, section, screen) => {
|
||||||
|
popoutService?.toggleControlCenter(x, y, width, section, screen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
The PluginComponent automatically handles:
|
The PluginComponent automatically handles:
|
||||||
- Bar orientation detection
|
- Bar orientation detection
|
||||||
|
|||||||
132
PLUGINS/THEME_REFERENCE.md
Normal file
132
PLUGINS/THEME_REFERENCE.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# Theme Property Reference for Plugins
|
||||||
|
|
||||||
|
Quick reference for commonly used Theme properties in plugin development.
|
||||||
|
|
||||||
|
## Font Sizes
|
||||||
|
|
||||||
|
```qml
|
||||||
|
Theme.fontSizeSmall // 12px (scaled)
|
||||||
|
Theme.fontSizeMedium // 14px (scaled)
|
||||||
|
Theme.fontSizeLarge // 16px (scaled)
|
||||||
|
Theme.fontSizeXLarge // 20px (scaled)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: These are scaled by `SettingsData.fontScale`
|
||||||
|
|
||||||
|
## Icon Sizes
|
||||||
|
|
||||||
|
```qml
|
||||||
|
Theme.iconSizeSmall // 16px
|
||||||
|
Theme.iconSize // 24px (default)
|
||||||
|
Theme.iconSizeLarge // 32px
|
||||||
|
```
|
||||||
|
|
||||||
|
## Spacing
|
||||||
|
|
||||||
|
```qml
|
||||||
|
Theme.spacingXS // Extra small
|
||||||
|
Theme.spacingS // Small
|
||||||
|
Theme.spacingM // Medium
|
||||||
|
Theme.spacingL // Large
|
||||||
|
Theme.spacingXL // Extra large
|
||||||
|
```
|
||||||
|
|
||||||
|
## Border Radius
|
||||||
|
|
||||||
|
```qml
|
||||||
|
Theme.cornerRadius // Standard corner radius
|
||||||
|
Theme.cornerRadiusSmall // Smaller radius
|
||||||
|
Theme.cornerRadiusLarge // Larger radius
|
||||||
|
```
|
||||||
|
|
||||||
|
## Colors
|
||||||
|
|
||||||
|
### Surface Colors
|
||||||
|
```qml
|
||||||
|
Theme.surface
|
||||||
|
Theme.surfaceContainerLow
|
||||||
|
Theme.surfaceContainer
|
||||||
|
Theme.surfaceContainerHigh
|
||||||
|
Theme.surfaceContainerHighest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Text Colors
|
||||||
|
```qml
|
||||||
|
Theme.onSurface // Primary text on surface
|
||||||
|
Theme.onSurfaceVariant // Secondary text on surface
|
||||||
|
Theme.outline // Border/divider color
|
||||||
|
```
|
||||||
|
|
||||||
|
### Semantic Colors
|
||||||
|
```qml
|
||||||
|
Theme.primary
|
||||||
|
Theme.onPrimary
|
||||||
|
Theme.secondary
|
||||||
|
Theme.onSecondary
|
||||||
|
Theme.error
|
||||||
|
Theme.warning
|
||||||
|
Theme.success
|
||||||
|
```
|
||||||
|
|
||||||
|
### Special Functions
|
||||||
|
```qml
|
||||||
|
Theme.popupBackground() // Popup background with opacity
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Icon with Text
|
||||||
|
```qml
|
||||||
|
DankIcon {
|
||||||
|
name: "icon_name"
|
||||||
|
color: Theme.onSurface
|
||||||
|
font.pixelSize: Theme.iconSize
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "Label"
|
||||||
|
color: Theme.onSurface
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Container with Border
|
||||||
|
```qml
|
||||||
|
Rectangle {
|
||||||
|
color: Theme.surfaceContainerHigh
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
|
border.width: 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hover Effect
|
||||||
|
```qml
|
||||||
|
MouseArea {
|
||||||
|
hoverEnabled: true
|
||||||
|
onEntered: parent.color = Qt.lighter(Theme.surfaceContainerHigh, 1.1)
|
||||||
|
onExited: parent.color = Theme.surfaceContainerHigh
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Mistakes
|
||||||
|
|
||||||
|
❌ **Wrong**:
|
||||||
|
```qml
|
||||||
|
font.pixelSize: Theme.fontSizeS // Property doesn't exist
|
||||||
|
font.pixelSize: Theme.iconSizeS // Property doesn't exist
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ **Correct**:
|
||||||
|
```qml
|
||||||
|
font.pixelSize: Theme.fontSizeSmall // Use full name
|
||||||
|
font.pixelSize: Theme.iconSizeSmall // Use full name
|
||||||
|
```
|
||||||
|
|
||||||
|
## Checking Available Properties
|
||||||
|
|
||||||
|
To see all available Theme properties, check `Common/Theme.qml` or use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grep "property" Common/Theme.qml
|
||||||
|
```
|
||||||
@@ -9,6 +9,7 @@ PluginComponent {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string scriptPath: pluginData.scriptPath || ""
|
property string scriptPath: pluginData.scriptPath || ""
|
||||||
|
property var popoutService: null
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: SessionData
|
target: SessionData
|
||||||
|
|||||||
295
Services/PopoutService.qml
Normal file
295
Services/PopoutService.qml
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
pragma Singleton
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var controlCenterPopout: null
|
||||||
|
property var notificationCenterPopout: null
|
||||||
|
property var appDrawerPopout: null
|
||||||
|
property var processListPopout: null
|
||||||
|
property var dankDashPopout: null
|
||||||
|
property var batteryPopout: null
|
||||||
|
property var vpnPopout: null
|
||||||
|
property var systemUpdatePopout: null
|
||||||
|
|
||||||
|
property var settingsModal: null
|
||||||
|
property var clipboardHistoryModal: null
|
||||||
|
property var spotlightModal: null
|
||||||
|
property var powerMenuModal: null
|
||||||
|
property var processListModal: null
|
||||||
|
property var colorPickerModal: null
|
||||||
|
property var notificationModal: null
|
||||||
|
property var wifiPasswordModal: null
|
||||||
|
property var networkInfoModal: null
|
||||||
|
|
||||||
|
property var notepadSlideouts: []
|
||||||
|
|
||||||
|
function setPosition(popout, x, y, width, section, screen) {
|
||||||
|
if (popout && popout.setTriggerPosition && arguments.length >= 6) {
|
||||||
|
popout.setTriggerPosition(x, y, width, section, screen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openControlCenter(x, y, width, section, screen) {
|
||||||
|
if (controlCenterPopout) {
|
||||||
|
setPosition(controlCenterPopout, x, y, width, section, screen)
|
||||||
|
controlCenterPopout.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeControlCenter() {
|
||||||
|
controlCenterPopout?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleControlCenter(x, y, width, section, screen) {
|
||||||
|
if (controlCenterPopout) {
|
||||||
|
setPosition(controlCenterPopout, x, y, width, section, screen)
|
||||||
|
controlCenterPopout.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openNotificationCenter(x, y, width, section, screen) {
|
||||||
|
if (notificationCenterPopout) {
|
||||||
|
setPosition(notificationCenterPopout, x, y, width, section, screen)
|
||||||
|
notificationCenterPopout.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeNotificationCenter() {
|
||||||
|
notificationCenterPopout?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleNotificationCenter(x, y, width, section, screen) {
|
||||||
|
if (notificationCenterPopout) {
|
||||||
|
setPosition(notificationCenterPopout, x, y, width, section, screen)
|
||||||
|
notificationCenterPopout.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openAppDrawer(x, y, width, section, screen) {
|
||||||
|
if (appDrawerPopout) {
|
||||||
|
setPosition(appDrawerPopout, x, y, width, section, screen)
|
||||||
|
appDrawerPopout.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeAppDrawer() {
|
||||||
|
appDrawerPopout?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleAppDrawer(x, y, width, section, screen) {
|
||||||
|
if (appDrawerPopout) {
|
||||||
|
setPosition(appDrawerPopout, x, y, width, section, screen)
|
||||||
|
appDrawerPopout.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openProcessList(x, y, width, section, screen) {
|
||||||
|
if (processListPopout) {
|
||||||
|
setPosition(processListPopout, x, y, width, section, screen)
|
||||||
|
processListPopout.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeProcessList() {
|
||||||
|
processListPopout?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleProcessList(x, y, width, section, screen) {
|
||||||
|
if (processListPopout) {
|
||||||
|
setPosition(processListPopout, x, y, width, section, screen)
|
||||||
|
processListPopout.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openDankDash(tabIndex, x, y, width, section, screen) {
|
||||||
|
if (dankDashPopout) {
|
||||||
|
if (arguments.length >= 6) {
|
||||||
|
setPosition(dankDashPopout, x, y, width, section, screen)
|
||||||
|
}
|
||||||
|
dankDashPopout.currentTabIndex = tabIndex || 0
|
||||||
|
dankDashPopout.dashVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDankDash() {
|
||||||
|
if (dankDashPopout) {
|
||||||
|
dankDashPopout.dashVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleDankDash(tabIndex, x, y, width, section, screen) {
|
||||||
|
if (dankDashPopout) {
|
||||||
|
if (arguments.length >= 6) {
|
||||||
|
setPosition(dankDashPopout, x, y, width, section, screen)
|
||||||
|
}
|
||||||
|
if (dankDashPopout.dashVisible) {
|
||||||
|
dankDashPopout.dashVisible = false
|
||||||
|
} else {
|
||||||
|
dankDashPopout.currentTabIndex = tabIndex || 0
|
||||||
|
dankDashPopout.dashVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openBattery(x, y, width, section, screen) {
|
||||||
|
if (batteryPopout) {
|
||||||
|
setPosition(batteryPopout, x, y, width, section, screen)
|
||||||
|
batteryPopout.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeBattery() {
|
||||||
|
batteryPopout?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleBattery(x, y, width, section, screen) {
|
||||||
|
if (batteryPopout) {
|
||||||
|
setPosition(batteryPopout, x, y, width, section, screen)
|
||||||
|
batteryPopout.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openVpn(x, y, width, section, screen) {
|
||||||
|
if (vpnPopout) {
|
||||||
|
setPosition(vpnPopout, x, y, width, section, screen)
|
||||||
|
vpnPopout.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeVpn() {
|
||||||
|
vpnPopout?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleVpn(x, y, width, section, screen) {
|
||||||
|
if (vpnPopout) {
|
||||||
|
setPosition(vpnPopout, x, y, width, section, screen)
|
||||||
|
vpnPopout.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openSystemUpdate(x, y, width, section, screen) {
|
||||||
|
if (systemUpdatePopout) {
|
||||||
|
setPosition(systemUpdatePopout, x, y, width, section, screen)
|
||||||
|
systemUpdatePopout.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeSystemUpdate() {
|
||||||
|
systemUpdatePopout?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleSystemUpdate(x, y, width, section, screen) {
|
||||||
|
if (systemUpdatePopout) {
|
||||||
|
setPosition(systemUpdatePopout, x, y, width, section, screen)
|
||||||
|
systemUpdatePopout.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openSettings() {
|
||||||
|
settingsModal?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeSettings() {
|
||||||
|
settingsModal?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function openClipboardHistory() {
|
||||||
|
clipboardHistoryModal?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeClipboardHistory() {
|
||||||
|
clipboardHistoryModal?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function openSpotlight() {
|
||||||
|
spotlightModal?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeSpotlight() {
|
||||||
|
spotlightModal?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function openPowerMenu() {
|
||||||
|
powerMenuModal?.openCentered()
|
||||||
|
}
|
||||||
|
|
||||||
|
function closePowerMenu() {
|
||||||
|
powerMenuModal?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function togglePowerMenu() {
|
||||||
|
if (powerMenuModal) {
|
||||||
|
if (powerMenuModal.shouldBeVisible) {
|
||||||
|
powerMenuModal.close()
|
||||||
|
} else {
|
||||||
|
powerMenuModal.openCentered()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showProcessListModal() {
|
||||||
|
processListModal?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideProcessListModal() {
|
||||||
|
processListModal?.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleProcessListModal() {
|
||||||
|
processListModal?.toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
function showColorPicker() {
|
||||||
|
colorPickerModal?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideColorPicker() {
|
||||||
|
colorPickerModal?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function showNotificationModal() {
|
||||||
|
notificationModal?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideNotificationModal() {
|
||||||
|
notificationModal?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function showWifiPasswordModal() {
|
||||||
|
wifiPasswordModal?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideWifiPasswordModal() {
|
||||||
|
wifiPasswordModal?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function showNetworkInfoModal() {
|
||||||
|
networkInfoModal?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideNetworkInfoModal() {
|
||||||
|
networkInfoModal?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function openNotepad() {
|
||||||
|
if (notepadSlideouts.length > 0) {
|
||||||
|
notepadSlideouts[0]?.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeNotepad() {
|
||||||
|
if (notepadSlideouts.length > 0) {
|
||||||
|
notepadSlideouts[0]?.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleNotepad() {
|
||||||
|
if (notepadSlideouts.length > 0) {
|
||||||
|
notepadSlideouts[0]?.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user