10#include <QtDBus/QDBusConnection>
11#include <QtDBus/QDBusError>
12#include <QtDBus/QDBusInterface>
13#include <QtDBus/QDBusMessage>
14#include <QtDBus/QDBusReply>
15#include <QtDBus/QDBusPendingCallWatcher>
16#include <QtDBus/QDBusObjectPath>
17#include <QtDBus/QDBusPendingCall>
19#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"_L1
21#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager"
24#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"_L1
30using namespace Qt::StringLiterals;
33constexpr QLatin1StringView propertiesChangedKey =
"PropertiesChanged"_L1;
34const QString &stateKey()
36 static auto key = u"State"_s;
39const QString &connectivityKey()
41 static auto key = u"Connectivity"_s;
44const QString &primaryConnectionKey()
46 static auto key = u"PrimaryConnection"_s;
65 if (!QDBusAbstractInterface::isValid())
70 QDBusConnection::systemBus());
71 QList<QVariant> argumentList;
73 QDBusPendingReply<QVariantMap> propsReply = managerPropertiesInterface.callWithArgumentList(
74 QDBus::Block,
"GetAll"_L1, argumentList);
75 if (propsReply.isError()) {
76 validDBusConnection =
false;
77 if (
auto error = propsReply.error(); error.type() != QDBusError::AccessDenied)
78 qWarning() <<
"Failed to query NetworkManager properties:" << error.message();
81 propertyMap = propsReply.value();
85 SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>)));
92 SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>)));
97 auto it = propertyMap.constFind(stateKey());
98 if (it != propertyMap.cend())
99 return static_cast<QNetworkManagerInterface::NMState>(it->toUInt());
100 return QNetworkManagerInterface::NM_STATE_UNKNOWN;
105 auto it = propertyMap.constFind(connectivityKey());
106 if (it != propertyMap.cend())
107 return static_cast<NMConnectivityState>(it->toUInt());
108 return QNetworkManagerInterface::NM_CONNECTIVITY_UNKNOWN;
115 if (!connection.isValid())
118 const auto devicePaths = connection.property(
"Devices").value<QList<QDBusObjectPath>>();
119 if (devicePaths.isEmpty())
122 const QDBusObjectPath primaryDevicePath = devicePaths.front();
123 return std::make_optional<QDBusInterface>(
NM_DBUS_SERVICE, primaryDevicePath.path(),
125 QDBusConnection::systemBus());
130 auto it = propertyMap.constFind(primaryConnectionKey());
131 if (it != propertyMap.cend())
132 return it->value<QDBusObjectPath>();
138 if (
const auto path = primaryConnectionDevicePath())
139 return extractDeviceType(*path);
140 return NM_DEVICE_TYPE_UNKNOWN;
145 if (
const auto path = primaryConnectionDevicePath())
146 return extractDeviceMetered(*path);
153 const auto primaryDevice = getPrimaryDevice(devicePath);
155 return NM_DEVICE_TYPE_UNKNOWN;
156 if (!primaryDevice->isValid())
157 return NM_DEVICE_TYPE_UNKNOWN;
158 const QVariant deviceType = primaryDevice->property(
"DeviceType");
159 if (!deviceType.isValid())
160 return NM_DEVICE_TYPE_UNKNOWN;
161 return static_cast<NMDeviceType>(deviceType.toUInt());
167 const auto primaryDevice = getPrimaryDevice(devicePath);
170 if (!primaryDevice->isValid())
172 const QVariant metered = primaryDevice->property(
"Metered");
173 if (!metered.isValid())
175 return static_cast<
NMMetered>(metered.toUInt());
180 backend = ourBackend;
184 const QMap<QString, QVariant> &map,
185 const QStringList &invalidatedProperties)
187 Q_UNUSED(interfaceName);
188 Q_UNUSED(invalidatedProperties);
190 for (
auto i = map.cbegin(), end = map.cend(); i != end; ++i) {
191 bool valueChanged =
true;
193 auto it = propertyMap.lowerBound(i.key());
194 if (it != propertyMap.end() && it.key() == i.key()) {
195 valueChanged = (it.value() != i.value());
198 propertyMap.insert(it, i.key(), i.value());
202 if (i.key() == stateKey()) {
203 quint32 state = i.value().toUInt();
204 backend->onStateChanged(
static_cast<NMState>(state));
205 }
else if (i.key() == connectivityKey()) {
206 quint32 state = i.value().toUInt();
207 backend->onConnectivityChanged(
static_cast<NMConnectivityState>(state));
208 }
else if (i.key() == primaryConnectionKey()) {
209 const QDBusObjectPath devicePath = i->value<QDBusObjectPath>();
210 backend->onDeviceTypeChanged(extractDeviceType(devicePath));
212 }
else if (i.key() ==
"Metered"_L1) {
221#include "moc_qnetworkmanagerservice.cpp"
static bool networkManagerAvailable()
void setBackend(QNetworkManagerNetworkInformationBackend *ourBackend)
NMConnectivityState connectivityState() const
QNetworkManagerInterface(QObject *parent=nullptr)
NMDeviceType deviceType() const
~QNetworkManagerInterface()
NMMetered meteredState() const
#define NM_DEVICE_DBUS_INTERFACE
#define NM_DBUS_INTERFACE
static std::optional< QDBusInterface > getPrimaryDevice(const QDBusObjectPath &devicePath)
#define DBUS_PROPERTIES_INTERFACE
#define NM_CONNECTION_DBUS_INTERFACE