refactor: network plugin wireless

Change-Id: If44223be8dc1f221fde3c5e4525fa66940410bd4
This commit is contained in:
listenerri 2018-06-22 19:07:11 +08:00 committed by ListenerRi
parent 09bbd59adb
commit f4ec8d859f
Notes: gerrit 2018-06-27 09:01:43 +08:00
Verified+1: <jenkins@deepin.com>
Code-Review+2: hualet <mr.asianwang@gmail.com>
Submitted-by: ListenerRi <listenerri@gmail.com>
Submitted-at: Wed, 27 Jun 2018 09:01:41 +0800
Reviewed-on: https://cr.deepin.io/35983
Project: dde/dde-dock
Branch: refs/heads/master
112 changed files with 1517 additions and 27 deletions

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "accesspoint.h"
#include <QDebug>
#include <QJsonDocument>
AccessPoint::AccessPoint(const QJsonObject &apInfo)
: QObject(nullptr)
{
loadApInfo(apInfo);
}
AccessPoint::AccessPoint(const AccessPoint &ap)
: QObject(nullptr)
{
*this = ap;
}
AccessPoint::AccessPoint(const QString &info)
{
const QJsonDocument doc = QJsonDocument::fromJson(info.toUtf8());
Q_ASSERT(doc.isObject());
loadApInfo(doc.object());
}
AccessPoint::AccessPoint()
: QObject(nullptr),
m_strength(0),
m_secured(false),
m_securedInEap(false)
{
}
bool AccessPoint::operator==(const AccessPoint &ap) const
{
// return m_path == ap.m_path;
return m_ssid == ap.ssid();
}
bool AccessPoint::operator>(const AccessPoint &ap) const
{
return m_strength > ap.m_strength;
}
AccessPoint &AccessPoint::operator=(const AccessPoint &ap)
{
m_strength = ap.m_strength;
m_secured = ap.m_secured;
m_securedInEap = ap.m_securedInEap;
m_path = ap.m_path;
m_ssid = ap.m_ssid;
return *this;
}
const QString AccessPoint::ssid() const
{
return m_ssid;
}
const QString AccessPoint::path() const
{
return m_path;
}
int AccessPoint::strength() const
{
return m_strength;
}
bool AccessPoint::secured() const
{
return m_secured;
}
void AccessPoint::loadApInfo(const QJsonObject &apInfo)
{
m_strength = apInfo.value("Strength").toInt();
m_secured = apInfo.value("Secured").toBool();
m_securedInEap = apInfo.value("SecuredInEap").toBool();
m_path = apInfo.value("Path").toString();
m_ssid = apInfo.value("Ssid").toString();
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACCESSPOINT_H
#define ACCESSPOINT_H
#include <QObject>
#include <QJsonObject>
class AccessPoint : public QObject
{
Q_OBJECT
public:
explicit AccessPoint(const QJsonObject &apInfo);
explicit AccessPoint(const QString &info);
explicit AccessPoint();
AccessPoint(const AccessPoint &ap);
bool operator==(const AccessPoint &ap) const;
bool operator>(const AccessPoint &ap) const;
AccessPoint &operator=(const AccessPoint &ap);
const QString ssid() const;
const QString path() const;
int strength() const;
bool secured() const;
private:
void loadApInfo(const QJsonObject &apInfo);
private:
int m_strength;
bool m_secured;
bool m_securedInEap;
QString m_path;
QString m_ssid;
};
#endif // ACCESSPOINT_H

View File

@ -0,0 +1,176 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "accesspointwidget.h"
#include "horizontalseperator.h"
#include <QHBoxLayout>
#include <QDebug>
#include <DSvgRenderer>
using namespace dde::network;
DWIDGET_USE_NAMESPACE
AccessPointWidget::AccessPointWidget()
: QFrame(nullptr),
m_activeState(NetworkDevice::Unknow),
m_ssidBtn(new QPushButton(this)),
m_disconnectBtn(new DImageButton(this)),
m_securityIcon(new QLabel),
m_strengthIcon(new QLabel)
{
const auto ratio = devicePixelRatioF();
m_ssidBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
m_ssidBtn->setObjectName("Ssid");
m_disconnectBtn->setVisible(false);
m_disconnectBtn->setNormalPic(":/wireless/resources/wireless/select.svg");
m_disconnectBtn->setHoverPic(":/wireless/resources/wireless/disconnect_hover.svg");
m_disconnectBtn->setPressPic(":/wireless/resources/wireless/disconnect_press.svg");
QPixmap iconPix = DSvgRenderer::render(":/wireless/resources/wireless/security.svg", QSize(16, 16) * ratio);
iconPix.setDevicePixelRatio(ratio);
m_securityIcon->setPixmap(iconPix);
m_securityIcon->hide();
QHBoxLayout *infoLayout = new QHBoxLayout;
infoLayout->addWidget(m_securityIcon);
infoLayout->addSpacing(5);
infoLayout->addWidget(m_strengthIcon);
infoLayout->addSpacing(10);
infoLayout->addWidget(m_ssidBtn);
infoLayout->addWidget(m_disconnectBtn);
infoLayout->addSpacing(20);
infoLayout->setSpacing(0);
infoLayout->setContentsMargins(15, 0, 0, 0);
QVBoxLayout *centralLayout = new QVBoxLayout;
centralLayout->addLayout(infoLayout);
centralLayout->setSpacing(0);
centralLayout->setMargin(0);
setLayout(centralLayout);
setStyleSheet("AccessPointWidget #Ssid {"
"color:white;"
"background-color:transparent;"
"border:none;"
"text-align:left;"
"}"
"AccessPointWidget {"
"border-radius:4px;"
"margin:0 2px;"
"border-top:1px solid rgba(255, 255, 255, .05);"
"}"
"AccessPointWidget:hover {"
"border:none;"
"margin:0;"
"background-color:rgba(255, 255, 255, .1);"
"}"
"AccessPointWidget[active=true] #Ssid {"
// "color:#2ca7f8;"
"}");
connect(m_ssidBtn, &QPushButton::clicked, this, &AccessPointWidget::clicked);
connect(m_ssidBtn, &QPushButton::clicked, this, &AccessPointWidget::ssidClicked);
connect(m_disconnectBtn, &DImageButton::clicked, this, &AccessPointWidget::disconnectBtnClicked);
}
void AccessPointWidget::updateAP(const AccessPoint &ap)
{
m_ap = ap;
m_ssidBtn->setText(ap.ssid());
setStrengthIcon(ap.strength());
m_securityIcon->setVisible(ap.secured());
// reset state
setActiveState(NetworkDevice::Unknow);
}
bool AccessPointWidget::active() const
{
return m_activeState == NetworkDevice::Activated;
}
void AccessPointWidget::setActiveState(const NetworkDevice::DeviceStatus state)
{
if (m_activeState == state)
return;
m_activeState = state;
setStyleSheet(styleSheet());
const bool isActive = active();
m_disconnectBtn->setVisible(isActive);
}
void AccessPointWidget::enterEvent(QEvent *e)
{
QWidget::enterEvent(e);
m_disconnectBtn->setNormalPic(":/wireless/resources/wireless/disconnect.svg");
}
void AccessPointWidget::leaveEvent(QEvent *e)
{
QWidget::leaveEvent(e);
m_disconnectBtn->setNormalPic(":/wireless/resources/wireless/select.svg");
}
void AccessPointWidget::setStrengthIcon(const int strength)
{
QPixmap iconPix;
const auto ratio = devicePixelRatioF();
const QSize s = QSize(16, 16) * ratio;
QString type;
if (strength == 100)
type = "80";
else if (strength < 20)
type = "0";
else
type = QString::number(strength / 10 & ~0x1) + "0";
iconPix = DSvgRenderer::render(QString(":/wireless/resources/wireless/wireless-%1-symbolic.svg").arg(type), s);
iconPix.setDevicePixelRatio(ratio);
m_strengthIcon->setPixmap(iconPix);
}
void AccessPointWidget::ssidClicked()
{
if (m_activeState == NetworkDevice::Activated)
return;
setActiveState(NetworkDevice::Prepare);
emit requestActiveAP(m_ap.path(), m_ap.ssid());
}
void AccessPointWidget::disconnectBtnClicked()
{
setActiveState(NetworkDevice::Unknow);
emit requestDeactiveAP(m_ap);
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACCESSPOINTWIDGET_H
#define ACCESSPOINTWIDGET_H
#include "accesspoint.h"
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QDBusObjectPath>
#include <dimagebutton.h>
#include <NetworkDevice>
class AccessPointWidget : public QFrame
{
Q_OBJECT
Q_PROPERTY(bool active READ active DESIGNABLE true)
public:
explicit AccessPointWidget();
const AccessPoint ap() const { return m_ap; }
void updateAP(const AccessPoint &ap);
bool active() const;
void setActiveState(const dde::network::NetworkDevice::DeviceStatus state);
signals:
void requestActiveAP(const QString &apPath, const QString &ssid) const;
void requestDeactiveAP(const AccessPoint &ap) const;
void clicked() const;
private:
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void setStrengthIcon(const int strength);
private slots:
void ssidClicked();
void disconnectBtnClicked();
private:
dde::network::NetworkDevice::DeviceStatus m_activeState;
AccessPoint m_ap;
QPushButton *m_ssidBtn;
Dtk::Widget::DImageButton *m_disconnectBtn;
QLabel *m_securityIcon;
QLabel *m_strengthIcon;
};
#endif // ACCESSPOINTWIDGET_H

View File

@ -0,0 +1,119 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devicecontrolwidget.h"
#include "horizontalseperator.h"
#include <DHiDPIHelper>
#include <QTimer>
#include <QHBoxLayout>
#include <QDebug>
#include <QEvent>
DWIDGET_USE_NAMESPACE
DeviceControlWidget::DeviceControlWidget(QWidget *parent)
: QWidget(parent)
{
m_deviceName = new QLabel;
m_deviceName->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
m_deviceName->setStyleSheet("color:white;");
m_switchBtn = new DSwitchButton;
const QPixmap pixmap = DHiDPIHelper::loadNxPixmap(":/wireless/resources/wireless/refresh_normal.svg");
m_loadingIndicator = new DLoadingIndicator;
m_loadingIndicator->setImageSource(pixmap);
m_loadingIndicator->setLoading(false);
m_loadingIndicator->setSmooth(true);
m_loadingIndicator->setAniDuration(1000);
m_loadingIndicator->setAniEasingCurve(QEasingCurve::InOutCirc);
m_loadingIndicator->installEventFilter(this);
m_loadingIndicator->setFixedSize(pixmap.size() / devicePixelRatioF());
QHBoxLayout *infoLayout = new QHBoxLayout;
infoLayout->addWidget(m_deviceName);
infoLayout->addWidget(m_loadingIndicator);
infoLayout->addSpacing(10);
infoLayout->addWidget(m_switchBtn);
infoLayout->setSpacing(0);
infoLayout->setContentsMargins(15, 0, 5, 0);
// m_seperator = new HorizontalSeperator;
// m_seperator->setFixedHeight(1);
// m_seperator->setColor(Qt::black);
QVBoxLayout *centralLayout = new QVBoxLayout;
centralLayout->addStretch();
centralLayout->addLayout(infoLayout);
centralLayout->addStretch();
// centralLayout->addWidget(m_seperator);
centralLayout->setMargin(0);
centralLayout->setSpacing(0);
setLayout(centralLayout);
setFixedHeight(30);
connect(m_switchBtn, &DSwitchButton::checkedChanged, this, &DeviceControlWidget::enableButtonToggled);
}
void DeviceControlWidget::setDeviceName(const QString &name)
{
m_deviceName->setText(name);
}
void DeviceControlWidget::setDeviceEnabled(const bool enable)
{
m_switchBtn->blockSignals(true);
m_switchBtn->setChecked(enable);
m_loadingIndicator->setVisible(enable);
m_switchBtn->blockSignals(false);
}
bool DeviceControlWidget::eventFilter(QObject *watched, QEvent *event)
{
if (watched == m_loadingIndicator) {
if (event->type() == QEvent::MouseButtonPress) {
if (!m_loadingIndicator->loading()) {
refreshNetwork();
}
}
}
return QWidget::eventFilter(watched, event);
}
void DeviceControlWidget::refreshNetwork()
{
emit requestRefresh();
m_loadingIndicator->setLoading(true);
QTimer::singleShot(1000, this, [=] {
m_loadingIndicator->setLoading(false);
});
}
//void DeviceControlWidget::setSeperatorVisible(const bool visible)
//{
// m_seperator->setVisible(visible);
//}

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DEVICECONTROLWIDGET_H
#define DEVICECONTROLWIDGET_H
#include "horizontalseperator.h"
#include <QWidget>
#include <QLabel>
#include <dloadingindicator.h>
#include <dswitchbutton.h>
DWIDGET_USE_NAMESPACE
class DeviceControlWidget : public QWidget
{
Q_OBJECT
public:
explicit DeviceControlWidget(QWidget *parent = 0);
void setDeviceName(const QString &name);
void setDeviceEnabled(const bool enable);
// void setSeperatorVisible(const bool visible);
signals:
void enableButtonToggled(const bool enable) const;
void requestRefresh() const;
protected:
bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE;
private slots:
void refreshNetwork();
private:
QLabel *m_deviceName;
Dtk::Widget::DSwitchButton *m_switchBtn;
// HorizontalSeperator *m_seperator;
DLoadingIndicator *m_loadingIndicator;
};
#endif // DEVICECONTROLWIDGET_H

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "horizontalseperator.h"
#include <QPainter>
HorizontalSeperator::HorizontalSeperator(QWidget *parent)
: QWidget(parent),
m_color(255, 255, 255, 255 * 0.1)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
}
void HorizontalSeperator::setColor(const QColor color)
{
m_color = color;
}
void HorizontalSeperator::paintEvent(QPaintEvent *e)
{
QWidget::paintEvent(e);
QPainter painter(this);
painter.fillRect(rect(), m_color);
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HORIZONTALSEPERATOR_H
#define HORIZONTALSEPERATOR_H
#include <QWidget>
class HorizontalSeperator : public QWidget
{
Q_OBJECT
public:
explicit HorizontalSeperator(QWidget *parent = 0);
void setColor(const QColor color);
protected:
void paintEvent(QPaintEvent *e);
private:
QColor m_color;
};
#endif // HORIZONTALSEPERATOR_H

View File

@ -0,0 +1,430 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "wirelesslist.h"
#include "accesspointwidget.h"
#include <QJsonDocument>
#include <QScreen>
#include <QDebug>
#include <QGuiApplication>
#include <dinputdialog.h>
#include <QScrollBar>
DWIDGET_USE_NAMESPACE
using namespace dde::network;
#define WIDTH 300
#define MAX_HEIGHT 300
#define ITEM_HEIGHT 30
WirelessList::WirelessList(WirelessDevice *deviceIter, QWidget *parent)
: QScrollArea(parent),
m_device(deviceIter),
m_activeAP(),
m_updateAPTimer(new QTimer(this)),
m_pwdDialog(new DInputDialog(nullptr)),
m_autoConnBox(new QCheckBox),
m_centralLayout(new QVBoxLayout),
m_centralWidget(new QWidget),
m_controlPanel(new DeviceControlWidget)
//m_networkInter(new DBusNetwork(this))
{
setFixedHeight(WIDTH);
m_currentClickAPW = nullptr;
m_autoConnBox->setText(tr("Auto-connect"));
const auto ratio = qApp->devicePixelRatio();
QPixmap iconPix = QIcon::fromTheme("notification-network-wireless-full").pixmap(QSize(48, 48) * ratio);
iconPix.setDevicePixelRatio(ratio);
m_pwdDialog->setTextEchoMode(QLineEdit::Password);
m_pwdDialog->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Dialog);
m_pwdDialog->setTextEchoMode(DLineEdit::Password);
m_pwdDialog->setIcon(iconPix);
m_pwdDialog->addSpacing(10);
m_pwdDialog->addContent(m_autoConnBox, Qt::AlignLeft);
m_pwdDialog->setOkButtonText(tr("Connect"));
m_pwdDialog->setCancelButtonText(tr("Cancel"));
m_updateAPTimer->setSingleShot(true);
m_updateAPTimer->setInterval(100);
m_centralWidget->setFixedWidth(WIDTH);
m_centralWidget->setLayout(m_centralLayout);
// m_centralLayout->addWidget(m_controlPanel);
m_centralLayout->setSpacing(0);
m_centralLayout->setMargin(0);
setWidget(m_centralWidget);
setFrameStyle(QFrame::NoFrame);
setFixedWidth(300);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setStyleSheet("background-color:transparent;");
m_indicator = new DPictureSequenceView(this);
m_indicator->setPictureSequence(":/wireless/indicator/resources/wireless/spinner14/Spinner%1.png", QPair<int, int>(1, 91), 2);
m_indicator->setFixedSize(QSize(14, 14) * ratio);
m_indicator->setVisible(false);
connect(m_device, &WirelessDevice::apAdded, this, &WirelessList::APAdded);
connect(m_device, &WirelessDevice::apRemoved, this, &WirelessList::APRemoved);
connect(m_device, &WirelessDevice::apInfoChanged, this, &WirelessList::APPropertiesChanged);
connect(m_device, &WirelessDevice::needSecrets, this, &WirelessList::onNeedSecrets);
connect(m_device, &WirelessDevice::needSecretsFinished, this, &WirelessList::onNeedSecretsFinished);
connect(m_device, &WirelessDevice::enableChanged, this, &WirelessList::onDeviceEnableChanged);
connect(m_controlPanel, &DeviceControlWidget::enableButtonToggled, this, &WirelessList::onEnableButtonToggle);
/* TODO: <22-06-18, yourname> */
//connect(m_controlPanel, &DeviceControlWidget::requestRefresh, m_networkInter, &DBusNetwork::RequestWirelessScan);
connect(m_updateAPTimer, &QTimer::timeout, this, &WirelessList::updateAPList);
connect(m_device, &WirelessDevice::activeConnectionChanged, m_updateAPTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
connect(m_device, static_cast<void (WirelessDevice:: *) (NetworkDevice::DeviceStatus stat) const>(&WirelessDevice::statusChanged), m_updateAPTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
connect(m_pwdDialog, &DInputDialog::textValueChanged, this, &WirelessList::onPwdDialogTextChanged);
connect(m_pwdDialog, &DInputDialog::cancelButtonClicked, this, &WirelessList::pwdDialogCanceled);
connect(m_pwdDialog, &DInputDialog::accepted, this, &WirelessList::pwdDialogAccepted);
connect(this->verticalScrollBar(), &QScrollBar::valueChanged, this, [=] {
if (!m_currentClickAPW) return;
const int h = -(m_currentClickAPW->height() - m_indicator->height()) / 2;
m_indicator->move(m_currentClickAPW->mapTo(this, m_currentClickAPW->rect().topRight()) - QPoint(35, h));
});
QMetaObject::invokeMethod(this, "loadAPList", Qt::QueuedConnection);
/* TODO: remove */
//loadAPList();
}
WirelessList::~WirelessList()
{
m_pwdDialog->deleteLater();
}
QWidget *WirelessList::controlPanel()
{
return m_controlPanel;
}
void WirelessList::APAdded(const QJsonObject &apInfo)
{
AccessPoint ap(apInfo);
if (m_apList.contains(ap))
return;
m_apList.append(ap);
m_updateAPTimer->start();
}
void WirelessList::APRemoved(const QJsonObject &apInfo)
{
AccessPoint ap(apInfo);
if (ap.ssid() == m_activeAP.ssid())
return;
/* TODO: <22-06-18, yourname> */
// m_apList.removeOne(ap);
// m_updateAPTimer->start();
// NOTE: if one ap removed, prehaps another ap has same ssid, so we need to refersh ap list instead of remove it
m_apList.clear();
loadAPList();
}
void WirelessList::setDeviceInfo(const int index)
{
// set device enable state
m_controlPanel->setDeviceEnabled(m_device->enabled());
// set device name
if (index == -1)
m_controlPanel->setDeviceName(tr("Wireless Network"));
else
m_controlPanel->setDeviceName(tr("Wireless Network %1").arg(index));
}
void WirelessList::loadAPList()
{
for (auto item : m_device->apList()) {
AccessPoint ap(item.toObject());
if (!m_apList.contains(ap))
m_apList.append(ap);
}
m_updateAPTimer->start();
}
void WirelessList::APPropertiesChanged(const QJsonObject &apInfo)
{
const AccessPoint ap(apInfo);
//auto it = std::find_if(m_apList.begin(), m_apList.end(),
//[&] (const AccessPoint &a) {return a == ap;});
//if (it == m_apList.end())
//return;
//*it = ap;
if (m_apList.contains(ap) && m_activeAP.path() == ap.path())
{
m_activeAP = ap;
}
// if (*it > ap)
// {
// *it = ap;
// m_activeAP = ap;
// m_updateAPTimer->start();
// emit activeAPChanged();
// }
}
void WirelessList::updateAPList()
{
Q_ASSERT(sender() == m_updateAPTimer);
int avaliableAPCount = 0;
//if (m_networkInter->IsDeviceEnabled(m_device.dbusPath()))
if (m_device->enabled())
{
m_currentClickAPW = nullptr;
// sort ap list by strength
// std::sort(m_apList.begin(), m_apList.end(), std::greater<AccessPoint>());
// const bool wirelessActived = m_device.state() == NetworkDevice::Activated;
// NOTE: Keep the amount consistent
if(m_apList.size() > m_apwList.size()) {
int i = m_apList.size() - m_apwList.size();
for (int index = 0; index != i; index++) {
AccessPointWidget *apw = new AccessPointWidget;
apw->setFixedHeight(ITEM_HEIGHT);
m_apwList << apw;
m_centralLayout->addWidget(apw);
connect(apw, &AccessPointWidget::requestActiveAP, this, &WirelessList::activateAP);
connect(apw, &AccessPointWidget::requestDeactiveAP, this, &WirelessList::deactiveAP);
}
} else if (m_apList.size() < m_apwList.size()) {
if (!m_apwList.isEmpty()) {
int i = m_apwList.size() - m_apList.size();
for (int index = 0; index != i; index++) {
AccessPointWidget *apw = m_apwList.last();
m_apwList.removeLast();
m_centralLayout->removeWidget(apw);
disconnect(apw, &AccessPointWidget::clicked, this, &WirelessList::updateIndicatorPos);
apw->deleteLater();
}
}
}
std::sort(m_apList.begin(), m_apList.end(), [&] (const AccessPoint &ap1, const AccessPoint &ap2) {
if (ap1 == m_activeAP)
return true;
if (ap2 == m_activeAP)
return false;
return ap1.strength() > ap2.strength();
});
for (int i = 0; i != m_apList.size(); i++) {
m_apwList[i]->updateAP(m_apList[i]);
++avaliableAPCount;
connect(m_apwList[i], &AccessPointWidget::clicked, this, &WirelessList::updateIndicatorPos, Qt::UniqueConnection);
}
// update active AP state
NetworkDevice::DeviceStatus deviceStatus = m_device->status();
if (!m_apwList.isEmpty()) {
AccessPointWidget *apw = m_apwList.first();
apw->setActiveState(deviceStatus);
}
// If the order of item changes
if (m_apList.contains(m_currentClickAP) && m_indicator->isVisible()) {
m_currentClickAPW = m_apwList.at(m_apList.indexOf(m_currentClickAP));
const int h = -(m_currentClickAPW->height() - m_indicator->height()) / 2;
m_indicator->move(m_currentClickAPW->mapTo(this, m_currentClickAPW->rect().topRight()) - QPoint(35, h));
}
if (deviceStatus == NetworkDevice::Activated ||
deviceStatus == NetworkDevice::Failed ||
deviceStatus == NetworkDevice::Unknow) {
m_indicator->stop();
m_indicator->hide();
}
}
const int contentHeight = avaliableAPCount * ITEM_HEIGHT;
m_centralWidget->setFixedHeight(contentHeight);
setFixedHeight(std::min(contentHeight, MAX_HEIGHT));
}
void WirelessList::onEnableButtonToggle(const bool enable)
{
Q_EMIT requestSetDeviceEnable(m_device->path(), enable);
m_updateAPTimer->start();
}
void WirelessList::pwdDialogAccepted()
{
if (m_pwdDialog->textValue().isEmpty())
return m_pwdDialog->setTextAlert(true);
Q_EMIT feedSecret(m_lastConnPath, m_lastConnSecurity, m_pwdDialog->textValue(), m_autoConnBox->isChecked());
}
void WirelessList::pwdDialogCanceled()
{
Q_EMIT cancelSecret(m_lastConnPath, m_lastConnSecurity);
m_pwdDialog->close();
}
void WirelessList::onPwdDialogTextChanged(const QString &text)
{
m_pwdDialog->setTextAlert(false);
do {
if (text.isEmpty())
break;
const int len = text.length();
// in wpa, password length must >= 8
if (len < 8 && m_lastConnSecurityType.startsWith("wifi-wpa"))
break;
if (!(len == 5 || len == 13 || len == 16) && m_lastConnSecurityType.startsWith("wifi-wep"))
break;
return m_pwdDialog->setOkButtonEnabled(true);
} while (false);
m_pwdDialog->setOkButtonEnabled(false);
}
void WirelessList::onDeviceEnableChanged(const bool enable)
{
m_controlPanel->setDeviceEnabled(enable);
m_updateAPTimer->start();
}
void WirelessList::activateAP(const QString &apPath, const QString &ssid)
{
QString uuid;
QList<QJsonObject> connections = m_device->connections();
for (auto item : connections) {
if (item.value("Ssid").toString() != ssid)
continue;
if (item.value("HwAddress").toString() != m_device->usingHwAdr())
continue;
uuid = item.value("Uuid").toString();
if (!uuid.isEmpty())
break;
}
Q_EMIT requestActiveAP(m_device->path(), apPath, uuid);
}
void WirelessList::deactiveAP()
{
Q_EMIT requestDeactiveAP(m_device->path());
}
void WirelessList::onNeedSecrets(const QString &info)
{
const QJsonObject infoObject = QJsonDocument::fromJson(info.toUtf8()).object();
const QString connPath = infoObject.value("ConnectionPath").toString();
const QString security = infoObject.value("SettingName").toString();
const QString securityType = infoObject.value("KeyType").toString();
const QString ssid = infoObject.value("ConnectionId").toString();
const bool defaultAutoConnect = infoObject.value("AutoConnect").toBool();
// check is our device' ap
QString connHwAddr;
QList<QJsonObject> connections = m_device->connections();
for (auto item : connections) {
if (item.value("Path").toString() != connPath)
continue;
connHwAddr = item.value("HwAddress").toString();
break;
}
if (connHwAddr != m_device->usingHwAdr())
return;
m_lastConnPath = connPath;
m_lastConnSecurity = security;
m_lastConnSecurityType = securityType;
m_autoConnBox->setChecked(defaultAutoConnect);
m_pwdDialog->setTitle(tr("Password required to connect to <font color=\"#faca57\">%1</font>").arg(ssid));
// clear old config
m_pwdDialog->setTextValue(QString());
m_pwdDialog->setTextAlert(true);
m_pwdDialog->setOkButtonEnabled(false);
// check if controlcenter handle this request
// QDBusInterface iface("com.deepin.dde.ControlCenter",
// "/com/deepin/dde/ControlCenter/Network",
// "com.deepin.dde.ControlCenter.Network");
// if (iface.isValid() && iface.call("active").arguments().first().toBool())
// return m_pwdDialog->hide();
if (!m_pwdDialog->isVisible())
m_pwdDialog->show();
}
void WirelessList::onNeedSecretsFinished(const QString &info0, const QString &info1)
{
m_pwdDialog->close();
}
void WirelessList::updateIndicatorPos()
{
m_currentClickAPW = static_cast<AccessPointWidget*>(sender());
if (m_currentClickAPW->active()) return;
m_currentClickAP = m_currentClickAPW->ap();
const int h = -(m_currentClickAPW->height() - m_indicator->height()) / 2;
m_indicator->move(m_currentClickAPW->mapTo(this, m_currentClickAPW->rect().topRight()) - QPoint(35, h));
m_indicator->show();
m_indicator->play();
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WIRELESSAPPLET_H
#define WIRELESSAPPLET_H
#include "devicecontrolwidget.h"
#include "accesspoint.h"
#include <QScrollArea>
#include <QVBoxLayout>
#include <QList>
#include <QTimer>
#include <QCheckBox>
#include <QDBusObjectPath>
#include <dpicturesequenceview.h>
#include <dinputdialog.h>
#include <WirelessDevice>
DWIDGET_USE_NAMESPACE
class AccessPointWidget;
class WirelessList : public QScrollArea
{
Q_OBJECT
public:
explicit WirelessList(dde::network::WirelessDevice *deviceIter, QWidget *parent = 0);
~WirelessList();
QWidget *controlPanel();
public Q_SLOTS:
void onNeedSecrets(const QString &info);
void onNeedSecretsFinished(const QString &info0, const QString &info1);
void setDeviceInfo(const int index);
signals:
void requestSetDeviceEnable(const QString &path, const bool enable) const;
void requestActiveAP(const QString &devPath, const QString &apPath, const QString &uuid) const;
void requestDeactiveAP(const QString &devPath) const;
void feedSecret(const QString &connectionPath, const QString &settingName, const QString &password, const bool autoConnect);
void cancelSecret(const QString &connectionPath, const QString &settingName);
private:
void loadAPList();
private slots:
void APAdded(const QJsonObject &apInfo);
void APRemoved(const QJsonObject &apInfo);
void APPropertiesChanged(const QJsonObject &apInfo);
void updateAPList();
void onEnableButtonToggle(const bool enable);
void pwdDialogAccepted();
void pwdDialogCanceled();
void onPwdDialogTextChanged(const QString &text);
void onDeviceEnableChanged(const bool enable);
void activateAP(const QString &apPath, const QString &ssid);
void deactiveAP();
void updateIndicatorPos();
private:
dde::network::WirelessDevice *m_device;
AccessPoint m_activeAP;
QList<AccessPoint> m_apList;
QList<AccessPointWidget*> m_apwList;
QTimer *m_updateAPTimer;
Dtk::Widget::DInputDialog *m_pwdDialog;
QCheckBox *m_autoConnBox;
Dtk::Widget::DPictureSequenceView *m_indicator;
AccessPointWidget *m_currentClickAPW;
AccessPoint m_currentClickAP;
QString m_lastConnPath;
QString m_lastConnSecurity;
QString m_lastConnSecurityType;
QVBoxLayout *m_centralLayout;
QWidget *m_centralWidget;
DeviceControlWidget *m_controlPanel;
};
#endif // WIRELESSAPPLET_H

View File

@ -34,8 +34,8 @@ WirelessItem::WirelessItem(WirelessDevice *device)
m_refershTimer(new QTimer(this)),
m_wirelessApplet(new QWidget),
m_wirelessPopup(new QLabel)
//m_APList(nullptr)
m_wirelessPopup(new QLabel),
m_APList(nullptr)
{
m_refershTimer->setSingleShot(false);
m_refershTimer->setInterval(100);
@ -48,13 +48,14 @@ WirelessItem::WirelessItem(WirelessDevice *device)
connect(m_device, static_cast<void (NetworkDevice::*) (const QString &statStr) const>(&NetworkDevice::statusChanged), m_refershTimer, static_cast<void (QTimer::*) ()>(&QTimer::start));
connect(m_refershTimer, &QTimer::timeout, this, static_cast<void (WirelessItem::*)()>(&WirelessItem::update));
QMetaObject::invokeMethod(this, "init", Qt::QueuedConnection);
}
WirelessItem::~WirelessItem()
{
//m_APList->deleteLater();
//m_APList->controlPanel()->deleteLater();
m_APList->deleteLater();
m_APList->controlPanel()->deleteLater();
}
QWidget *WirelessItem::itemApplet()
@ -70,7 +71,7 @@ QWidget *WirelessItem::itemTips()
if (stat == NetworkDevice::Activated)
{
const QJsonObject obj = static_cast<WirelessDevice *>(m_device)->activeApInfo();
const QJsonObject obj = static_cast<WirelessDevice *>(m_device)->activeConnectionInfo();
if (obj.contains("Ip4"))
{
const QJsonObject ip4 = obj["Ip4"].toObject();
@ -84,11 +85,25 @@ QWidget *WirelessItem::itemTips()
return m_wirelessPopup;
}
void WirelessItem::onNeedSecrets(const QString &info)
{
m_APList->onNeedSecrets(info);
}
void WirelessItem::onNeedSecretsFinished(const QString &info0, const QString &info1)
{
m_APList->onNeedSecretsFinished(info0, info1);
}
void WirelessItem::setDeviceInfo(const int index)
{
m_APList->setDeviceInfo(index);
}
bool WirelessItem::eventFilter(QObject *o, QEvent *e)
{
/* TODO: refactor */
//if (o == m_APList && e->type() == QEvent::Resize)
//QMetaObject::invokeMethod(this, "adjustHeight", Qt::QueuedConnection);
if (o == m_APList && e->type() == QEvent::Resize)
QMetaObject::invokeMethod(this, "adjustHeight", Qt::QueuedConnection);
return false;
}
@ -140,8 +155,6 @@ const QPixmap WirelessItem::iconPix(const Dock::DisplayMode displayMode, const i
{
QString type;
/* TODO: refactor */
//const auto state = m_APList->wirelessState();
const auto state = m_device->status();
if (state <= NetworkDevice::Disconnected)
{
@ -153,7 +166,7 @@ const QPixmap WirelessItem::iconPix(const Dock::DisplayMode displayMode, const i
int strength = 0;
if (state == NetworkDevice::Activated)
{
strength = static_cast<WirelessDevice *>(m_device)->activeApStrgength();
strength = static_cast<WirelessDevice *>(m_device)->activeApInfo().value("Strength").toInt();
m_refershTimer->stop();
}
else
@ -198,24 +211,27 @@ void WirelessItem::init()
//const auto devInfo = m_networkManager->device(m_devicePath);
//m_APList = new WirelessList(devInfo);
//m_APList->installEventFilter(this);
//m_APList->setObjectName("wireless-" + m_devicePath);
m_APList = new WirelessList(static_cast<WirelessDevice *>(m_device));
m_APList->installEventFilter(this);
m_APList->setObjectName("wireless-" + m_device->path());
//QVBoxLayout *vLayout = new QVBoxLayout;
//vLayout->addWidget(m_APList->controlPanel());
//vLayout->addWidget(m_APList);
//vLayout->setMargin(0);
//vLayout->setSpacing(0);
//m_wirelessApplet->setLayout(vLayout);
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(m_APList->controlPanel());
vLayout->addWidget(m_APList);
vLayout->setMargin(0);
vLayout->setSpacing(0);
m_wirelessApplet->setLayout(vLayout);
//connect(m_APList, &WirelessList::activeAPChanged, this, static_cast<void (WirelessItem::*)()>(&WirelessItem::update));
//connect(m_APList, &WirelessList::wirelessStateChanged, this, static_cast<void (WirelessItem::*)()>(&WirelessItem::update));
connect(m_APList, &WirelessList::requestSetDeviceEnable, this, &WirelessItem::requestSetDeviceEnable);
connect(m_APList, &WirelessList::requestActiveAP, this, &WirelessItem::requestActiveAP);
connect(m_APList, &WirelessList::requestDeactiveAP, this, &WirelessItem::requestDeactiveAP);
connect(m_APList, &WirelessList::feedSecret, this, &WirelessItem::feedSecret);
connect(m_APList, &WirelessList::cancelSecret, this, &WirelessItem::cancelSecret);
}
void WirelessItem::adjustHeight()
{
/* TODO: refactor */
//m_wirelessApplet->setFixedHeight(m_APList->height() + m_APList->controlPanel()->height());
m_wirelessApplet->setFixedHeight(m_APList->height() + m_APList->controlPanel()->height());
}
void WirelessItem::refreshIcon()

View File

@ -25,7 +25,7 @@
#include "constants.h"
#include "deviceitem.h"
//#include "applet/wirelessapplet.h"
#include "applet/wirelesslist.h"
#include <QHash>
#include <QLabel>
@ -43,6 +43,19 @@ public:
QWidget *itemApplet();
QWidget *itemTips();
public Q_SLOTS:
void onNeedSecrets(const QString &info);
void onNeedSecretsFinished(const QString &info0, const QString &info1);
// set the device name displayed
// in the top-left corner of the applet
void setDeviceInfo(const int index);
Q_SIGNALS:
void requestActiveAP(const QString &devPath, const QString &apPath, const QString &uuid) const;
void requestDeactiveAP(const QString &devPath) const;
void feedSecret(const QString &connectionPath, const QString &settingName, const QString &password, const bool autoConnect);
void cancelSecret(const QString &connectionPath, const QString &settingName);
protected:
bool eventFilter(QObject *o, QEvent *e);
void paintEvent(QPaintEvent *e);
@ -65,8 +78,7 @@ private:
QTimer *m_refershTimer;
QWidget *m_wirelessApplet;
QLabel *m_wirelessPopup;
/* TODO: refactor */
//WirelessList *m_APList;
WirelessList *m_APList;
};
#endif // WIRELESSITEM_H

View File

@ -131,7 +131,12 @@ QWidget *NetworkPlugin::itemTipsWidget(const QString &itemKey)
QWidget *NetworkPlugin::itemPopupApplet(const QString &itemKey)
{
/* TODO: refactor */
DeviceItem *item = itemByPath(itemKey);
if (item) {
return item->itemApplet();
}
Q_UNREACHABLE();
return nullptr;
}
@ -152,6 +157,8 @@ void NetworkPlugin::onDeviceListChanged(const QList<NetworkDevice *> devices)
QList<QString> mPaths = m_itemsMap.keys();
QList<QString> newPaths;
QList<WirelessItem *> wirelessItems;
for (auto device : devices) {
const QString &path = device->path();
newPaths << path;
@ -164,6 +171,22 @@ void NetworkPlugin::onDeviceListChanged(const QList<NetworkDevice *> devices)
break;
case NetworkDevice::Wireless:
item = new WirelessItem(static_cast<WirelessDevice *>(device));
wirelessItems.append(static_cast<WirelessItem *>(item));
connect(static_cast<WirelessItem *>(item), &WirelessItem::requestActiveAP,
m_networkWorker, &NetworkWorker::activateAccessPoint);
connect(static_cast<WirelessItem *>(item), &WirelessItem::requestDeactiveAP,
m_networkWorker, &NetworkWorker::disconnectDevice);
connect(static_cast<WirelessItem *>(item), &WirelessItem::feedSecret,
m_networkWorker, &NetworkWorker::feedSecret);
connect(static_cast<WirelessItem *>(item), &WirelessItem::cancelSecret,
m_networkWorker, &NetworkWorker::cancelSecret);
connect(m_networkModel, &NetworkModel::needSecrets,
static_cast<WirelessItem *>(item), &WirelessItem::onNeedSecrets);
connect(m_networkModel, &NetworkModel::needSecretsFinished,
static_cast<WirelessItem *>(item), &WirelessItem::onNeedSecretsFinished);
m_networkWorker->queryAccessPoints(path);
break;
default:
Q_UNREACHABLE();
@ -185,6 +208,13 @@ void NetworkPlugin::onDeviceListChanged(const QList<NetworkDevice *> devices)
m_itemsMap.take(mPath)->deleteLater();
}
}
int wirelessItemCount = wirelessItems.size();
for (int i = 0; i < wirelessItemCount; ++i) {
QTimer::singleShot(1, [=] {
wirelessItems.at(i)->setDeviceInfo(wirelessItemCount == 1 ? -1 : i + 1);
});
}
}
DeviceItem *NetworkPlugin::itemByPath(const QString &path)

View File

@ -20,5 +20,105 @@
<file>resources/wireless/wireless-60-symbolic.svg</file>
<file>resources/wireless/wireless-80-symbolic.svg</file>
<file>resources/wireless/wireless-disconnect-symbolic.svg</file>
<file>resources/wireless/security.svg</file>
<file>resources/wireless/refresh_press.svg</file>
<file>resources/wireless/refresh_normal.svg</file>
<file>resources/wireless/refresh_hover.svg</file>
<file>resources/wireless/select.svg</file>
<file>resources/wireless/disconnect_hover.svg</file>
<file>resources/wireless/disconnect_press.svg</file>
<file>resources/wireless/disconnect.svg</file>
</qresource>
<qresource prefix="/wireless/indicator">
<file>resources/wireless/spinner14/Spinner01.png</file>
<file>resources/wireless/spinner14/Spinner02.png</file>
<file>resources/wireless/spinner14/Spinner03.png</file>
<file>resources/wireless/spinner14/Spinner04.png</file>
<file>resources/wireless/spinner14/Spinner05.png</file>
<file>resources/wireless/spinner14/Spinner06.png</file>
<file>resources/wireless/spinner14/Spinner07.png</file>
<file>resources/wireless/spinner14/Spinner08.png</file>
<file>resources/wireless/spinner14/Spinner09.png</file>
<file>resources/wireless/spinner14/Spinner10.png</file>
<file>resources/wireless/spinner14/Spinner11.png</file>
<file>resources/wireless/spinner14/Spinner12.png</file>
<file>resources/wireless/spinner14/Spinner13.png</file>
<file>resources/wireless/spinner14/Spinner14.png</file>
<file>resources/wireless/spinner14/Spinner15.png</file>
<file>resources/wireless/spinner14/Spinner16.png</file>
<file>resources/wireless/spinner14/Spinner17.png</file>
<file>resources/wireless/spinner14/Spinner18.png</file>
<file>resources/wireless/spinner14/Spinner19.png</file>
<file>resources/wireless/spinner14/Spinner20.png</file>
<file>resources/wireless/spinner14/Spinner21.png</file>
<file>resources/wireless/spinner14/Spinner22.png</file>
<file>resources/wireless/spinner14/Spinner23.png</file>
<file>resources/wireless/spinner14/Spinner24.png</file>
<file>resources/wireless/spinner14/Spinner25.png</file>
<file>resources/wireless/spinner14/Spinner26.png</file>
<file>resources/wireless/spinner14/Spinner27.png</file>
<file>resources/wireless/spinner14/Spinner28.png</file>
<file>resources/wireless/spinner14/Spinner29.png</file>
<file>resources/wireless/spinner14/Spinner30.png</file>
<file>resources/wireless/spinner14/Spinner31.png</file>
<file>resources/wireless/spinner14/Spinner32.png</file>
<file>resources/wireless/spinner14/Spinner33.png</file>
<file>resources/wireless/spinner14/Spinner34.png</file>
<file>resources/wireless/spinner14/Spinner35.png</file>
<file>resources/wireless/spinner14/Spinner36.png</file>
<file>resources/wireless/spinner14/Spinner37.png</file>
<file>resources/wireless/spinner14/Spinner38.png</file>
<file>resources/wireless/spinner14/Spinner39.png</file>
<file>resources/wireless/spinner14/Spinner40.png</file>
<file>resources/wireless/spinner14/Spinner41.png</file>
<file>resources/wireless/spinner14/Spinner42.png</file>
<file>resources/wireless/spinner14/Spinner43.png</file>
<file>resources/wireless/spinner14/Spinner44.png</file>
<file>resources/wireless/spinner14/Spinner45.png</file>
<file>resources/wireless/spinner14/Spinner46.png</file>
<file>resources/wireless/spinner14/Spinner47.png</file>
<file>resources/wireless/spinner14/Spinner48.png</file>
<file>resources/wireless/spinner14/Spinner49.png</file>
<file>resources/wireless/spinner14/Spinner50.png</file>
<file>resources/wireless/spinner14/Spinner51.png</file>
<file>resources/wireless/spinner14/Spinner52.png</file>
<file>resources/wireless/spinner14/Spinner53.png</file>
<file>resources/wireless/spinner14/Spinner54.png</file>
<file>resources/wireless/spinner14/Spinner55.png</file>
<file>resources/wireless/spinner14/Spinner56.png</file>
<file>resources/wireless/spinner14/Spinner57.png</file>
<file>resources/wireless/spinner14/Spinner58.png</file>
<file>resources/wireless/spinner14/Spinner59.png</file>
<file>resources/wireless/spinner14/Spinner60.png</file>
<file>resources/wireless/spinner14/Spinner61.png</file>
<file>resources/wireless/spinner14/Spinner62.png</file>
<file>resources/wireless/spinner14/Spinner63.png</file>
<file>resources/wireless/spinner14/Spinner64.png</file>
<file>resources/wireless/spinner14/Spinner65.png</file>
<file>resources/wireless/spinner14/Spinner66.png</file>
<file>resources/wireless/spinner14/Spinner67.png</file>
<file>resources/wireless/spinner14/Spinner68.png</file>
<file>resources/wireless/spinner14/Spinner69.png</file>
<file>resources/wireless/spinner14/Spinner70.png</file>
<file>resources/wireless/spinner14/Spinner71.png</file>
<file>resources/wireless/spinner14/Spinner72.png</file>
<file>resources/wireless/spinner14/Spinner73.png</file>
<file>resources/wireless/spinner14/Spinner74.png</file>
<file>resources/wireless/spinner14/Spinner75.png</file>
<file>resources/wireless/spinner14/Spinner76.png</file>
<file>resources/wireless/spinner14/Spinner77.png</file>
<file>resources/wireless/spinner14/Spinner78.png</file>
<file>resources/wireless/spinner14/Spinner79.png</file>
<file>resources/wireless/spinner14/Spinner80.png</file>
<file>resources/wireless/spinner14/Spinner81.png</file>
<file>resources/wireless/spinner14/Spinner82.png</file>
<file>resources/wireless/spinner14/Spinner83.png</file>
<file>resources/wireless/spinner14/Spinner84.png</file>
<file>resources/wireless/spinner14/Spinner85.png</file>
<file>resources/wireless/spinner14/Spinner86.png</file>
<file>resources/wireless/spinner14/Spinner87.png</file>
<file>resources/wireless/spinner14/Spinner88.png</file>
<file>resources/wireless/spinner14/Spinner89.png</file>
<file>resources/wireless/spinner14/Spinner90.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>disconnect</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="disconnect">
<circle id="Oval-58" fill="#FFFFFF" opacity="0.800000012" cx="8" cy="8" r="8"></circle>
<g id="Group" transform="translate(5.500000, 5.500000)" stroke="#303030" stroke-width="1.2" stroke-linecap="round">
<path d="M0.384439573,4.94443861 L5.05110624,0.277771944" id="Stroke-12"></path>
<path d="M5.05110624,4.94443861 L0.384439573,0.277771944" id="Stroke-13"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 932 B

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>disconnect_hover</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="disconnect_hover">
<circle id="Oval-58" fill="#FFFFFF" cx="8" cy="8" r="8"></circle>
<g id="Group" transform="translate(5.500000, 5.500000)" stroke="#303030" stroke-width="1.2" stroke-linecap="round">
<path d="M0.384439573,4.94443861 L5.05110624,0.277771944" id="Stroke-12"></path>
<path d="M5.05110624,4.94443861 L0.384439573,0.277771944" id="Stroke-13"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 922 B

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>disconnect_press</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="disconnect_press">
<circle id="Oval-58" fill="#FFFFFF" opacity="0.200000003" cx="8" cy="8" r="8"></circle>
<g id="Group" transform="translate(5.500000, 5.500000)" stroke="#2CA7F8" stroke-width="1.2" stroke-linecap="round">
<path d="M0.384439573,4.94443861 L5.05110624,0.277771944" id="Stroke-12"></path>
<path d="M5.05110624,4.94443861 L0.384439573,0.277771944" id="Stroke-13"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 944 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>refresh_hover</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="dock位置" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="refresh_hover" stroke="#FFFFFF">
<g id="Group-9" transform="translate(1.000000, 0.000000)">
<path d="M13.4319825,5.23329444 C12.3594699,2.74325894 9.88331491,1 7,1 C3.13400675,1 0,4.13400675 0,8 C0,11.8659932 3.13400675,15 7,15 L7,15 C9.92193589,15 12.4257313,13.2097276 13.4743224,10.6662466" id="Oval-5"></path>
<path d="M13.5,1.20710678 L9.20710678,5.5 L13.5,5.5 L13.5,1.20710678 Z" id="Rectangle"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 956 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>refresh_normal</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="dock位置" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.600000024">
<g id="refresh_normal" stroke="#FFFFFF">
<g id="Group-9" transform="translate(1.000000, 0.000000)">
<path d="M13.4319825,5.23329444 C12.3594699,2.74325894 9.88331491,1 7,1 C3.13400675,1 0,4.13400675 0,8 C0,11.8659932 3.13400675,15 7,15 L7,15 C9.92193589,15 12.4257313,13.2097276 13.4743224,10.6662466" id="Oval-5"></path>
<path d="M13.5,1.20710678 L9.20710678,5.5 L13.5,5.5 L13.5,1.20710678 Z" id="Rectangle"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 980 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>refresh_press</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="dock位置" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="refresh_press" stroke="#2CA7F8">
<g id="Group-9" transform="translate(1.000000, 0.000000)">
<path d="M13.4319825,5.23329444 C12.3594699,2.74325894 9.88331491,1 7,1 C3.13400675,1 0,4.13400675 0,8 C0,11.8659932 3.13400675,15 7,15 L7,15 C9.92193589,15 12.4257313,13.2097276 13.4743224,10.6662466" id="Oval-5"></path>
<path d="M13.5,1.20710678 L9.20710678,5.5 L13.5,5.5 L13.5,1.20710678 Z" id="Rectangle"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 956 B

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<title>小锁</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="小锁" fill="#FFFFFF">
<path d="M5.987,11.006 L9.994,11.006 L9.994,9 L5.987,9 L5.987,11.006 Z M7.008,6.74 C7.008,6.341 7.333,6.016 7.732,6.016 L8.283,6.016 C8.683,6.016 9.008,6.341 9.008,6.74 L9.008,8.016 L7.008,8.016 L7.008,6.74 Z M10.459,8 L10,8 L10,6.74 C10,5.789 9.234,5 8.283,5 L7.732,5 C6.781,5 6,5.789 6,6.74 L6,8 L5.557,8 C5.254,8 5,8.261 5,8.565 L5,11.466 C5,11.77 5.254,12 5.557,12 L10.459,12 C10.762,12 11,11.77 11,11.466 L11,8.565 C11,8.261 10.762,8 10.459,8 L10.459,8 Z" id="Page-1"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1009 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>select</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="select">
<path d="M8,0 C3.6,0 0,3.59334258 0,7.98520574 C0,12.3770689 3.6,15.9704115 8,15.9704115 C12.4,15.9704115 16,12.3770689 16,7.98520574 C16,3.59334258 12.4,0 8,0 L8,0 Z" id="select_active-copy-24" fill="#FFFFFF" opacity="0.800000012"></path>
<g transform="translate(4.000000, 4.000000)" id="Path-1112" stroke-width="1.2" stroke="#303030">
<polyline points="0.601182426 4.06499815 3.2576281 6.88760344 8.63650463 0"></polyline>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Some files were not shown because too many files have changed in this diff Show More