Skip to content

Commit 6429991

Browse files
committed
feat: AccessPoints -> WifiNetworks
Access point objects shouldn't be provided to the user. Instead, we should expose WifiNetworks which represent a set of APs with the same SSID. A WifiNetwork signal represents the maximum signal of its APs.
1 parent 7090633 commit 6429991

File tree

7 files changed

+229
-119
lines changed

7 files changed

+229
-119
lines changed

src/network/api.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ void NetworkDevice::disconnect() {
7777

7878
// WirelessNetworkDevice
7979

80-
WirelessNetworkDevice::WirelessNetworkDevice(QObject* parent): NetworkDevice(parent) {};
80+
NetworkWifiDevice::NetworkWifiDevice(QObject* parent): NetworkDevice(parent) {};
8181

82-
void WirelessNetworkDevice::scanComplete(qint64 lastScan) {
82+
void NetworkWifiDevice::scanComplete(qint64 lastScan) {
8383
this->bLastScan = lastScan;
8484
emit this->lastScanChanged();
8585

@@ -89,7 +89,7 @@ void WirelessNetworkDevice::scanComplete(qint64 lastScan) {
8989
}
9090
}
9191

92-
void WirelessNetworkDevice::scan() {
92+
void NetworkWifiDevice::scan() {
9393
if (this->bScanning) {
9494
qCCritical(logNetworkDevice) << "Wireless device" << this << "is already scanning";
9595
return;
@@ -100,26 +100,24 @@ void WirelessNetworkDevice::scan() {
100100
signalScan();
101101
}
102102

103-
void WirelessNetworkDevice::addAccessPoint(NetworkAccessPoint* ap) {
104-
mAccessPoints.insertObject(ap);
105-
}
103+
void NetworkWifiDevice::addNetwork(NetworkWifiNetwork* network) { mNetworks.insertObject(network); }
106104

107-
void WirelessNetworkDevice::removeAccessPoint(NetworkAccessPoint* ap) {
108-
mAccessPoints.removeObject(ap);
105+
void NetworkWifiDevice::removeNetwork(NetworkWifiNetwork* network) {
106+
mNetworks.removeObject(network);
109107
}
110108

111109
// NetworkAccessPoint
112110

113-
NetworkAccessPoint::NetworkAccessPoint(QObject* parent): QObject(parent) {};
111+
NetworkWifiNetwork::NetworkWifiNetwork(QObject* parent): QObject(parent) {};
114112

115-
void NetworkAccessPoint::setSsid(const QString& ssid) {
113+
void NetworkWifiNetwork::setSsid(const QString& ssid) {
116114
if (this->bSsid != ssid) {
117115
this->bSsid = ssid;
118116
emit ssidChanged();
119117
}
120118
}
121119

122-
void NetworkAccessPoint::setSignal(quint8 signal) {
120+
void NetworkWifiNetwork::setSignal(quint8 signal) {
123121
if (this->bSignal != signal) {
124122
this->bSignal = signal;
125123
emit signalChanged();

src/network/api.hpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414

1515
namespace qs::network {
1616

17-
///! A tracked access point on the network
18-
class NetworkAccessPoint: public QObject {
17+
///! A wifi network available to a wifi device
18+
class NetworkWifiNetwork: public QObject {
1919
Q_OBJECT;
2020
QML_ELEMENT;
21-
QML_UNCREATABLE("WirelessNetwork can only be acquired through Network");
21+
QML_UNCREATABLE("Wifi netorks can only be acquired through Network");
2222
// clang-format off
23-
/// The service set identifier of the access point.
23+
/// The service set identifier of the wifi network
2424
Q_PROPERTY(QString ssid READ default NOTIFY ssidChanged BINDABLE bindableSsid);
25-
// The current signal quality of the access point, in percent.
25+
// The current signal quality of the best access point on the network, in percent.
2626
Q_PROPERTY(quint8 signal READ default NOTIFY signalChanged BINDABLE bindableSignal);
2727
//clang-format on
2828

@@ -35,14 +35,14 @@ public slots:
3535
void setSignal(quint8 signal);
3636

3737
public:
38-
explicit NetworkAccessPoint(QObject* parent = nullptr);
38+
explicit NetworkWifiNetwork(QObject* parent = nullptr);
3939

4040
[[nodiscard]] QBindable<QString> bindableSsid() const { return &this->bSsid; };
4141
[[nodiscard]] QBindable<quint8> bindableSignal() const { return &this->bSignal; };
4242

4343
private:
44-
Q_OBJECT_BINDABLE_PROPERTY(NetworkAccessPoint, QString, bSsid, &NetworkAccessPoint::ssidChanged);
45-
Q_OBJECT_BINDABLE_PROPERTY(NetworkAccessPoint, quint8, bSignal, &NetworkAccessPoint::signalChanged);
44+
Q_OBJECT_BINDABLE_PROPERTY(NetworkWifiNetwork, QString, bSsid, &NetworkWifiNetwork::ssidChanged);
45+
Q_OBJECT_BINDABLE_PROPERTY(NetworkWifiNetwork, quint8, bSignal, &NetworkWifiNetwork::signalChanged);
4646
};
4747

4848
///! Type of network device.
@@ -139,17 +139,17 @@ public slots:
139139
};
140140

141141
///! Wireless variant of a tracked network device.
142-
class WirelessNetworkDevice: public NetworkDevice {
142+
class NetworkWifiDevice: public NetworkDevice {
143143
Q_OBJECT;
144144

145145
// clang-format off
146146
/// The timestamp (in CLOCK_BOOTTIME milliseconds) for the last finished network scan.
147147
Q_PROPERTY(qint64 lastScan READ default NOTIFY lastScanChanged BINDABLE bindableLastScan);
148148
/// True if the wireless device is currently scanning for available wifi networks.
149149
Q_PROPERTY(bool scanning READ default NOTIFY scanningChanged BINDABLE bindableScanning);
150-
/// A list of all available access points
151-
Q_PROPERTY(UntypedObjectModel* accessPoints READ accessPoints CONSTANT);
152-
QSDOC_TYPE_OVERRIDE(ObjectModel<NetworkAccessPoint>*)
150+
/// A list of all available wifi networks
151+
Q_PROPERTY(UntypedObjectModel* networks READ networks CONSTANT);
152+
QSDOC_TYPE_OVERRIDE(ObjectModel<NetworkWifiNetwork>*)
153153
//clang-format on
154154

155155
signals:
@@ -160,11 +160,11 @@ class WirelessNetworkDevice: public NetworkDevice {
160160

161161
public slots:
162162
void scanComplete(qint64 lastScan);
163-
void addAccessPoint(NetworkAccessPoint* ap);
164-
void removeAccessPoint(NetworkAccessPoint* ap);
163+
void addNetwork(NetworkWifiNetwork* network);
164+
void removeNetwork(NetworkWifiNetwork* network);
165165

166166
public:
167-
explicit WirelessNetworkDevice(QObject* parent = nullptr);
167+
explicit NetworkWifiDevice(QObject* parent = nullptr);
168168
[[nodiscard]] NetworkDeviceType::Enum type() const override { return NetworkDeviceType::Wireless; };
169169

170170
/// Request the wireless device to scan for available WiFi networks.
@@ -173,12 +173,12 @@ public slots:
173173
[[nodiscard]] QBindable<bool> bindableScanning() { return &this->bScanning; };
174174
[[nodiscard]] QBindable<qint64> bindableLastScan() { return &this->bLastScan; };
175175

176-
UntypedObjectModel* accessPoints() { return &this->mAccessPoints; };
176+
UntypedObjectModel* networks() { return &this->mNetworks; };
177177

178178
private:
179-
ObjectModel<NetworkAccessPoint> mAccessPoints{this};
180-
Q_OBJECT_BINDABLE_PROPERTY(WirelessNetworkDevice, bool, bScanning, &WirelessNetworkDevice::scanningChanged);
181-
Q_OBJECT_BINDABLE_PROPERTY(WirelessNetworkDevice, qint64, bLastScan, &WirelessNetworkDevice::lastScanChanged);
179+
ObjectModel<NetworkWifiNetwork> mNetworks {this};
180+
Q_OBJECT_BINDABLE_PROPERTY(NetworkWifiDevice, bool, bScanning, &NetworkWifiDevice::scanningChanged);
181+
Q_OBJECT_BINDABLE_PROPERTY(NetworkWifiDevice, qint64, bLastScan, &NetworkWifiDevice::lastScanChanged);
182182
};
183183

184184
// -- Network --

src/network/nm_adapters.cpp

Lines changed: 115 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void NMDeviceAdapter::init(const QString& path) {
3434
);
3535

3636
if (!this->proxy->isValid()) {
37-
qCWarning(logNetworkManager) << "Cannot create NMDeviceAdapter for" << path;
37+
qCWarning(logNetworkManager) << "Cannot create dbus proxy for" << path;
3838
return;
3939
}
4040

@@ -72,7 +72,7 @@ void NMWirelessAdapter::init(const QString& path) {
7272
);
7373

7474
if (!this->proxy->isValid()) {
75-
qCWarning(logNetworkManager) << "Cannot create NMWirelessAdapter for" << path;
75+
qCWarning(logNetworkManager) << "Cannot create dbus proxy for" << path;
7676
return;
7777
}
7878

@@ -101,16 +101,16 @@ void NMWirelessAdapter::onAccessPointAdded(const QDBusObjectPath& path) {
101101
}
102102

103103
void NMWirelessAdapter::onAccessPointRemoved(const QDBusObjectPath& path) {
104-
auto iter = this->mAPHash.find(path.path());
105-
if (iter == this->mAPHash.end()) {
106-
qCWarning(logNetworkManager) << "NMWirelessAdapter sent removal signal for" << path.path()
107-
<< "which is not registered.";
108-
} else {
109-
auto* ap = iter.value();
110-
this->mAPHash.erase(iter);
111-
emit accessPointRemoved(ap);
112-
qCDebug(logNetworkManager) << "Access point" << path.path() << "removed.";
104+
auto* ap = mPathToApHash.take(path.path());
105+
106+
if (!ap) {
107+
qCDebug(logNetworkManager) << "NetworkManager backend sent removal signal for" << path.path()
108+
<< "which is not registered.";
109+
return;
113110
}
111+
112+
removeApFromNetwork(ap);
113+
delete ap;
114114
}
115115

116116
void NMWirelessAdapter::registerAccessPoints() {
@@ -135,35 +135,80 @@ void NMWirelessAdapter::registerAccessPoints() {
135135
}
136136

137137
void NMWirelessAdapter::registerAccessPoint(const QString& path) {
138-
if (this->mAPHash.contains(path)) {
138+
if (this->mPathToApHash.contains(path)) {
139139
qCDebug(logNetworkManager) << "Skipping duplicate registration of access point" << path;
140140
return;
141141
}
142142

143-
// Create an access point adapter
144-
auto* apAdapter = new NMAccessPointAdapter();
145-
apAdapter->init(path);
143+
auto* ap = new NMAccessPointAdapter(this);
144+
ap->init(path);
146145

147-
if (!apAdapter->isValid()) {
148-
qCWarning(logNetworkManager) << "Cannot create NMAccessPointAdapter for" << path;
149-
delete apAdapter;
146+
if (!ap->isValid()) {
147+
qCWarning(logNetworkManager) << "Cannot create access point for" << path;
148+
delete ap;
150149
return;
151150
}
152-
auto* ap = new NetworkAccessPoint(this);
153-
apAdapter->setParent(ap);
154151

155-
// NMAccessPointAdapter signal -> NetworkAccessPoint slot
156-
QObject::connect(apAdapter, &NMAccessPointAdapter::ssidChanged, ap, &NetworkAccessPoint::setSsid);
152+
this->mPathToApHash.insert(path, ap);
153+
qCDebug(logNetworkManager) << "Registered access point" << path;
154+
157155
QObject::connect(
158-
apAdapter,
159-
&NMAccessPointAdapter::signalChanged,
160156
ap,
161-
&NetworkAccessPoint::setSignal
157+
&NMAccessPointAdapter::ssidChanged,
158+
this,
159+
[this, ap](const QByteArray& ssid) {
160+
if (ssid.isEmpty()) {
161+
this->removeApFromNetwork(ap);
162+
} else {
163+
this->addApToNetwork(ap, ssid);
164+
}
165+
}
162166
);
167+
}
163168

164-
this->mAPHash.insert(path, ap);
165-
emit accessPointAdded(ap);
166-
qCDebug(logNetworkManager) << "Registered access point" << path;
169+
void NMWirelessAdapter::addApToNetwork(NMAccessPointAdapter* ap, const QByteArray& ssid) {
170+
// Remove AP from old network
171+
removeApFromNetwork(ap);
172+
173+
auto* group = mSsidToApGroupHash.value(ssid);
174+
if (!group) {
175+
// Create a new AP group and wifi network
176+
group = new NMAccessPointGroup(ssid, this);
177+
auto* network = new NetworkWifiNetwork(this);
178+
network->setSsid(ssid);
179+
180+
// NMAccessPointGroup signal -> NetworkWifiNetwork slot
181+
QObject::connect(
182+
group,
183+
&NMAccessPointGroup::maxSignalChanged,
184+
network,
185+
&NetworkWifiNetwork::setSignal
186+
);
187+
188+
this->mSsidToApGroupHash.insert(ssid, group);
189+
this->mSsidToNetworkHash.insert(ssid, network);
190+
emit this->wifiNetworkAdded(network);
191+
qCDebug(logNetworkManager) << "Registered wifi network" << ssid;
192+
}
193+
194+
group->addAccessPoint(ap);
195+
this->mPathToSsidHash.insert(ap->path(), ssid);
196+
}
197+
198+
void NMWirelessAdapter::removeApFromNetwork(NMAccessPointAdapter* ap) {
199+
QByteArray ssid = mPathToSsidHash.take(ap->path());
200+
if (ssid.isEmpty()) return; // AP wasn't in any network
201+
202+
auto* group = mSsidToApGroupHash.value(ssid);
203+
group->removeAccessPoint(ap);
204+
if (group->isEmpty()) {
205+
mSsidToApGroupHash.remove(ssid);
206+
auto* network = mSsidToNetworkHash.take(ssid);
207+
emit wifiNetworkRemoved(network);
208+
delete network;
209+
delete group;
210+
qCDebug(logNetworkManager) << "Deleted wifi network" << ssid;
211+
}
167212
}
168213

169214
void NMWirelessAdapter::scan() { this->proxy->RequestScan({}); }
@@ -176,10 +221,6 @@ QString NMWirelessAdapter::path() const { return this->proxy ? this->proxy->path
176221

177222
// Access Point
178223

179-
namespace {
180-
Q_LOGGING_CATEGORY(logNMAccessPoint, "quickshell.network.networkmanager.accesspoint", QtWarningMsg);
181-
}
182-
183224
NMAccessPointAdapter::NMAccessPointAdapter(QObject* parent): QObject(parent) {}
184225

185226
void NMAccessPointAdapter::init(const QString& path) {
@@ -191,7 +232,7 @@ void NMAccessPointAdapter::init(const QString& path) {
191232
);
192233

193234
if (!this->proxy->isValid()) {
194-
qCWarning(logNMAccessPoint) << "Cannot create NMWirelessAdapter for" << path;
235+
qCWarning(logNetworkManager) << "Cannot create access point proxy for" << path;
195236
return;
196237
}
197238

@@ -205,6 +246,47 @@ QString NMAccessPointAdapter::address() const {
205246
}
206247
QString NMAccessPointAdapter::path() const { return this->proxy ? this->proxy->path() : QString(); }
207248

249+
// Access Point Group
250+
251+
NMAccessPointGroup::NMAccessPointGroup(const QByteArray& ssid, QObject* parent)
252+
: QObject(parent)
253+
, mSsid(ssid) {}
254+
255+
void NMAccessPointGroup::updateMaxSignal() {
256+
quint8 max = 0;
257+
for (auto* ap: mAccessPoints) {
258+
max = qMax(max, ap->getSignal());
259+
}
260+
if (this->bMaxSignal != max) {
261+
this->bMaxSignal = max;
262+
}
263+
}
264+
265+
void NMAccessPointGroup::addAccessPoint(NMAccessPointAdapter* ap) {
266+
if (this->mAccessPoints.contains(ap)) return;
267+
268+
this->mAccessPoints.append(ap);
269+
QObject::connect(
270+
ap,
271+
&NMAccessPointAdapter::signalChanged,
272+
this,
273+
&NMAccessPointGroup::updateMaxSignal
274+
);
275+
this->updateMaxSignal();
276+
}
277+
278+
void NMAccessPointGroup::removeAccessPoint(NMAccessPointAdapter* ap) {
279+
if (mAccessPoints.removeOne(ap)) {
280+
QObject::disconnect(
281+
ap,
282+
&NMAccessPointAdapter::signalChanged,
283+
this,
284+
&NMAccessPointGroup::updateMaxSignal
285+
);
286+
this->updateMaxSignal();
287+
}
288+
}
289+
208290
} // namespace qs::network
209291

210292
namespace qs::dbus {

0 commit comments

Comments
 (0)