Skip to content

Commit e5e0544

Browse files
committed
feat: backend connections
Added adapters to the Settings and Settings.Connections NetworkManager interfaces. Fixed the NetworkBackend constructor to wait for the ready status of each backend before trying the next.
1 parent c955811 commit e5e0544

13 files changed

+277
-24
lines changed

src/network/CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,33 @@ qt_add_dbus_interface(NM_DBUS_INTERFACES
3939
nm/dbus_nm_accesspoint
4040
)
4141

42+
set_source_files_properties(nm/org.freedesktop.NetworkManager.Settings.Connection.xml PROPERTIES
43+
CLASSNAME DBusNMConnectionProxy
44+
NO_NAMESPACE TRUE
45+
)
46+
47+
qt_add_dbus_interface(NM_DBUS_INTERFACES
48+
nm/org.freedesktop.NetworkManager.Settings.Connection.xml
49+
nm/dbus_nm_connection
50+
)
51+
52+
set_source_files_properties(nm/org.freedesktop.NetworkManager.Settings.xml PROPERTIES
53+
CLASSNAME DBusNMSettingsProxy
54+
NO_NAMESPACE TRUE
55+
)
56+
57+
qt_add_dbus_interface(NM_DBUS_INTERFACES
58+
nm/org.freedesktop.NetworkManager.Settings.xml
59+
nm/dbus_nm_settings
60+
)
61+
4262
qt_add_library(quickshell-network STATIC
4363
api.cpp
4464
nm/backend.cpp
4565
nm/device.cpp
4666
nm/accesspoint.cpp
4767
nm/wireless.cpp
68+
nm/connection.cpp
4869
${NM_DBUS_INTERFACES}
4970
)
5071

src/network/api.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,17 @@ Network::Network(QObject* parent): QObject(parent) {
123123
// Try each backend
124124

125125
// NetworkManager
126-
auto* nm = new NetworkManager();
127-
if (nm->isAvailable()) {
128-
QObject::connect(nm, &NetworkManager::deviceAdded, this, &Network::addDevice);
129-
QObject::connect(nm, &NetworkManager::deviceRemoved, this, &Network::removeDevice);
130-
this->backend = nm;
131-
return;
132-
} else {
133-
delete nm;
134-
}
135-
136-
// None found
137-
qCCritical(logNetwork) << "Network will not work. Could not find an available backend.";
126+
auto* nm = new NetworkManager(this);
127+
connect(nm, &NetworkBackend::ready, this, [this, nm](bool success) {
128+
if (success) {
129+
QObject::connect(nm, &NetworkManager::deviceAdded, this, &Network::addDevice);
130+
QObject::connect(nm, &NetworkManager::deviceRemoved, this, &Network::removeDevice);
131+
this->backend = nm;
132+
} else {
133+
delete nm;
134+
qCCritical(logNetwork) << "Network will not work. Could not find an available backend.";
135+
}
136+
});
138137
}
139138

140139
void Network::addDevice(NetworkDevice* device) { this->mDevices.insertObject(device); }

src/network/api.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ public slots:
183183
class NetworkBackend: public QObject {
184184
Q_OBJECT;
185185

186-
public:
187-
[[nodiscard]] virtual bool isAvailable() const = 0;
186+
signals:
187+
void ready(bool success);
188188

189189
protected:
190190
explicit NetworkBackend(QObject* parent = nullptr): QObject(parent) {};

src/network/nm/accesspoint.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include <qtypes.h>
1010

1111
#include "../../dbus/properties.hpp"
12-
#include "dbus_nm_accesspoint.h"
12+
#include "nm/dbus_nm_accesspoint.h"
1313

1414
using namespace qs::dbus;
1515

src/network/nm/accesspoint.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <qtypes.h>
1212

1313
#include "../../dbus/properties.hpp"
14-
#include "dbus_nm_accesspoint.h"
14+
#include "nm/dbus_nm_accesspoint.h"
1515

1616
namespace qs::network {
1717

src/network/nm/backend.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
#include "../../dbus/properties.hpp"
1515
#include "../api.hpp"
1616
#include "device.hpp"
17+
#include "nm/dbus_nm_backend.h"
1718
#include "wireless.hpp"
18-
#include "dbus_nm_backend.h"
1919

2020
namespace qs::network {
2121

@@ -25,6 +25,7 @@ Q_LOGGING_CATEGORY(logNetworkManager, "quickshell.network.networkmanager", QtWar
2525

2626
const QString NM_SERVICE = "org.freedesktop.NetworkManager";
2727
const QString NM_PATH = "/org/freedesktop/NetworkManager";
28+
const QString NM_SETTINGS_PATH = "/org/freedesktop/NetworkManager/Settings";
2829

2930
NetworkManager::NetworkManager(QObject* parent): NetworkBackend(parent) {
3031
qCDebug(logNetworkManager) << "Starting NetworkManager Network Backend";
@@ -33,6 +34,7 @@ NetworkManager::NetworkManager(QObject* parent): NetworkBackend(parent) {
3334
if (!bus.isConnected()) {
3435
qCWarning(logNetworkManager
3536
) << "Could not connect to DBus. NetworkManager backend will not work.";
37+
emit ready(false);
3638
return;
3739
}
3840

@@ -49,6 +51,7 @@ NetworkManager::NetworkManager(QObject* parent): NetworkBackend(parent) {
4951
} else {
5052
qCWarning(logNetworkManager)
5153
<< "Could not start NetworkManager. This network backend will not work.";
54+
emit ready(false);
5255
}
5356
});
5457
} else {
@@ -57,6 +60,15 @@ NetworkManager::NetworkManager(QObject* parent): NetworkBackend(parent) {
5760
}
5861

5962
void NetworkManager::init() {
63+
emit ready(true);
64+
65+
this->settings = new NMSettingsAdapter(NM_SETTINGS_PATH, this);
66+
if (!this->settings->isValid()) {
67+
qCWarning(logNetworkManager) << "Failed to connect to NetworkManager settings service.";
68+
delete this->settings;
69+
return;
70+
}
71+
6072
QObject::connect(
6173
this->proxy,
6274
&DBusNetworkManagerProxy::DeviceAdded,
@@ -232,6 +244,4 @@ void NetworkManager::onDeviceRemoved(const QDBusObjectPath& path) {
232244
}
233245
}
234246

235-
bool NetworkManager::isAvailable() const { return this->proxy && this->proxy->isValid(); }
236-
237247
} // namespace qs::network

src/network/nm/backend.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212

1313
#include "../../dbus/properties.hpp"
1414
#include "../api.hpp"
15-
#include "dbus_nm_backend.h"
15+
#include "connection.hpp"
1616
#include "device.hpp"
17+
#include "nm/dbus_nm_backend.h"
1718

1819
namespace qs::network {
1920

@@ -26,7 +27,6 @@ class NetworkManager: public NetworkBackend {
2627

2728
public:
2829
explicit NetworkManager(QObject* parent = nullptr);
29-
[[nodiscard]] bool isAvailable() const override;
3030

3131
private slots:
3232
void onDeviceAdded(const QDBusObjectPath& path);
@@ -42,6 +42,7 @@ private slots:
4242
NetworkDevice* bindDevice(NMDeviceAdapter* deviceAdapter);
4343

4444
QHash<QString, NetworkDevice*> mDeviceHash;
45+
NMSettingsAdapter* settings = nullptr;
4546

4647
QS_DBUS_BINDABLE_PROPERTY_GROUP(NetworkManager, dbusProperties);
4748
DBusNetworkManagerProxy* proxy = nullptr;

src/network/nm/connection.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#include "connection.hpp"
2+
3+
#include <qcontainerfwd.h>
4+
#include <qdbusconnection.h>
5+
#include <qlogging.h>
6+
#include <qloggingcategory.h>
7+
#include <qobject.h>
8+
#include <qstring.h>
9+
#include <qtypes.h>
10+
11+
#include "../../dbus/properties.hpp"
12+
#include "nm/dbus_nm_connection.h"
13+
14+
using namespace qs::dbus;
15+
16+
namespace qs::network {
17+
18+
namespace {
19+
Q_LOGGING_CATEGORY(logNetworkManager, "quickshell.network.networkmanager", QtWarningMsg);
20+
}
21+
22+
NMConnectionAdapter::NMConnectionAdapter(const QString& path, QObject* parent): QObject(parent) {
23+
this->proxy = new DBusNMConnectionProxy(
24+
"org.freedesktop.NetworkManager",
25+
path,
26+
QDBusConnection::systemBus(),
27+
this
28+
);
29+
30+
if (!this->proxy->isValid()) {
31+
qCWarning(logNetworkManager) << "Cannot create DBus interface for connection at" << path;
32+
return;
33+
}
34+
35+
this->connectionProperties.setInterface(this->proxy);
36+
this->connectionProperties.updateAllViaGetAll();
37+
}
38+
39+
bool NMConnectionAdapter::isValid() const { return this->proxy && this->proxy->isValid(); }
40+
QString NMConnectionAdapter::address() const {
41+
return this->proxy ? this->proxy->service() : QString();
42+
}
43+
QString NMConnectionAdapter::path() const { return this->proxy ? this->proxy->path() : QString(); }
44+
45+
NMSettingsAdapter::NMSettingsAdapter(const QString& path, QObject* parent): QObject(parent) {
46+
this->proxy = new DBusNMSettingsProxy(
47+
"org.freedesktop.NetworkManager",
48+
path,
49+
QDBusConnection::systemBus(),
50+
this
51+
);
52+
53+
if (!this->proxy->isValid()) {
54+
qCWarning(logNetworkManager) << "Cannot create DBus interface for connection at" << path;
55+
return;
56+
}
57+
58+
QObject::connect(
59+
this->proxy,
60+
&DBusNMSettingsProxy::NewConnection,
61+
this,
62+
&NMSettingsAdapter::onNewConnection
63+
);
64+
65+
QObject::connect(
66+
this->proxy,
67+
&DBusNMSettingsProxy::ConnectionRemoved,
68+
this,
69+
&NMSettingsAdapter::onConnectionRemoved
70+
);
71+
72+
this->settingsProperties.setInterface(this->proxy);
73+
this->settingsProperties.updateAllViaGetAll();
74+
75+
this->registerConnections();
76+
}
77+
78+
void NMSettingsAdapter::onNewConnection(const QDBusObjectPath& path) {
79+
this->registerConnection(path.path());
80+
}
81+
82+
void NMSettingsAdapter::onConnectionRemoved(const QDBusObjectPath& path) {
83+
auto* connection = this->mConnectionMap.take(path.path());
84+
85+
if (!connection) {
86+
qCDebug(logNetworkManager) << "NetworkManager backend sent removal signal for" << path.path()
87+
<< "which is not registered.";
88+
return;
89+
}
90+
91+
delete connection;
92+
}
93+
94+
void NMSettingsAdapter::registerConnections() {
95+
auto pending = this->proxy->ListConnections();
96+
auto* call = new QDBusPendingCallWatcher(pending, this);
97+
98+
auto responseCallback = [this](QDBusPendingCallWatcher* call) {
99+
const QDBusPendingReply<QList<QDBusObjectPath>> reply = *call;
100+
101+
if (reply.isError()) {
102+
qCWarning(logNetworkManager) << "Failed to get connections: " << reply.error().message();
103+
} else {
104+
for (const QDBusObjectPath& devicePath: reply.value()) {
105+
this->registerConnection(devicePath.path());
106+
}
107+
}
108+
109+
delete call;
110+
};
111+
112+
QObject::connect(call, &QDBusPendingCallWatcher::finished, this, responseCallback);
113+
}
114+
115+
void NMSettingsAdapter::registerConnection(const QString& path) {
116+
auto* connection = new NMConnectionAdapter(path, this);
117+
118+
if (!connection->isValid()) {
119+
qCWarning(logNetworkManager) << "Ignoring invalid registration of" << path;
120+
delete connection;
121+
return;
122+
}
123+
124+
this->mConnectionMap.insert(path, connection);
125+
qCDebug(logNetworkManager) << "Registered connection" << connection;
126+
}
127+
128+
bool NMSettingsAdapter::isValid() const { return this->proxy && this->proxy->isValid(); }
129+
QString NMSettingsAdapter::address() const {
130+
return this->proxy ? this->proxy->service() : QString();
131+
}
132+
QString NMSettingsAdapter::path() const { return this->proxy ? this->proxy->path() : QString(); }
133+
134+
} // namespace qs::network

src/network/nm/connection.hpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#pragma once
2+
3+
#include <qcontainerfwd.h>
4+
#include <qdbusextratypes.h>
5+
#include <qdbusservicewatcher.h>
6+
#include <qhash.h>
7+
#include <qobject.h>
8+
#include <qqmlintegration.h>
9+
#include <qqmllist.h>
10+
#include <qtmetamacros.h>
11+
#include <qtypes.h>
12+
13+
#include "../../dbus/properties.hpp"
14+
#include "nm/dbus_nm_connection.h"
15+
#include "nm/dbus_nm_settings.h"
16+
17+
namespace qs::network {
18+
19+
class NMConnectionAdapter: public QObject {
20+
Q_OBJECT;
21+
22+
public:
23+
explicit NMConnectionAdapter(const QString& path, QObject* parent = nullptr);
24+
[[nodiscard]] bool isValid() const;
25+
[[nodiscard]] QString path() const;
26+
[[nodiscard]] QString address() const;
27+
28+
private:
29+
QS_DBUS_BINDABLE_PROPERTY_GROUP(NMConnectionAdapter, connectionProperties);
30+
DBusNMConnectionProxy* proxy = nullptr;
31+
};
32+
33+
class NMSettingsAdapter: public QObject {
34+
Q_OBJECT;
35+
36+
public:
37+
explicit NMSettingsAdapter(const QString& path, QObject* parent = nullptr);
38+
39+
void registerConnections();
40+
void registerConnection(const QString& path);
41+
42+
[[nodiscard]] bool isValid() const;
43+
[[nodiscard]] QString path() const;
44+
[[nodiscard]] QString address() const;
45+
46+
private slots:
47+
void onNewConnection(const QDBusObjectPath& path);
48+
void onConnectionRemoved(const QDBusObjectPath& path);
49+
50+
private:
51+
QHash<QString, NMConnectionAdapter*> mConnectionMap;
52+
53+
QS_DBUS_BINDABLE_PROPERTY_GROUP(NMSettingsAdapter, settingsProperties);
54+
55+
DBusNMSettingsProxy* proxy = nullptr;
56+
};
57+
58+
} // namespace qs::network

src/network/nm/device.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include <qtypes.h>
1010

1111
#include "../../dbus/properties.hpp"
12-
#include "dbus_nm_device.h"
12+
#include "nm/dbus_nm_device.h"
1313

1414
using namespace qs::dbus;
1515

0 commit comments

Comments
 (0)