diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(PROJECT_VERSION_MAJOR 5) set(QT_MIN_VERSION "5.9.0") -set(KF5_MIN_VERSION "5.42.0") +set(KF5_MIN_VERSION "5.50.0") ################# set KDE specific information ################# diff --git a/applet/contents/ui/ConnectionItem.qml b/applet/contents/ui/ConnectionItem.qml --- a/applet/contents/ui/ConnectionItem.qml +++ b/applet/contents/ui/ConnectionItem.qml @@ -34,7 +34,8 @@ property bool predictableWirelessPassword: !Uuid && Type == PlasmaNM.Enums.Wireless && (SecurityType == PlasmaNM.Enums.StaticWep || SecurityType == PlasmaNM.Enums.WpaPsk || SecurityType == PlasmaNM.Enums.Wpa2Psk) - property bool showSpeed: ConnectionState == PlasmaNM.Enums.Activated && + property bool showSpeed: plasmoid.expanded && + ConnectionState == PlasmaNM.Enums.Activated && (Type == PlasmaNM.Enums.Wired || Type == PlasmaNM.Enums.Wireless || Type == PlasmaNM.Enums.Gsm || @@ -46,17 +47,6 @@ enabled: true height: expanded ? baseHeight + separator.height + expandableComponentLoader.height + (2 * Math.round(units.gridUnit / 3)) : baseHeight - PlasmaCore.DataSource { - id: dataSource - - property string downloadSource: "network/interfaces/" + DeviceName + "/receiver/data" - property string uploadSource: "network/interfaces/" + DeviceName + "/transmitter/data" - - connectedSources: showSpeed && plasmoid.expanded ? [downloadSource, uploadSource] : [] - engine: "systemmonitor" - interval: 2000 - } - ColumnLayout { anchors.fill: parent @@ -159,7 +149,7 @@ top: parent.top } height: visible ? implicitHeight : 0 - visible: showSpeed && dataSource.data && dataSource.data[dataSource.downloadSource] && dataSource.data[dataSource.uploadSource] + visible: showSpeed PlasmaComponents.TabButton { id: speedTabButton @@ -197,8 +187,9 @@ top: detailsTabBar.visible ? detailsTabBar.bottom : parent.top topMargin: Math.round(units.gridUnit / 3) } - dataEngine: dataSource - deviceName: DeviceName + rxBytes: RxBytes + txBytes: TxBytes + interval: 2000 visible: detailsTabBar.currentTab == speedTabButton } } @@ -313,22 +304,26 @@ result += ", " + SecurityTypeString return result } else if (ConnectionState == PlasmaNM.Enums.Activated) { - if (showSpeed && dataSource.data && dataSource.data[dataSource.downloadSource] && dataSource.data[dataSource.uploadSource]) { + if (showSpeed) { var downloadColor = theme.highlightColor // cycle upload color by 180 degrees var uploadColor = Qt.hsva((downloadColor.hsvHue + 0.5) % 1, downloadColor.hsvSaturation, downloadColor.hsvValue, downloadColor.a) - return i18n("Connected, %2/s, %4/s", + return i18n("Connected, %2, %4", downloadColor, - KCoreAddons.Format.formatByteSize(dataSource.data[dataSource.downloadSource].value * 1024 || 0), + KCoreAddons.Format.formatByteSize(RxBytes), uploadColor, - KCoreAddons.Format.formatByteSize(dataSource.data[dataSource.uploadSource].value * 1024 || 0)) + KCoreAddons.Format.formatByteSize(TxBytes)) } else { return i18n("Connected") } } } + onShowSpeedChanged: { + connectionModel.setDeviceStatisticsRefreshRateMs(DevicePath, showSpeed ? 2000 : 0) + } + onActivatingChanged: { if (ConnectionState == PlasmaNM.Enums.Activating) { ListView.view.positionViewAtBeginning() diff --git a/applet/contents/ui/TrafficMonitor.qml b/applet/contents/ui/TrafficMonitor.qml --- a/applet/contents/ui/TrafficMonitor.qml +++ b/applet/contents/ui/TrafficMonitor.qml @@ -24,8 +24,9 @@ import org.kde.plasma.components 2.0 as PlasmaComponents Item { - property QtObject dataEngine: null - property string deviceName + property real rxBytes: 0 + property real txBytes: 0 + property alias interval: timer.interval height: visible ? plotter.height + units.gridUnit : 0 @@ -41,7 +42,7 @@ height: paintedHeight font.pointSize: theme.smallestFont.pointSize lineHeight: 1.75 - text: KCoreAddons.Format.formatByteSize((plotter.maxValue * 1024) * (1 - index / 5)) + text: KCoreAddons.Format.formatByteSize(plotter.maxValue * (1 - index / 5)) + i18n("/s") } } @@ -75,20 +76,22 @@ } ] - Connections { - target: dataEngine; - onNewData: { - if (sourceName.indexOf("network/interfaces/" + deviceName) != 0) { - return; - } - var rx = dataEngine.data[dataEngine.downloadSource]; - var tx = dataEngine.data[dataEngine.uploadSource]; - if (rx === undefined || rx.value === undefined || - tx === undefined || tx.value === undefined) { - return; - } - - plotter.addSample([rx.value, tx.value]); + Timer { + id: timer + repeat: true + running: parent.visible + property real prevRxBytes + property real prevTxBytes + Component.onCompleted: { + prevRxBytes = rxBytes + prevTxBytes = txBytes + } + onTriggered: { + var rxSpeed = (rxBytes - prevRxBytes) * 1000 / interval + var txSpeed = (txBytes - prevTxBytes) * 1000 / interval + prevRxBytes = rxBytes + prevTxBytes = txBytes + plotter.addSample([rxSpeed, txSpeed]); } } } diff --git a/libs/models/networkmodel.h b/libs/models/networkmodel.h --- a/libs/models/networkmodel.h +++ b/libs/models/networkmodel.h @@ -67,15 +67,18 @@ UniRole, UuidRole, VpnState, - VpnType + VpnType, + RxBytesRole, + TxBytesRole }; int rowCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; QHash roleNames() const override; public Q_SLOTS: void onItemUpdated(); + void setDeviceStatisticsRefreshRateMs(const QString &devicePath, uint refreshRate); private Q_SLOTS: void accessPointSignalStrengthChanged(int signal); diff --git a/libs/models/networkmodel.cpp b/libs/models/networkmodel.cpp --- a/libs/models/networkmodel.cpp +++ b/libs/models/networkmodel.cpp @@ -106,6 +106,10 @@ return item->vpnState(); case VpnType: return item->vpnType(); + case RxBytesRole: + return item->rxBytes(); + case TxBytesRole: + return item->txBytes(); default: break; } @@ -149,6 +153,8 @@ roles[UuidRole] = "Uuid"; roles[VpnState] = "VpnState"; roles[VpnType] = "VpnType"; + roles[RxBytesRole] = "RxBytes"; + roles[TxBytesRole] = "TxBytes"; return roles; } @@ -210,6 +216,20 @@ connect(device.data(), &NetworkManager::Device::ipInterfaceChanged, this, &NetworkModel::ipInterfaceChanged); connect(device.data(), &NetworkManager::Device::stateChanged, this, &NetworkModel::deviceStateChanged, Qt::UniqueConnection); + auto deviceStatistics = device->deviceStatistics(); + connect(deviceStatistics.data(), &NetworkManager::DeviceStatistics::rxBytesChanged, this, [this, device](qulonglong rxBytes) { + for (auto *item : m_list.returnItems(NetworkItemsList::Device, device->uni())) { + item->setRxBytes(rxBytes); + updateItem(item); + } + }); + connect(deviceStatistics.data(), &NetworkManager::DeviceStatistics::txBytesChanged, this, [this, device](qulonglong txBytes) { + for (auto *item : m_list.returnItems(NetworkItemsList::Device, device->uni())) { + item->setTxBytes(txBytes); + updateItem(item); + } + }); + if (device->type() == NetworkManager::Device::Wifi) { NetworkManager::WirelessDevice::Ptr wifiDev = device.objectCast(); connect(wifiDev.data(), &NetworkManager::WirelessDevice::networkAppeared, this, &NetworkModel::wirelessNetworkAppeared, Qt::UniqueConnection); @@ -508,6 +528,15 @@ } } +void NetworkModel::setDeviceStatisticsRefreshRateMs(const QString &devicePath, uint refreshRate) +{ + NetworkManager::Device::Ptr device = NetworkManager::findNetworkInterface(devicePath); + + if (device) { + device->deviceStatistics()->setRefreshRateMs(refreshRate); + } +} + void NetworkModel::updateItem(NetworkModelItem*item) { const int row = m_list.indexOf(item); diff --git a/libs/models/networkmodelitem.h b/libs/models/networkmodelitem.h --- a/libs/models/networkmodelitem.h +++ b/libs/models/networkmodelitem.h @@ -108,6 +108,12 @@ QString vpnType() const; void setVpnType(const QString &type); + qulonglong rxBytes() const; + void setRxBytes(qulonglong bytes); + + qulonglong txBytes() const; + void setTxBytes(qulonglong bytes); + bool operator==(const NetworkModelItem *item) const; public Q_SLOTS: @@ -137,6 +143,8 @@ QString m_uuid; QString m_vpnType; NetworkManager::VpnConnection::State m_vpnState; + qulonglong m_rxBytes; + qulonglong m_txBytes; }; #endif // PLASMA_NM_MODEL_NETWORK_MODEL_ITEM_H diff --git a/libs/models/networkmodelitem.cpp b/libs/models/networkmodelitem.cpp --- a/libs/models/networkmodelitem.cpp +++ b/libs/models/networkmodelitem.cpp @@ -62,6 +62,8 @@ , m_slave(false) , m_type(NetworkManager::ConnectionSettings::Unknown) , m_vpnState(NetworkManager::VpnConnection::Unknown) + , m_rxBytes(0) + , m_txBytes(0) { } @@ -80,6 +82,8 @@ , m_type(item->type()) , m_uuid(item->uuid()) , m_vpnState(NetworkManager::VpnConnection::Unknown) + , m_rxBytes(0) + , m_txBytes(0) { } @@ -408,6 +412,26 @@ m_vpnType = type; } +qulonglong NetworkModelItem::rxBytes() const +{ + return m_rxBytes; +} + +void NetworkModelItem::setRxBytes(qulonglong bytes) +{ + m_rxBytes = bytes; +} + +qulonglong NetworkModelItem::txBytes() const +{ + return m_txBytes; +} + +void NetworkModelItem::setTxBytes(qulonglong bytes) +{ + m_txBytes = bytes; +} + bool NetworkModelItem::operator==(const NetworkModelItem *item) const { if (!item->uuid().isEmpty() && !uuid().isEmpty()) {