Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/network/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <qobject.h>
#include <qstring.h>
#include <qtmetamacros.h>
#include <qtypes.h>

#include "../core/logcat.hpp"
#include "enums.hpp"
Expand Down Expand Up @@ -33,6 +34,11 @@ void NetworkDevice::setNmManaged(bool managed) {
emit this->requestSetNmManaged(managed);
}

void NetworkDevice::setRefreshRate(quint32 refreshRate) {
if (this->bRefreshRate == refreshRate) return;
emit this->requestSetRefreshRate(refreshRate);
}

void NetworkDevice::disconnect() {
if (this->bState == ConnectionState::Disconnected) {
qCCritical(logNetworkDevice) << "Device" << this << "is already disconnected";
Expand Down
21 changes: 21 additions & 0 deletions src/network/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ class NetworkDevice: public QObject {
Q_PROPERTY(bool nmManaged READ nmManaged WRITE setNmManaged NOTIFY nmManagedChanged)
/// True if the device is allowed to autoconnect to a network.
Q_PROPERTY(bool autoconnect READ autoconnect WRITE setAutoconnect NOTIFY autoconnectChanged);
/// Refresh rate of the @@rxBytes and @@txBytes in milliseconds.
///
/// > [!NOTE] @@rxBytes and @@txBytes are guaranteed to be refreshed each @@refreshRate milliseconds in the case the underlying counter has changed too.
/// > If zero, there is no guaranteed refresh rate of the properties.
Q_PROPERTY(quint32 refreshRate READ default WRITE setRefreshRate NOTIFY refreshRateChanged BINDABLE bindableRefreshRate);
/// Number of bytes this device received.
Q_PROPERTY(quint64 rxBytes READ default NOTIFY rxBytesChanged BINDABLE bindableRxBytes);
/// Number of bytes this device transmitted.
Q_PROPERTY(quint64 txBytes READ default NOTIFY txBytesChanged BINDABLE bindableTxBytes);

// clang-format on

public:
Expand All @@ -69,17 +79,25 @@ class NetworkDevice: public QObject {
QBindable<bool> bindableAutoconnect() { return &this->bAutoconnect; }
[[nodiscard]] bool autoconnect() { return this->bAutoconnect; }
void setAutoconnect(bool autoconnect);
QBindable<quint32> bindableRefreshRate() { return &this->bRefreshRate; }
void setRefreshRate(quint32 refreshRate);
QBindable<quint64> bindableRxBytes() { return &this->bRxBytes; }
QBindable<quint64> bindableTxBytes() { return &this->bTxBytes; }

signals:
QSDOC_HIDE void requestDisconnect();
QSDOC_HIDE void requestSetAutoconnect(bool autoconnect);
QSDOC_HIDE void requestSetNmManaged(bool managed);
QSDOC_HIDE void requestSetRefreshRate(quint32 refreshRate);
void nameChanged();
void addressChanged();
void connectedChanged();
void stateChanged();
void nmManagedChanged();
void autoconnectChanged();
void refreshRateChanged();
void rxBytesChanged();
void txBytesChanged();

protected:
ObjectModel<Network> mNetworks {this};
Expand All @@ -93,6 +111,9 @@ class NetworkDevice: public QObject {
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, ConnectionState::Enum, bState, &NetworkDevice::stateChanged);
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, bool, bNmManaged, &NetworkDevice::nmManagedChanged);
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, bool, bAutoconnect, &NetworkDevice::autoconnectChanged);
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, quint32, bRefreshRate, &NetworkDevice::refreshRateChanged);
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, quint64, bRxBytes, &NetworkDevice::rxBytesChanged);
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, quint64, bTxBytes, &NetworkDevice::txBytesChanged);
// clang-format on
};

Expand Down
10 changes: 10 additions & 0 deletions src/network/nm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ qt_add_dbus_interface(NM_DBUS_INTERFACES
dbus_nm_device
)

set_source_files_properties(org.freedesktop.NetworkManager.Device.Statistics.xml PROPERTIES
CLASSNAME DBusNMDeviceStatisticsProxy
NO_NAMESPACE TRUE
)

qt_add_dbus_interface(NM_DBUS_INTERFACES
org.freedesktop.NetworkManager.Device.Statistics.xml
dbus_nm_device_statistics
)

set_source_files_properties(org.freedesktop.NetworkManager.Device.Wireless.xml PROPERTIES
CLASSNAME DBusNMWirelessProxy
NO_NAMESPACE TRUE
Expand Down
31 changes: 31 additions & 0 deletions src/network/nm/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "../enums.hpp"
#include "active_connection.hpp"
#include "dbus_nm_device.h"
#include "dbus_nm_device_statistics.h"
#include "dbus_types.hpp"
#include "enums.hpp"
#include "network.hpp"
Expand All @@ -38,11 +39,26 @@ NMDevice::NMDevice(const QString& path, QObject* parent): QObject(parent) {
this
);

this->deviceStatisticsProxy = new DBusNMDeviceStatisticsProxy(
"org.freedesktop.NetworkManager",
path,
QDBusConnection::systemBus(),
this
);

if (!this->deviceProxy->isValid()) {
qCWarning(logNetworkManager) << "Cannot create DBus interface for device at" << path;
return;
}

// Valid statistics aren't required to register a device.
if (!this->deviceStatisticsProxy->isValid()) {
qCWarning(logNetworkManager) << "Cannot create DBus interface for device statistics at" << path;
} else {
this->deviceStatisticsProperties.setInterface(this->deviceStatisticsProxy);
this->deviceStatisticsProperties.updateAllViaGetAll();
}

// clang-format off
QObject::connect(this, &NMDevice::availableSettingsPathsChanged, this, &NMDevice::onAvailableSettingsPathsChanged);
QObject::connect(this, &NMDevice::activeConnectionPathChanged, this, &NMDevice::onActiveConnectionPathChanged);
Expand All @@ -69,9 +85,13 @@ void NMDevice::bindFrontend(NetworkDevice* frontend) {
frontend->bindableState().setBinding(translateState);
frontend->bindableAutoconnect().setBinding([this]() { return this->autoconnect(); });
frontend->bindableNmManaged().setBinding([this]() { return this->managed(); });
frontend->bindableRefreshRate().setBinding([this]() { return this->refreshRate(); });
frontend->bindableRxBytes().setBinding([this]() { return this->rxBytes(); });
frontend->bindableTxBytes().setBinding([this]() { return this->txBytes(); });
QObject::connect(frontend, &NetworkDevice::requestDisconnect, this, &NMDevice::disconnect);
QObject::connect(frontend, &NetworkDevice::requestSetAutoconnect, this, &NMDevice::setAutoconnect);
QObject::connect(frontend, &NetworkDevice::requestSetNmManaged, this, &NMDevice::setManaged);
QObject::connect(frontend, &NetworkDevice::requestSetRefreshRate, this, &NMDevice::setRefreshRate);
QObject::connect(this, &NMDevice::networkAdded, frontend, &NetworkDevice::networkAdded);
QObject::connect(this, &NMDevice::networkRemoved, frontend, &NetworkDevice::networkRemoved);
}
Expand Down Expand Up @@ -188,6 +208,17 @@ void NMDevice::setManaged(bool managed) {
this->pManaged.write();
}

void NMDevice::setRefreshRate(quint32 refreshRate) {
if (refreshRate == this->bRefreshRate) return;
if (!this->deviceStatisticsProxy->isValid()) {
qCWarning(logNetworkManager) << "Cannot set refresh rate: Invalid device statistics interface";
return;
}

this->bRefreshRate = refreshRate;
this->pRefreshRate.write();
}

bool NMDevice::isValid() const { return this->deviceProxy && this->deviceProxy->isValid(); }
QString NMDevice::address() const {
return this->deviceProxy ? this->deviceProxy->service() : QString();
Expand Down
18 changes: 17 additions & 1 deletion src/network/nm/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../device.hpp"
#include "active_connection.hpp"
#include "dbus_nm_device.h"
#include "dbus_nm_device_statistics.h"
#include "enums.hpp"
#include "network.hpp"
#include "settings.hpp"
Expand Down Expand Up @@ -56,6 +57,9 @@ class NMDevice: public QObject {
[[nodiscard]] NMDeviceInterfaceFlags::Enum interfaceFlags() const {
return this->bInterfaceFlags;
}
[[nodiscard]] quint32 refreshRate() const { return this->bRefreshRate; }
[[nodiscard]] quint64 rxBytes() const { return this->bRxBytes; }
[[nodiscard]] quint64 txBytes() const { return this->bTxBytes; }
[[nodiscard]] bool autoconnect() const { return this->bAutoconnect; }
[[nodiscard]] NMActiveConnection* activeConnection() const { return this->mActiveConnection; }
[[nodiscard]] virtual NetworkDevice* frontend() = 0;
Expand Down Expand Up @@ -83,11 +87,15 @@ class NMDevice: public QObject {
void lastFailReasonChanged(NMDeviceStateReason::Enum reason);
void autoconnectChanged(bool autoconnect);
void interfaceFlagsChanged(NMDeviceInterfaceFlags::Enum flags);
void refreshRateChanged(quint32 refreshRate);
void rxBytesChanged(quint64 rxBytes);
void txBytesChanged(quint64 txBytes);

public slots:
void disconnect();
void setAutoconnect(bool autoconnect);
void setManaged(bool managed);
void setRefreshRate(quint32 refreshRate);

protected:
void bindFrontend(NetworkDevice* frontend);
Expand Down Expand Up @@ -115,8 +123,11 @@ private slots:
Q_OBJECT_BINDABLE_PROPERTY(NMDevice, QList<QDBusObjectPath>, bAvailableConnections, &NMDevice::availableSettingsPathsChanged);
Q_OBJECT_BINDABLE_PROPERTY(NMDevice, QDBusObjectPath, bActiveConnection, &NMDevice::activeConnectionPathChanged);
Q_OBJECT_BINDABLE_PROPERTY(NMDevice, NMDeviceInterfaceFlags::Enum, bInterfaceFlags, &NMDevice::interfaceFlagsChanged);
Q_OBJECT_BINDABLE_PROPERTY(NMDevice, quint32, bRefreshRate, &NMDevice::refreshRateChanged);
Q_OBJECT_BINDABLE_PROPERTY(NMDevice, quint64, bRxBytes, &NMDevice::rxBytesChanged);
Q_OBJECT_BINDABLE_PROPERTY(NMDevice, quint64, bTxBytes, &NMDevice::txBytesChanged);

QS_DBUS_BINDABLE_PROPERTY_GROUP(NMDeviceAdapter, deviceProperties);
QS_DBUS_BINDABLE_PROPERTY_GROUP(NMDevice, deviceProperties);
QS_DBUS_PROPERTY_BINDING(NMDevice, pName, bInterface, deviceProperties, "Interface");
QS_DBUS_PROPERTY_BINDING(NMDevice, pAddress, bHwAddress, deviceProperties, "HwAddress");
QS_DBUS_PROPERTY_BINDING(NMDevice, pManaged, bManaged, deviceProperties, "Managed");
Expand All @@ -125,9 +136,14 @@ private slots:
QS_DBUS_PROPERTY_BINDING(NMDevice, pAvailableConnections, bAvailableConnections, deviceProperties, "AvailableConnections");
QS_DBUS_PROPERTY_BINDING(NMDevice, pActiveConnection, bActiveConnection, deviceProperties, "ActiveConnection");
QS_DBUS_PROPERTY_BINDING(NMDevice, pInterfaceFlags, bInterfaceFlags, deviceProperties, "InterfaceFlags");
QS_DBUS_BINDABLE_PROPERTY_GROUP(NMDevice, deviceStatisticsProperties);
QS_DBUS_PROPERTY_BINDING(NMDevice, pRefreshRate, bRefreshRate, deviceStatisticsProperties, "RefreshRateMs");
QS_DBUS_PROPERTY_BINDING(NMDevice, pRxBytes, bRxBytes, deviceStatisticsProperties, "RxBytes");
QS_DBUS_PROPERTY_BINDING(NMDevice, pTxBytes, bTxBytes, deviceStatisticsProperties, "TxBytes");
// clang-format on

DBusNMDeviceProxy* deviceProxy = nullptr;
DBusNMDeviceStatisticsProxy* deviceStatisticsProxy = nullptr;
};

} // namespace qs::network
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<node>
<interface name="org.freedesktop.NetworkManager.Device.Statistics">
</interface>
</node>
27 changes: 27 additions & 0 deletions src/network/test/manual/network.qml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ Scope {
Component {
id: deviceDelegate
WrapperRectangle {
id: deviceRoot

function formatMib(bytes) {
return `${(bytes / 1024 / 1024).toFixed(3)} MiB`;
}

width: parent.width
color: "transparent"
border.color: palette.button
Expand Down Expand Up @@ -140,6 +146,27 @@ Scope {
}
}
}
RowLayout {
Label {
text: `RX: ${deviceRoot.formatMib(modelData.rxBytes)}`
color: palette.placeholderText
}
Label {
text: `TX: ${deviceRoot.formatMib(modelData.txBytes)}`
color: palette.placeholderText
}
Label {
text: "Refresh rate:"
}
SpinBox {
from: 0
to: 60000
stepSize: 250
value: modelData.refreshRate
onValueModified: modelData.refreshRate = value
textFromValue: value => value === 0 ? "Off" : value + "ms"
}
}

Repeater {
model: ScriptModel {
Expand Down
Loading