Skip to content

Commit 77537fc

Browse files
committed
network: NMConnection, Network.nmConnections, Network.nmDefaultConnection
1 parent 191085a commit 77537fc

23 files changed

+472
-198
lines changed

src/network/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ qt_add_library(quickshell-network STATIC
44
network.cpp
55
device.cpp
66
wifi.cpp
7+
connection.cpp
78
)
89

910
target_include_directories(quickshell-network PRIVATE

src/network/connection.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include "connection.hpp"
2+
3+
#include <qobject.h>
4+
#include <qtmetamacros.h>
5+
6+
#include "nm/types.hpp"
7+
8+
namespace qs::network {
9+
10+
NMConnection::NMConnection(QObject* parent): QObject(parent) {}
11+
12+
void NMConnection::updateSettings(const ConnectionSettingsMap& settings) {
13+
emit this->requestUpdateSettings(settings);
14+
}
15+
16+
void NMConnection::clearSecrets() { emit this->requestClearSecrets(); }
17+
18+
void NMConnection::forget() { emit this->requestForget(); }
19+
20+
} // namespace qs::network

src/network/connection.hpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#pragma once
2+
3+
#include <qobject.h>
4+
#include <qproperty.h>
5+
#include <qqmlintegration.h>
6+
#include <qtypes.h>
7+
8+
#include "nm/types.hpp"
9+
10+
namespace qs::network {
11+
12+
///! A NetworkManager connection settings profile.
13+
class NMConnection: public QObject {
14+
Q_OBJECT;
15+
QML_ELEMENT;
16+
QML_UNCREATABLE("");
17+
18+
// clang-format off
19+
/// A settings map describing this network configuration.
20+
Q_PROPERTY(ConnectionSettingsMap settings READ default NOTIFY settingsChanged BINDABLE bindableSettings);
21+
/// A settings map describing the secrets belonging to this network configuration.
22+
Q_PROPERTY(ConnectionSettingsMap secretSettings READ default NOTIFY secretSettingsChanged BINDABLE bindableSecretSettings);
23+
/// A human readable unique identifier for the connection.
24+
Q_PROPERTY(QString id READ default NOTIFY idChanged BINDABLE bindableId);
25+
// clang-format on
26+
27+
public:
28+
explicit NMConnection(QObject* parent = nullptr);
29+
/// Attempt to update the connection with new settings and save the connection to disk. Secrets may be a part of the update request,
30+
/// and will either be stored in persistent storage tor sent to a Secret Agent for storage, depending on the flags
31+
/// associated with each secret and the presence of a registered Secret Agent.
32+
Q_INVOKABLE void updateSettings(const ConnectionSettingsMap& settings);
33+
/// Attempt to clear all of the secrets belonging to this connection.
34+
Q_INVOKABLE void clearSecrets();
35+
/// Delete the connection.
36+
Q_INVOKABLE void forget();
37+
38+
QBindable<ConnectionSettingsMap> bindableSettings() { return &this->bSettings; }
39+
QBindable<ConnectionSettingsMap> bindableSecretSettings() { return &this->bSecretSettings; }
40+
QBindable<QString> bindableId() { return &this->bId; }
41+
42+
signals:
43+
void requestUpdateSettings(ConnectionSettingsMap settings);
44+
void requestClearSecrets();
45+
void requestForget();
46+
void settingsChanged();
47+
void secretSettingsChanged();
48+
void idChanged();
49+
50+
private:
51+
// clang-format off
52+
Q_OBJECT_BINDABLE_PROPERTY(NMConnection, ConnectionSettingsMap, bSettings, &NMConnection::settingsChanged);
53+
Q_OBJECT_BINDABLE_PROPERTY(NMConnection, ConnectionSettingsMap, bSecretSettings, &NMConnection::secretSettingsChanged);
54+
Q_OBJECT_BINDABLE_PROPERTY(NMConnection, QString, bId, &NMConnection::idChanged);
55+
// clang-format on
56+
};
57+
} // namespace qs::network

src/network/device.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ void NetworkDevice::setAutoconnect(bool autoconnect) {
6666
emit this->requestSetAutoconnect(autoconnect);
6767
}
6868

69+
void NetworkDevice::setNmManaged(bool managed) {
70+
if (this->bNmManaged == managed) return;
71+
emit this->requestSetNmManaged(managed);
72+
}
73+
6974
void NetworkDevice::disconnect() {
7075
if (this->bState == DeviceConnectionState::Disconnected) {
7176
qCCritical(logNetworkDevice) << "Device" << this << "is already disconnected";

src/network/device.hpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,15 @@ class NetworkDevice: public QObject {
8585
Q_PROPERTY(bool connected READ default NOTIFY connectedChanged BINDABLE bindableConnected);
8686
/// Connection state of the device.
8787
Q_PROPERTY(qs::network::DeviceConnectionState::Enum state READ default NOTIFY stateChanged BINDABLE bindableState);
88-
/// A more specific device state when the backend is NetworkManager.
88+
/// A more specific device state.
89+
///
90+
/// > [!WARNING] Only valid for the NetworkManager backend.
8991
Q_PROPERTY(qs::network::NMDeviceState::Enum nmState READ default NOTIFY nmStateChanged BINDABLE bindableNmState);
90-
/// True if the device is allowed to autoconnect.
92+
/// True if the device is managed by NetworkManager.
93+
///
94+
/// > [!WARNING] Only valid for the NetworkManager backend.
95+
Q_PROPERTY(bool nmManaged READ nmManaged WRITE setNmManaged NOTIFY nmManagedChanged)
96+
/// True if the device is allowed to autoconnect to a network.
9197
Q_PROPERTY(bool autoconnect READ autoconnect WRITE setAutoconnect NOTIFY autoconnectChanged);
9298
// clang-format on
9399

@@ -104,18 +110,23 @@ class NetworkDevice: public QObject {
104110
QBindable<bool> bindableConnected() { return &this->bConnected; };
105111
QBindable<DeviceConnectionState::Enum> bindableState() { return &this->bState; };
106112
QBindable<NMDeviceState::Enum> bindableNmState() { return &this->bNmState; };
107-
[[nodiscard]] bool autoconnect() const { return this->bAutoconnect; };
113+
QBindable<bool> bindableNmManaged() { return &this->bNmManaged; };
114+
[[nodiscard]] bool nmManaged() { return this->bNmManaged; };
115+
void setNmManaged(bool managed);
108116
QBindable<bool> bindableAutoconnect() { return &this->bAutoconnect; };
117+
[[nodiscard]] bool autoconnect() { return this->bAutoconnect; };
109118
void setAutoconnect(bool autoconnect);
110119

111120
signals:
112121
void requestDisconnect();
113122
void requestSetAutoconnect(bool autoconnect);
123+
void requestSetNmManaged(bool managed);
114124
void nameChanged();
115125
void addressChanged();
116126
void connectedChanged();
117127
void stateChanged();
118128
void nmStateChanged();
129+
void nmManagedChanged();
119130
void autoconnectChanged();
120131

121132
private:
@@ -126,6 +137,7 @@ class NetworkDevice: public QObject {
126137
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, bool, bConnected, &NetworkDevice::connectedChanged);
127138
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, DeviceConnectionState::Enum, bState, &NetworkDevice::stateChanged);
128139
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, NMDeviceState::Enum, bNmState, &NetworkDevice::nmStateChanged);
140+
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, bool, bNmManaged, &NetworkDevice::nmManagedChanged);
129141
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, bool, bAutoconnect, &NetworkDevice::autoconnectChanged);
130142
// clang-format on
131143
};

src/network/network.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <qtmetamacros.h>
99

1010
#include "../core/logcat.hpp"
11+
#include "connection.hpp"
1112
#include "device.hpp"
1213
#include "nm/backend.hpp"
1314

@@ -27,6 +28,37 @@ QString NetworkState::toString(NetworkState::Enum state) {
2728
}
2829
}
2930

31+
QString NMNetworkStateReason::toString(NMNetworkStateReason::Enum reason) {
32+
switch (reason) {
33+
case Unknown: return QStringLiteral("Unknown");
34+
case None: return QStringLiteral("No reason");
35+
case UserDisconnected: return QStringLiteral("User disconnection");
36+
case DeviceDisconnected:
37+
return QStringLiteral("The device the connection was using was disconnected.");
38+
case ServiceStopped:
39+
return QStringLiteral("The service providing the VPN connection was stopped.");
40+
case IpConfigInvalid:
41+
return QStringLiteral("The IP config of the active connection was invalid.");
42+
case ConnectTimeout:
43+
return QStringLiteral("The connection attempt to the VPN service timed out.");
44+
case ServiceStartTimeout:
45+
return QStringLiteral(
46+
"A timeout occurred while starting the service providing the VPN connection."
47+
);
48+
case ServiceStartFailed:
49+
return QStringLiteral("Starting the service providing the VPN connection failed.");
50+
case NoSecrets: return QStringLiteral("Necessary secrets for the connection were not provided.");
51+
case LoginFailed: return QStringLiteral("Authentication to the server failed.");
52+
case ConnectionRemoved:
53+
return QStringLiteral("Necessary secrets for the connection were not provided.");
54+
case DependencyFailed:
55+
return QStringLiteral("Master connection of this connection failed to activate.");
56+
case DeviceRealizeFailed: return QStringLiteral("Could not create the software device link.");
57+
case DeviceRemoved: return QStringLiteral("The device this connection depended on disappeared.");
58+
default: return QStringLiteral("Unknown");
59+
};
60+
};
61+
3062
Networking::Networking(QObject* parent): QObject(parent) {
3163
// Try to create the NetworkManager backend and bind to it.
3264
auto* nm = new NetworkManager(this);
@@ -62,4 +94,33 @@ Network::Network(QString name, QObject* parent): QObject(parent), mName(std::mov
6294
});
6395
};
6496

97+
void Network::setNmDefaultConnection(NMConnection* conn) {
98+
if (this->bNmDefaultConnection == conn) return;
99+
if (!this->mNmConnections.valueList().contains(conn)) return;
100+
emit this->requestSetNmDefaultConnection(conn);
101+
}
102+
103+
void Network::connect() {
104+
if (this->bConnected) {
105+
qCCritical(logNetwork) << this << "is already connected.";
106+
return;
107+
}
108+
109+
this->requestConnect();
110+
}
111+
112+
void Network::disconnect() {
113+
if (!this->bConnected) {
114+
qCCritical(logNetwork) << this << "is not currently connected";
115+
return;
116+
}
117+
118+
this->requestDisconnect();
119+
}
120+
121+
void Network::forget() { this->requestForget(); }
122+
123+
void Network::connectionAdded(NMConnection* conn) { this->mNmConnections.insertObject(conn); }
124+
void Network::connectionRemoved(NMConnection* conn) { this->mNmConnections.removeObject(conn); }
125+
65126
} // namespace qs::network

src/network/network.hpp

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <qtypes.h>
88

99
#include "../core/model.hpp"
10+
#include "connection.hpp"
1011
#include "device.hpp"
1112

1213
namespace qs::network {
@@ -29,6 +30,35 @@ class NetworkState: public QObject {
2930
Q_INVOKABLE static QString toString(NetworkState::Enum state);
3031
};
3132

33+
///! The reason for the NMConnectionState of an NMConnection.
34+
/// In sync with https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMActiveConnectionStateReason.
35+
class NMNetworkStateReason: public QObject {
36+
Q_OBJECT;
37+
QML_ELEMENT;
38+
QML_SINGLETON;
39+
40+
public:
41+
enum Enum : quint8 {
42+
Unknown = 0,
43+
None = 1,
44+
UserDisconnected = 2,
45+
DeviceDisconnected = 3,
46+
ServiceStopped = 4,
47+
IpConfigInvalid = 5,
48+
ConnectTimeout = 6,
49+
ServiceStartTimeout = 7,
50+
ServiceStartFailed = 8,
51+
NoSecrets = 9,
52+
LoginFailed = 10,
53+
ConnectionRemoved = 11,
54+
DependencyFailed = 12,
55+
DeviceRealizeFailed = 13,
56+
DeviceRemoved = 14
57+
};
58+
Q_ENUM(Enum);
59+
Q_INVOKABLE static QString toString(NMNetworkStateReason::Enum reason);
60+
};
61+
3262
///! The backend supplying the Network service.
3363
class NetworkBackendType: public QObject {
3464
Q_OBJECT;
@@ -105,38 +135,81 @@ private slots:
105135
class Network: public QObject {
106136
Q_OBJECT;
107137
QML_ELEMENT;
108-
QML_UNCREATABLE("BaseNetwork can only be aqcuired through network devices");
138+
QML_UNCREATABLE("Network can only be aqcuired through networking devices");
109139

110140
// clang-format off
111141
/// The name of the network.
112142
Q_PROPERTY(QString name READ name CONSTANT);
143+
/// A list of connnection settings profiles for this network.
144+
///
145+
/// > [!WARNING] Only valid for the NetworkManager backend.
146+
QSDOC_TYPE_OVERRIDE(ObjectModel<qs::network::NMConnection>*);
147+
Q_PROPERTY(UntypedObjectModel* nmConnections READ nmConnections CONSTANT);
148+
/// The default connection settings profile for this network. This is the connection settings used when connect() is invoked.
149+
/// Only available when the connection is known.
150+
///
151+
/// > [!WARNING] Only valid for the NetworkManager backend.
152+
Q_PROPERTY(NMConnection* nmDefaultConnection READ nmDefaultConnection WRITE setNmDefaultConnection NOTIFY nmDefaultConnectionChanged BINDABLE bindableNmDefaultConnection);
113153
/// True if the network is connected.
114154
Q_PROPERTY(bool connected READ default NOTIFY connectedChanged BINDABLE bindableConnected);
155+
/// True if the wifi network has known connection settings saved.
156+
Q_PROPERTY(bool known READ default NOTIFY knownChanged BINDABLE bindableKnown);
115157
/// The connectivity state of the network.
116158
Q_PROPERTY(NetworkState::Enum state READ default NOTIFY stateChanged BINDABLE bindableState);
159+
/// A specific reason for the connection state. Only available for the NetworkManager backend.
160+
Q_PROPERTY(NMNetworkStateReason::Enum stateReason READ default NOTIFY stateReasonChanged BINDABLE bindableStateReason);
117161
/// If the network is currently connecting or disconnecting. Shorthand for checking @@state.
118162
Q_PROPERTY(bool stateChanging READ default NOTIFY stateChangingChanged BINDABLE bindableStateChanging);
119163
// clang-format on
120164

121165
public:
122166
explicit Network(QString name, QObject* parent = nullptr);
123167

168+
/// Attempt to connect to the network.
169+
Q_INVOKABLE void connect();
170+
/// Disconnect from the network.
171+
Q_INVOKABLE void disconnect();
172+
/// Forget all connection settings for this network.
173+
Q_INVOKABLE void forget();
174+
175+
void connectionAdded(NMConnection* conn);
176+
void connectionRemoved(NMConnection* conn);
177+
124178
[[nodiscard]] QString name() const { return this->mName; };
179+
[[nodiscard]] ObjectModel<NMConnection>* nmConnections() { return &this->mNmConnections; };
180+
[[nodiscard]] NMConnection* nmDefaultConnection() { return this->bNmDefaultConnection; };
181+
QBindable<NMConnection*> bindableNmDefaultConnection() { return &this->bNmDefaultConnection; };
182+
void setNmDefaultConnection(NMConnection* conn);
125183
QBindable<bool> bindableConnected() { return &this->bConnected; }
184+
QBindable<bool> bindableKnown() { return &this->bKnown; }
126185
QBindable<NetworkState::Enum> bindableState() { return &this->bState; }
186+
QBindable<NMNetworkStateReason::Enum> bindableStateReason() { return &this->bStateReason; }
127187
QBindable<bool> bindableStateChanging() { return &this->bStateChanging; }
128188

129189
signals:
190+
void requestSetNmDefaultConnection(NMConnection* conn);
191+
void requestConnect();
192+
void requestDisconnect();
193+
void requestForget();
194+
void nmDefaultConnectionChanged();
130195
void connectedChanged();
196+
void knownChanged();
131197
void stateChanged();
198+
void stateReasonChanged();
132199
void stateChangingChanged();
133200

134201
protected:
135202
QString mName;
203+
ObjectModel<NMConnection> mNmConnections {this};
136204

205+
// clang-format off
206+
Q_OBJECT_BINDABLE_PROPERTY(Network, NMConnection*, bNmDefaultConnection, &Network::nmDefaultConnectionChanged);
137207
Q_OBJECT_BINDABLE_PROPERTY(Network, bool, bConnected, &Network::connectedChanged);
208+
Q_OBJECT_BINDABLE_PROPERTY(Network, bool, bKnown, &Network::knownChanged);
138209
Q_OBJECT_BINDABLE_PROPERTY(Network, NetworkState::Enum, bState, &Network::stateChanged);
210+
Q_OBJECT_BINDABLE_PROPERTY(Network, NMNetworkStateReason::Enum, bStateReason, &Network::stateReasonChanged);
139211
Q_OBJECT_BINDABLE_PROPERTY(Network, bool, bStateChanging, &Network::stateChangingChanged);
212+
// clang-format on
140213
};
141214

142215
} // namespace qs::network

src/network/nm/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
set_source_files_properties(org.freedesktop.NetworkManager.xml PROPERTIES
22
CLASSNAME DBusNetworkManagerProxy
33
NO_NAMESPACE TRUE
4-
INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/dbus_types.hpp
4+
INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/types.hpp
55
)
66

77
qt_add_dbus_interface(NM_DBUS_INTERFACES
@@ -42,7 +42,7 @@ qt_add_dbus_interface(NM_DBUS_INTERFACES
4242
set_source_files_properties(org.freedesktop.NetworkManager.Settings.Connection.xml PROPERTIES
4343
CLASSNAME DBusNMConnectionSettingsProxy
4444
NO_NAMESPACE TRUE
45-
INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/dbus_types.hpp
45+
INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/types.hpp
4646
)
4747

4848
qt_add_dbus_interface(NM_DBUS_INTERFACES

0 commit comments

Comments
 (0)