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>
18#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"_L1
20#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager"
23#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"_L1
29using namespace Qt::StringLiterals;
32constexpr QLatin1StringView propertiesChangedKey =
"PropertiesChanged"_L1;
33const QString &stateKey()
35 static auto key = u"State"_s;
38const QString &connectivityKey()
40 static auto key = u"Connectivity"_s;
43const QString &primaryConnectionKey()
45 static auto key = u"PrimaryConnection"_s;
64 if (!QDBusAbstractInterface::isValid())
69 QDBusConnection::systemBus());
70 QList<QVariant> argumentList;
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();
80 propertyMap = propsReply.value();
84 SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>)));
91 SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>)));
96 auto it = propertyMap.constFind(stateKey());
97 if (it != propertyMap.cend())
98 return static_cast<QNetworkManagerInterface::NMState>(it->toUInt());
99 return QNetworkManagerInterface::NM_STATE_UNKNOWN;
104 auto it = propertyMap.constFind(connectivityKey());
105 if (it != propertyMap.cend())
106 return static_cast<NMConnectivityState>(it->toUInt());
107 return QNetworkManagerInterface::NM_CONNECTIVITY_UNKNOWN;
114 if (!connection.isValid())
117 const auto devicePaths = connection.property(
"Devices").value<QList<QDBusObjectPath>>();
118 if (devicePaths.isEmpty())
121 const QDBusObjectPath primaryDevicePath = devicePaths.front();
122 return std::make_optional<QDBusInterface>(
NM_DBUS_SERVICE, primaryDevicePath.path(),
124 QDBusConnection::systemBus());
129 auto it = propertyMap.constFind(primaryConnectionKey());
130 if (it != propertyMap.cend())
131 return it->value<QDBusObjectPath>();
137 if (
const auto path = primaryConnectionDevicePath())
138 return extractDeviceType(*path);
139 return NM_DEVICE_TYPE_UNKNOWN;
144 if (
const auto path = primaryConnectionDevicePath())
145 return extractDeviceMetered(*path);
152 const auto primaryDevice = getPrimaryDevice(devicePath);
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());
166 const auto primaryDevice = getPrimaryDevice(devicePath);
169 if (!primaryDevice->isValid())
171 const QVariant metered = primaryDevice->property(
"Metered");
172 if (!metered.isValid())
174 return static_cast<
NMMetered>(metered.toUInt());
179 backend = ourBackend;
183 const QMap<QString, QVariant> &map,
184 const QStringList &invalidatedProperties)
186 Q_UNUSED(interfaceName);
187 Q_UNUSED(invalidatedProperties);
189 for (
auto i = map.cbegin(), end = map.cend(); i != end; ++i) {
190 bool valueChanged =
true;
192 auto it = propertyMap.lowerBound(i.key());
193 if (it != propertyMap.end() && it.key() == i.key()) {
194 valueChanged = (it.value() != i.value());
197 propertyMap.insert(it, i.key(), i.value());
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));
211 }
else if (i.key() ==
"Metered"_L1) {
220#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
Combined button and popup list for selecting options.
#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