Compare commits
41
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1a045787e | ||
|
|
7c55d9627a | ||
|
|
5fd2720f00 | ||
|
|
731b323670 | ||
|
|
520020b7f8 | ||
|
|
82ca5b5335 | ||
|
|
bd699e72a7 | ||
|
|
ed7ec326b1 | ||
|
|
04869656aa | ||
|
|
74261f0a49 | ||
|
|
e76350fa7f | ||
|
|
015c1fb27d | ||
|
|
f6cb7e44c2 | ||
|
|
5a8939bc1e | ||
|
|
6071223009 | ||
|
|
2d40ce33d1 | ||
|
|
954dc10fbb | ||
|
|
15ccfd24c6 | ||
|
|
33b08523e9 | ||
|
|
742bece30b | ||
|
|
a64eadd14a | ||
|
|
f9eeb793db | ||
|
|
6bb193c78c | ||
|
|
aadecbfe44 | ||
|
|
53f0aa80ae | ||
|
|
d9856c9409 | ||
|
|
8dc9753e2b | ||
|
|
2a4bd3dfdd | ||
|
|
f75f51ef50 | ||
|
|
e0873304d1 | ||
|
|
99a0155c17 | ||
|
|
f309debea5 | ||
|
|
0979fd014d | ||
|
|
656bd0a54d | ||
|
|
f01001dcfa | ||
|
|
bc6b0d50ab | ||
|
|
f27c9afc25 | ||
|
|
5962fc8354 | ||
|
|
1adcb9841c | ||
|
|
0e0f8555ed | ||
|
|
1d63e67554 |
@@ -16,7 +16,7 @@ CustomRect {
|
|||||||
property color activeOnColor
|
property color activeOnColor
|
||||||
property bool checked
|
property bool checked
|
||||||
property real checkedRadius: Tokens.rounding.medium
|
property real checkedRadius: Tokens.rounding.medium
|
||||||
property real defaultRadius: Tokens.rounding.large
|
property real defaultRadius: Math.min(width, height) / 2
|
||||||
property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1)
|
property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1)
|
||||||
property color disabledOnColor: Qt.alpha(Colors.palette.m3onSurface, 0.38)
|
property color disabledOnColor: Qt.alpha(Colors.palette.m3onSurface, 0.38)
|
||||||
property bool fillWidth
|
property bool fillWidth
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ BusyIndicator {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
bgColor: root.bgColor
|
bgColor: root.bgColor
|
||||||
fgColor: root.fgColor
|
fgColor: root.fgColor
|
||||||
|
hasEndIndicator: false
|
||||||
padding: root.padding
|
padding: root.padding
|
||||||
rotation: manager.rotation
|
rotation: manager.rotation
|
||||||
startAngle: manager.startFraction * 360
|
startAngle: manager.startFraction * 360
|
||||||
@@ -53,6 +54,7 @@ BusyIndicator {
|
|||||||
Anim {
|
Anim {
|
||||||
duration: manager.completeEndDuration * Tokens.anim.durations.scale
|
duration: manager.completeEndDuration * Tokens.anim.durations.scale
|
||||||
properties: "opacity,internalStrokeWidth"
|
properties: "opacity,internalStrokeWidth"
|
||||||
|
type: Anim.DefaultEffects
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ TextFieldBase {
|
|||||||
property string leadingIcon
|
property string leadingIcon
|
||||||
readonly property int leadingOffset: leadingIcon ? leadingIconLoader.width + leadingIconLoader.anchors.leftMargin : 0
|
readonly property int leadingOffset: leadingIcon ? leadingIconLoader.width + leadingIconLoader.anchors.leftMargin : 0
|
||||||
property int radius: Tokens.rounding.small
|
property int radius: Tokens.rounding.small
|
||||||
|
property alias sLayer: stateLayer
|
||||||
readonly property real smallFontScale: smallFontSize / font.pointSize
|
readonly property real smallFontScale: smallFontSize / font.pointSize
|
||||||
property int smallFontSize: Tokens.font.size.small
|
property int smallFontSize: Tokens.font.size.small
|
||||||
property string supportingText
|
property string supportingText
|
||||||
@@ -145,6 +146,7 @@ TextFieldBase {
|
|||||||
|
|
||||||
sourceComponent: MaterialIcon {
|
sourceComponent: MaterialIcon {
|
||||||
color: Colors.palette.m3onSurfaceVariant
|
color: Colors.palette.m3onSurfaceVariant
|
||||||
|
font.pointSize: Tokens.font.size.larger
|
||||||
text: root.leadingIcon
|
text: root.leadingIcon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.dock.enable && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y))
|
if (Config.dock.enabled && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y))
|
||||||
root.visibilities.dock = true;
|
root.visibilities.dock = true;
|
||||||
|
|
||||||
if (root.geometry.barContains(x, y))
|
if (root.geometry.barContains(x, y))
|
||||||
|
|||||||
+12
-1
@@ -11,6 +11,7 @@ import ZShell.Blobs
|
|||||||
import qs.Daemons
|
import qs.Daemons
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Modules.Bar
|
import qs.Modules.Bar
|
||||||
|
import qs.Modules.Bar.Popouts.Network as N
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
import qs.Drawers
|
import qs.Drawers
|
||||||
@@ -144,7 +145,17 @@ CustomWindow {
|
|||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
id: focusGrab
|
id: focusGrab
|
||||||
|
|
||||||
active: visibilities.dock || visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || visibilities.clipboard || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu") && (!Config.bar.tray.showOnHover || (panels.popouts.current as StackView)?.depth > 1))
|
active: {
|
||||||
|
const v = visibilities;
|
||||||
|
const conf = Config;
|
||||||
|
if (!N.PopupManager.closed && panels.popouts.hasCurrent)
|
||||||
|
return true;
|
||||||
|
if ((v.launcher && conf.launcher.enabled) || (v.sidebar && conf.sidebar.enabled) || (v.resources && conf.dashboard.performance.enabled) || (v.dashboard && conf.dashboard.enabled) || v.settings || (v.clipboard && conf.clipboard.enabled) || (v.dock && conf.dock.enabled))
|
||||||
|
return true;
|
||||||
|
if (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu") && (!conf.bar.tray.showOnHover || (panels.popouts.current as StackView)?.depth > 1))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
windows: [root]
|
windows: [root]
|
||||||
|
|
||||||
onCleared: {
|
onCleared: {
|
||||||
|
|||||||
@@ -77,16 +77,6 @@ Singleton {
|
|||||||
"99": "thunderstorm"
|
"99": "thunderstorm"
|
||||||
})
|
})
|
||||||
|
|
||||||
function getAppCategoryIcon(name: string, fallback: string): string {
|
|
||||||
const categories = DesktopEntries.heuristicLookup(name)?.categories;
|
|
||||||
|
|
||||||
if (categories)
|
|
||||||
for (const [key, value] of Object.entries(categoryIcons))
|
|
||||||
if (categories.includes(key))
|
|
||||||
return value;
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAppIcon(name: string, fallback: string): string {
|
function getAppIcon(name: string, fallback: string): string {
|
||||||
const icon = DesktopEntries.heuristicLookup(name)?.icon;
|
const icon = DesktopEntries.heuristicLookup(name)?.icon;
|
||||||
if (fallback !== "undefined")
|
if (fallback !== "undefined")
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Networking
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool active: false
|
||||||
|
readonly property list<Network> connectedNetworks: networks.filter(n => n.connected)
|
||||||
|
property Network connectingNetwork
|
||||||
|
readonly property list<NetworkDevice> devices: Networking.devices.values
|
||||||
|
property Network failedNetwork
|
||||||
|
readonly property list<Network> knownNetworks: networks.filter(n => n.known && !n.connected)
|
||||||
|
readonly property list<Network> networks: {
|
||||||
|
const list = [];
|
||||||
|
for (const d of wifiDevices) {
|
||||||
|
for (const n of d.networks.values) {
|
||||||
|
if (!list.includes(n))
|
||||||
|
list.push(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
property bool scanning: false
|
||||||
|
readonly property list<Network> unknownNetworks: networks.filter(n => !n.known)
|
||||||
|
readonly property list<WifiDevice> wifiDevices: devices.filter(d => wifiDevice(d))
|
||||||
|
readonly property bool wifiEnabled: Networking.wifiEnabled
|
||||||
|
|
||||||
|
signal networkConnected
|
||||||
|
|
||||||
|
function forgetNetwork(target): void {
|
||||||
|
if (!target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
target.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSecure(security): bool {
|
||||||
|
return (security === WifiSecurityType.WpaPsk || security === WifiSecurityType.Wpa2Psk || security === WifiSecurityType.Sae);
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestConnect(network: Network, secret = undefined): void {
|
||||||
|
connectingNetwork = network;
|
||||||
|
if (secret === undefined || secret === "") {
|
||||||
|
network.connect();
|
||||||
|
} else {
|
||||||
|
(network as WifiNetwork).connectWithPsk(secret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setScan(value: bool): void {
|
||||||
|
for (const d of wifiDevices) {
|
||||||
|
d.scannerEnabled = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setWifi(value: bool): void {
|
||||||
|
Networking.wifiEnabled = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function wifiDevice(dev): bool {
|
||||||
|
return dev.type === DeviceType.Wifi;
|
||||||
|
}
|
||||||
|
|
||||||
|
onActiveChanged: {
|
||||||
|
for (const d of wifiDevices)
|
||||||
|
d.scannerEnabled = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: flushFailed
|
||||||
|
|
||||||
|
interval: 5000
|
||||||
|
running: root.failedNetwork
|
||||||
|
|
||||||
|
onTriggered: {
|
||||||
|
root.failedNetwork = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: checkConnection
|
||||||
|
|
||||||
|
interval: 500
|
||||||
|
repeat: true
|
||||||
|
running: root.connectingNetwork
|
||||||
|
|
||||||
|
onTriggered: {
|
||||||
|
var completedNetwork;
|
||||||
|
|
||||||
|
switch (root.connectingNetwork.state) {
|
||||||
|
case ConnectionState.Connecting:
|
||||||
|
break;
|
||||||
|
case ConnectionState.Connected:
|
||||||
|
completedNetwork = root.connectingNetwork;
|
||||||
|
root.networkConnected();
|
||||||
|
break;
|
||||||
|
case ConnectionState.Disconnected:
|
||||||
|
root.failedNetwork = root.connectingNetwork;
|
||||||
|
completedNetwork = root.connectingNetwork;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (completedNetwork) {
|
||||||
|
root.connectingNetwork = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: 10000
|
||||||
|
running: checkConnection.running
|
||||||
|
|
||||||
|
onTriggered: {
|
||||||
|
root.failedNetwork = root.connectingNetwork;
|
||||||
|
root.connectingNetwork = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import QtQuick
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Services
|
||||||
|
import qs.Modules.Settings.Common
|
||||||
|
import qs.Modules.Bar.Popouts.Network
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
required property var modelData
|
||||||
|
|
||||||
|
bottomPadding: Tokens.spacing.extraSmall
|
||||||
|
color: Colors.palette.m3onSurfaceVariant
|
||||||
|
font.pointSize: Tokens.font.size.smaller
|
||||||
|
text: {
|
||||||
|
if (modelData.type === "known") {
|
||||||
|
const count = Network.knownNetworks.filter(n => !n.connected).length;
|
||||||
|
|
||||||
|
return qsTr("%1 known network%2").arg(count).arg(count === 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelData.type === "unknown") {
|
||||||
|
const count = Network.unknownNetworks.filter(n => !n.connected).length;
|
||||||
|
|
||||||
|
return qsTr("%1 network%2 available").arg(count).arg(count === 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
|
||||||
|
return qsTr("object unknown");
|
||||||
|
}
|
||||||
|
topPadding: Tokens.spacing.small
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Modules.Settings.Common
|
||||||
|
import qs.Modules.Bar.Popouts.Network
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Helpers.Network
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
ConnectedRect {
|
||||||
|
id: networkItem
|
||||||
|
|
||||||
|
readonly property int connectedCount: Network.connectedNetworks.length
|
||||||
|
readonly property bool connecting: Network.connectingNetwork === modelData
|
||||||
|
property int horizontalPadding: Tokens.padding.largeIncreased
|
||||||
|
readonly property bool inConnectedGroup: index < connectedCount
|
||||||
|
// sectioning first / last item in list reminder
|
||||||
|
// if index === network.connectedNetworks.length - 1
|
||||||
|
// if index === network.connectedNetworks.length - 1 + network.knownNetworks.length - 2
|
||||||
|
// if index === network.connectedNetworks.length - 1 + network.knownNetworks.length
|
||||||
|
// list.model.values.length - 1
|
||||||
|
required property int index
|
||||||
|
readonly property bool isSecure: Network.isSecure(modelData.security)
|
||||||
|
required property ListView list
|
||||||
|
required property var modelData
|
||||||
|
property int verticalPadding: Tokens.padding.smaller
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
first: !inConnectedGroup && index === connectedCount + 1
|
||||||
|
implicitHeight: rowLayout.implicitHeight + verticalPadding * 2
|
||||||
|
last: inConnectedGroup ? index === connectedCount - 1 : index === (list?.count ?? -1)
|
||||||
|
radius: Tokens.rounding.small
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: rowLayout
|
||||||
|
|
||||||
|
Layout.preferredHeight: visible ? rowLayout.implicitHeight + Tokens.padding.smaller * 2 : 0
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: networkItem.horizontalPadding
|
||||||
|
anchors.rightMargin: networkItem.horizontalPadding
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: column
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: Tokens.spacing.extraSmall
|
||||||
|
Layout.rightMargin: Tokens.spacing.extraSmall
|
||||||
|
color: networkItem.modelData.active ? Colors.palette.m3primary : Colors.palette.m3onSurface
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: networkItem.modelData.name ? networkItem.modelData.name : qsTr("Unknown Network")
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: subtext
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
color: Colors.palette.m3outline
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pointSize: Tokens.font.size.small
|
||||||
|
text: networkItem.modelData.connected ? qsTr("Connected: %1 strength").arg(Math.round(networkItem.modelData.signalStrength * 100) + "%") : qsTr("%1 strength").arg(Math.round(networkItem.modelData.signalStrength * 100) + "%")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
implicitHeight: icon.height
|
||||||
|
implicitWidth: icon.width
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: icon
|
||||||
|
|
||||||
|
color: networkItem.modelData.active ? Colors.palette.m3primary : Colors.palette.m3onSurfaceVariant
|
||||||
|
font.pointSize: Tokens.font.size.large
|
||||||
|
opacity: networkItem.connecting ? 0 : 1
|
||||||
|
text: Icons.getNetworkIcon(networkItem.modelData.signalStrength * 100, networkItem.isSecure)
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
active: opacity > 0
|
||||||
|
anchors.fill: parent
|
||||||
|
opacity: networkItem.connecting ? 1 : 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sourceComponent: CircularIndicator {
|
||||||
|
bgColor: "transparent"
|
||||||
|
running: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
color: networkItem.modelData.active ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (networkItem.isSecure && !networkItem.known) {
|
||||||
|
PopupManager.requestOpen(Qt.resolvedUrl("../../Modules/Bar/Popouts/Network/PSKOverlay.qml"), {
|
||||||
|
network: networkItem.modelData
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Network.requestConnect(networkItem.modelData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Services
|
||||||
|
import qs.Components
|
||||||
|
import qs.Modules.Settings.Common
|
||||||
|
|
||||||
|
CustomSwitch {
|
||||||
|
id: toggleItem
|
||||||
|
|
||||||
|
readonly property alias bg: bg
|
||||||
|
property alias first: bg.first
|
||||||
|
property alias last: bg.last
|
||||||
|
property string subtext
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
cLayer: 2
|
||||||
|
horizontalPadding: Tokens.padding.largeIncreased
|
||||||
|
implicitHeight: Math.max(implicitContentHeight, implicitIndicatorHeight) + verticalPadding * 2
|
||||||
|
implicitWidth: implicitContentWidth + implicitIndicatorWidth + horizontalPadding * 2
|
||||||
|
indicator.anchors.right: right
|
||||||
|
indicator.anchors.rightMargin: toggleItem.horizontalPadding
|
||||||
|
indicator.anchors.verticalCenter: verticalCenter
|
||||||
|
verticalPadding: Tokens.padding.normal
|
||||||
|
|
||||||
|
background: ConnectedRect {
|
||||||
|
id: bg
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
id: stateLayer
|
||||||
|
|
||||||
|
manualPressOverride: toggleItem.pressed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentItem: Item {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: toggleItem.horizontalPadding
|
||||||
|
anchors.right: toggleItem.indicator.left
|
||||||
|
anchors.rightMargin: Tokens.spacing.normal
|
||||||
|
implicitHeight: column.implicitHeight
|
||||||
|
implicitWidth: column.implicitWidth
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: column
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: label
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pointSize: Tokens.font.size.smaller
|
||||||
|
text: toggleItem.text
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: subtext
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
color: Colors.palette.m3outline
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pointSize: Tokens.font.size.small
|
||||||
|
text: toggleItem.subtext
|
||||||
|
visible: toggleItem.subtext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPressed: stateLayer.press(stateLayer.mouseX, stateLayer.mouseY)
|
||||||
|
}
|
||||||
@@ -205,15 +205,6 @@ GridLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: "network"
|
|
||||||
|
|
||||||
delegate: EntryWrapper {
|
|
||||||
NetworkWidget {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "media"
|
roleValue: "media"
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,28 @@ WidgetBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: "bluetooth"
|
||||||
|
|
||||||
|
delegate: EntryWrapper {
|
||||||
|
name: "bluetooth"
|
||||||
|
|
||||||
|
BluetoothWidget {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: "network"
|
||||||
|
|
||||||
|
delegate: EntryWrapper {
|
||||||
|
name: "network"
|
||||||
|
|
||||||
|
NetworkWidget {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "power"
|
roleValue: "power"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Services
|
||||||
|
import qs.Components
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
animate: true
|
||||||
|
color: Colors.palette.m3onSurface // Network.connected ? root.textColor : Colors.palette.m3error
|
||||||
|
fill: 1
|
||||||
|
font.pointSize: Tokens.font.size.larger
|
||||||
|
text: "bluetooth"
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Services
|
||||||
|
import qs.Components
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
animate: true
|
||||||
|
color: Colors.palette.m3onSurface // Network.connected ? root.textColor : Colors.palette.m3error
|
||||||
|
fill: 1
|
||||||
|
font.pointSize: Tokens.font.size.larger
|
||||||
|
text: "android_wifi_4_bar"
|
||||||
|
}
|
||||||
@@ -0,0 +1,385 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQml.Models
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Bluetooth
|
||||||
|
import ZShell.Components
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Services
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
|
CustomClippingRect {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
readonly property list<var> btConnected: Bluetooth.devices.values.filter(d => d.connected)
|
||||||
|
|
||||||
|
implicitHeight: layout.implicitHeight + layout.anchors.margins * 2
|
||||||
|
implicitWidth: 500
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Tokens.padding.larger
|
||||||
|
spacing: Tokens.spacing.extraSmall / 2
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
Layout.rightMargin: Tokens.padding.extraSmall
|
||||||
|
Layout.topMargin: Tokens.padding.normal
|
||||||
|
font.pointSize: Tokens.font.size.large
|
||||||
|
text: qsTr("Bluetooth")
|
||||||
|
}
|
||||||
|
|
||||||
|
Toggle {
|
||||||
|
checked: Bluetooth.defaultAdapter?.enabled ?? false // qmllint disable unresolved-type
|
||||||
|
first: true
|
||||||
|
subtext: qsTr("Toggle bluetooth device state")
|
||||||
|
text: checked ? qsTr("Enabled") : qsTr("Disabled")
|
||||||
|
|
||||||
|
onToggled: {
|
||||||
|
const adapter = Bluetooth.defaultAdapter; // qmllint disable unresolved-type
|
||||||
|
if (adapter)
|
||||||
|
adapter.enabled = checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Toggle {
|
||||||
|
checked: Bluetooth.defaultAdapter?.discovering ?? false // qmllint disable unresolved-type
|
||||||
|
last: root.btConnected.length === 0
|
||||||
|
subtext: qsTr("Enable scanning for new devices")
|
||||||
|
text: qsTr("Discover")
|
||||||
|
|
||||||
|
onToggled: {
|
||||||
|
const adapter = Bluetooth.defaultAdapter; // qmllint disable unresolved-type
|
||||||
|
if (adapter)
|
||||||
|
adapter.discovering = checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: rows
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: contentHeight
|
||||||
|
interactive: false
|
||||||
|
section.property: "connected"
|
||||||
|
spacing: Tokens.spacing.extraSmall / 2
|
||||||
|
|
||||||
|
add: Transition {
|
||||||
|
Anim {
|
||||||
|
from: 0
|
||||||
|
property: "opacity"
|
||||||
|
to: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate: DelegateChooser {
|
||||||
|
role: "isDivider"
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: true
|
||||||
|
|
||||||
|
delegate: StatusDivider {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
delegate: BluetoothItem {
|
||||||
|
list: rows
|
||||||
|
width: rows.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displaced: Transition {
|
||||||
|
Anim {
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model: ScriptModel {
|
||||||
|
objectProp: "address"
|
||||||
|
values: {
|
||||||
|
const byName = (a, b) => a.name.localeCompare(b.name);
|
||||||
|
return [...[...Bluetooth.devices.values].filter(d => d.connected).sort(byName).slice(0, 5),
|
||||||
|
{
|
||||||
|
isDivider: true
|
||||||
|
},
|
||||||
|
...[...Bluetooth.devices.values].filter(d => !d.connected).sort(byName).slice(0, 5)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
move: Transition {
|
||||||
|
Anim {
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remove: Transition {
|
||||||
|
Anim {
|
||||||
|
property: "opacity"
|
||||||
|
to: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
section.delegate: Rectangle {
|
||||||
|
required property string section
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
height: childrenRect.height
|
||||||
|
width: ListView.view.width
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
text: parent.section
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component BluetoothItem: ConnectedRect {
|
||||||
|
id: btItem
|
||||||
|
|
||||||
|
readonly property int connectedCount: root.btConnected.length
|
||||||
|
readonly property bool connecting: Network.connectingNetwork === modelData
|
||||||
|
property int horizontalPadding: Tokens.padding.largeIncreased
|
||||||
|
readonly property bool inConnectedGroup: index < connectedCount
|
||||||
|
required property int index
|
||||||
|
required property ListView list
|
||||||
|
readonly property bool loading: modelData.state === BluetoothDeviceState.Connecting || modelData.state === BluetoothDeviceState.Disconnecting // qmllint disable unresolved-type
|
||||||
|
|
||||||
|
required property BluetoothDevice modelData
|
||||||
|
property int verticalPadding: Tokens.padding.smaller
|
||||||
|
|
||||||
|
first: !inConnectedGroup && index === connectedCount + 1
|
||||||
|
implicitHeight: rowLayout.implicitHeight + verticalPadding * 2
|
||||||
|
last: inConnectedGroup ? index === connectedCount - 1 : index === list.count - 1
|
||||||
|
radius: Tokens.rounding.small
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: 50
|
||||||
|
running: btItem.ListView.delayRemove
|
||||||
|
|
||||||
|
onTriggered: btItem.ListView.delayRemove = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
function onConnectedChanged(): void {
|
||||||
|
if (!btItem.modelData.connected)
|
||||||
|
btItem.ListView.delayRemove = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPairedChanged(): void {
|
||||||
|
if (btItem.modelData.paired)
|
||||||
|
btItem.modelData.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
target: btItem.modelData
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: rowLayout
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: btItem.horizontalPadding
|
||||||
|
anchors.rightMargin: btItem.horizontalPadding
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: column
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: Tokens.spacing.extraSmall
|
||||||
|
Layout.rightMargin: Tokens.spacing.extraSmall
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: btItem.modelData.name
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: subtext
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
color: Colors.palette.m3outline
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pointSize: Tokens.font.size.small
|
||||||
|
text: btItem.modelData.connected ? (btItem.modelData.batteryAvailable ? qsTr("%1 battery left").arg(Math.round(btItem.modelData.battery * 100) + "%") : qsTr("Battery status unknown")) : btItem.modelData.address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
implicitHeight: icon.height
|
||||||
|
implicitWidth: icon.width
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: icon
|
||||||
|
|
||||||
|
font.pointSize: Tokens.font.size.large
|
||||||
|
opacity: btItem.connecting ? 0 : 1
|
||||||
|
text: btItem.modelData.batteryAvailable ? Icons.getBatteryIcon(btItem.modelData.battery) : "battery_unknown"
|
||||||
|
visible: btItem.modelData.state === BluetoothDeviceState.Connected // qmllint disable unresolved-type
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
active: opacity > 0
|
||||||
|
anchors.fill: parent
|
||||||
|
opacity: btItem.connecting ? 1 : 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sourceComponent: CircularIndicator {
|
||||||
|
bgColor: "transparent"
|
||||||
|
running: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonRow {
|
||||||
|
spacing: Tokens.spacing.small
|
||||||
|
|
||||||
|
IconTextButton {
|
||||||
|
font.pointSize: Tokens.font.size.small
|
||||||
|
icon: btItem.modelData.connected ? "link_off" : btItem.modelData.paired ? "link" : "add_link"
|
||||||
|
text: btItem.modelData.connected ? qsTr("Disconnect") : btItem.modelData.paired ? qsTr("Connect") : qsTr("Pair")
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (btItem.modelData.connected)
|
||||||
|
btItem.modelData.disconnect();
|
||||||
|
else if (btItem.modelData.paired)
|
||||||
|
btItem.modelData.connect();
|
||||||
|
else if (!btItem.modelData.paired)
|
||||||
|
btItem.modelData.pair();
|
||||||
|
else if (btItem.modelData.pairing)
|
||||||
|
btItem.modelData.cancelPair();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
component ConnectedRect: CustomRect {
|
||||||
|
id: bg
|
||||||
|
|
||||||
|
property bool first
|
||||||
|
property bool last
|
||||||
|
|
||||||
|
bottomLeftRadius: last ? Tokens.rounding.large : Tokens.rounding.extraSmall
|
||||||
|
bottomRightRadius: last ? Tokens.rounding.large : Tokens.rounding.extraSmall
|
||||||
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
|
topLeftRadius: first ? Tokens.rounding.large : Tokens.rounding.extraSmall
|
||||||
|
topRightRadius: first ? Tokens.rounding.large : Tokens.rounding.extraSmall
|
||||||
|
|
||||||
|
Behavior on bottomLeftRadius {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Behavior on bottomRightRadius {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Behavior on topLeftRadius {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Behavior on topRightRadius {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
component StatusDivider: CustomText {
|
||||||
|
bottomPadding: Tokens.spacing.extraSmall
|
||||||
|
color: Colors.palette.m3onSurfaceVariant
|
||||||
|
font.pointSize: Tokens.font.size.smaller
|
||||||
|
text: {
|
||||||
|
const devices = Bluetooth.devices.values; // qmllint disable unresolved-type
|
||||||
|
const connectedCount = devices.filter(d => d.connected).length;
|
||||||
|
let available = qsTr("%1 device%2 available").arg(devices.length - connectedCount).arg(devices.length === 1 ? "" : "s");
|
||||||
|
return available;
|
||||||
|
}
|
||||||
|
topPadding: Tokens.spacing.small
|
||||||
|
}
|
||||||
|
component Toggle: CustomSwitch {
|
||||||
|
id: toggleItem
|
||||||
|
|
||||||
|
readonly property alias bg: bg
|
||||||
|
property alias first: bg.first
|
||||||
|
property alias last: bg.last
|
||||||
|
property string subtext
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
cLayer: 2
|
||||||
|
horizontalPadding: Tokens.padding.largeIncreased
|
||||||
|
implicitHeight: Math.max(implicitContentHeight, implicitIndicatorHeight) + verticalPadding * 2
|
||||||
|
implicitWidth: implicitContentWidth + implicitIndicatorWidth + horizontalPadding * 2
|
||||||
|
indicator.anchors.right: right
|
||||||
|
indicator.anchors.rightMargin: toggleItem.horizontalPadding
|
||||||
|
indicator.anchors.verticalCenter: verticalCenter
|
||||||
|
verticalPadding: Tokens.padding.normal
|
||||||
|
|
||||||
|
background: ConnectedRect {
|
||||||
|
id: bg
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
id: stateLayer
|
||||||
|
|
||||||
|
manualPressOverride: toggleItem.pressed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentItem: Item {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: toggleItem.horizontalPadding
|
||||||
|
anchors.right: toggleItem.indicator.left
|
||||||
|
anchors.rightMargin: Tokens.spacing.normal
|
||||||
|
implicitHeight: column.implicitHeight
|
||||||
|
implicitWidth: column.implicitWidth
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: column
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: label
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: {
|
||||||
|
const f = Qt.font(label.font);
|
||||||
|
f.pointSize = Tokens.font.size.smaller;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
text: toggleItem.text
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: subtext
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
color: Colors.palette.m3outline
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: {
|
||||||
|
const f = Qt.font(subtext.font);
|
||||||
|
f.pointSize = Tokens.font.size.small;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
text: toggleItem.subtext
|
||||||
|
visible: toggleItem.subtext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPressed: stateLayer.press(stateLayer.mouseX, stateLayer.mouseY)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -82,6 +82,13 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Popout {
|
||||||
|
name: "bluetooth"
|
||||||
|
|
||||||
|
sourceComponent: BluetoothPopout {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Popout {
|
Popout {
|
||||||
name: "updates"
|
name: "updates"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import QtQuick
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Services
|
||||||
|
import qs.Helpers.Network
|
||||||
|
import qs.Components
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
readonly property bool closing: PopupManager.closed
|
||||||
|
readonly property url currentPopup: PopupManager.currentPopup
|
||||||
|
property bool shouldBeVisible: loader.status === Loader.Ready
|
||||||
|
|
||||||
|
color: Qt.alpha(Colors.palette.m3shadow, 0.3)
|
||||||
|
opacity: shouldBeVisible && !closing ? 1 : 0
|
||||||
|
visible: opacity > 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (!visible) {
|
||||||
|
PopupManager.requestClose();
|
||||||
|
PopupManager.currentPopup = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomMouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
preventStealing: true
|
||||||
|
propagateComposedEvents: false
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
const insideItemWidth = mouseX < loader.x + loader.item.width && mouseX > loader.x;
|
||||||
|
const insideItemHeight = mouseY < loader.y + loader.item.height && mouseY > loader.y;
|
||||||
|
if (insideItemHeight && insideItemWidth)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PopupManager.requestClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: loader
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
function onCurrentPopupChanged(): void {
|
||||||
|
if (PopupManager.currentPopup) {
|
||||||
|
loader.setSource(PopupManager.currentPopup, PopupManager.currentPopupProps);
|
||||||
|
} else {
|
||||||
|
loader.source = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target: PopupManager
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
function onNetworkConnected(): void {
|
||||||
|
PopupManager.requestClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
target: Network
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ZShell.Components
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Services
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers.Network
|
||||||
|
|
||||||
|
CustomClippingRect {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var network
|
||||||
|
|
||||||
|
color: Colors.palette.m3surfaceContainer
|
||||||
|
implicitHeight: layout.implicitHeight + layout.anchors.margins * 2
|
||||||
|
implicitWidth: layout.implicitWidth + layout.anchors.margins * 2
|
||||||
|
radius: Tokens.rounding.large
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Tokens.padding.extraLarge
|
||||||
|
spacing: Tokens.spacing.medium
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
font.pointSize: Tokens.font.size.extraLarge * 2
|
||||||
|
text: "lock"
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
color: Colors.palette.m3onSurfaceVariant
|
||||||
|
text: qsTr("Connect to %1").arg(root.network.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomTextField {
|
||||||
|
id: passwordField
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredWidth: 400
|
||||||
|
echoMode: CustomTextField.Password
|
||||||
|
errorText: qsTr("Failed to connect with given password")
|
||||||
|
isError: Network.failedNetwork
|
||||||
|
leadingIcon: "lock"
|
||||||
|
passwordMaskDelay: 5000
|
||||||
|
placeholderText: qsTr("Input password")
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonRow {
|
||||||
|
id: buttonRow
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Tokens.spacing.extraSmall
|
||||||
|
|
||||||
|
IconTextButton {
|
||||||
|
fillWidth: true
|
||||||
|
font.pointSize: Tokens.font.size.normal
|
||||||
|
icon: "close"
|
||||||
|
inactiveColor: Colors.layer(Colors.palette.m3surfaceContainerHighest, 2)
|
||||||
|
inactiveOnColor: Colors.palette.m3onSurfaceVariant
|
||||||
|
isRound: true
|
||||||
|
isToggle: false
|
||||||
|
shapeMorph: true
|
||||||
|
text: "Cancel"
|
||||||
|
|
||||||
|
onClicked: PopupManager.requestClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
IconTextButton {
|
||||||
|
fillWidth: true
|
||||||
|
font.pointSize: Tokens.font.size.normal
|
||||||
|
icon: Network.connectingNetwork ? "" : "check"
|
||||||
|
inactiveColor: Network.connectingNetwork ? Colors.palette.m3primaryContainer : Network.failedNetwork ? Colors.palette.m3error : Colors.palette.m3primary
|
||||||
|
inactiveOnColor: Network.connectingNetwork ? Colors.palette.m3onPrimaryContainer : Network.failedNetwork ? Colors.palette.m3onError : Colors.palette.m3onPrimary
|
||||||
|
isRound: true
|
||||||
|
isToggle: false
|
||||||
|
shapeMorph: true
|
||||||
|
text: Network.connectingNetwork ? "" : "Apply"
|
||||||
|
|
||||||
|
onClicked: Network.requestConnect(root.network, passwordField.text)
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
active: opacity > 0
|
||||||
|
anchors.centerIn: parent
|
||||||
|
opacity: Network.connectingNetwork ? 1 : 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sourceComponent: CircularIndicator {
|
||||||
|
bgColor: "transparent"
|
||||||
|
implicitSize: buttonRow.height - Tokens.padding.normal
|
||||||
|
running: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool closed: true
|
||||||
|
property url currentPopup: ""
|
||||||
|
property var currentPopupProps: ({})
|
||||||
|
|
||||||
|
function requestClose(): void {
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestOpen(source: url, properties = {}): void {
|
||||||
|
currentPopupProps = properties;
|
||||||
|
currentPopup = source;
|
||||||
|
closed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +1,142 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Networking
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import qs.Components
|
import Quickshell
|
||||||
|
import ZShell.Components
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Modules
|
import qs.Services
|
||||||
import qs.Helpers as Helpers
|
import qs.Modules.Settings.Common
|
||||||
|
import qs.Modules.Bar.Popouts.Network
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers.Network
|
||||||
|
|
||||||
Item {
|
CustomClippingRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property var wrapper
|
required property var wrapper
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
implicitHeight: networkPopContent.height + networkPopContent.anchors.margins * 2
|
||||||
|
implicitWidth: 500 + 8 * 2
|
||||||
|
radius: (20 - Tokens.padding.small) * Tokens.rounding.scale
|
||||||
|
|
||||||
|
Component.onCompleted: Network.active = true
|
||||||
|
Component.onDestruction: Network.active = false
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: layout
|
id: networkPopContent
|
||||||
|
|
||||||
spacing: 8
|
anchors.left: parent.left
|
||||||
|
anchors.margins: Tokens.padding.large
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
spacing: Tokens.spacing.extraSmall / 2
|
||||||
|
|
||||||
Repeater {
|
CustomText {
|
||||||
model: Helpers.Network.devices
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
||||||
|
Layout.rightMargin: Tokens.padding.extraSmall
|
||||||
|
font.pointSize: Tokens.font.size.large
|
||||||
|
text: qsTr("Wifi")
|
||||||
|
}
|
||||||
|
|
||||||
CustomRadioButton {
|
Toggle {
|
||||||
id: network
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
||||||
|
checked: Network.wifiEnabled
|
||||||
|
first: true
|
||||||
|
last: Network.connectedNetworks.length === 0
|
||||||
|
subtext: qsTr("Toggle WiFi device state")
|
||||||
|
text: checked ? qsTr("Enabled") : qsTr("Disabled")
|
||||||
|
|
||||||
required property NetworkDevice modelData
|
onToggled: Network.setWifi(checked)
|
||||||
|
}
|
||||||
|
|
||||||
checked: Helpers.Network.activeDevice?.name === modelData.name
|
ListView {
|
||||||
text: modelData.description
|
id: rows
|
||||||
visible: modelData.name !== "lo"
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: contentHeight
|
||||||
|
interactive: false
|
||||||
|
section.property: "connected"
|
||||||
|
spacing: Tokens.spacing.extraSmall / 2
|
||||||
|
|
||||||
|
add: Transition {
|
||||||
|
Anim {
|
||||||
|
from: 0
|
||||||
|
property: "opacity"
|
||||||
|
to: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate: DelegateChooser {
|
||||||
|
role: "isDivider"
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: true
|
||||||
|
|
||||||
|
delegate: NetworkDivider {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
delegate: NetworkItem {
|
||||||
|
list: rows
|
||||||
|
width: rows.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displaced: Transition {
|
||||||
|
Anim {
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model: ScriptModel {
|
||||||
|
values: {
|
||||||
|
const byStrengthName = (a, b) => b.signalStrength - a.signalStrength || a.name.localeCompare(b.name);
|
||||||
|
const cNetworks = [...Network.connectedNetworks];
|
||||||
|
const kNetworks = [...Network.knownNetworks];
|
||||||
|
const uNetworks = [...Network.unknownNetworks];
|
||||||
|
|
||||||
|
return [...cNetworks.sort(byStrengthName), ...(kNetworks.length > 0 ? [
|
||||||
|
{
|
||||||
|
isDivider: true,
|
||||||
|
type: "known"
|
||||||
|
},
|
||||||
|
...kNetworks.sort(byStrengthName)] : []), ...(uNetworks.length > 0 ? [
|
||||||
|
{
|
||||||
|
isDivider: true,
|
||||||
|
type: "unknown"
|
||||||
|
},
|
||||||
|
...uNetworks.sort(byStrengthName)] : [])];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
move: Transition {
|
||||||
|
Anim {
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remove: Transition {
|
||||||
|
Anim {
|
||||||
|
property: "opacity"
|
||||||
|
to: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
section.delegate: Rectangle {
|
||||||
|
required property string section
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
height: childrenRect.height
|
||||||
|
width: ListView.view.width
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
text: parent.section
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetworkOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ Column {
|
|||||||
|
|
||||||
CustomText {
|
CustomText {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
elide: CustomText.ElideRight
|
||||||
text: layout.modelData.model
|
text: layout.modelData.model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Item {
|
|||||||
property real offsetScale: shouldBeActive ? 0 : 1
|
property real offsetScale: shouldBeActive ? 0 : 1
|
||||||
required property var panels
|
required property var panels
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
readonly property bool shouldBeActive: visibilities.dock && Config.dock.enable
|
readonly property bool shouldBeActive: visibilities.dock && Config.dock.enabled
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
|
anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
|
|||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
|
import QtQuick
|
||||||
import ZShell.Internal
|
import ZShell.Internal
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
@@ -30,12 +31,12 @@ Scope {
|
|||||||
Quickshell.execDetached(action);
|
Quickshell.execDetached(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
LidWatcher {
|
LidWatcher {
|
||||||
onAboutToSleep: root.lock.lock.locked = true
|
onAboutToSleep: root.lock.lock.locked = true
|
||||||
}
|
}
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
model: Config.general.idle.timeouts
|
model: Config.general.idle.timeouts.values
|
||||||
|
|
||||||
IdleMonitor {
|
IdleMonitor {
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
|||||||
+15
-18
@@ -73,20 +73,21 @@ Scope {
|
|||||||
|
|
||||||
// mask: Region { item: inputPanel }
|
// mask: Region { item: inputPanel }
|
||||||
|
|
||||||
Rectangle {
|
CustomRect {
|
||||||
id: inputPanel
|
id: inputPanel
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
color: Colors.tPalette.m3surface
|
color: Colors.tPalette.m3surface
|
||||||
implicitHeight: layout.childrenRect.height + 28
|
implicitHeight: layout.implicitHeight + layout.anchors.margins * 2
|
||||||
implicitWidth: layout.childrenRect.width + 32
|
implicitWidth: Math.max(layout.implicitWidth + layout.anchors.margins * 2, 450)
|
||||||
opacity: 0
|
opacity: 0
|
||||||
radius: Tokens.rounding.small * 2
|
radius: Tokens.rounding.small * 2
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: layout
|
id: layout
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.fill: parent
|
||||||
|
anchors.margins: Tokens.padding.medium
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: contentRow
|
id: contentRow
|
||||||
@@ -147,8 +148,8 @@ Scope {
|
|||||||
TextField {
|
TextField {
|
||||||
id: passInput
|
id: passInput
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 40
|
Layout.preferredHeight: 40
|
||||||
Layout.preferredWidth: contentColumn.implicitWidth
|
|
||||||
color: Colors.palette.m3onSurfaceVariant
|
color: Colors.palette.m3onSurfaceVariant
|
||||||
echoMode: polkitAgent.flow?.responseVisible ? TextInput.Normal : TextInput.Password
|
echoMode: polkitAgent.flow?.responseVisible ? TextInput.Normal : TextInput.Password
|
||||||
placeholderText: polkitAgent.flow?.failed ? " Incorrect Password" : " Input Password"
|
placeholderText: polkitAgent.flow?.failed ? " Incorrect Password" : " Input Password"
|
||||||
@@ -189,7 +190,8 @@ Scope {
|
|||||||
clip: true
|
clip: true
|
||||||
color: Colors.tPalette.m3surfaceContainerLow
|
color: Colors.tPalette.m3surfaceContainerLow
|
||||||
implicitHeight: 0
|
implicitHeight: 0
|
||||||
radius: 16
|
implicitWidth: textDetailsColumn.implicitWidth + textDetailsColumn.anchors.margins * 2
|
||||||
|
radius: Tokens.rounding.medium
|
||||||
visible: true
|
visible: true
|
||||||
|
|
||||||
Behavior on open {
|
Behavior on open {
|
||||||
@@ -197,7 +199,8 @@ Scope {
|
|||||||
Anim {
|
Anim {
|
||||||
property: "implicitHeight"
|
property: "implicitHeight"
|
||||||
target: detailsPanel
|
target: detailsPanel
|
||||||
to: !detailsPanel.open ? textDetailsColumn.childrenRect.height + 16 : 0
|
to: !detailsPanel.open ? textDetailsColumn.implicitHeight + Tokens.padding.small * 2 : 0
|
||||||
|
type: Anim.DefaultEffects
|
||||||
}
|
}
|
||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
@@ -205,12 +208,6 @@ Scope {
|
|||||||
target: textDetailsColumn
|
target: textDetailsColumn
|
||||||
to: !detailsPanel.open ? 1 : 0
|
to: !detailsPanel.open ? 1 : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Anim {
|
|
||||||
property: "scale"
|
|
||||||
target: textDetailsColumn
|
|
||||||
to: !detailsPanel.open ? 1 : 0.9
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,10 +215,9 @@ Scope {
|
|||||||
id: textDetailsColumn
|
id: textDetailsColumn
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 8
|
anchors.margins: Tokens.padding.small
|
||||||
opacity: 0
|
opacity: 0
|
||||||
scale: 0.9
|
spacing: Tokens.spacing.small
|
||||||
spacing: 8
|
|
||||||
|
|
||||||
CustomText {
|
CustomText {
|
||||||
text: `actionId: ${polkitAgent.flow?.actionId}`
|
text: `actionId: ${polkitAgent.flow?.actionId}`
|
||||||
@@ -239,16 +235,17 @@ Scope {
|
|||||||
Layout.preferredWidth: contentRow.implicitWidth
|
Layout.preferredWidth: contentRow.implicitWidth
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
IconTextButton {
|
IconButton {
|
||||||
id: detailsButton
|
id: detailsButton
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
horizontalPadding: Tokens.padding.medium
|
||||||
icon: "info"
|
icon: "info"
|
||||||
inactiveColor: Colors.palette.m3surfaceContainer
|
inactiveColor: Colors.palette.m3surfaceContainer
|
||||||
inactiveOnColor: Colors.palette.m3onSurface
|
inactiveOnColor: Colors.palette.m3onSurface
|
||||||
isRound: true
|
isRound: true
|
||||||
shapeMorph: true
|
shapeMorph: true
|
||||||
text: "Details"
|
verticalPadding: Tokens.padding.medium
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
panelWindow.detailsOpen = !panelWindow.detailsOpen;
|
panelWindow.detailsOpen = !panelWindow.detailsOpen;
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ CustomRect {
|
|||||||
bottomLeftRadius: last ? Tokens.rounding.largeIncreased : Tokens.rounding.extraSmall
|
bottomLeftRadius: last ? Tokens.rounding.largeIncreased : Tokens.rounding.extraSmall
|
||||||
bottomRightRadius: last ? Tokens.rounding.largeIncreased : Tokens.rounding.extraSmall
|
bottomRightRadius: last ? Tokens.rounding.largeIncreased : Tokens.rounding.extraSmall
|
||||||
color: Colors.tPalette.m3surfaceContainer
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
opacity: enabled && parent.enabled ? 1 : 0.5
|
opacity: enabled && (!parent || parent.enabled) ? 1 : 0.5
|
||||||
topLeftRadius: first ? Tokens.rounding.largeIncreased : Tokens.rounding.extraSmall
|
topLeftRadius: first ? Tokens.rounding.large : Tokens.rounding.extraSmall
|
||||||
topRightRadius: first ? Tokens.rounding.largeIncreased : Tokens.rounding.extraSmall
|
topRightRadius: first ? Tokens.rounding.large : Tokens.rounding.extraSmall
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
Anim {
|
Anim {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ pragma Singleton
|
|||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import qs.Components
|
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
|
import qs.Components
|
||||||
import qs.Modules.Settings.Common
|
import qs.Modules.Settings.Common
|
||||||
import qs.Modules.Settings.Pages
|
import qs.Modules.Settings.Pages
|
||||||
import qs.Modules.Settings.Pages.Wallpaper
|
import qs.Modules.Settings.Pages.Wallpaper
|
||||||
@@ -45,7 +45,11 @@ QtObject {
|
|||||||
|
|
||||||
// Connectivity
|
// Connectivity
|
||||||
Component {
|
Component {
|
||||||
PlaceholderComp {
|
StackPage {
|
||||||
|
Component {
|
||||||
|
NetworkPage {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Component {
|
Component {
|
||||||
|
|||||||
@@ -0,0 +1,251 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Modules.Settings.Common
|
||||||
|
import qs.Modules.Bar.Popouts.Network
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers.Network
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
PageBase {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
title: qsTr("Network")
|
||||||
|
|
||||||
|
Component.onCompleted: Network.active = true
|
||||||
|
Component.onDestruction: Network.active = false
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: networkContent
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: parent.top
|
||||||
|
spacing: Tokens.spacing.extraSmall / 2
|
||||||
|
width: root.cappedWidth
|
||||||
|
|
||||||
|
Toggle {
|
||||||
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
||||||
|
checked: Network.wifiEnabled
|
||||||
|
first: true
|
||||||
|
last: Network.connectedNetworks.length === 0
|
||||||
|
subtext: qsTr("Toggle WiFi device state")
|
||||||
|
text: checked ? qsTr("Enabled") : qsTr("Disabled")
|
||||||
|
|
||||||
|
onToggled: Network.setWifi(checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: rows
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: contentHeight
|
||||||
|
interactive: false
|
||||||
|
section.property: "connected"
|
||||||
|
spacing: Tokens.spacing.extraSmall / 2
|
||||||
|
|
||||||
|
add: Transition {
|
||||||
|
Anim {
|
||||||
|
from: 0
|
||||||
|
property: "opacity"
|
||||||
|
to: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate: DelegateChooser {
|
||||||
|
role: "isDivider"
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: true
|
||||||
|
|
||||||
|
delegate: NetworkDivider {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: false
|
||||||
|
|
||||||
|
delegate: KnownNetworkManager {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
delegate: NetworkItem {
|
||||||
|
list: rows
|
||||||
|
width: rows.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displaced: Transition {
|
||||||
|
Anim {
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model: ScriptModel {
|
||||||
|
values: {
|
||||||
|
const byStrengthName = (a, b) => b.signalStrength - a.signalStrength || a.name.localeCompare(b.name);
|
||||||
|
const cNetworks = [...Network.connectedNetworks];
|
||||||
|
const kNetworks = [...Network.knownNetworks];
|
||||||
|
const uNetworks = [...Network.unknownNetworks];
|
||||||
|
|
||||||
|
return [...cNetworks.sort(byStrengthName), ...(kNetworks.length > 0 ? [
|
||||||
|
{
|
||||||
|
isDivider: true,
|
||||||
|
type: "known"
|
||||||
|
},
|
||||||
|
...kNetworks.sort(byStrengthName),
|
||||||
|
{
|
||||||
|
isDivider: false
|
||||||
|
}
|
||||||
|
] : []), ...(uNetworks.length > 0 ? [
|
||||||
|
{
|
||||||
|
isDivider: true,
|
||||||
|
type: "unknown"
|
||||||
|
},
|
||||||
|
...uNetworks.sort(byStrengthName)] : [])];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
move: Transition {
|
||||||
|
Anim {
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remove: Transition {
|
||||||
|
Anim {
|
||||||
|
property: "opacity"
|
||||||
|
to: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
section.delegate: Rectangle {
|
||||||
|
required property string section
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
height: childrenRect.height
|
||||||
|
width: ListView.view.width
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
text: parent.section
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkOverlay {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component KnownNetworkManager: NetworkSelect {
|
||||||
|
acceptLabel: qsTr("Remove")
|
||||||
|
enabled: Object.keys(model).length > 0
|
||||||
|
header: qsTr("Manage known networks")
|
||||||
|
icon: "Network_Manage"
|
||||||
|
label: qsTr("Manage known networks")
|
||||||
|
model: Network.networks.filter(n => n.known && !n.connected).map(n => ({
|
||||||
|
id: n.name,
|
||||||
|
label: n.name
|
||||||
|
}))
|
||||||
|
rootParent: root.flickable
|
||||||
|
width: rows.width
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
if (!selectedItem)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const networkToForget = Network.networks.find(n => n.name === selectedItem);
|
||||||
|
Network.forgetNetwork(networkToForget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
component NetworkSelect: DialogRowButton {
|
||||||
|
id: klist
|
||||||
|
|
||||||
|
required property var model
|
||||||
|
property var selectedItem
|
||||||
|
|
||||||
|
function keyFor(item: var): string {
|
||||||
|
return item.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function labelFor(item: var): string {
|
||||||
|
return item.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptAllowed: !!selectedItem
|
||||||
|
horizontalContentMargin: -Tokens.padding.extraSmall
|
||||||
|
separateContent: true
|
||||||
|
|
||||||
|
content: Component {
|
||||||
|
VerticalFadeListView {
|
||||||
|
bottomMargin: Tokens.padding.large
|
||||||
|
model: klist.model
|
||||||
|
spacing: 0
|
||||||
|
topMargin: Tokens.padding.large
|
||||||
|
|
||||||
|
delegate: CustomRect {
|
||||||
|
id: item
|
||||||
|
|
||||||
|
required property var modelData
|
||||||
|
readonly property bool selected: klist.selectedItem === klist.keyFor(modelData)
|
||||||
|
|
||||||
|
anchors.left: ListView.view.contentItem.left
|
||||||
|
anchors.margins: 1 // Gets cut off for some reason without this
|
||||||
|
anchors.right: ListView.view.contentItem.right
|
||||||
|
color: Qt.alpha(Colors.palette.m3tertiaryContainer, selected ? 1 : 0)
|
||||||
|
implicitHeight: label.implicitHeight + Tokens.padding.small * 2
|
||||||
|
radius: stateLayer.pressed ? Tokens.rounding.extraSmall : selected ? Tokens.rounding.largeIncreased : Tokens.rounding.medium
|
||||||
|
|
||||||
|
Behavior on radius {
|
||||||
|
Anim {
|
||||||
|
type: Anim.SlowEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
id: stateLayer
|
||||||
|
|
||||||
|
onClicked: klist.selectedItem = klist.keyFor(item.modelData)
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: label
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: Tokens.padding.large
|
||||||
|
anchors.right: item.selected ? checkIcon.left : parent.right
|
||||||
|
anchors.rightMargin: item.selected ? Tokens.spacing.medium : anchors.margins
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: item.selected ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurface
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pointSize: Tokens.font.size.smaller
|
||||||
|
text: klist.labelFor(item.modelData)
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: checkIcon
|
||||||
|
|
||||||
|
anchors.margins: Tokens.padding.large
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: Colors.palette.m3onTertiaryContainer
|
||||||
|
font.pointSize: Tokens.font.size.normal
|
||||||
|
opacity: item.selected ? 1 : 0
|
||||||
|
text: "check"
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
type: Anim.SlowEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpenChanged: {
|
||||||
|
if (open)
|
||||||
|
selectedItem = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,9 @@ PageBase {
|
|||||||
readonly property var builtinIcons: ({
|
readonly property var builtinIcons: ({
|
||||||
audio: qsTr("Speakers"),
|
audio: qsTr("Speakers"),
|
||||||
microphone: qsTr("Microphone"),
|
microphone: qsTr("Microphone"),
|
||||||
power: qsTr("Battery")
|
power: qsTr("Battery"),
|
||||||
|
network: qsTr("Network"),
|
||||||
|
bluetooth: qsTr("Bluetooth")
|
||||||
})
|
})
|
||||||
|
|
||||||
isSubPage: true
|
isSubPage: true
|
||||||
@@ -91,5 +93,15 @@ PageBase {
|
|||||||
|
|
||||||
onToggled: Config.bar.popouts.statusIcons = checked
|
onToggled: Config.bar.popouts.statusIcons = checked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ToggleRow {
|
||||||
|
checked: Config.bar.popouts.network
|
||||||
|
last: true
|
||||||
|
settingAnchor: "bar-status-network-popout"
|
||||||
|
subtext: qsTr("Show a details popout when hovering the network icon")
|
||||||
|
text: qsTr("Network popout on hover")
|
||||||
|
|
||||||
|
onToggled: Config.bar.popouts.network = checked
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ void Gpu::tick() {
|
|||||||
const Type t = type();
|
const Type t = type();
|
||||||
if (t == Generic) {
|
if (t == Generic) {
|
||||||
readGenericUsage();
|
readGenericUsage();
|
||||||
|
readGenericMemory();
|
||||||
readGpuTemperature();
|
readGpuTemperature();
|
||||||
} else if (t == Nvidia) {
|
} else if (t == Nvidia) {
|
||||||
startNvidiaUsage();
|
startNvidiaUsage();
|
||||||
@@ -334,8 +335,10 @@ void Gpu::startNvidiaUsage() {
|
|||||||
const qreal usage =
|
const qreal usage =
|
||||||
parts.at(0).trimmed().toDouble(&ok1) / 100.0;
|
parts.at(0).trimmed().toDouble(&ok1) / 100.0;
|
||||||
const qreal temp = parts.at(1).trimmed().toDouble(&ok2);
|
const qreal temp = parts.at(1).trimmed().toDouble(&ok2);
|
||||||
const qreal memUsed = parts.at(2).trimmed().toDouble(&ok3);
|
const qreal memUsed =
|
||||||
const qreal memTotal = parts.at(3).trimmed().toDouble(&ok4);
|
parts.at(2).trimmed().toDouble(&ok3) * 1024;
|
||||||
|
const qreal memTotal =
|
||||||
|
parts.at(3).trimmed().toDouble(&ok4) * 1024;
|
||||||
|
|
||||||
if (ok1 && std::abs(usage - m_percentage) > 0.0001) {
|
if (ok1 && std::abs(usage - m_percentage) > 0.0001) {
|
||||||
m_percentage = usage;
|
m_percentage = usage;
|
||||||
|
|||||||
Reference in New Issue
Block a user