diff --git a/applet/contents/ui/ConnectionItem.qml b/applet/contents/ui/ConnectionItem.qml --- a/applet/contents/ui/ConnectionItem.qml +++ b/applet/contents/ui/ConnectionItem.qml @@ -166,6 +166,20 @@ icon: (ConnectionState == PlasmaNM.Enums.Deactivated) ? "network-connect" : "network-disconnect" onClicked: changeState() } + PlasmaComponents.MenuItem { + text: i18n("Show network's QR code") + visible: ConnectionState !== PlasmaNM.Enums.Deactivated + onClicked: { + const data = handler.wifiCode(ConnectionPath, SpecificPath) + var obj = showQR.createObject(connectionItem, { content: data }); + obj.showMaximized() + } + + Component { + id: showQR + ShowQR {} + } + } PlasmaComponents.MenuItem { text: i18n("Configure...") icon: "settings-configure" diff --git a/applet/contents/ui/ShowQR.qml b/applet/contents/ui/ShowQR.qml new file mode 100644 --- /dev/null +++ b/applet/contents/ui/ShowQR.qml @@ -0,0 +1,53 @@ +/* + Copyright 2019 Aleix Pol Gonzalez + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +import QtQuick 2.0 +import QtQuick.Window 2.0 +import QtQuick.Layouts 1.0 +import org.kde.kirigami 2.3 as Kirigami +import org.kde.prison 1.0 as Prison + +Window +{ + id: window + color: Qt.rgba(0, 0, 0, 0.3) + flags: Qt.FramelessWindowHint + + property alias content: dataInput.content + + MouseArea { + anchors.fill: parent + + onClicked: { + window.visible = false + window.destroy() + } + + Prison.Barcode { + anchors { + fill: parent + margins: Kirigami.Units.largeSpacing * 4 + } + + id: dataInput + barcodeType: "QRCode" + } + } +} diff --git a/kded/networkmanagement.notifyrc b/kded/networkmanagement.notifyrc --- a/kded/networkmanagement.notifyrc +++ b/kded/networkmanagement.notifyrc @@ -812,3 +812,7 @@ Name[zh_TW]=偵測到強制入口 IconName=dialog-password Action=Popup + +[Event/WifiQR] +Name=Show network's QR code +Action=Popup diff --git a/libs/handler.h b/libs/handler.h --- a/libs/handler.h +++ b/libs/handler.h @@ -68,6 +68,9 @@ * it will open the connection editor for advanced configuration. * */ void addAndActivateConnection(const QString &device, const QString &specificParameter, const QString &password = QString()); + + QString wifiCode(const QString& connection, const QString& specificObject) const; + /** * Adds a new connection * @map - NMVariantMapMap with connection settings diff --git a/libs/handler.cpp b/libs/handler.cpp --- a/libs/handler.cpp +++ b/libs/handler.cpp @@ -165,6 +165,75 @@ connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); } +QString Handler::wifiCode(const QString& connectionPath, const QString& specificObject) const +{ + NetworkManager::AccessPoint::Ptr ap; + NetworkManager::WirelessDevice::Ptr wifiDev; + for (const NetworkManager::Device::Ptr &dev : NetworkManager::networkInterfaces()) { + if (dev->type() == NetworkManager::Device::Wifi) { + wifiDev = dev.objectCast(); + ap = wifiDev->findAccessPoint(specificObject); + if (ap) { + break; + } + } + } + + if (!ap) { + return {}; + } + + // https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11 + + const NetworkManager::WirelessSecurityType securityType = NetworkManager::findBestWirelessSecurity(wifiDev->wirelessCapabilities(), true, (ap->mode() == NetworkManager::AccessPoint::Adhoc), ap->capabilities(), ap->wpaFlags(), ap->rsnFlags()); + QString ret = QStringLiteral("WIFI:"); + if (securityType != NetworkManager::NoneSecurity) { + switch (securityType) { + case NetworkManager::NoneSecurity: + break; + case NetworkManager::StaticWep: + case NetworkManager::DynamicWep: + ret += "T:WEP;"; + break; + case NetworkManager::WpaPsk: + case NetworkManager::Wpa2Psk: + ret += "T:WPA;"; + break; + default: + case NetworkManager::WpaEap: + case NetworkManager::Wpa2Eap: + case NetworkManager::Leap: + return {}; + } + } + ret += QStringLiteral("S:") + ap->ssid() + QLatin1Char(';'); + + NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(connectionPath); + const auto key = QStringLiteral("802-11-wireless-security"); + auto reply = connection->secrets(key); + + const auto secret = reply.argumentAt<0>()[key]; + QString pass; + switch (securityType) { + case NetworkManager::NoneSecurity: + break; + case NetworkManager::WpaPsk: + case NetworkManager::Wpa2Psk: + pass = secret["psk"].toString(); + break; + default: + return {}; + } + if (!pass.isEmpty()) + ret += QStringLiteral("P:") + pass; + + KNotification *notification = new KNotification("WifiQR", KNotification::CloseOnTimeout); + notification->setComponentName("networkmanagement"); + notification->setTitle(connection->name()); + + return ret + QLatin1Char(';'); +} + void Handler::addAndActivateConnection(const QString& device, const QString& specificObject, const QString& password) { NetworkManager::AccessPoint::Ptr ap;