mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 13:32:50 -05:00
1059 lines
40 KiB
QML
1059 lines
40 KiB
QML
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
|
|
property string screenName: ""
|
|
property string screenModel: ""
|
|
property var parentScreen: null
|
|
|
|
signal expandClicked(var widgetData, int globalIndex)
|
|
signal removeWidget(int index)
|
|
signal moveWidget(int fromIndex, int toIndex)
|
|
signal toggleWidgetSize(int index)
|
|
signal collapseRequested
|
|
|
|
function requestCollapse() {
|
|
collapseRequested();
|
|
}
|
|
|
|
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" || modelData.id === "brightnessSlider") {
|
|
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 widgetWidth <= 25 ? smallDiskUsageComponent : 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 {
|
|
id: detailHost
|
|
width: parent.width
|
|
height: active ? (getDetailHeight(root.expandedSection) + 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);
|
|
}
|
|
|
|
if (root.expandedSection.startsWith("brightnessSlider_") && root.expandedWidgetData) {
|
|
const expandedInstanceId = root.expandedWidgetData.instanceId;
|
|
return rowWidgets.some(w => w.id === "brightnessSlider" && w.instanceId === expandedInstanceId);
|
|
}
|
|
|
|
return rowIndex === root.expandedRowIndex;
|
|
}
|
|
visible: active
|
|
expandedSection: root.expandedSection
|
|
expandedWidgetData: root.expandedWidgetData
|
|
bluetoothCodecSelector: root.bluetoothCodecSelector
|
|
widgetModel: root.model
|
|
collapseCallback: root.requestCollapse
|
|
screenName: root.screenName
|
|
screenModel: root.screenModel
|
|
}
|
|
}
|
|
}
|
|
|
|
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";
|
|
|
|
const status = NetworkService.networkStatus;
|
|
if (status === "ethernet")
|
|
return "settings_ethernet";
|
|
if (status === "vpn")
|
|
return NetworkService.ethernetConnected ? "settings_ethernet" : NetworkService.wifiSignalIcon;
|
|
if (status === "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";
|
|
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...";
|
|
|
|
const status = NetworkService.networkStatus;
|
|
if (status === "ethernet")
|
|
return "Ethernet";
|
|
if (status === "vpn") {
|
|
if (NetworkService.ethernetConnected)
|
|
return "Ethernet";
|
|
if (NetworkService.wifiConnected && NetworkService.currentWifiSSID)
|
|
return NetworkService.currentWifiSSID;
|
|
}
|
|
if (status === "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...";
|
|
|
|
const status = NetworkService.networkStatus;
|
|
if (status === "ethernet")
|
|
return "Connected";
|
|
if (status === "vpn") {
|
|
if (NetworkService.ethernetConnected)
|
|
return "Connected";
|
|
if (NetworkService.wifiConnected)
|
|
return NetworkService.wifiSignalStrength > 0 ? NetworkService.wifiSignalStrength + "%" : "Connected";
|
|
}
|
|
if (status === "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";
|
|
const volume = AudioService.sink.audio.volume;
|
|
if (typeof volume !== "number" || isNaN(volume))
|
|
return "0%";
|
|
return Math.round(volume * 100) + "%";
|
|
}
|
|
case "audioInput":
|
|
{
|
|
if (!AudioService.source)
|
|
return "Select device";
|
|
if (AudioService.source.audio.muted)
|
|
return "Muted";
|
|
const volume = AudioService.source.audio.volume;
|
|
if (typeof volume !== "number" || isNaN(volume))
|
|
return "0%";
|
|
return Math.round(volume * 100) + "%";
|
|
}
|
|
default:
|
|
return widgetDef?.description || "";
|
|
}
|
|
}
|
|
isActive: {
|
|
switch (widgetData.id || "") {
|
|
case "wifi":
|
|
{
|
|
if (NetworkService.wifiToggling)
|
|
return false;
|
|
|
|
const status = NetworkService.networkStatus;
|
|
if (status === "ethernet")
|
|
return true;
|
|
if (status === "vpn")
|
|
return NetworkService.ethernetConnected || NetworkService.wifiConnected;
|
|
if (status === "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.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: brightnessSliderComponent
|
|
Item {
|
|
property var widgetData: parent.widgetData || {}
|
|
property int widgetIndex: parent.widgetIndex || 0
|
|
width: parent.width
|
|
height: 16
|
|
|
|
BrightnessSliderRow {
|
|
id: brightnessSliderRow
|
|
anchors.centerIn: parent
|
|
width: parent.width
|
|
height: 14
|
|
deviceName: widgetData.deviceName || ""
|
|
instanceId: widgetData.instanceId || ""
|
|
screenName: root.screenName
|
|
parentScreen: root.parentScreen
|
|
property color sliderTrackColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
|
|
|
onIconClicked: {
|
|
if (!root.editMode && DisplayService.devices && DisplayService.devices.length > 1) {
|
|
root.expandClicked(widgetData, widgetIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
|
}
|
|
}
|
|
}
|
|
|
|
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 I18n.tr("Night Mode");
|
|
case "darkMode":
|
|
return I18n.tr("Dark Mode");
|
|
case "doNotDisturb":
|
|
return I18n.tr("Do Not Disturb");
|
|
case "idleInhibitor":
|
|
return SessionService.idleInhibited ? I18n.tr("Keeping Awake") : I18n.tr("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":
|
|
{
|
|
const newMode = !SessionData.isLightMode;
|
|
Theme.screenTransition();
|
|
Theme.setLightMode(newMode);
|
|
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":
|
|
{
|
|
const newMode = !SessionData.isLightMode;
|
|
Theme.screenTransition();
|
|
Theme.setLightMode(newMode);
|
|
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: smallDiskUsageComponent
|
|
SmallDiskUsageButton {
|
|
property var widgetData: parent.widgetData || {}
|
|
property int widgetIndex: parent.widgetIndex || 0
|
|
width: parent.width
|
|
height: 48
|
|
|
|
mountPath: widgetData.mountPath || "/"
|
|
instanceId: widgetData.instanceId || ""
|
|
|
|
onClicked: {
|
|
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);
|
|
}
|
|
if (id === "builtin_cups") {
|
|
if (root.model?.cupsLoader) {
|
|
root.model.cupsLoader.active = true;
|
|
}
|
|
builtinInstance = Qt.binding(() => root.model?.cupsBuiltinInstance);
|
|
}
|
|
}
|
|
|
|
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;
|
|
if (builtinInstance) {
|
|
builtinInstance.ccWidgetExpanded();
|
|
}
|
|
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;
|
|
if (pluginInstance) {
|
|
pluginInstance.ccWidgetExpanded();
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|