mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-08-02 09:48:50 +00:00
kcm: Add ability to reorder quicksettings
Implements #75, reordering of quick settings, and also includes the mobile form components into the kcm.
This commit is contained in:
parent
35dec9d3d7
commit
17b4b774a3
19 changed files with 670 additions and 47 deletions
|
|
@ -9,35 +9,120 @@ import QtQuick.Controls 2.15 as QQC2
|
||||||
|
|
||||||
import org.kde.kirigami 2.19 as Kirigami
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
import org.kde.kcm 1.3 as KCM
|
import org.kde.kcm 1.3 as KCM
|
||||||
|
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
|
|
||||||
|
import "mobileform" as MobileForm
|
||||||
|
|
||||||
KCM.SimpleKCM {
|
KCM.SimpleKCM {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
title: i18n("Shell")
|
title: i18n("Shell")
|
||||||
|
|
||||||
leftPadding: Kirigami.Units.largeSpacing
|
leftPadding: 0
|
||||||
rightPadding: Kirigami.Units.largeSpacing
|
rightPadding: 0
|
||||||
|
topPadding: Kirigami.Units.gridUnit
|
||||||
|
bottomPadding: Kirigami.Units.gridUnit
|
||||||
|
|
||||||
Kirigami.FormLayout {
|
ColumnLayout {
|
||||||
id: form
|
spacing: 0
|
||||||
wideMode: false
|
width: root.width
|
||||||
|
|
||||||
Item {
|
MobileForm.FormCard {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Kirigami.FormData.label: i18n("Navigation Panel")
|
|
||||||
Kirigami.FormData.isSection: true
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
MobileForm.FormCardHeader {
|
||||||
|
title: i18n("Navigation Panel")
|
||||||
}
|
}
|
||||||
|
|
||||||
QQC2.CheckBox {
|
MobileForm.FormSwitchDelegate {
|
||||||
Kirigami.FormData.label: i18n("Remove panel (only use gestures):")
|
text: i18n("Gesture-only Mode")
|
||||||
Layout.maximumWidth: form.width
|
description: i18n("Whether to hide the navigation panel.")
|
||||||
text: checked ? i18n("On") : i18n("Off")
|
|
||||||
checked: !kcm.navigationPanelEnabled
|
checked: !kcm.navigationPanelEnabled
|
||||||
onCheckStateChanged: {
|
switchControl.onCheckStateChanged: {
|
||||||
if (checked != !kcm.navigationPanelEnabled) {
|
if (checked != !kcm.navigationPanelEnabled) {
|
||||||
kcm.navigationPanelEnabled = !checked;
|
kcm.navigationPanelEnabled = !checked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MobileForm.FormCard {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
MobileForm.FormCardHeader {
|
||||||
|
title: i18n("Quick Settings")
|
||||||
|
subtitle: i18n("Customize the order of quick settings in the pull-down panel.")
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: enabledQSListView
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: contentHeight
|
||||||
|
interactive: false
|
||||||
|
|
||||||
|
model: savedQuickSettings.enabledModel
|
||||||
|
|
||||||
|
moveDisplaced: Transition {
|
||||||
|
YAnimator {
|
||||||
|
duration: Kirigami.Units.longDuration
|
||||||
|
easing.type: Easing.InOutQuad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: listItemComponent
|
||||||
|
|
||||||
|
MobileForm.AbstractFormDelegate {
|
||||||
|
id: qsDelegate
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Kirigami.ListItemDragHandle {
|
||||||
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
|
listItem: qsDelegate
|
||||||
|
listView: enabledQSListView
|
||||||
|
onMoveRequested: savedQuickSettings.enabledModel.moveRow(oldIndex, newIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Icon {
|
||||||
|
visible: model.icon !== ""
|
||||||
|
source: model.icon
|
||||||
|
Layout.rightMargin: (model.icon !== "") ? Kirigami.Units.largeSpacing : 0
|
||||||
|
implicitWidth: (model.icon !== "") ? Kirigami.Units.iconSizes.small : 0
|
||||||
|
implicitHeight: (model.icon !== "") ? Kirigami.Units.iconSizes.small : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
QQC2.Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: model.name
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: Kirigami.DelegateRecycler {
|
||||||
|
width: enabledQSListView.width
|
||||||
|
sourceComponent: listItemComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MobileShell.SavedQuickSettings {
|
||||||
|
id: savedQuickSettings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.12 as Kirigami
|
||||||
|
|
||||||
|
Control {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool showSeparator: false
|
||||||
|
|
||||||
|
readonly property bool controlHovered: hoverHandler.hovered
|
||||||
|
|
||||||
|
signal clicked()
|
||||||
|
signal rightClicked()
|
||||||
|
|
||||||
|
leftPadding: Kirigami.Units.gridUnit
|
||||||
|
topPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
|
||||||
|
bottomPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
|
||||||
|
rightPadding: Kirigami.Units.gridUnit
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
|
background: Rectangle {
|
||||||
|
color: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, mouseArea.pressed ? 0.2 : hoverHandler.hovered ? 0.07 : 0)
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: 70 }
|
||||||
|
}
|
||||||
|
|
||||||
|
HoverHandler {
|
||||||
|
id: hoverHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Separator {
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: root.leftPadding
|
||||||
|
anchors.rightMargin: root.rightPadding
|
||||||
|
visible: root.showSeparator
|
||||||
|
opacity: 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
root.rightClicked();
|
||||||
|
} else if (mouse.button === Qt.LeftButton) {
|
||||||
|
root.clicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
|
AbstractFormDelegate {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string text: ""
|
||||||
|
property string description: ""
|
||||||
|
property string iconName: ""
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Kirigami.Icon {
|
||||||
|
visible: root.iconName !== ""
|
||||||
|
source: root.iconName
|
||||||
|
Layout.rightMargin: (root.iconName !== "") ? Kirigami.Units.largeSpacing : 0
|
||||||
|
implicitWidth: (root.iconName !== "") ? Kirigami.Units.iconSizes.small : 0
|
||||||
|
implicitHeight: (root.iconName !== "") ? Kirigami.Units.iconSizes.small : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.text
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.description
|
||||||
|
color: Kirigami.Theme.disabledTextColor
|
||||||
|
font: Kirigami.Theme.smallFont
|
||||||
|
elide: Text.ElideRight
|
||||||
|
visible: root.description !== ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Icon {
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
source: "arrow-right"
|
||||||
|
implicitWidth: Kirigami.Units.iconSizes.small
|
||||||
|
implicitHeight: Kirigami.Units.iconSizes.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
80
kcms/mobileshell/package/contents/ui/mobileform/FormCard.qml
Normal file
80
kcms/mobileshell/package/contents/ui/mobileform/FormCard.qml
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single card that is contained in a form.
|
||||||
|
*
|
||||||
|
* The height will take the implicit height of the contentItem, while the width
|
||||||
|
* is expected to be given by the parent.
|
||||||
|
*/
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The contents of the form card.
|
||||||
|
*/
|
||||||
|
property Item contentItem: Item {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum width of the card.
|
||||||
|
*/
|
||||||
|
property real maximumWidth: Kirigami.Units.gridUnit * 30
|
||||||
|
|
||||||
|
property real padding: 0
|
||||||
|
property real verticalPadding: padding
|
||||||
|
property real horizontalPadding: padding
|
||||||
|
property real topPadding: verticalPadding
|
||||||
|
property real bottomPadding: verticalPadding
|
||||||
|
property real leftPadding: horizontalPadding
|
||||||
|
property real rightPadding: horizontalPadding
|
||||||
|
|
||||||
|
readonly property bool cardWidthRestricted: root.width > root.maximumWidth
|
||||||
|
|
||||||
|
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||||
|
Kirigami.Theme.inherit: false
|
||||||
|
|
||||||
|
implicitHeight: topPadding + bottomPadding + contentItem.implicitHeight
|
||||||
|
|
||||||
|
onContentItemChanged: {
|
||||||
|
// clear old items
|
||||||
|
contentItemLoader.children = "";
|
||||||
|
|
||||||
|
contentItem.parent = contentItemLoader;
|
||||||
|
contentItem.anchors.fill = contentItemLoader;
|
||||||
|
contentItemLoader.children.push(contentItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
border.color: Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.15)
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
// only have card radius if it isn't filling the entire width
|
||||||
|
radius: root.cardWidthRestricted ? Kirigami.Units.smallSpacing : 0
|
||||||
|
color: Kirigami.Theme.backgroundColor
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
anchors.leftMargin: root.cardWidthRestricted ? Math.round((root.width - root.maximumWidth) / 2) : -1
|
||||||
|
anchors.rightMargin: root.cardWidthRestricted ? Math.round((root.width - root.maximumWidth) / 2) : -1
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: contentItemLoader
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: root.leftPadding
|
||||||
|
anchors.rightMargin: root.rightPadding
|
||||||
|
anchors.topMargin: root.topPadding
|
||||||
|
anchors.bottomMargin: root.bottomPadding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: root
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
property string title: ""
|
||||||
|
property string subtitle: ""
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
visible: title !== "" || subtitle !== ""
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.leftMargin: Kirigami.Units.gridUnit
|
||||||
|
Layout.rightMargin: Kirigami.Units.gridUnit
|
||||||
|
|
||||||
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.weight: Font.Bold
|
||||||
|
text: title
|
||||||
|
visible: title !== ""
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
color: Kirigami.Theme.disabledTextColor
|
||||||
|
font: Kirigami.Theme.smallFont
|
||||||
|
text: subtitle
|
||||||
|
visible: subtitle !== ""
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Separator {
|
||||||
|
opacity: 0.5
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
|
AbstractFormDelegate {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string text: ""
|
||||||
|
property alias checked: checkBoxItem.checked
|
||||||
|
property alias checkBox: checkBoxItem
|
||||||
|
|
||||||
|
onClicked: checked = !checked;
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
CheckBox {
|
||||||
|
id: checkBoxItem
|
||||||
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: root.text
|
||||||
|
elide: Text.ElideRight
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
|
AbstractFormDelegate {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string text: ""
|
||||||
|
property string description: ""
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
property string currentValue: ""
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.text
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
visible: root.description !== ""
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.description
|
||||||
|
color: Kirigami.Theme.disabledTextColor
|
||||||
|
font: Kirigami.Theme.smallFont
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
Layout.rightMargin: Kirigami.Units.smallSpacing
|
||||||
|
color: Kirigami.Theme.disabledTextColor
|
||||||
|
text: root.currentValue
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Icon {
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
source: "arrow-down"
|
||||||
|
implicitWidth: Kirigami.Units.iconSizes.small
|
||||||
|
implicitHeight: Kirigami.Units.iconSizes.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
|
AbstractFormDelegate {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string text: ""
|
||||||
|
property alias checked: radioButtonItem.checked
|
||||||
|
property alias radioButton: radioButtonItem
|
||||||
|
|
||||||
|
onClicked: checked = true;
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
RadioButton {
|
||||||
|
id: radioButtonItem
|
||||||
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: root.text
|
||||||
|
elide: Text.ElideRight
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
|
Label {
|
||||||
|
color: Kirigami.Theme.disabledTextColor
|
||||||
|
wrapMode: Label.Wrap
|
||||||
|
|
||||||
|
Layout.maximumWidth: Kirigami.Units.gridUnit * 30
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.leftMargin: Kirigami.Units.gridUnit
|
||||||
|
Layout.rightMargin: Kirigami.Units.gridUnit
|
||||||
|
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
|
AbstractFormDelegate {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string text: ""
|
||||||
|
property string description: ""
|
||||||
|
property alias checked: switchItem.checked
|
||||||
|
property alias switchControl: switchItem
|
||||||
|
|
||||||
|
onClicked: checked = !checked;
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.text
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
visible: root.description !== ""
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.description
|
||||||
|
color: Kirigami.Theme.disabledTextColor
|
||||||
|
font: Kirigami.Theme.smallFont
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Switch {
|
||||||
|
id: switchItem
|
||||||
|
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
|
AbstractFormDelegate {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string text: ""
|
||||||
|
property string description: ""
|
||||||
|
property string iconName: ""
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
background: Item {}
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Kirigami.Icon {
|
||||||
|
visible: root.iconName !== ""
|
||||||
|
source: root.iconName
|
||||||
|
Layout.rightMargin: (root.iconName !== "") ? Kirigami.Units.largeSpacing : 0
|
||||||
|
implicitWidth: (root.iconName !== "") ? Kirigami.Units.iconSizes.small : 0
|
||||||
|
implicitHeight: (root.iconName !== "") ? Kirigami.Units.iconSizes.small : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.text
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.description
|
||||||
|
color: Kirigami.Theme.disabledTextColor
|
||||||
|
font: Kirigami.Theme.smallFont
|
||||||
|
elide: Text.ElideRight
|
||||||
|
visible: root.description !== ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "mobileshellsettings.h"
|
#include "mobileshellsettings.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
using namespace MobileShell;
|
using namespace MobileShell;
|
||||||
|
|
||||||
const QString CONFIG_FILE = QStringLiteral("plasmamobilerc");
|
const QString CONFIG_FILE = QStringLiteral("plasmamobilerc");
|
||||||
|
|
@ -25,6 +27,7 @@ MobileShellSettings::MobileShellSettings(QObject *parent)
|
||||||
m_configWatcher = KConfigWatcher::create(m_config);
|
m_configWatcher = KConfigWatcher::create(m_config);
|
||||||
|
|
||||||
connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) -> void {
|
connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) -> void {
|
||||||
|
qDebug() << "config changed"; // TODO
|
||||||
if (group.name() == GENERAL_CONFIG_GROUP) {
|
if (group.name() == GENERAL_CONFIG_GROUP) {
|
||||||
Q_EMIT navigationPanelEnabledChanged();
|
Q_EMIT navigationPanelEnabledChanged();
|
||||||
} else if (group.name() == QUICKSETTINGS_CONFIG_GROUP) {
|
} else if (group.name() == QUICKSETTINGS_CONFIG_GROUP) {
|
||||||
|
|
@ -74,7 +77,7 @@ QList<QString> MobileShellSettings::enabledQuickSettings() const
|
||||||
|
|
||||||
void MobileShellSettings::setEnabledQuickSettings(QList<QString> &list)
|
void MobileShellSettings::setEnabledQuickSettings(QList<QString> &list)
|
||||||
{
|
{
|
||||||
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
auto group = KConfigGroup{m_config, QUICKSETTINGS_CONFIG_GROUP};
|
||||||
group.writeEntry("enabledQuickSettings", list, KConfigGroup::Notify);
|
group.writeEntry("enabledQuickSettings", list, KConfigGroup::Notify);
|
||||||
m_config->sync();
|
m_config->sync();
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +90,7 @@ QList<QString> MobileShellSettings::disabledQuickSettings() const
|
||||||
|
|
||||||
void MobileShellSettings::setDisabledQuickSettings(QList<QString> &list)
|
void MobileShellSettings::setDisabledQuickSettings(QList<QString> &list)
|
||||||
{
|
{
|
||||||
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
auto group = KConfigGroup{m_config, QUICKSETTINGS_CONFIG_GROUP};
|
||||||
group.writeEntry("disabledQuickSettings", list, KConfigGroup::Notify);
|
group.writeEntry("disabledQuickSettings", list, KConfigGroup::Notify);
|
||||||
m_config->sync();
|
m_config->sync();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ void QuickSettingsModel::loadQuickSettings()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
for (auto *quickSetting : m_quickSettings) {
|
for (auto *quickSetting : m_quickSettings) {
|
||||||
quickSetting->deleteLater();
|
quickSetting->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +74,7 @@ void QuickSettingsModel::loadQuickSettings()
|
||||||
// loop through enabled quick settings metadata
|
// loop through enabled quick settings metadata
|
||||||
for (const auto &metaData : m_savedQuickSettings->enabledQuickSettingsModel()->list()) {
|
for (const auto &metaData : m_savedQuickSettings->enabledQuickSettingsModel()->list()) {
|
||||||
// load kpackage
|
// load kpackage
|
||||||
KPackage::Package package = KPackage::PackageLoader::self()->loadPackage("KPackage/GenericQML", QFileInfo(metaData.fileName()).path());
|
KPackage::Package package = KPackage::PackageLoader::self()->loadPackage("KPackage/GenericQML", QFileInfo(metaData->fileName()).path());
|
||||||
if (!package.isValid()) {
|
if (!package.isValid()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -91,10 +93,12 @@ void QuickSettingsModel::loadQuickSettings()
|
||||||
}
|
}
|
||||||
delete created;
|
delete created;
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Loaded quicksetting" << metaData.fileName();
|
qDebug() << "Loaded quicksetting" << metaData->fileName();
|
||||||
m_quickSettings.push_back(createdSetting);
|
m_quickSettings.push_back(createdSetting);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete c;
|
delete c;
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,14 @@ SavedQuickSettings::SavedQuickSettings(QObject *parent)
|
||||||
, m_disabledPackages{}
|
, m_disabledPackages{}
|
||||||
, m_enabledQSModel{new SavedQuickSettingsModel{this}}
|
, m_enabledQSModel{new SavedQuickSettingsModel{this}}
|
||||||
, m_disabledQSModel{new SavedQuickSettingsModel{this}}
|
, m_disabledQSModel{new SavedQuickSettingsModel{this}}
|
||||||
|
, m_updateTimer{new QTimer{this}}
|
||||||
{
|
{
|
||||||
|
// throttle model updates from config, to avoid performance issues with fast reloading
|
||||||
|
m_updateTimer->setInterval(2000);
|
||||||
|
connect(m_updateTimer, &QTimer::timeout, this, [this]() {
|
||||||
|
refreshModel();
|
||||||
|
});
|
||||||
|
|
||||||
// load quicksettings packages
|
// load quicksettings packages
|
||||||
auto packages = KPackage::PackageLoader::self()->listPackages(QStringLiteral("KPackage/GenericQML"), "plasma/quicksettings");
|
auto packages = KPackage::PackageLoader::self()->listPackages(QStringLiteral("KPackage/GenericQML"), "plasma/quicksettings");
|
||||||
|
|
||||||
|
|
@ -27,29 +34,33 @@ SavedQuickSettings::SavedQuickSettings(QObject *parent)
|
||||||
qWarning() << "Quick setting package invalid:" << metaData.fileName();
|
qWarning() << "Quick setting package invalid:" << metaData.fileName();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
m_validPackages.push_back(metaData);
|
m_validPackages.push_back(new KPluginMetaData{metaData});
|
||||||
}
|
}
|
||||||
|
|
||||||
// subscribe to config changes
|
// subscribe to config changes
|
||||||
connect(m_settings, &MobileShellSettings::enabledQuickSettingsChanged, this, [this]() {
|
connect(m_settings, &MobileShellSettings::enabledQuickSettingsChanged, this, [this]() {
|
||||||
refreshModel();
|
m_updateTimer->start();
|
||||||
});
|
});
|
||||||
connect(m_settings, &MobileShellSettings::disabledQuickSettingsChanged, this, [this]() {
|
connect(m_settings, &MobileShellSettings::disabledQuickSettingsChanged, this, [this]() {
|
||||||
refreshModel();
|
m_updateTimer->start();
|
||||||
});
|
});
|
||||||
|
|
||||||
// subscribe to model changes
|
// subscribe to model changes
|
||||||
connect(m_enabledQSModel, &SavedQuickSettingsModel::dataUpdated, this, [this](QList<KPluginMetaData> data) -> void {
|
connect(m_enabledQSModel, &SavedQuickSettingsModel::dataUpdated, this, [this](QList<KPluginMetaData *> data) -> void {
|
||||||
m_enabledPackages.clear();
|
m_enabledPackages.clear();
|
||||||
for (auto metaData : data) {
|
for (auto metaData : data) {
|
||||||
m_enabledPackages.push_back(metaData);
|
m_enabledPackages.push_back(metaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveModel();
|
||||||
});
|
});
|
||||||
connect(m_disabledQSModel, &SavedQuickSettingsModel::dataUpdated, this, [this](QList<KPluginMetaData> data) -> void {
|
connect(m_disabledQSModel, &SavedQuickSettingsModel::dataUpdated, this, [this](QList<KPluginMetaData *> data) -> void {
|
||||||
m_disabledPackages.clear();
|
m_disabledPackages.clear();
|
||||||
for (auto metaData : data) {
|
for (auto metaData : data) {
|
||||||
m_disabledPackages.push_back(metaData);
|
m_disabledPackages.push_back(metaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveModel();
|
||||||
});
|
});
|
||||||
|
|
||||||
// load
|
// load
|
||||||
|
|
@ -77,7 +88,7 @@ void SavedQuickSettings::refreshModel()
|
||||||
// add enabled quick settings in order
|
// add enabled quick settings in order
|
||||||
for (const QString &pluginId : enabledQS) {
|
for (const QString &pluginId : enabledQS) {
|
||||||
for (auto &metaData : m_validPackages) {
|
for (auto &metaData : m_validPackages) {
|
||||||
if (pluginId == metaData.pluginId()) {
|
if (pluginId == metaData->pluginId()) {
|
||||||
m_enabledPackages.push_back(metaData);
|
m_enabledPackages.push_back(metaData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +98,7 @@ void SavedQuickSettings::refreshModel()
|
||||||
// add disabled quick settings in order
|
// add disabled quick settings in order
|
||||||
for (const QString &pluginId : disabledQS) {
|
for (const QString &pluginId : disabledQS) {
|
||||||
for (auto &metaData : m_validPackages) {
|
for (auto &metaData : m_validPackages) {
|
||||||
if (pluginId == metaData.pluginId()) {
|
if (pluginId == metaData->pluginId()) {
|
||||||
m_disabledPackages.push_back(metaData);
|
m_disabledPackages.push_back(metaData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +107,7 @@ void SavedQuickSettings::refreshModel()
|
||||||
|
|
||||||
// add undefined quick settings to the back of enabled quick settings
|
// add undefined quick settings to the back of enabled quick settings
|
||||||
for (auto &metaData : m_validPackages) {
|
for (auto &metaData : m_validPackages) {
|
||||||
if (!enabledQS.contains(metaData.pluginId()) && !disabledQS.contains(metaData.pluginId())) {
|
if (!enabledQS.contains(metaData->pluginId()) && !disabledQS.contains(metaData->pluginId())) {
|
||||||
m_enabledPackages.push_back(metaData);
|
m_enabledPackages.push_back(metaData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -111,10 +122,10 @@ void SavedQuickSettings::saveModel()
|
||||||
QList<QString> disabledQS;
|
QList<QString> disabledQS;
|
||||||
|
|
||||||
for (auto &metaData : m_enabledPackages) {
|
for (auto &metaData : m_enabledPackages) {
|
||||||
enabledQS.push_back(metaData.pluginId());
|
enabledQS.push_back(metaData->pluginId());
|
||||||
}
|
}
|
||||||
for (auto &metaData : m_disabledPackages) {
|
for (auto &metaData : m_disabledPackages) {
|
||||||
disabledQS.push_back(metaData.pluginId());
|
disabledQS.push_back(metaData->pluginId());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_settings->setEnabledQuickSettings(enabledQS);
|
m_settings->setEnabledQuickSettings(enabledQS);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QQmlListProperty>
|
#include <QQmlListProperty>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include "mobileshell_export.h"
|
#include "mobileshell_export.h"
|
||||||
|
|
||||||
|
|
@ -22,6 +23,8 @@ namespace MobileShell
|
||||||
class MOBILESHELL_EXPORT SavedQuickSettings : public QObject
|
class MOBILESHELL_EXPORT SavedQuickSettings : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(SavedQuickSettingsModel *enabledModel READ enabledQuickSettingsModel CONSTANT)
|
||||||
|
Q_PROPERTY(SavedQuickSettingsModel *disabledModel READ disabledQuickSettingsModel CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SavedQuickSettings(QObject *parent = nullptr);
|
SavedQuickSettings(QObject *parent = nullptr);
|
||||||
|
|
@ -34,12 +37,14 @@ private:
|
||||||
void saveModel();
|
void saveModel();
|
||||||
|
|
||||||
MobileShellSettings *m_settings;
|
MobileShellSettings *m_settings;
|
||||||
QList<KPluginMetaData> m_validPackages;
|
QList<KPluginMetaData *> m_validPackages;
|
||||||
QList<KPluginMetaData> m_enabledPackages;
|
QList<KPluginMetaData *> m_enabledPackages;
|
||||||
QList<KPluginMetaData> m_disabledPackages;
|
QList<KPluginMetaData *> m_disabledPackages;
|
||||||
|
|
||||||
SavedQuickSettingsModel *m_enabledQSModel;
|
SavedQuickSettingsModel *m_enabledQSModel;
|
||||||
SavedQuickSettingsModel *m_disabledQSModel;
|
SavedQuickSettingsModel *m_disabledQSModel;
|
||||||
|
|
||||||
|
QTimer *m_updateTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MobileShell
|
} // namespace MobileShell
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ QVariant SavedQuickSettingsModel::data(const QModelIndex &index, int role) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == NameRole) {
|
if (role == NameRole) {
|
||||||
return m_data[index.row()].name();
|
return m_data[index.row()]->name();
|
||||||
} else if (role == IconRole) {
|
} else if (role == IconRole) {
|
||||||
return QString(); // TODO m_data[index.row()].icon();
|
return m_data[index.row()]->iconName();
|
||||||
} else if (role == IdRole) {
|
} else if (role == IdRole) {
|
||||||
return m_data[index.row()].pluginId();
|
return m_data[index.row()]->pluginId();
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
@ -43,14 +43,18 @@ void SavedQuickSettingsModel::moveRow(int oldIndex, int newIndex)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldIndex < newIndex) {
|
||||||
|
++newIndex;
|
||||||
|
}
|
||||||
|
|
||||||
Q_EMIT beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
|
Q_EMIT beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
|
||||||
std::iter_swap(m_data.begin() + oldIndex, m_data.end() + newIndex);
|
std::iter_swap(m_data.begin() + oldIndex, m_data.begin() + newIndex);
|
||||||
Q_EMIT endMoveRows();
|
Q_EMIT endMoveRows();
|
||||||
|
|
||||||
Q_EMIT dataUpdated(m_data);
|
Q_EMIT dataUpdated(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SavedQuickSettingsModel::insertRow(KPluginMetaData metaData, int index)
|
void SavedQuickSettingsModel::insertRow(KPluginMetaData *metaData, int index)
|
||||||
{
|
{
|
||||||
Q_EMIT beginInsertRows(QModelIndex(), index, index);
|
Q_EMIT beginInsertRows(QModelIndex(), index, index);
|
||||||
m_data.insert(index, metaData);
|
m_data.insert(index, metaData);
|
||||||
|
|
@ -72,12 +76,12 @@ void SavedQuickSettingsModel::removeRow(int index)
|
||||||
Q_EMIT dataUpdated(m_data);
|
Q_EMIT dataUpdated(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<KPluginMetaData> SavedQuickSettingsModel::list() const
|
QList<KPluginMetaData *> SavedQuickSettingsModel::list() const
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SavedQuickSettingsModel::updateData(QList<KPluginMetaData> data)
|
void SavedQuickSettingsModel::updateData(QList<KPluginMetaData *> data)
|
||||||
{
|
{
|
||||||
Q_EMIT beginResetModel();
|
Q_EMIT beginResetModel();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,19 +35,19 @@ public:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
Q_INVOKABLE void moveRow(int oldIndex, int newIndex);
|
Q_INVOKABLE void moveRow(int oldIndex, int newIndex);
|
||||||
Q_INVOKABLE void insertRow(KPluginMetaData metaData, int index);
|
Q_INVOKABLE void insertRow(KPluginMetaData *metaData, int index);
|
||||||
Q_INVOKABLE void removeRow(int index);
|
Q_INVOKABLE void removeRow(int index);
|
||||||
|
|
||||||
QList<KPluginMetaData> list() const;
|
QList<KPluginMetaData *> list() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void updateData(QList<KPluginMetaData> data);
|
void updateData(QList<KPluginMetaData *> data);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void dataUpdated(QList<KPluginMetaData> data);
|
void dataUpdated(QList<KPluginMetaData *> data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<KPluginMetaData> m_data;
|
QList<KPluginMetaData *> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MobileShell
|
} // namespace MobileShell
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=Mobile Data
|
Name=Mobile Data
|
||||||
Icon=flashlight-on
|
Icon=network-modem
|
||||||
Description=Location quick setting
|
Description=Location quick setting
|
||||||
|
|
||||||
Type=Service
|
Type=Service
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=Wi-Fi
|
Name=Wi-Fi
|
||||||
Icon=flashlight-on
|
Icon=network-wireless-signal
|
||||||
Description=Wi-Fi quick setting
|
Description=Wi-Fi quick setting
|
||||||
|
|
||||||
Type=Service
|
Type=Service
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue