Compare commits

...

3 Commits

Author SHA1 Message Date
59e3b21071 feat: use singleton connection to systemstats
it has been found in #174, that if there are multiple instances of
widget, it keeps subscribing on all sources, because of how dbus
interface works.

In order to hande it, all subscriptions are now kept from singleton with
tracking active clients
2026-01-30 16:03:45 +02:00
7e13e1eef7 Release 4.0.5 2026-01-28 19:53:21 +02:00
da53052a6f fix: always unsubscribe on sources 2026-01-28 19:51:51 +02:00
10 changed files with 84 additions and 15 deletions

View File

@@ -2,7 +2,7 @@
pkgname=plasma6-applet-awesome-widgets
_pkgname=awesome-widgets
pkgver=4.0.4
pkgver=4.0.5
pkgrel=1
pkgdesc="Collection of minimalistic Plasmoids which look like Awesome WM widgets (ex-PyTextMonitor)"
arch=('x86_64')

View File

@@ -19,7 +19,7 @@ set(PROJECT_CONTACT "esalexeev@gmail.com")
set(PROJECT_LICENSE "GPL3")
set(PROJECT_VERSION_MAJOR "4")
set(PROJECT_VERSION_MINOR "0")
set(PROJECT_VERSION_PATCH "4")
set(PROJECT_VERSION_PATCH "5")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
# append git version if any
set(PROJECT_COMMIT_SHA "Commit hash" CACHE INTERNAL "")

View File

@@ -19,7 +19,7 @@
"Id": "org.kde.plasma.awesomewidget",
"License": "GPLv3",
"Name": "Awesome Widget",
"Version": "4.0.4",
"Version": "4.0.5",
"Website": "https://arcanis.me/projects/awesome-widgets/"
},
"X-Plasma-API-Minimum-Version": "6.0"

View File

@@ -95,14 +95,55 @@ void AWDataEngineAggregator::loadSources()
}
void AWDataEngineAggregator::registerClient(QObject *_client)
{
qCDebug(LOG_AW) << "Register client" << _client;
// register new client
m_clients.insert(_client);
// (re)connect sources for new client
connectSources();
}
void AWDataEngineAggregator::unregisterClient(QObject *_client)
{
qCDebug(LOG_AW) << "Unregister client" << _client;
m_clients.remove(_client);
for (auto [source, clients] : m_droppedBy.asKeyValueRange()) {
if (clients.remove(_client)) {
if (isSubscriptionUnused(source))
dropSource(source);
}
}
}
void AWDataEngineAggregator::dropSource(const QString &_source)
{
qCDebug(LOG_AW) << "Disconnect sensor" << _source;
if (m_subscribed.contains(_source)) {
if (m_subscribed.remove(_source))
m_interface->unsubscribe({_source}).waitForFinished();
m_subscribed.remove(_source);
}
void AWDataEngineAggregator::dropSourceForClient(QObject *_client, const QString &_source)
{
qCDebug(LOG_AW) << "Client" << _client << "dropping source" << _source;
m_droppedBy[_source].insert(_client);
// only unsubscribe if ALL clients have dropped this source
if (isSubscriptionUnused(_source))
dropSource(_source);
}
bool AWDataEngineAggregator::isSubscriptionUnused(const QString &_source) const
{
return m_droppedBy.value(_source).size() >= m_clients.size() && !m_clients.isEmpty();
}

View File

@@ -23,6 +23,7 @@
#include <QObject>
#include <QSet>
#include <memory>
namespace KSysGuard::SystemStats
{
@@ -34,12 +35,26 @@ class AWDataEngineAggregator : public QObject
Q_OBJECT
public:
explicit AWDataEngineAggregator(QObject *_parent = nullptr);
~AWDataEngineAggregator() override;
AWDataEngineAggregator(AWDataEngineAggregator &) = delete;
void operator=(const AWDataEngineAggregator &) = delete;
[[nodiscard]] static AWDataEngineAggregator *instance(QObject *_client)
{
static auto instance = loadInstance();
instance->registerClient(_client);
return instance.get();
};
void connectSources();
void disconnectSources();
void dropSourceForClient(QObject *_client, const QString &_source);
[[nodiscard]] inline bool isSubscriptionUnused(const QString &_source) const;
[[nodiscard]] static bool isValidSensor(const KSysGuard::SensorInfo &_sensor);
void loadSources();
void registerClient(QObject *_client);
void unregisterClient(QObject *_client);
signals:
void dataUpdated(const QHash<QString, KSysGuard::SensorInfo> &_sensors, const KSysGuard::SensorDataList &_data);
@@ -52,7 +67,18 @@ public slots:
void updateData(const KSysGuard::SensorDataList &_data);
void updateSensors(const QHash<QString, KSysGuard::SensorInfo> &_sensors);
protected:
explicit AWDataEngineAggregator(QObject *_parent = nullptr);
[[nodiscard]] static std::unique_ptr<AWDataEngineAggregator> loadInstance()
{
auto instance = new AWDataEngineAggregator();
return std::unique_ptr<AWDataEngineAggregator>(instance);
};
private:
QSet<QObject *> m_clients;
QHash<QString, QSet<QObject *>> m_droppedBy;
KSysGuard::SystemStats::DBusInterface *m_interface = nullptr;
QHash<QString, KSysGuard::SensorInfo> m_sensors;
QSet<QString> m_subscribed;

View File

@@ -43,7 +43,7 @@ AWKeys::AWKeys(QObject *_parent)
m_aggregator = new AWKeysAggregator(this);
m_dataAggregator = new AWDataAggregator(this);
m_dataEngineAggregator = new AWDataEngineAggregator(this);
m_dataEngineAggregator = AWDataEngineAggregator::instance(this);
m_keyOperator = new AWKeyOperations(this);
m_timer = new QTimer(this);
@@ -59,7 +59,8 @@ AWKeys::AWKeys(QObject *_parent)
connect(m_dataAggregator, &AWDataAggregator::toolTipPainted,
[this](const QString &_tooltip) { emit(needToolTipToBeUpdated(_tooltip)); });
connect(this, &AWKeys::dropSourceFromDataengine, m_dataEngineAggregator, &AWDataEngineAggregator::dropSource);
connect(this, &AWKeys::dropSourceFromDataengine, this,
[this](const QString &_source) { m_dataEngineAggregator->dropSourceForClient(this, _source); });
connect(m_dataEngineAggregator, &AWDataEngineAggregator::dataUpdated, this, &AWKeys::dataUpdated);
// transfer signal from dataengine to update source list
connect(m_dataEngineAggregator, &AWDataEngineAggregator::deviceAdded, m_keyOperator, &AWKeyOperations::addDevice);
@@ -70,6 +71,8 @@ AWKeys::~AWKeys()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_dataEngineAggregator->unregisterClient(this);
m_timer->stop();
// delete dbus session
auto id = reinterpret_cast<qlonglong>(this);
@@ -294,8 +297,8 @@ QString AWKeys::parsePattern(QString _pattern) const
// bars
for (auto &bar : m_foundBars) {
auto item = m_keyOperator->giByKey(bar);
auto image = item->isCustom() ? item->image(
AWPatternFunctions::expandLambdas(item->bar(), m_aggregator, m_values, item->usedKeys()))
auto image = item->isCustom() ? item->image(AWPatternFunctions::expandLambdas(item->bar(), m_aggregator,
m_values, item->usedKeys()))
: item->image(m_values[item->bar()]);
_pattern.replace(QString("$%1").arg(bar), image);
}

View File

@@ -22,4 +22,3 @@
#ifndef ui_i18n
#define ui_i18n(text, parent) i18n(text)
#endif /* ui_i18n */

View File

@@ -19,7 +19,7 @@
"Id": "org.kde.plasma.desktoppanel",
"License": "GPLv3",
"Name": "Desktop Panel",
"Version": "4.0.4",
"Version": "4.0.5",
"Website": "https://arcanis.me/projects/awesome-widgets/"
},
"X-Plasma-API-Minimum-Version": "6.0"