Warning, /plasma/bluedevil/src/kcm/package/contents/ui/main.qml is written in an unsupported language. File is not indexed.
0001 /** 0002 * SPDX-FileCopyrightText: 2020 Nicolas Fella <nicolas.fella@gmx.de> 0003 * SPDX-FileCopyrightText: 2021 Tom Zander <tom@flowee.org> 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 import QtQuick 2.2 0008 import QtQuick.Layouts 1.1 0009 import QtQuick.Controls 2.10 as QQC2 0010 0011 import org.kde.kirigami 2.20 as Kirigami 0012 import org.kde.kcm 1.2 0013 0014 import org.kde.bluezqt 1.0 as BluezQt 0015 0016 import org.kde.plasma.private.bluetooth 1.0 0017 0018 ScrollViewKCM { 0019 0020 id: root 0021 0022 function makeCall(call) { 0023 busyIndicator.running = true 0024 call.finished.connect(call => { 0025 busyIndicator.running = false 0026 if (call.error) { 0027 errorMessage.text = call.errorText 0028 errorMessage.visible = true 0029 } 0030 }) 0031 } 0032 0033 Connections { 0034 target: kcm 0035 0036 function onErrorOccured(errorText) { 0037 errorMessage.text = errorText 0038 errorMessage.visible = true 0039 } 0040 } 0041 0042 Component { 0043 id: forgetDialogComponent 0044 0045 Kirigami.PromptDialog { 0046 id: dialog 0047 0048 required property BluezQt.Adapter adapter 0049 required property BluezQt.Device device 0050 required property string name 0051 0052 signal call(BluezQt.PendingCall pc) 0053 0054 title: i18n("Forget this Device?") 0055 subtitle: i18n("Are you sure you want to forget \"%1\"?", dialog.name) 0056 0057 showCloseButton: false 0058 0059 // Need to use fully custom actions because it's not possible to override 0060 // the text and icon of a single standardbutton, and if we use just a 0061 // custom action for that one, then it's in the wrong visual position 0062 // relative to the StandardButton-provided Cancel button 0063 standardButtons: Kirigami.Dialog.NoButton 0064 customFooterActions: [ 0065 Kirigami.Action { 0066 text: i18nc("@action:button", "Forget Device") 0067 icon.name: "edit-delete-remove" 0068 onTriggered: { 0069 dialog.accept(); 0070 } 0071 }, 0072 Kirigami.Action { 0073 text: i18nc("@action:button", "Cancel") 0074 icon.name: "dialog-cancel" 0075 onTriggered: { 0076 dialog.reject(); 0077 } 0078 shortcut: StandardKey.Cancel 0079 } 0080 ] 0081 0082 onAccepted: call(adapter.removeDevice(device)) 0083 0084 contentData: [ 0085 Connections { 0086 target: dialog.device 0087 function onDeviceRemoved() { 0088 dialog.reject(); 0089 } 0090 }, 0091 Connections { 0092 target: dialog.adapter 0093 function onAdapterRemoved() { 0094 dialog.reject(); 0095 } 0096 function onPoweredChanged() { 0097 if (!dialog.adapter.powered) { 0098 dialog.reject(); 0099 } 0100 } 0101 } 0102 ] 0103 } 0104 } 0105 0106 implicitHeight: Kirigami.Units.gridUnit * 28 0107 implicitWidth: Kirigami.Units.gridUnit * 28 0108 0109 function setBluetoothEnabled(enabled) { 0110 BluezQt.Manager.bluetoothBlocked = !enabled 0111 0112 for (var i = 0; i < BluezQt.Manager.adapters.length; ++i) { 0113 var adapter = BluezQt.Manager.adapters[i]; 0114 adapter.powered = enabled; 0115 } 0116 } 0117 0118 header: Kirigami.InlineMessage { 0119 id: errorMessage 0120 type: Kirigami.MessageType.Error 0121 showCloseButton: true 0122 } 0123 0124 view: ListView { 0125 id: list 0126 clip: true 0127 0128 Kirigami.PlaceholderMessage { 0129 id: noBluetoothMessage 0130 // We cannot use the adapter count here because that can be zero when 0131 // bluetooth is disabled even when there are physical devices 0132 visible: BluezQt.Manager.rfkill.state === BluezQt.Rfkill.Unknown 0133 icon.name: "edit-none" 0134 text: i18n("No Bluetooth adapters found") 0135 width: parent.width - (Kirigami.Units.largeSpacing * 4) 0136 anchors.centerIn: parent 0137 } 0138 0139 Kirigami.PlaceholderMessage { 0140 id: bluetoothDisabledMessage 0141 visible: BluezQt.Manager.operational && !BluezQt.Manager.bluetoothOperational && !noBluetoothMessage.visible 0142 icon.name: "network-bluetooth" 0143 text: i18n("Bluetooth is disabled") 0144 width: parent.width - (Kirigami.Units.largeSpacing * 4) 0145 anchors.centerIn: parent 0146 0147 helpfulAction: Kirigami.Action { 0148 iconName: "network-bluetooth" 0149 text: i18n("Enable") 0150 onTriggered: { 0151 root.setBluetoothEnabled(true) 0152 } 0153 } 0154 } 0155 0156 Kirigami.PlaceholderMessage { 0157 visible: !noBluetoothMessage.visible && !bluetoothDisabledMessage.visible && list.count === 0 0158 icon.name: "network-bluetooth-activated" 0159 text: i18n("No devices paired") 0160 width: parent.width - (Kirigami.Units.largeSpacing * 4) 0161 anchors.centerIn: parent 0162 } 0163 0164 model: BluezQt.Manager.bluetoothOperational ? devicesModel : null 0165 0166 QQC2.BusyIndicator { 0167 id: busyIndicator 0168 running: false 0169 anchors.centerIn: parent 0170 } 0171 0172 0173 DevicesProxyModel { 0174 id: devicesModel 0175 sourceModel: BluezQt.DevicesModel { } 0176 } 0177 0178 section.property: "Connected" 0179 section.delegate: Kirigami.ListSectionHeader { 0180 text: section === "true" ? i18n("Connected") : i18n("Available") 0181 } 0182 0183 delegate: Kirigami.SwipeListItem { 0184 0185 // content item includes its own padding 0186 padding: 0 0187 0188 contentItem: Kirigami.BasicListItem { 0189 // The parent item already has a highlight 0190 activeBackgroundColor: "transparent" 0191 0192 separatorVisible: false 0193 0194 text: model.Name 0195 icon: model.Icon 0196 iconSize: Kirigami.Units.iconSizes.medium 0197 onClicked: kcm.push("Device.qml", {device: model.Device}) 0198 } 0199 0200 actions: [ 0201 Kirigami.Action { 0202 text: model.Connected ? i18n("Disconnect") : i18n("Connect") 0203 icon.name: model.Connected ? "network-disconnect" : "network-connect" 0204 onTriggered: { 0205 if (model.Connected) { 0206 root.makeCall(model.Device.disconnectFromDevice()) 0207 } else { 0208 root.makeCall(model.Device.connectToDevice()) 0209 } 0210 } 0211 }, 0212 Kirigami.Action { 0213 text: i18nc("@action:button %1 is the name of a Bluetooth device", "Forget \"%1\"", model.Name) 0214 icon.name: "edit-delete-remove" 0215 onTriggered: { 0216 const dialog = forgetDialogComponent.createObject(root, { 0217 adapter: model.Adapter, 0218 device: model.Device, 0219 name: model.Name, 0220 }); 0221 // Use IIFE (Immediately Invoked Function Expression) to hard-copy a reference 0222 // to root object, to avoid it being lost if the delegate is destroyed. 0223 dialog.call.connect((function (root) { 0224 return (call => root.makeCall(call)); 0225 })(root)); 0226 dialog.closed.connect(() => dialog.destroy()); 0227 dialog.open(); 0228 } 0229 } 0230 ] 0231 } 0232 } 0233 0234 // System Settings doesn't draw its own footer buttons, so extra footer 0235 // paddings here to make them look better isn't necessary 0236 extraFooterTopPadding: false 0237 footer: RowLayout { 0238 visible: BluezQt.Manager.bluetoothOperational 0239 0240 QQC2.Button { 0241 text: i18n("Add New Deviceā¦") 0242 icon.name: "list-add" 0243 onClicked: kcm.runWizard() 0244 } 0245 0246 QQC2.Button { 0247 text: i18n("Disable Bluetooth") 0248 icon.name: "network-bluetooth" 0249 onClicked: { 0250 root.setBluetoothEnabled(false) 0251 } 0252 } 0253 0254 Item { 0255 Layout.fillWidth: true 0256 } 0257 0258 QQC2.Button { 0259 text: i18n("Configureā¦") 0260 icon.name: "configure" 0261 onClicked: kcm.push("General.qml") 0262 } 0263 } 0264 }