feature:1、add networkmanager-qt library with dbus
2、add collect networkresource class with connect 、activate connect、device and wifinetwork 3、add network connect and disconnect function.
This commit is contained in:
parent
5536e64c09
commit
38c052912e
12
kylin-nm.pro
12
kylin-nm.pro
|
@ -15,11 +15,13 @@ LANGUAGE = C++
|
|||
CONFIG += c++14
|
||||
CONFIG += qt warn_on
|
||||
#CONFIG += release
|
||||
#CONFIG += link_pkgconfig
|
||||
CONFIG += link_pkgconfig
|
||||
|
||||
#PKGCONFIG += glib-2.0 gio-2.0 gsettings-qt
|
||||
PKGCONFIG +=gio-2.0 glib-2.0 gio-unix-2.0 libnm
|
||||
|
||||
LIBS += -L/usr/lib/ -lgsettings-qt -lX11
|
||||
INCLUDEPATH += /usr/include/KF5/NetworkManagerQt
|
||||
|
||||
LIBS += -L/usr/lib/ -lgsettings-qt -lX11 -lKF5NetworkManagerQt
|
||||
#LIBS += -lkysec
|
||||
target.path = /usr/bin
|
||||
target.source += $$TARGET
|
||||
|
@ -62,6 +64,8 @@ include(src/singleapplication/qt-single-application.pri)
|
|||
|
||||
SOURCES += \
|
||||
src/backthread.cpp \
|
||||
src/kylinnetworkconnect.cpp \
|
||||
src/kylinnetworkresourcemanager.cpp \
|
||||
src/wifi-auth-thread.cpp \
|
||||
src/confform.cpp \
|
||||
src/dbusadaptor.cpp \
|
||||
|
@ -94,6 +98,8 @@ SOURCES += \
|
|||
|
||||
HEADERS += \
|
||||
src/backthread.h \
|
||||
src/kylinnetworkconnect.h \
|
||||
src/kylinnetworkresourcemanager.h \
|
||||
src/wifi-auth-thread.h \
|
||||
src/confform.h \
|
||||
src/dbusadaptor.h \
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
#include "kylinnetworkconnect.h"
|
||||
|
||||
KyNetworkConnect::KyNetworkConnect()
|
||||
{
|
||||
m_networkResourceInstance = KyNetworkResourceManager::getInstance();
|
||||
}
|
||||
|
||||
KyNetworkConnect::~KyNetworkConnect()
|
||||
{
|
||||
m_networkResourceInstance = nullptr;
|
||||
}
|
||||
|
||||
int KyNetworkConnect::activateConnection(const QString connectUuid)
|
||||
{
|
||||
QString conn_uni;
|
||||
QString dev_uni;
|
||||
QString conn_name;
|
||||
QString dev_name;
|
||||
QString spec_object;
|
||||
|
||||
qDebug()<<"it will activate connect"<<connectUuid;
|
||||
NetworkManager::Connection::Ptr connectPtr = m_networkResourceInstance->getConnect(connectUuid);
|
||||
conn_uni = connectPtr->path();
|
||||
conn_name = connectPtr->name();
|
||||
if (NetworkManager::ConnectionSettings::Vpn == connectPtr->settings()->connectionType()) {
|
||||
spec_object = dev_uni = QStringLiteral("/");
|
||||
/*
|
||||
// find first non-vpn active connection
|
||||
const auto act_i = std::find_if(d->mActiveConns.cbegin(), d->mActiveConns.cend(), [] (NetworkManager::ActiveConnection::Ptr const & conn) -> bool
|
||||
{
|
||||
return nullptr != dynamic_cast<NetworkManager::VpnConnection const *>(conn.data());
|
||||
});
|
||||
if (act_i != d->mActiveConns.cend() && !(*act_i)->devices().empty())
|
||||
{
|
||||
dev_uni = (*act_i)->devices().front();
|
||||
spec_object = (*act_i)->path();
|
||||
}
|
||||
*/
|
||||
|
||||
} else {
|
||||
dev_name = connectPtr->settings()->interfaceName();
|
||||
for (auto const & dev : m_networkResourceInstance->m_devices) {
|
||||
for (auto const & dev_conn : dev->availableConnections()) {
|
||||
if (dev_conn == connectPtr) {
|
||||
dev_uni = dev->uni();
|
||||
dev_name = dev->interfaceName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dev_uni.isEmpty() && !dev_name.isEmpty()) {
|
||||
auto dev = m_networkResourceInstance->findDeviceInterface(dev_name);
|
||||
if (!dev.isNull())
|
||||
dev_uni = dev->uni();
|
||||
}
|
||||
}
|
||||
|
||||
if (dev_uni.isEmpty()) {
|
||||
//TODO: in what form should we output the warning messages
|
||||
qWarning() << QStringLiteral("can't find device '%1' to activate connection '%2' on").arg(dev_name).arg(connectPtr->name());
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qDebug() << __FUNCTION__ << conn_uni << dev_uni << conn_name << dev_name << spec_object;
|
||||
|
||||
//TODO: check vpn type etc..
|
||||
QDBusPendingCallWatcher * watcher;
|
||||
watcher = new QDBusPendingCallWatcher{NetworkManager::activateConnection(conn_uni, dev_uni, spec_object), this};
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, [conn_name, dev_name] (QDBusPendingCallWatcher * watcher) {
|
||||
if (watcher->isError() || !watcher->isValid()) {
|
||||
//TODO: in what form should we output the warning messages
|
||||
qWarning() << QStringLiteral("activation of connection '%1' on interface '%2' failed: %3").arg(conn_name)
|
||||
.arg(dev_name).arg(watcher->error().message());
|
||||
}
|
||||
watcher->deleteLater();
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyNetworkConnect::deactivateConnection(const QString connectName, const QString &uuid)
|
||||
{
|
||||
int index = 0;
|
||||
NetworkManager::ActiveConnection::Ptr activateConnectPtr = nullptr;
|
||||
|
||||
qDebug()<<"deactivetate connect name"<<connectName<<"uuid"<<uuid;
|
||||
for (index = 0; index < m_networkResourceInstance->m_activeConns.size(); ++index) {
|
||||
activateConnectPtr = m_networkResourceInstance->m_activeConns.at(index);
|
||||
if (activateConnectPtr->uuid() == uuid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index >= m_networkResourceInstance->m_activeConns.size()) {
|
||||
qWarning()<<"it can not find the activate connect"<<connectName << "uuid"<<uuid;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qDebug() << __FUNCTION__ <<"dead active connection path:"<< activateConnectPtr->path();
|
||||
|
||||
QDBusPendingReply<> reply = NetworkManager::deactivateConnection(activateConnectPtr->path());
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, [activateConnectPtr] (QDBusPendingCallWatcher * watcher) {
|
||||
//TODO::it may should send signal deactivateConnectionFinished
|
||||
if (watcher->isError() || !watcher->isValid()) {
|
||||
//TODO: in what form should we output the warning messages
|
||||
qWarning() << QStringLiteral("deactivation of connection '%1' failed: %3").arg(activateConnectPtr->connection()->name())
|
||||
.arg(watcher->error().message());
|
||||
} else {
|
||||
qWarning()<<"deactive connect finished"<<activateConnectPtr->connection()->name();
|
||||
}
|
||||
watcher->deleteLater();
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KyNetworkConnect::requestScan(const QString ifaceName)
|
||||
{
|
||||
auto const & dev = m_networkResourceInstance->getNetworkDevice(ifaceName);
|
||||
auto spec_dev = dev->as<NetworkManager::WirelessDevice>();
|
||||
if (nullptr == spec_dev) {
|
||||
//TODO: in what form should we output the warning messages
|
||||
qWarning() << "dropping request for scan on non wireles device " << dev->interfaceName();
|
||||
return;
|
||||
}
|
||||
|
||||
m_networkResourceInstance->requestScan(spec_dev);
|
||||
}
|
||||
|
||||
void KyNetworkConnect::requestAllWifiScan()
|
||||
{
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef KYLINNETWORKCONNECT_H
|
||||
#define KYLINNETWORKCONNECT_H
|
||||
|
||||
#include "kylinnetworkresourcemanager.h"
|
||||
|
||||
class KyNetworkConnect : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KyNetworkConnect();
|
||||
~KyNetworkConnect();
|
||||
|
||||
public:
|
||||
int addAndActivateConnect(const QString );
|
||||
int activateConnection(const QString connectUuid);
|
||||
int deactivateConnection(const QString connectName, const QString &uuid);
|
||||
void requestScan(const QString ifaceName);
|
||||
void requestAllWifiScan();
|
||||
|
||||
signals:
|
||||
void activateConnectionFinished(NetworkManager::Connection::Ptr conn);
|
||||
void deactivateConnectionFinished(NetworkManager::Connection::Ptr conn);
|
||||
|
||||
private:
|
||||
KyNetworkResourceManager *m_networkResourceInstance = nullptr;
|
||||
};
|
||||
|
||||
#endif // KYLINNETWORKCONNECT_H
|
|
@ -0,0 +1,480 @@
|
|||
#include "kylinnetworkresourcemanager.h"
|
||||
|
||||
KyNetworkResourceManager* KyNetworkResourceManager::m_pInstance = nullptr;
|
||||
|
||||
KyNetworkResourceManager* KyNetworkResourceManager::getInstance()
|
||||
{
|
||||
if (m_pInstance == NULL) {
|
||||
m_pInstance = new KyNetworkResourceManager();
|
||||
}
|
||||
return m_pInstance;
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::Release()
|
||||
{
|
||||
if (m_pInstance != NULL) {
|
||||
delete m_pInstance;
|
||||
m_pInstance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
KyNetworkResourceManager::KyNetworkResourceManager()
|
||||
{
|
||||
insertActiveConnections();
|
||||
insertConnections();
|
||||
insertDevices();
|
||||
insertWifiNetworks();
|
||||
|
||||
//initialize NetworkManager signals
|
||||
connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &KyNetworkResourceManager::onDeviceAdded);
|
||||
connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &KyNetworkResourceManager::onDeviceRemoved);
|
||||
connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionAdded, this, &KyNetworkResourceManager::onActiveConnectionAdded);
|
||||
connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionRemoved, this, &KyNetworkResourceManager::onActiveConnectionRemoved);
|
||||
connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionAdded, this, &KyNetworkResourceManager::onConnectionAdded);
|
||||
connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionRemoved, this, static_cast<void (KyNetworkResourceManager::*)(QString const &)>(&KyNetworkResourceManager::onConnectionRemoved));
|
||||
|
||||
// Note: the connectionRemoved is never emitted in case network-manager service stop,
|
||||
// we need remove the connections manually.
|
||||
connect(NetworkManager::notifier(), &NetworkManager::Notifier::serviceDisappeared, this, &KyNetworkResourceManager::clearConnections);
|
||||
|
||||
qDebug() << m_activeConns.size() << m_connections.size() << m_devices.size();
|
||||
}
|
||||
|
||||
KyNetworkResourceManager::~KyNetworkResourceManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::removeActiveConnection(int pos)
|
||||
{
|
||||
//active connections signals
|
||||
NetworkManager::ActiveConnection::Ptr conn = m_activeConns.takeAt(pos);
|
||||
conn->disconnect(this);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::clearActiveConnections()
|
||||
{
|
||||
while (0 < m_activeConns.size())
|
||||
removeActiveConnection(0);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::addActiveConnection(NetworkManager::ActiveConnection::Ptr conn)
|
||||
{
|
||||
m_activeConns.push_back(conn);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::connectionChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::default4Changed, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::default6Changed, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::dhcp4ConfigChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::dhcp6ConfigChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::ipV4ConfigChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::ipV6ConfigChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::idChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::typeChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::masterChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::specificObjectChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::stateChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::vpnChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::uuidChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::ActiveConnection::devicesChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
if (conn->vpn())
|
||||
{
|
||||
connect(qobject_cast<NetworkManager::VpnConnection *>(conn.data()), &NetworkManager::VpnConnection::bannerChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
connect(qobject_cast<NetworkManager::VpnConnection *>(conn.data()), &NetworkManager::VpnConnection::stateChanged, this, &KyNetworkResourceManager::onActiveConnectionUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::insertActiveConnections()
|
||||
{
|
||||
for (auto const & conn : NetworkManager::activeConnections())
|
||||
addActiveConnection(conn);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::removeConnection(int pos)
|
||||
{
|
||||
//connections signals
|
||||
NetworkManager::Connection::Ptr conn = m_connections.takeAt(pos);
|
||||
conn->disconnect(this);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::clearConnections()
|
||||
{
|
||||
while (0 < m_connections.size())
|
||||
removeConnection(0);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::addConnection(NetworkManager::Connection::Ptr conn)
|
||||
{
|
||||
m_connections.push_back(conn);
|
||||
//connections signals
|
||||
connect(conn.data(), &NetworkManager::Connection::updated, this, &KyNetworkResourceManager::onConnectionUpdated);
|
||||
connect(conn.data(), &NetworkManager::Connection::removed, this, static_cast<void (KyNetworkResourceManager::*)()>(&KyNetworkResourceManager::onConnectionRemoved));
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::insertConnections()
|
||||
{
|
||||
for (auto const & conn : NetworkManager::listConnections())
|
||||
addConnection(conn);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::removeDevice(int pos)
|
||||
{
|
||||
//connections signals
|
||||
NetworkManager::Device::Ptr device = m_devices.takeAt(pos);
|
||||
device->disconnect(this);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::clearDevices()
|
||||
{
|
||||
while (0 < m_devices.size())
|
||||
removeDevice(0);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::addDevice(NetworkManager::Device::Ptr device)
|
||||
{
|
||||
m_devices.push_back(device);
|
||||
//device signals
|
||||
connect(device.data(), &NetworkManager::Device::stateChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::activeConnectionChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::autoconnectChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::availableConnectionChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::availableConnectionAppeared, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::availableConnectionDisappeared, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::capabilitiesChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::dhcp4ConfigChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::dhcp6ConfigChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::driverChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::driverVersionChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::firmwareMissingChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::firmwareVersionChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::interfaceNameChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::ipV4AddressChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::ipV4ConfigChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::ipV6ConfigChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::ipInterfaceChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::managedChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::physicalPortIdChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::mtuChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::nmPluginMissingChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::meteredChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::connectionStateChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::stateReasonChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(device.data(), &NetworkManager::Device::udiChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
switch (device->type())
|
||||
{
|
||||
case NetworkManager::Ethernet:
|
||||
connect(qobject_cast<NetworkManager::WiredDevice *>(device.data()), &NetworkManager::WiredDevice::bitRateChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WiredDevice *>(device.data()), &NetworkManager::WiredDevice::carrierChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WiredDevice *>(device.data()), &NetworkManager::WiredDevice::hardwareAddressChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WiredDevice *>(device.data()), &NetworkManager::WiredDevice::permanentHardwareAddressChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
break;
|
||||
|
||||
case NetworkManager::Device::Wifi:
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::bitRateChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::activeAccessPointChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::modeChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::wirelessCapabilitiesChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::hardwareAddressChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::permanentHardwareAddressChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::wirelessPropertiesChanged, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::accessPointAppeared, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::accessPointDisappeared, this, &KyNetworkResourceManager::onDeviceUpdated);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::networkAppeared, this, &KyNetworkResourceManager::onWifiNetworkAppeared);
|
||||
connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::networkDisappeared, this, &KyNetworkResourceManager::onWifiNetworkDisappeared);
|
||||
break;
|
||||
default:
|
||||
//TODO: other device types!
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::insertDevices()
|
||||
{
|
||||
for (auto const & device : NetworkManager::networkInterfaces())
|
||||
addDevice(device);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::removeWifiNetwork(int pos)
|
||||
{
|
||||
//network signals
|
||||
NetworkManager::WirelessNetwork::Ptr net = m_wifiNets.takeAt(pos);
|
||||
net->disconnect(this);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::clearWifiNetworks()
|
||||
{
|
||||
while (0 < m_wifiNets.size())
|
||||
removeWifiNetwork(0);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::addWifiNetwork(NetworkManager::WirelessNetwork::Ptr net)
|
||||
{
|
||||
m_wifiNets.push_back(net);
|
||||
//device signals
|
||||
connect(net.data(), &NetworkManager::WirelessNetwork::signalStrengthChanged, this, &KyNetworkResourceManager::onWifiNetworkUpdated);
|
||||
connect(net.data(), &NetworkManager::WirelessNetwork::referenceAccessPointChanged, this, &KyNetworkResourceManager::onWifiNetworkUpdated);
|
||||
connect(net.data(), &NetworkManager::WirelessNetwork::disappeared, this, &KyNetworkResourceManager::onWifiNetworkUpdated);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::insertWifiNetworks()
|
||||
{
|
||||
for (auto const & device : m_devices)
|
||||
{
|
||||
if (NetworkManager::Device::Wifi == device->type())
|
||||
{
|
||||
NetworkManager::WirelessDevice::Ptr w_dev = device.objectCast<NetworkManager::WirelessDevice>();
|
||||
for (auto const & net : w_dev->networks())
|
||||
{
|
||||
if (!net.isNull())
|
||||
{
|
||||
addWifiNetwork(net);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetworkManager::ActiveConnection::Ptr KyNetworkResourceManager::findActiveConnection(QString const & path)
|
||||
{
|
||||
auto i = std::find_if(m_activeConns.cbegin(), m_activeConns.cend(), [&path] (NetworkManager::ActiveConnection::Ptr const & conn) -> bool {
|
||||
return conn->path() == path;
|
||||
});
|
||||
return m_activeConns.cend() == i ? NetworkManager::ActiveConnection::Ptr{} : *i;
|
||||
}
|
||||
|
||||
template <typename Predicate>
|
||||
NetworkManager::Device::Ptr KyNetworkResourceManager::findDevice(Predicate const & pred)
|
||||
{
|
||||
auto i = std::find_if(m_devices.cbegin(), m_devices.cend(), pred);
|
||||
return m_devices.cend() == i ? NetworkManager::Device::Ptr{} : *i;
|
||||
}
|
||||
|
||||
NetworkManager::Device::Ptr KyNetworkResourceManager::findDeviceUni(QString const & uni)
|
||||
{
|
||||
return findDevice([&uni] (NetworkManager::Device::Ptr const & dev) { return dev->uni() == uni; });
|
||||
}
|
||||
|
||||
NetworkManager::Device::Ptr KyNetworkResourceManager::findDeviceInterface(QString const & interfaceName)
|
||||
{
|
||||
return findDevice([&interfaceName] (NetworkManager::Device::Ptr const & dev) { return dev->interfaceName() == interfaceName; });
|
||||
}
|
||||
|
||||
NetworkManager::WirelessNetwork::Ptr KyNetworkResourceManager::findWifiNetwork(QString const & ssid, QString const & devUni)
|
||||
{
|
||||
auto i = std::find_if(m_wifiNets.cbegin(), m_wifiNets.cend(), [&ssid, &devUni] (NetworkManager::WirelessNetwork::Ptr const & net) -> bool {
|
||||
return net->ssid() == ssid && net->device() == devUni;
|
||||
});
|
||||
return m_wifiNets.cend() == i ? NetworkManager::WirelessNetwork::Ptr{} : *i;
|
||||
}
|
||||
|
||||
NetworkManager::Device::Ptr KyNetworkResourceManager::getNetworkDevice(const QString ifaceName)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NetworkManager::ActiveConnection::Ptr KyNetworkResourceManager::getActiveConnect(const QString connectUuid)
|
||||
{
|
||||
int index = 0;
|
||||
NetworkManager::ActiveConnection::Ptr activateConnectPtr = nullptr;
|
||||
|
||||
qDebug()<<"get activetate connect with uuid"<<connectUuid;
|
||||
for (index = 0; index < m_activeConns.size(); ++index) {
|
||||
activateConnectPtr = m_activeConns.at(index);
|
||||
if (activateConnectPtr->uuid() == connectUuid) {
|
||||
return activateConnectPtr;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning()<<"it can not find the activate connect with uuid" <<connectUuid;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NetworkManager::Connection::Ptr KyNetworkResourceManager::getConnect(const QString connectUuid)
|
||||
{
|
||||
int index = 0;
|
||||
NetworkManager::Connection::Ptr connectPtr = nullptr;
|
||||
|
||||
qDebug()<<"get connect with uuid"<<connectUuid;
|
||||
|
||||
for (index = 0; index < m_connections.size(); ++index) {
|
||||
connectPtr = m_connections.at(index);
|
||||
if (connectPtr->uuid() == connectUuid) {
|
||||
return connectPtr;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning()<<"it can not find connect with uuid"<<connectUuid;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NetworkManager::WirelessNetwork::Ptr KyNetworkResourceManager::getWifiNetwork(const QString apName)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::requestScan(NetworkManager::WirelessDevice * dev)
|
||||
{
|
||||
qDebug() << __FUNCTION__ << dev->interfaceName();
|
||||
QDBusPendingReply<> reply = dev->requestScan();
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, dev);
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, [dev] (QDBusPendingCallWatcher * watcher) {
|
||||
if (watcher->isError() || !watcher->isValid())
|
||||
{
|
||||
//TODO: in what form should we output the warning messages
|
||||
qWarning() << QStringLiteral("requestScan on device '%1' failed: %3").arg(dev->interfaceName())
|
||||
.arg(watcher->error().message());
|
||||
}
|
||||
watcher->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onConnectionUpdated()
|
||||
{
|
||||
emit connectionUpdate(qobject_cast<NetworkManager::Connection *>(sender()));
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onConnectionRemoved()
|
||||
{
|
||||
emit connectionRemove(qobject_cast<NetworkManager::Connection *>(sender()));
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onActiveConnectionUpdated()
|
||||
{
|
||||
emit activeConnectionUpdate(qobject_cast<NetworkManager::ActiveConnection *>(sender()));
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onDeviceUpdated()
|
||||
{
|
||||
emit deviceUpdate(qobject_cast<NetworkManager::Device *>(sender()));
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onWifiNetworkAppeared(QString const & ssid)
|
||||
{
|
||||
NetworkManager::Device * dev = qobject_cast<NetworkManager::Device *>(sender());
|
||||
emit wifiNetworkAdd(dev, ssid);
|
||||
emit deviceUpdate(dev);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onWifiNetworkDisappeared(QString const & ssid)
|
||||
{
|
||||
NetworkManager::Device * dev = qobject_cast<NetworkManager::Device *>(sender());
|
||||
emit wifiNetworkRemove(dev, ssid);
|
||||
emit deviceUpdate(dev);
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onWifiNetworkUpdated()
|
||||
{
|
||||
emit wifiNetworkUpdate(qobject_cast<NetworkManager::WirelessNetwork *>(sender()));
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onDeviceAdded(QString const & uni)
|
||||
{
|
||||
qDebug()<<Q_FUNC_INFO<<"onDeviceAdded"<<uni;
|
||||
|
||||
NetworkManager::Device::Ptr dev = NetworkManager::findNetworkInterface(uni);
|
||||
if (!dev.isNull()) {
|
||||
if (dev->isValid())
|
||||
qWarning() << Q_FUNC_INFO << uni << " is currently invalid...";
|
||||
|
||||
if (0 > m_devices.indexOf(dev)) {
|
||||
addDevice(dev);
|
||||
}
|
||||
|
||||
emit deviceAdd(dev);
|
||||
}
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onDeviceRemoved(QString const & uni)
|
||||
{
|
||||
qDebug()<<Q_FUNC_INFO<<"onDeviceRemoved"<<uni;
|
||||
NetworkManager::Device::Ptr dev = findDeviceUni(uni);
|
||||
if (!dev.isNull())
|
||||
{
|
||||
if (dev->isValid())
|
||||
qWarning() << Q_FUNC_INFO << uni << " is currently invalid...";
|
||||
|
||||
auto index = std::find(m_devices.cbegin(), m_devices.cend(), dev);
|
||||
if (m_devices.cend() != index) {
|
||||
const int pos = index - m_devices.cbegin();
|
||||
removeDevice(pos);
|
||||
}
|
||||
|
||||
emit deviceRemove(dev.data());
|
||||
}
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onActiveConnectionAdded(QString const & path)
|
||||
{
|
||||
NetworkManager::ActiveConnection::Ptr conn = NetworkManager::findActiveConnection(path);//XXX: const QString &uni
|
||||
if (!conn.isNull()) {
|
||||
if (conn->isValid())
|
||||
qWarning() << Q_FUNC_INFO << path << " is currently invalid...";
|
||||
|
||||
if (0 > m_activeConns.indexOf(conn)) {
|
||||
addActiveConnection(conn);
|
||||
} else {
|
||||
//TODO: onActiveConnectionUpdate
|
||||
qWarning() << Q_FUNC_INFO << "update active connection tp do";
|
||||
}
|
||||
|
||||
emit activeConnectionAdd(conn);
|
||||
}
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onActiveConnectionRemoved(QString const & path)
|
||||
{
|
||||
NetworkManager::ActiveConnection::Ptr conn = findActiveConnection(path);//XXX: const QString &uni
|
||||
if (!conn.isNull()) {
|
||||
if (conn->isValid())
|
||||
qWarning() << Q_FUNC_INFO << path << " is currently invalid...";
|
||||
|
||||
auto index = std::find(m_activeConns.cbegin(), m_activeConns.cend(), conn);
|
||||
if (m_activeConns.cend() != index) {
|
||||
const int pos = index - m_activeConns.cbegin();
|
||||
removeActiveConnection(pos);
|
||||
}
|
||||
|
||||
emit activeConnectionRemove(conn.data());
|
||||
}
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onActiveConnectionsChanged()
|
||||
{
|
||||
emit activeConnectionsReset();
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onConnectionAdded(QString const & path)
|
||||
{
|
||||
NetworkManager::Connection::Ptr conn = NetworkManager::findConnection(path);
|
||||
if (!conn.isNull())
|
||||
{
|
||||
if (conn->isValid())
|
||||
qWarning() << Q_FUNC_INFO << path << " is currently invalid...";
|
||||
|
||||
if (0 > m_connections.indexOf(conn)) {
|
||||
addConnection(conn);
|
||||
} else {
|
||||
//TODO: onConnectionUpdate
|
||||
}
|
||||
|
||||
emit connectionAdd(conn);
|
||||
}
|
||||
}
|
||||
|
||||
void KyNetworkResourceManager::onConnectionRemoved(QString const & path)
|
||||
{
|
||||
NetworkManager::Connection::Ptr conn = NetworkManager::findConnection(path);
|
||||
if (!conn.isNull()) {
|
||||
if (conn->isValid())
|
||||
qWarning() << Q_FUNC_INFO << path << " is currently invalid...";
|
||||
|
||||
auto index = std::find(m_connections.cbegin(), m_connections.cend(), conn);
|
||||
if (m_connections.cend() != index) {
|
||||
const int pos = index - m_connections.cbegin();
|
||||
removeConnection(pos);
|
||||
}
|
||||
|
||||
emit connectionRemove(conn.data());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
#ifndef KYLINNETWORKRESOURCEMANAGER_H
|
||||
#define KYLINNETWORKRESOURCEMANAGER_H
|
||||
|
||||
#include <NetworkManagerQt/Manager>
|
||||
#include <NetworkManagerQt/Settings>
|
||||
#include <NetworkManagerQt/WirelessDevice>
|
||||
#include <NetworkManagerQt/GenericTypes>
|
||||
#include <NetworkManagerQt/VpnConnection>
|
||||
#include <NetworkManagerQt/WirelessDevice>
|
||||
#include <NetworkManagerQt/AdslDevice>
|
||||
#include <NetworkManagerQt/WiredDevice>
|
||||
#include <NetworkManagerQt/WimaxDevice>
|
||||
#include <NetworkManagerQt/VlanDevice>
|
||||
#include <NetworkManagerQt/BondDevice>
|
||||
#include <NetworkManagerQt/BridgeDevice>
|
||||
#include <NetworkManagerQt/GenericDevice>
|
||||
#include <NetworkManagerQt/InfinibandDevice>
|
||||
#include <NetworkManagerQt/BluetoothDevice>
|
||||
#include <NetworkManagerQt/OlpcMeshDevice>
|
||||
#include <NetworkManagerQt/TeamDevice>
|
||||
#include <NetworkManagerQt/WirelessSetting>
|
||||
#include <NetworkManagerQt/WirelessSecuritySetting>
|
||||
#include <NetworkManagerQt/Utils>
|
||||
#include <NetworkManagerQt/ConnectionSettings>
|
||||
#include <QDBusPendingCallWatcher>
|
||||
#include <QInputDialog>
|
||||
#include <QMetaEnum>
|
||||
|
||||
class KyNetworkResourceManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static KyNetworkResourceManager* getInstance();
|
||||
static void Release();
|
||||
|
||||
public:
|
||||
explicit KyNetworkResourceManager();
|
||||
~KyNetworkResourceManager();
|
||||
|
||||
void removeActiveConnection(int pos);
|
||||
void clearActiveConnections();
|
||||
void insertActiveConnections();
|
||||
void addActiveConnection(NetworkManager::ActiveConnection::Ptr conn);
|
||||
|
||||
void removeConnection(int pos);
|
||||
void clearConnections();
|
||||
void insertConnections();
|
||||
void addConnection(NetworkManager::Connection::Ptr conn);
|
||||
|
||||
void removeDevice(int pos);
|
||||
void clearDevices();
|
||||
void insertDevices();
|
||||
void addDevice(NetworkManager::Device::Ptr conn);
|
||||
|
||||
void removeWifiNetwork(int pos);
|
||||
void clearWifiNetworks();
|
||||
void insertWifiNetworks();
|
||||
void addWifiNetwork(NetworkManager::WirelessNetwork::Ptr net);
|
||||
|
||||
NetworkManager::ActiveConnection::Ptr findActiveConnection(QString const & path);
|
||||
template <typename Predicate>
|
||||
NetworkManager::Device::Ptr findDevice(Predicate const & pred);
|
||||
NetworkManager::Device::Ptr findDeviceUni(QString const & uni);
|
||||
NetworkManager::Device::Ptr findDeviceInterface(QString const & interfaceName);
|
||||
NetworkManager::WirelessNetwork::Ptr findWifiNetwork(QString const & ssid, QString const & devUni);
|
||||
|
||||
void requestScan(NetworkManager::WirelessDevice * dev);
|
||||
|
||||
public:
|
||||
NetworkManager::Device::Ptr getNetworkDevice(const QString ifaceName);
|
||||
NetworkManager::ActiveConnection::Ptr getActiveConnect(const QString uuid);
|
||||
NetworkManager::Connection::Ptr getConnect(const QString uuid);
|
||||
NetworkManager::WirelessNetwork::Ptr getWifiNetwork(const QString apName);
|
||||
|
||||
signals:
|
||||
void connectionAdd(NetworkManager::Connection::Ptr conn);
|
||||
void connectionUpdate(NetworkManager::Connection * conn);
|
||||
void connectionRemove(NetworkManager::Connection * conn);
|
||||
void activeConnectionAdd(NetworkManager::ActiveConnection::Ptr conn);
|
||||
void activeConnectionUpdate(NetworkManager::ActiveConnection * conn);
|
||||
void activeConnectionRemove(NetworkManager::ActiveConnection * conn);
|
||||
void activeConnectionsReset();
|
||||
void deviceAdd(NetworkManager::Device::Ptr dev);
|
||||
void deviceUpdate(NetworkManager::Device * dev);
|
||||
void deviceRemove(NetworkManager::Device * dev);
|
||||
void wifiNetworkAdd(NetworkManager::Device * dev, QString const & ssid);
|
||||
void wifiNetworkUpdate(NetworkManager::WirelessNetwork * net);
|
||||
void wifiNetworkRemove(NetworkManager::Device * dev, QString const & ssid);
|
||||
|
||||
|
||||
private slots:
|
||||
//connection
|
||||
void onConnectionUpdated();
|
||||
void onConnectionRemoved();
|
||||
|
||||
//active connection
|
||||
void onActiveConnectionUpdated();
|
||||
|
||||
//device
|
||||
void onDeviceUpdated();
|
||||
void onWifiNetworkAppeared(QString const & ssid);
|
||||
void onWifiNetworkDisappeared(QString const & ssid);
|
||||
|
||||
//wifi network
|
||||
void onWifiNetworkUpdated();
|
||||
|
||||
//notifier
|
||||
void onDeviceAdded(QString const & uni);
|
||||
void onDeviceRemoved(QString const & uni);
|
||||
void onActiveConnectionAdded(QString const & path);
|
||||
void onActiveConnectionRemoved(QString const & path);
|
||||
void onActiveConnectionsChanged();
|
||||
|
||||
//settings notifier
|
||||
void onConnectionAdded(QString const & path);
|
||||
void onConnectionRemoved(QString const & path);
|
||||
|
||||
public:
|
||||
static KyNetworkResourceManager* m_pInstance;
|
||||
|
||||
NetworkManager::ActiveConnection::List m_activeConns;
|
||||
NetworkManager::Connection::List m_connections;
|
||||
NetworkManager::Device::List m_devices;
|
||||
NetworkManager::WirelessNetwork::List m_wifiNets;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // KYLINNETWORKRESOURCEMANAGER_H
|
|
@ -109,6 +109,9 @@ void MainWindow::firstlyStart()
|
|||
*/
|
||||
void MainWindow::secondaryStart()
|
||||
{
|
||||
m_networkResourceInstance = KyNetworkResourceManager::getInstance();
|
||||
//m_networkResourceInstance = new KyNetworkResourceManager();
|
||||
|
||||
if (m_load_finished)
|
||||
return;
|
||||
// 连接kds的dbus接收rfkill变化的信号&获取当前WIFI状态
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "kylin-network-interface.h"
|
||||
#include "utils.h"
|
||||
#include "switchbutton.h"
|
||||
#include "kylinnetworkresourcemanager.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -378,6 +379,8 @@ private:
|
|||
QDBusInterface *mDbusXrandInter;
|
||||
QDBusInterface *kdsDbus;
|
||||
|
||||
KyNetworkResourceManager *m_networkResourceInstance = nullptr;
|
||||
|
||||
private slots:
|
||||
void iconActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
|
||||
|
|
|
@ -103,11 +103,14 @@ OneLancForm::OneLancForm(QWidget *parent, MainWindow *mainWindow, ConfForm *conf
|
|||
ui->btnConn->setShortcut(Qt::Key_Return);//将字母区回车键与连接按钮绑定在一起
|
||||
ui->btnConnSub->setShortcut(Qt::Key_Return);//点击连接按钮触发回车键
|
||||
|
||||
m_networkConnect = new KyNetworkConnect();
|
||||
|
||||
srand((unsigned)time(NULL));
|
||||
}
|
||||
|
||||
OneLancForm::~OneLancForm()
|
||||
{
|
||||
delete m_networkConnect;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
@ -332,7 +335,8 @@ void OneLancForm::on_btnDisConn_clicked()
|
|||
//使用有线网ssid断开网络
|
||||
//kylin_network_set_con_down(ssidName.toUtf8().data());
|
||||
//使用有线网uuid断开网络
|
||||
kylin_network_set_con_down(uuidName.toUtf8().data());
|
||||
//kylin_network_set_con_down(uuidName.toUtf8().data());
|
||||
m_networkConnect->deactivateConnection(ui->lbName->text(), uuidName);
|
||||
//使用dbus接口断开网络
|
||||
//toDisConnWiredNetwork(uuidName);
|
||||
|
||||
|
@ -402,6 +406,7 @@ void OneLancForm::toConnectWiredNetwork()
|
|||
}
|
||||
|
||||
mw->is_stop_check_net_state = 1;
|
||||
/*
|
||||
QThread *t = new QThread();
|
||||
BackThread *bt = new BackThread();
|
||||
bt->moveToThread(t);
|
||||
|
@ -411,6 +416,9 @@ void OneLancForm::toConnectWiredNetwork()
|
|||
connect(bt, SIGNAL(connDone(int)), mw, SLOT(connLanDone(int)));
|
||||
connect(bt, SIGNAL(btFinish()), t, SLOT(quit()));
|
||||
t->start();
|
||||
*/
|
||||
|
||||
m_networkConnect->activateConnection(uuidName);
|
||||
}
|
||||
|
||||
//点击列表中item扩展后显示信息的位置时,执行该函数,用于显示网络配置界面
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "confform.h"
|
||||
#include "kylin-network-interface.h"
|
||||
#include "kylinnetworkconnect.h"
|
||||
#include "backthread.h"
|
||||
#include "ksimplenm.h"
|
||||
|
||||
|
@ -115,6 +116,7 @@ private:
|
|||
MainWindow *mw = nullptr;
|
||||
ConfForm *cf = nullptr;
|
||||
KSimpleNM *ks = nullptr;
|
||||
KyNetworkConnect *m_networkConnect = nullptr;
|
||||
|
||||
QString leQssLow, leQssHigh;
|
||||
|
||||
|
|
Loading…
Reference in New Issue