Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qnetworkmanagerservice.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
7#include <QObject>
8#include <QList>
9#include <QtDBus/QDBusConnection>
10#include <QtDBus/QDBusError>
11#include <QtDBus/QDBusInterface>
12#include <QtDBus/QDBusMessage>
13#include <QtDBus/QDBusReply>
14#include <QtDBus/QDBusPendingCallWatcher>
15#include <QtDBus/QDBusObjectPath>
16#include <QtDBus/QDBusPendingCall>
17
18#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"_L1
19
20#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager"
21#define NM_DBUS_SERVICE NM_DBUS_INTERFACE ""_L1
22
23#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"_L1
24#define NM_CONNECTION_DBUS_INTERFACE NM_DBUS_SERVICE ".Connection.Active"_L1
25#define NM_DEVICE_DBUS_INTERFACE NM_DBUS_SERVICE ".Device"_L1
26
28
29using namespace Qt::StringLiterals;
30
31namespace {
32constexpr QLatin1StringView propertiesChangedKey = "PropertiesChanged"_L1;
33const QString &stateKey()
34{
35 static auto key = u"State"_s;
36 return key;
37}
38const QString &connectivityKey()
39{
40 static auto key = u"Connectivity"_s;
41 return key;
42}
43const QString &primaryConnectionKey()
44{
45 static auto key = u"PrimaryConnection"_s;
46 return key;
47}
48}
49
55
60
63{
65 return;
66
67 PropertiesDBusInterface managerPropertiesInterface(
70 QList<QVariant> argumentList;
71 argumentList << NM_DBUS_SERVICE;
72 QDBusPendingReply<QVariantMap> propsReply = managerPropertiesInterface.callWithArgumentList(
73 QDBus::Block, "GetAll"_L1, argumentList);
74 if (propsReply.isError()) {
75 validDBusConnection = false;
76 if (auto error = propsReply.error(); error.type() != QDBusError::AccessDenied)
77 qWarning() << "Failed to query NetworkManager properties:" << error.message();
78 return;
79 }
80 propertyMap = propsReply.value();
81
82 validDBusConnection = QDBusConnection::systemBus().connect(NM_DBUS_SERVICE, NM_DBUS_PATH,
83 DBUS_PROPERTIES_INTERFACE, propertiesChangedKey, this,
84 SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>)));
85}
86
88{
90 DBUS_PROPERTIES_INTERFACE, propertiesChangedKey, this,
91 SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>)));
92}
93
95{
96 auto it = propertyMap.constFind(stateKey());
97 if (it != propertyMap.cend())
98 return static_cast<QNetworkManagerInterface::NMState>(it->toUInt());
100}
101
103{
104 auto it = propertyMap.constFind(connectivityKey());
105 if (it != propertyMap.cend())
106 return static_cast<NMConnectivityState>(it->toUInt());
108}
109
110static std::optional<QDBusInterface> getPrimaryDevice(const QDBusObjectPath &devicePath)
111{
112 const QDBusInterface connection(NM_DBUS_SERVICE, devicePath.path(),
114 if (!connection.isValid())
115 return std::nullopt;
116
117 const auto devicePaths = connection.property("Devices").value<QList<QDBusObjectPath>>();
118 if (devicePaths.isEmpty())
119 return std::nullopt;
120
121 const QDBusObjectPath primaryDevicePath = devicePaths.front();
122 return std::make_optional<QDBusInterface>(NM_DBUS_SERVICE, primaryDevicePath.path(),
125}
126
127std::optional<QDBusObjectPath> QNetworkManagerInterface::primaryConnectionDevicePath() const
128{
129 auto it = propertyMap.constFind(primaryConnectionKey());
130 if (it != propertyMap.cend())
131 return it->value<QDBusObjectPath>();
132 return std::nullopt;
133}
134
136{
137 if (const auto path = primaryConnectionDevicePath())
138 return extractDeviceType(*path);
140}
141
143{
144 if (const auto path = primaryConnectionDevicePath())
145 return extractDeviceMetered(*path);
146 return NM_METERED_UNKNOWN;
147}
148
149auto QNetworkManagerInterface::extractDeviceType(const QDBusObjectPath &devicePath) const
150 -> NMDeviceType
151{
152 const auto primaryDevice = getPrimaryDevice(devicePath);
153 if (!primaryDevice)
154 return NM_DEVICE_TYPE_UNKNOWN;
155 if (!primaryDevice->isValid())
156 return NM_DEVICE_TYPE_UNKNOWN;
157 const QVariant deviceType = primaryDevice->property("DeviceType");
158 if (!deviceType.isValid())
159 return NM_DEVICE_TYPE_UNKNOWN;
160 return static_cast<NMDeviceType>(deviceType.toUInt());
161}
162
163auto QNetworkManagerInterface::extractDeviceMetered(const QDBusObjectPath &devicePath) const
164 -> NMMetered
165{
166 const auto primaryDevice = getPrimaryDevice(devicePath);
167 if (!primaryDevice)
168 return NM_METERED_UNKNOWN;
169 if (!primaryDevice->isValid())
170 return NM_METERED_UNKNOWN;
171 const QVariant metered = primaryDevice->property("Metered");
172 if (!metered.isValid())
173 return NM_METERED_UNKNOWN;
174 return static_cast<NMMetered>(metered.toUInt());
175}
176
178{
179 backend = ourBackend;
180}
181
182void QNetworkManagerInterface::setProperties(const QString &interfaceName,
183 const QMap<QString, QVariant> &map,
184 const QStringList &invalidatedProperties)
185{
187 Q_UNUSED(invalidatedProperties);
188
189 for (auto i = map.cbegin(), end = map.cend(); i != end; ++i) {
190 bool valueChanged = true;
191
192 auto it = propertyMap.lowerBound(i.key());
193 if (it != propertyMap.end() && it.key() == i.key()) {
194 valueChanged = (it.value() != i.value());
195 *it = *i;
196 } else {
197 propertyMap.insert(it, i.key(), i.value());
198 }
199
200 if (valueChanged) {
201 if (i.key() == stateKey()) {
202 quint32 state = i.value().toUInt();
203 backend->onStateChanged(static_cast<NMState>(state));
204 } else if (i.key() == connectivityKey()) {
205 quint32 state = i.value().toUInt();
206 backend->onConnectivityChanged(static_cast<NMConnectivityState>(state));
207 } else if (i.key() == primaryConnectionKey()) {
208 const QDBusObjectPath devicePath = i->value<QDBusObjectPath>();
209 backend->onDeviceTypeChanged(extractDeviceType(devicePath));
210 backend->onMeteredChanged(extractDeviceMetered(devicePath));
211 } else if (i.key() == "Metered"_L1) {
212 backend->onMeteredChanged(static_cast<NMMetered>(i->toUInt()));
213 }
214 }
215 }
216}
217
219
220#include "moc_qnetworkmanagerservice.cpp"
bool isValid() const
Returns true if this is a valid reference to a remote object.
\inmodule QtDBus
static QDBusConnection systemBus()
Returns a QDBusConnection object opened with the system bus.
\inmodule QtDBus
\inmodule QtDBus
QString path() const
Returns this object path.
iterator insert(const Key &key, const T &value)
Definition qmap.h:688
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
const_iterator cend() const
Definition qmap.h:605
const_iterator cbegin() const
Definition qmap.h:601
const_iterator constFind(const Key &key) const
Definition qmap.h:655
iterator lowerBound(const Key &key)
Definition qmap.h:660
iterator end()
Definition qmap.h:602
QNetworkManagerInterfaceBase(QObject *parent=nullptr)
void setBackend(QNetworkManagerNetworkInformationBackend *ourBackend)
NMConnectivityState connectivityState() const
QNetworkManagerInterface(QObject *parent=nullptr)
void onStateChanged(QNetworkManagerInterface::NMState state)
void onMeteredChanged(QNetworkManagerInterface::NMMetered metered)
void onConnectivityChanged(QNetworkManagerInterface::NMConnectivityState connectivityState)
void onDeviceTypeChanged(QNetworkManagerInterface::NMDeviceType deviceType)
\inmodule QtCore
Definition qobject.h:103
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4323
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
QMap< QString, QString > map
[6]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
DBusConnection * connection
#define qWarning
Definition qlogging.h:166
#define NM_DEVICE_DBUS_INTERFACE
#define NM_DBUS_INTERFACE
#define NM_DBUS_PATH
static std::optional< QDBusInterface > getPrimaryDevice(const QDBusObjectPath &devicePath)
#define DBUS_PROPERTIES_INTERFACE
#define NM_CONNECTION_DBUS_INTERFACE
#define NM_DBUS_SERVICE
#define SLOT(a)
Definition qobjectdefs.h:52
GLuint64 key
GLuint GLuint end
GLsizei const GLchar *const * path
QAnyStringView interfaceName(const Interface &iface)
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
static QInputDevice::DeviceType deviceType(const UINT cursorType)