mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-28 23:42:51 -05:00
Add VPN widget for control center
This commit is contained in:
241
Modules/ControlCenter/BuiltinPlugins/VpnWidget.qml
Normal file
241
Modules/ControlCenter/BuiltinPlugins/VpnWidget.qml
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
import qs.Modules.Plugins
|
||||||
|
|
||||||
|
PluginComponent {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
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: "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: "No VPN profiles found"
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import QtQuick
|
|||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Modules.ControlCenter.Details
|
import qs.Modules.ControlCenter.Details
|
||||||
|
import qs.Modules.ControlCenter.Models
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -11,6 +12,7 @@ Item {
|
|||||||
property var bluetoothCodecSelector: null
|
property var bluetoothCodecSelector: null
|
||||||
|
|
||||||
property var pluginDetailInstance: null
|
property var pluginDetailInstance: null
|
||||||
|
property var widgetModel: null
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: pluginDetailLoader
|
id: pluginDetailLoader
|
||||||
@@ -42,6 +44,23 @@ Item {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root.expandedSection.startsWith("builtin_")) {
|
||||||
|
const builtinId = root.expandedSection
|
||||||
|
let builtinInstance = null
|
||||||
|
|
||||||
|
if (builtinId === "builtin_vpn" && widgetModel?.vpnBuiltinInstance) {
|
||||||
|
builtinInstance = widgetModel.vpnBuiltinInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!builtinInstance || !builtinInstance.ccDetailContent) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginDetailLoader.sourceComponent = builtinInstance.ccDetailContent
|
||||||
|
pluginDetailLoader.active = parent.height > 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (root.expandedSection.startsWith("plugin_")) {
|
if (root.expandedSection.startsWith("plugin_")) {
|
||||||
const pluginId = root.expandedSection.replace("plugin_", "")
|
const pluginId = root.expandedSection.replace("plugin_", "")
|
||||||
const pluginComponent = PluginService.pluginWidgetComponents[pluginId]
|
const pluginComponent = PluginService.pluginWidgetComponents[pluginId]
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ Column {
|
|||||||
property var rowWidgets: modelData
|
property var rowWidgets: modelData
|
||||||
property bool isSliderOnlyRow: {
|
property bool isSliderOnlyRow: {
|
||||||
const widgets = rowWidgets || []
|
const widgets = rowWidgets || []
|
||||||
if (widgets.length === 0) return false
|
if (widgets.length === 0)
|
||||||
|
return false
|
||||||
return widgets.every(w => w.id === "volumeSlider" || w.id === "brightnessSlider" || w.id === "inputVolumeSlider")
|
return widgets.every(w => w.id === "volumeSlider" || w.id === "brightnessSlider" || w.id === "inputVolumeSlider")
|
||||||
}
|
}
|
||||||
topPadding: isSliderOnlyRow ? (root.editMode ? 4 : -6) : 0
|
topPadding: isSliderOnlyRow ? (root.editMode ? 4 : -6) : 0
|
||||||
@@ -121,7 +122,9 @@ Column {
|
|||||||
|
|
||||||
widgetComponent: {
|
widgetComponent: {
|
||||||
const id = modelData.id || ""
|
const id = modelData.id || ""
|
||||||
if (id.startsWith("plugin_")) {
|
if (id.startsWith("builtin_")) {
|
||||||
|
return builtinPluginWidgetComponent
|
||||||
|
} else if (id.startsWith("plugin_")) {
|
||||||
return pluginWidgetComponent
|
return pluginWidgetComponent
|
||||||
} else if (id === "wifi" || id === "bluetooth" || id === "audioOutput" || id === "audioInput") {
|
} else if (id === "wifi" || id === "bluetooth" || id === "audioOutput" || id === "audioInput") {
|
||||||
return compoundPillComponent
|
return compoundPillComponent
|
||||||
@@ -153,7 +156,8 @@ Column {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: active ? (250 + Theme.spacingS) : 0
|
height: active ? (250 + Theme.spacingS) : 0
|
||||||
property bool active: {
|
property bool active: {
|
||||||
if (root.expandedSection === "") return false
|
if (root.expandedSection === "")
|
||||||
|
return false
|
||||||
|
|
||||||
if (root.expandedSection.startsWith("diskUsage_") && root.expandedWidgetData) {
|
if (root.expandedSection.startsWith("diskUsage_") && root.expandedWidgetData) {
|
||||||
const expandedInstanceId = root.expandedWidgetData.instanceId
|
const expandedInstanceId = root.expandedWidgetData.instanceId
|
||||||
@@ -166,6 +170,7 @@ Column {
|
|||||||
expandedSection: root.expandedSection
|
expandedSection: root.expandedSection
|
||||||
expandedWidgetData: root.expandedWidgetData
|
expandedWidgetData: root.expandedWidgetData
|
||||||
bluetoothCodecSelector: root.bluetoothCodecSelector
|
bluetoothCodecSelector: root.bluetoothCodecSelector
|
||||||
|
widgetModel: root.model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,7 +352,8 @@ Column {
|
|||||||
}
|
}
|
||||||
enabled: widgetDef?.enabled ?? true
|
enabled: widgetDef?.enabled ?? true
|
||||||
onToggled: {
|
onToggled: {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
switch (widgetData.id || "") {
|
switch (widgetData.id || "") {
|
||||||
case "wifi":
|
case "wifi":
|
||||||
{
|
{
|
||||||
@@ -380,11 +386,13 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onExpandClicked: {
|
onExpandClicked: {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
root.expandClicked(widgetData, widgetIndex)
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
}
|
}
|
||||||
onWheelEvent: function (wheelEvent) {
|
onWheelEvent: function (wheelEvent) {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
const id = widgetData.id || ""
|
const id = widgetData.id || ""
|
||||||
if (id === "audioOutput") {
|
if (id === "audioOutput") {
|
||||||
if (!AudioService.sink || !AudioService.sink.audio)
|
if (!AudioService.sink || !AudioService.sink.audio)
|
||||||
@@ -539,7 +547,8 @@ Column {
|
|||||||
}
|
}
|
||||||
|
|
||||||
iconRotation: {
|
iconRotation: {
|
||||||
if (widgetData.id !== "darkMode") return 0
|
if (widgetData.id !== "darkMode")
|
||||||
|
return 0
|
||||||
if (darkModeTransitionPending) {
|
if (darkModeTransitionPending) {
|
||||||
return SessionData.isLightMode ? 180 : 0
|
return SessionData.isLightMode ? 180 : 0
|
||||||
}
|
}
|
||||||
@@ -561,7 +570,7 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enabled: !root.editMode
|
enabled: !root.editMode
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.editMode)
|
if (root.editMode)
|
||||||
@@ -617,7 +626,8 @@ enabled: !root.editMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
iconRotation: {
|
iconRotation: {
|
||||||
if (widgetData.id !== "darkMode") return 0
|
if (widgetData.id !== "darkMode")
|
||||||
|
return 0
|
||||||
if (darkModeTransitionPending) {
|
if (darkModeTransitionPending) {
|
||||||
return SessionData.isLightMode ? 180 : 0
|
return SessionData.isLightMode ? 180 : 0
|
||||||
}
|
}
|
||||||
@@ -639,7 +649,7 @@ enabled: !root.editMode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enabled: !root.editMode
|
enabled: !root.editMode
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.editMode)
|
if (root.editMode)
|
||||||
@@ -702,6 +712,111 @@ enabled: !root.editMode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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: {
|
||||||
|
const id = widgetData.id || ""
|
||||||
|
if (id === "builtin_vpn") {
|
||||||
|
return root.model?.vpnBuiltinInstance
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
Component {
|
||||||
id: pluginWidgetComponent
|
id: pluginWidgetComponent
|
||||||
Loader {
|
Loader {
|
||||||
@@ -715,7 +830,8 @@ enabled: !root.editMode
|
|||||||
property string pluginId: widgetData.id?.replace("plugin_", "") || ""
|
property string pluginId: widgetData.id?.replace("plugin_", "") || ""
|
||||||
|
|
||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
if (!pluginInstance) return null
|
if (!pluginInstance)
|
||||||
|
return null
|
||||||
|
|
||||||
const hasDetail = pluginInstance.ccDetailContent !== null
|
const hasDetail = pluginInstance.ccDetailContent !== null
|
||||||
|
|
||||||
@@ -730,20 +846,20 @@ enabled: !root.editMode
|
|||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
const pluginComponent = PluginService.pluginWidgetComponents[pluginId]
|
const pluginComponent = PluginService.pluginWidgetComponents[pluginId]
|
||||||
if (pluginComponent) {
|
if (pluginComponent) {
|
||||||
const instance = pluginComponent.createObject(null, {
|
const instance = pluginComponent.createObject(null, {
|
||||||
pluginId: pluginId,
|
"pluginId": pluginId,
|
||||||
pluginService: PluginService,
|
"pluginService": PluginService,
|
||||||
visible: false,
|
"visible": false,
|
||||||
width: 0,
|
"width": 0,
|
||||||
height: 0
|
"height": 0
|
||||||
})
|
})
|
||||||
if (instance) {
|
if (instance) {
|
||||||
pluginInstance = instance
|
pluginInstance = instance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -776,14 +892,16 @@ enabled: !root.editMode
|
|||||||
isActive: pluginInstance?.ccWidgetIsActive || false
|
isActive: pluginInstance?.ccWidgetIsActive || false
|
||||||
|
|
||||||
onToggled: {
|
onToggled: {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
if (pluginInstance) {
|
if (pluginInstance) {
|
||||||
pluginInstance.ccWidgetToggled()
|
pluginInstance.ccWidgetToggled()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onExpandClicked: {
|
onExpandClicked: {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
root.expandClicked(widgetData, widgetIndex)
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -804,7 +922,8 @@ enabled: !root.editMode
|
|||||||
enabled: !root.editMode
|
enabled: !root.editMode
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
if (pluginInstance) {
|
if (pluginInstance) {
|
||||||
pluginInstance.ccWidgetToggled()
|
pluginInstance.ccWidgetToggled()
|
||||||
}
|
}
|
||||||
@@ -825,7 +944,8 @@ enabled: !root.editMode
|
|||||||
enabled: !root.editMode
|
enabled: !root.editMode
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.editMode) return
|
if (root.editMode)
|
||||||
|
return
|
||||||
if (pluginInstance && pluginInstance.ccDetailContent) {
|
if (pluginInstance && pluginInstance.ccDetailContent) {
|
||||||
root.expandClicked(widgetData, widgetIndex)
|
root.expandClicked(widgetData, widgetIndex)
|
||||||
} else if (pluginInstance) {
|
} else if (pluginInstance) {
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
import qs.Modules.ControlCenter.BuiltinPlugins
|
||||||
import "../utils/widgets.js" as WidgetUtils
|
import "../utils/widgets.js" as WidgetUtils
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property var coreWidgetDefinitions: [
|
property var vpnBuiltinInstance: VpnWidget {}
|
||||||
{
|
|
||||||
|
readonly property var coreWidgetDefinitions: [{
|
||||||
"id": "nightMode",
|
"id": "nightMode",
|
||||||
"text": "Night Mode",
|
"text": "Night Mode",
|
||||||
"description": "Blue light filter",
|
"description": "Blue light filter",
|
||||||
@@ -15,32 +17,28 @@ QtObject {
|
|||||||
"type": "toggle",
|
"type": "toggle",
|
||||||
"enabled": DisplayService.automationAvailable,
|
"enabled": DisplayService.automationAvailable,
|
||||||
"warning": !DisplayService.automationAvailable ? "Requires night mode support" : undefined
|
"warning": !DisplayService.automationAvailable ? "Requires night mode support" : undefined
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "darkMode",
|
"id": "darkMode",
|
||||||
"text": "Dark Mode",
|
"text": "Dark Mode",
|
||||||
"description": "System theme toggle",
|
"description": "System theme toggle",
|
||||||
"icon": "contrast",
|
"icon": "contrast",
|
||||||
"type": "toggle",
|
"type": "toggle",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "doNotDisturb",
|
"id": "doNotDisturb",
|
||||||
"text": "Do Not Disturb",
|
"text": "Do Not Disturb",
|
||||||
"description": "Block notifications",
|
"description": "Block notifications",
|
||||||
"icon": "do_not_disturb_on",
|
"icon": "do_not_disturb_on",
|
||||||
"type": "toggle",
|
"type": "toggle",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "idleInhibitor",
|
"id": "idleInhibitor",
|
||||||
"text": "Keep Awake",
|
"text": "Keep Awake",
|
||||||
"description": "Prevent screen timeout",
|
"description": "Prevent screen timeout",
|
||||||
"icon": "motion_sensor_active",
|
"icon": "motion_sensor_active",
|
||||||
"type": "toggle",
|
"type": "toggle",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "wifi",
|
"id": "wifi",
|
||||||
"text": "Network",
|
"text": "Network",
|
||||||
"description": "Wi-Fi and Ethernet connection",
|
"description": "Wi-Fi and Ethernet connection",
|
||||||
@@ -48,8 +46,7 @@ QtObject {
|
|||||||
"type": "connection",
|
"type": "connection",
|
||||||
"enabled": NetworkService.wifiAvailable,
|
"enabled": NetworkService.wifiAvailable,
|
||||||
"warning": !NetworkService.wifiAvailable ? "Wi-Fi not available" : undefined
|
"warning": !NetworkService.wifiAvailable ? "Wi-Fi not available" : undefined
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "bluetooth",
|
"id": "bluetooth",
|
||||||
"text": "Bluetooth",
|
"text": "Bluetooth",
|
||||||
"description": "Device connections",
|
"description": "Device connections",
|
||||||
@@ -57,32 +54,28 @@ QtObject {
|
|||||||
"type": "connection",
|
"type": "connection",
|
||||||
"enabled": BluetoothService.available,
|
"enabled": BluetoothService.available,
|
||||||
"warning": !BluetoothService.available ? "Bluetooth not available" : undefined
|
"warning": !BluetoothService.available ? "Bluetooth not available" : undefined
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "audioOutput",
|
"id": "audioOutput",
|
||||||
"text": "Audio Output",
|
"text": "Audio Output",
|
||||||
"description": "Speaker settings",
|
"description": "Speaker settings",
|
||||||
"icon": "volume_up",
|
"icon": "volume_up",
|
||||||
"type": "connection",
|
"type": "connection",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "audioInput",
|
"id": "audioInput",
|
||||||
"text": "Audio Input",
|
"text": "Audio Input",
|
||||||
"description": "Microphone settings",
|
"description": "Microphone settings",
|
||||||
"icon": "mic",
|
"icon": "mic",
|
||||||
"type": "connection",
|
"type": "connection",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "volumeSlider",
|
"id": "volumeSlider",
|
||||||
"text": "Volume Slider",
|
"text": "Volume Slider",
|
||||||
"description": "Audio volume control",
|
"description": "Audio volume control",
|
||||||
"icon": "volume_up",
|
"icon": "volume_up",
|
||||||
"type": "slider",
|
"type": "slider",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "brightnessSlider",
|
"id": "brightnessSlider",
|
||||||
"text": "Brightness Slider",
|
"text": "Brightness Slider",
|
||||||
"description": "Display brightness control",
|
"description": "Display brightness control",
|
||||||
@@ -90,24 +83,21 @@ QtObject {
|
|||||||
"type": "slider",
|
"type": "slider",
|
||||||
"enabled": DisplayService.brightnessAvailable,
|
"enabled": DisplayService.brightnessAvailable,
|
||||||
"warning": !DisplayService.brightnessAvailable ? "Brightness control not available" : undefined
|
"warning": !DisplayService.brightnessAvailable ? "Brightness control not available" : undefined
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "inputVolumeSlider",
|
"id": "inputVolumeSlider",
|
||||||
"text": "Input Volume Slider",
|
"text": "Input Volume Slider",
|
||||||
"description": "Microphone volume control",
|
"description": "Microphone volume control",
|
||||||
"icon": "mic",
|
"icon": "mic",
|
||||||
"type": "slider",
|
"type": "slider",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "battery",
|
"id": "battery",
|
||||||
"text": "Battery",
|
"text": "Battery",
|
||||||
"description": "Battery and power management",
|
"description": "Battery and power management",
|
||||||
"icon": "battery_std",
|
"icon": "battery_std",
|
||||||
"type": "action",
|
"type": "action",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "diskUsage",
|
"id": "diskUsage",
|
||||||
"text": "Disk Usage",
|
"text": "Disk Usage",
|
||||||
"description": "Filesystem usage monitoring",
|
"description": "Filesystem usage monitoring",
|
||||||
@@ -116,22 +106,29 @@ QtObject {
|
|||||||
"enabled": DgopService.dgopAvailable,
|
"enabled": DgopService.dgopAvailable,
|
||||||
"warning": !DgopService.dgopAvailable ? "Requires 'dgop' tool" : undefined,
|
"warning": !DgopService.dgopAvailable ? "Requires 'dgop' tool" : undefined,
|
||||||
"allowMultiple": true
|
"allowMultiple": true
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"id": "colorPicker",
|
"id": "colorPicker",
|
||||||
"text": "Color Picker",
|
"text": "Color Picker",
|
||||||
"description": "Choose colors from palette",
|
"description": "Choose colors from palette",
|
||||||
"icon": "palette",
|
"icon": "palette",
|
||||||
"type": "action",
|
"type": "action",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
}
|
}, {
|
||||||
]
|
"id": "builtin_vpn",
|
||||||
|
"text": "VPN",
|
||||||
|
"description": "VPN connections",
|
||||||
|
"icon": "vpn_key",
|
||||||
|
"type": "builtin_plugin",
|
||||||
|
"enabled": VpnService.available,
|
||||||
|
"warning": !VpnService.available ? "VPN not available" : undefined,
|
||||||
|
"isBuiltinPlugin": true
|
||||||
|
}]
|
||||||
|
|
||||||
function getPluginWidgets() {
|
function getPluginWidgets() {
|
||||||
const plugins = []
|
const plugins = []
|
||||||
const loadedPlugins = PluginService.getLoadedPlugins()
|
const loadedPlugins = PluginService.getLoadedPlugins()
|
||||||
|
|
||||||
for (let i = 0; i < loadedPlugins.length; i++) {
|
for (var i = 0; i < loadedPlugins.length; i++) {
|
||||||
const plugin = loadedPlugins[i]
|
const plugin = loadedPlugins[i]
|
||||||
|
|
||||||
if (plugin.type === "daemon") {
|
if (plugin.type === "daemon") {
|
||||||
@@ -156,15 +153,15 @@ QtObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
plugins.push({
|
plugins.push({
|
||||||
"id": "plugin_" + plugin.id,
|
"id": "plugin_" + plugin.id,
|
||||||
"pluginId": plugin.id,
|
"pluginId": plugin.id,
|
||||||
"text": plugin.name || "Plugin",
|
"text": plugin.name || "Plugin",
|
||||||
"description": plugin.description || "",
|
"description": plugin.description || "",
|
||||||
"icon": plugin.icon || "extension",
|
"icon": plugin.icon || "extension",
|
||||||
"type": "plugin",
|
"type": "plugin",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"isPlugin": true
|
"isPlugin": true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return plugins
|
return plugins
|
||||||
@@ -199,4 +196,4 @@ QtObject {
|
|||||||
function clearAll() {
|
function clearAll() {
|
||||||
WidgetUtils.clearAll()
|
WidgetUtils.clearAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user