* fix bug in ui

* drop QUEUE_LIMIT build option (moved to runtime cfg)
* apply concurrent updates for slots
This commit is contained in:
arcan1s 2015-09-23 03:53:42 +03:00
parent 82e2bc23a1
commit 0fa274ad75
6 changed files with 93 additions and 55 deletions

View File

@ -29,7 +29,6 @@ option(BUILD_FUTURE "Build with the features which will be marked as stable late
option(BUILD_PLASMOIDS "Build plasmoids" ON) option(BUILD_PLASMOIDS "Build plasmoids" ON)
option(BUILD_DEB_PACKAGE "Build deb package" OFF) option(BUILD_DEB_PACKAGE "Build deb package" OFF)
option(BUILD_RPM_PACKAGE "Build rpm package" OFF) option(BUILD_RPM_PACKAGE "Build rpm package" OFF)
set(QUEUE_LIMIT 0 CACHE INTEGER "Limit data queue to this value")
# flags # flags
if(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCXX)

View File

@ -320,7 +320,7 @@ Item {
width: parent.width * 2 / 5 width: parent.width * 2 / 5
text: i18n("Preview") text: i18n("Preview")
onClicked: { onClicked: {
awKeys.initKeys(textPattern.text) awKeys.initKeys(textPattern.text, plasmoid.configuration.queueLimit)
awKeys.needToBeUpdated() awKeys.needToBeUpdated()
} }
} }

View File

@ -19,7 +19,11 @@
#include <KI18n/KLocalizedString> #include <KI18n/KLocalizedString>
#include <QtConcurrent/QtConcurrent>
#include <QBuffer> #include <QBuffer>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPixmap>
#include <math.h> #include <math.h>
@ -27,10 +31,13 @@
#include "awdebug.h" #include "awdebug.h"
AWDataAggregator::AWDataAggregator(QObject *parent) AWDataAggregator::AWDataAggregator(QObject *parent, QThreadPool *pThreadPool)
: QObject(parent) : QObject(parent),
threadPool(pThreadPool)
{ {
qCDebug(LOG_AW); qCDebug(LOG_AW);
// required by signals
qRegisterMetaType<QHash<QString, QString>>("QHash<QString, QString>");
initScene(); initScene();
@ -154,27 +161,13 @@ void AWDataAggregator::dataUpdate(const QHash<QString, QString> values)
{ {
qCDebug(LOG_AW); qCDebug(LOG_AW);
// battery update requires info is AC online or not #ifdef BUILD_FUTURE
setData(values[QString("ac")] == configuration[QString("acOnline")], QtConcurrent::run(threadPool, [this, values]() {
QString("batTooltip"), values[QString("bat")].toFloat()); setData(values);
// usual case });
setData(QString("cpuTooltip"), values[QString("cpu")].toFloat(), 90.0); #else /* BUILD_FUTURE */
setData(QString("cpuclTooltip"), values[QString("cpucl")].toFloat()); setData(values);
setData(QString("memTooltip"), values[QString("mem")].toFloat(), 90.0); #endif /* BUILD_FUTURE */
setData(QString("swapTooltip"), values[QString("swap")].toFloat(), 0.0);
setData(QString("downTooltip"), values[QString("downkb")].toFloat());
setData(QString("upTooltip"), values[QString("upkb")].toFloat());
// additional check for network device
[this](const QString value) {
checkValue(QString("netdev"), currentNetworkDevice, value);
currentNetworkDevice = value;
}(values[QString("netdev")]);
// additional check for GPU load
[this](const float value) {
checkValue(QString("gpu"), value, 90.0);
currentGPULoad = value;
}(values[QString("gpu")].toFloat());
emit(toolTipPainted(htmlImage(tooltipImage()))); emit(toolTipPainted(htmlImage(tooltipImage())));
} }
@ -205,7 +198,7 @@ void AWDataAggregator::checkValue(const QString source, const QString current,
qCDebug(LOG_AW) << "Current value" << current; qCDebug(LOG_AW) << "Current value" << current;
qCDebug(LOG_AW) << "Received value" << received; qCDebug(LOG_AW) << "Received value" << received;
if ((m_enablePopup) && (current != received)) if ((m_enablePopup) && (current != received) && (!received.isEmpty()))
return AWActions::sendNotification(QString("event"), notificationText(source, received)); return AWActions::sendNotification(QString("event"), notificationText(source, received));
} }
@ -262,6 +255,33 @@ QString AWDataAggregator::notificationText(const QString source, const QString v
} }
void AWDataAggregator::setData(const QHash< QString, QString > values)
{
qCDebug(LOG_AW);
// battery update requires info is AC online or not
setData(values[QString("ac")] == configuration[QString("acOnline")],
QString("batTooltip"), values[QString("bat")].toFloat());
// usual case
setData(QString("cpuTooltip"), values[QString("cpu")].toFloat(), 90.0);
setData(QString("cpuclTooltip"), values[QString("cpucl")].toFloat());
setData(QString("memTooltip"), values[QString("mem")].toFloat(), 90.0);
setData(QString("swapTooltip"), values[QString("swap")].toFloat(), 0.0);
setData(QString("downTooltip"), values[QString("downkb")].toFloat());
setData(QString("upTooltip"), values[QString("upkb")].toFloat());
// additional check for network device
[this](const QString value) {
checkValue(QString("netdev"), currentNetworkDevice, value);
currentNetworkDevice = value;
}(values[QString("netdev")]);
// additional check for GPU load
[this](const float value) {
checkValue(QString("gpu"), value, 90.0);
currentGPULoad = value;
}(values[QString("gpu")].toFloat());
}
void AWDataAggregator::setData(const QString source, float value, const float extremum) void AWDataAggregator::setData(const QString source, float value, const float extremum)
{ {
qCDebug(LOG_AW); qCDebug(LOG_AW);

View File

@ -19,18 +19,21 @@
#ifndef AWTOOLTIP_H #ifndef AWTOOLTIP_H
#define AWTOOLTIP_H #define AWTOOLTIP_H
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QObject> #include <QObject>
#include <QPixmap> #include <QVariant>
class QGraphicsScene;
class QGraphicsView;
class QPixmap;
class QThreadPool;
class AWDataAggregator : public QObject class AWDataAggregator : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AWDataAggregator(QObject *parent = nullptr); explicit AWDataAggregator(QObject *parent = nullptr, QThreadPool *pThreadPool = nullptr);
virtual ~AWDataAggregator(); virtual ~AWDataAggregator();
QList<float> getData(const QString key) const; QList<float> getData(const QString key) const;
QString htmlImage(const QPixmap source) const; QString htmlImage(const QPixmap source) const;
@ -41,7 +44,7 @@ signals:
void updateData(const QHash<QString, QString> values); void updateData(const QHash<QString, QString> values);
void toolTipPainted(const QString image) const; void toolTipPainted(const QString image) const;
private slots: public slots:
void dataUpdate(const QHash<QString, QString> values); void dataUpdate(const QHash<QString, QString> values);
private: private:
@ -53,6 +56,8 @@ private:
void initScene(); void initScene();
QString notificationText(const QString source, const float value) const; QString notificationText(const QString source, const float value) const;
QString notificationText(const QString source, const QString value) const; QString notificationText(const QString source, const QString value) const;
// main method
void setData(const QHash<QString, QString> values);
void setData(const QString source, float value, const float extremum = -1.0); void setData(const QString source, float value, const float extremum = -1.0);
// different signature for battery device // different signature for battery device
void setData(const bool dontInvert, const QString source, float value); void setData(const bool dontInvert, const QString source, float value);
@ -65,6 +70,7 @@ private:
QHash<QString, QList<float>> data; QHash<QString, QList<float>> data;
bool m_enablePopup = false; bool m_enablePopup = false;
QStringList requiredKeys; QStringList requiredKeys;
QThreadPool *threadPool = nullptr;
}; };

View File

@ -26,7 +26,6 @@
#include <QSettings> #include <QSettings>
#include <QStandardPaths> #include <QStandardPaths>
#include <QThread> #include <QThread>
#include <QThreadPool>
#include "awdebug.h" #include "awdebug.h"
#include "awkeysaggregator.h" #include "awkeysaggregator.h"
@ -47,21 +46,19 @@ AWKeys::AWKeys(QObject *parent)
// logging // logging
qSetMessagePattern(LOG_FORMAT); qSetMessagePattern(LOG_FORMAT);
aggregator = new AWKeysAggregator(this);
dataAggregator = new AWDataAggregator(this);
connect(this, SIGNAL(needToBeUpdated()), this, SLOT(dataUpdate()));
// transfer signal from AWDataAggregator object to QML ui
connect(dataAggregator, SIGNAL(toolTipPainted(const QString)),
this, SIGNAL(needToolTipToBeUpdated(const QString)));
#ifdef BUILD_FUTURE #ifdef BUILD_FUTURE
// queue limit. It may be configured by using QUEUE_LIMIT cmake limit flag.
// In other hand since I'm using global thread pool, it makes sense to limit
// queue by QThread::idealThreadCount() value
queueLimit = QUEUE_LIMIT == 0 ? QThread::idealThreadCount() : QUEUE_LIMIT;
// thread pool // thread pool
queueLimit = QThread::idealThreadCount();
threadPool = new QThreadPool(this); threadPool = new QThreadPool(this);
threadPool->setMaxThreadCount(queueLimit); threadPool->setMaxThreadCount(queueLimit);
#endif /* BUILD_FUTURE */ #endif /* BUILD_FUTURE */
aggregator = new AWKeysAggregator(this);
dataAggregator = new AWDataAggregator(this, threadPool);
// transfer signal from AWDataAggregator object to QML ui
connect(dataAggregator, SIGNAL(toolTipPainted(const QString)),
this, SIGNAL(needToolTipToBeUpdated(const QString)));
connect(this, SIGNAL(needToBeUpdated()), this, SLOT(dataUpdate()));
} }
@ -69,13 +66,15 @@ AWKeys::~AWKeys()
{ {
qCDebug(LOG_AW); qCDebug(LOG_AW);
// extensions
if (graphicalItems != nullptr) delete graphicalItems; if (graphicalItems != nullptr) delete graphicalItems;
if (extQuotes != nullptr) delete extQuotes; if (extQuotes != nullptr) delete extQuotes;
if (extScripts != nullptr) delete extScripts; if (extScripts != nullptr) delete extScripts;
if (extUpgrade != nullptr) delete extUpgrade; if (extUpgrade != nullptr) delete extUpgrade;
if (extWeather != nullptr) delete extWeather; if (extWeather != nullptr) delete extWeather;
delete threadPool; // core
if (threadPool != nullptr) delete threadPool;
delete aggregator; delete aggregator;
delete dataAggregator; delete dataAggregator;
} }
@ -90,17 +89,23 @@ void AWKeys::initDataAggregator(const QVariantMap tooltipParams)
} }
void AWKeys::initKeys(const QString currentPattern) void AWKeys::initKeys(const QString currentPattern, const int limit)
{ {
qCDebug(LOG_AW); qCDebug(LOG_AW);
qCDebug(LOG_AW) << "Pattern" << currentPattern; qCDebug(LOG_AW) << "Pattern" << currentPattern;
// init // init
m_pattern = currentPattern; m_pattern = currentPattern;
#ifdef BUILD_FUTURE
// queue limit. It may be configured by using QUEUE_LIMIT cmake limit flag.
// In other hand since I'm using global thread pool, it makes sense to limit
// queue by QThread::idealThreadCount() value
queueLimit = limit == 0 ? QThread::idealThreadCount() : limit;
threadPool->setMaxThreadCount(queueLimit);
#endif /* BUILD_FUTURE */
// update network and hdd list // update network and hdd list
addKeyToCache(QString("hdd")); addKeyToCache(QString("hdd"));
addKeyToCache(QString("net")); addKeyToCache(QString("net"));
loadKeysFromCache();
} }
@ -319,8 +324,12 @@ void AWKeys::dataUpdateReceived(const QString sourceName, const QVariantMap data
qCDebug(LOG_AW) << "Source" << sourceName; qCDebug(LOG_AW) << "Source" << sourceName;
qCDebug(LOG_AW) << "Data" << data; qCDebug(LOG_AW) << "Data" << data;
// run concurrent data update // we will update text even if queue limit is reached
if (sourceName == QString("update")) return emit(needToBeUpdated());
#ifdef BUILD_FUTURE #ifdef BUILD_FUTURE
// run concurrent data update
if ((lock = ((lock) && (queue > 0)))) return;
QtConcurrent::run(threadPool, [this, sourceName, data]() { QtConcurrent::run(threadPool, [this, sourceName, data]() {
return setDataBySource(sourceName, data); return setDataBySource(sourceName, data);
}); });
@ -393,8 +402,16 @@ void AWKeys::dataUpdate()
{ {
qCDebug(LOG_AW); qCDebug(LOG_AW);
#ifdef BUILD_FUTURE
QFuture<QString> text = QtConcurrent::run(threadPool, [this]() {
calculateValues();
return parsePattern(m_pattern);
});
#else /* BUILD_FUTURE */
calculateValues(); calculateValues();
emit(needTextToBeUpdated(parsePattern(m_pattern))); QString text = parsePattern(m_pattern);
#endif /* BUILD_FUTURE */
emit(needTextToBeUpdated(text));
emit(dataAggregator->updateData(values)); emit(dataAggregator->updateData(values));
} }
@ -442,7 +459,7 @@ void AWKeys::reinitKeys()
QStringList allKeys = dictKeys(); QStringList allKeys = dictKeys();
// not documented feature - place all available tags // not documented feature - place all available tags
m_pattern = m_pattern.replace(QString("$ALL"), [allKeys](){ m_pattern = m_pattern.replace(QString("$ALL"), [allKeys]() {
QStringList strings; QStringList strings;
foreach(QString tag, allKeys) foreach(QString tag, allKeys)
strings.append(QString("%1: $%1").arg(tag)); strings.append(QString("%1: $%1").arg(tag));
@ -661,8 +678,6 @@ void AWKeys::setDataBySource(const QString sourceName, const QVariantMap data)
qCDebug(LOG_AW) << "Data" << data; qCDebug(LOG_AW) << "Data" << data;
#ifdef BUILD_FUTURE #ifdef BUILD_FUTURE
// check if data stream is locked
if ((lock = ((lock) && (queue > 0)))) return;
// drop if limits are reached // drop if limits are reached
if (++queue > queueLimit) { if (++queue > queueLimit) {
qCWarning(LOG_AW) << "Messages queue" << queue-- << "more than limits" << queueLimit; qCWarning(LOG_AW) << "Messages queue" << queue-- << "more than limits" << queueLimit;
@ -677,15 +692,13 @@ void AWKeys::setDataBySource(const QString sourceName, const QVariantMap data)
tags = aggregator->registerSource(sourceName, data[QString("units")].toString()); tags = aggregator->registerSource(sourceName, data[QString("units")].toString());
// update data or drop source if there are no matches // update data or drop source if there are no matches
if (sourceName == QString("update")) { if (tags.isEmpty()) {
emit(needToBeUpdated());
} else if (tags.isEmpty()) {
qCDebug(LOG_AW) << "Source" << sourceName << "not found"; qCDebug(LOG_AW) << "Source" << sourceName << "not found";
emit(dropSourceFromDataengine(sourceName)); emit(dropSourceFromDataengine(sourceName));
} else { } else {
// HACK workaround for time values which are stored in the different path // HACK workaround for time values which are stored in the different path
QVariant value = sourceName == QString("Local") ? data[QString("DateTime")] : data[QString("value")]; QVariant value = sourceName == QString("Local") ? data[QString("DateTime")] : data[QString("value")];
std::for_each(tags.cbegin(), tags.cend(), [this, value](const QString tag){ std::for_each(tags.cbegin(), tags.cend(), [this, value](const QString tag) {
values[tag] = aggregator->formater(value, tag); values[tag] = aggregator->formater(value, tag);
}); });
} }

View File

@ -42,7 +42,7 @@ public:
virtual ~AWKeys(); virtual ~AWKeys();
Q_INVOKABLE void initDataAggregator(const QVariantMap tooltipParams); Q_INVOKABLE void initDataAggregator(const QVariantMap tooltipParams);
Q_INVOKABLE void initKeys(const QString currentPattern); Q_INVOKABLE void initKeys(const QString currentPattern, const int limit);
Q_INVOKABLE void setAggregatorProperty(const QString key, const QVariant value); Q_INVOKABLE void setAggregatorProperty(const QString key, const QVariant value);
Q_INVOKABLE void setWrapNewLines(const bool wrap = false); Q_INVOKABLE void setWrapNewLines(const bool wrap = false);
// keys // keys