Optimize DataSource

- Use QQmlParserStatus to provide event compression for setupDate() method
- Re-introduce interval alignment
- Cache sources and emit change signal only when it has actually changed

Changelog: DataSource can now align polling to full minutes

REVIEW: 122470
This commit is contained in:
Kai Uwe Broulik 2015-02-16 14:55:49 +01:00
parent 073b83b440
commit 5cfe737618
2 changed files with 110 additions and 51 deletions

View File

@ -26,7 +26,9 @@ namespace Plasma
{
DataSource::DataSource(QObject *parent)
: QObject(parent),
m_ready(false),
m_interval(0),
m_intervalAlignment(Plasma::Types::NoAlignment),
m_dataEngine(0),
m_dataEngineConsumer(0)
{
@ -35,6 +37,17 @@ DataSource::DataSource(QObject *parent)
setObjectName("DataSource");
}
void DataSource::classBegin()
{
}
void DataSource::componentComplete()
{
m_ready = true;
setupData();
}
void DataSource::setConnectedSources(const QStringList &sources)
{
bool sourcesChanged = false;
@ -43,7 +56,7 @@ void DataSource::setConnectedSources(const QStringList &sources)
sourcesChanged = true;
if (m_dataEngine) {
m_connectedSources.append(source);
m_dataEngine->connectSource(source, this, m_interval);
m_dataEngine->connectSource(source, this, m_interval, m_intervalAlignment);
emit sourceConnected(source);
}
}
@ -73,7 +86,48 @@ void DataSource::setEngine(const QString &e)
}
m_engine = e;
setupData();
if (m_engine.isEmpty()) {
emit engineChanged();
return;
}
m_dataEngineConsumer = new Plasma::DataEngineConsumer();
Plasma::DataEngine *engine = dataEngine(m_engine);
if (!engine) {
qWarning() << "DataEngine" << m_engine << "not found";
emit engineChanged();
return;
}
if (m_dataEngine) {
m_dataEngine->disconnect(this);
// Deleting the consumer triggers the reference counting
delete m_dataEngineConsumer;
m_dataEngineConsumer = 0;
}
/*
* It is due little explanation why this is a queued connection:
* If sourceAdded arrives immediately, in the case we have a datamodel
* with items at source level we connect too soon (before setData for
* all roles is done), having a dataupdated in the datamodel with only
* the first role, killing off the other roles.
* Besides causing a model reset more, unfortunately setRoleNames can be done a single time, so is not possible adding new roles after the
* first setRoleNames() is called.
* This fixes engines that have 1 item per source like the
* recommendations engine.
*/
m_dataEngine = engine;
connect(m_dataEngine, SIGNAL(sourceAdded(QString)), this, SLOT(updateSources()), Qt::QueuedConnection);
connect(m_dataEngine, SIGNAL(sourceRemoved(QString)), this, SLOT(updateSources()));
connect(m_dataEngine, SIGNAL(sourceAdded(QString)), this, SIGNAL(sourceAdded(QString)), Qt::QueuedConnection);
connect(m_dataEngine, SIGNAL(sourceRemoved(QString)), this, SLOT(removeSource(QString)));
connect(m_dataEngine, SIGNAL(sourceRemoved(QString)), this, SIGNAL(sourceRemoved(QString)));
updateSources();
emit engineChanged();
}
@ -88,56 +142,30 @@ void DataSource::setInterval(const int interval)
emit intervalChanged();
}
//TODO: event compression for this
void DataSource::setIntervalAlignment(Plasma::Types::IntervalAlignment intervalAlignment)
{
if (intervalAlignment == m_intervalAlignment) {
return;
}
m_intervalAlignment = intervalAlignment;
setupData();
emit intervalAlignmentChanged();
}
void DataSource::setupData()
{
if (!m_ready) {
return;
}
// qDebug() << " loading engine " << m_engine;
//FIXME: should all services be deleted just because we're changing the interval, etc?
qDeleteAll(m_services);
m_services.clear();
if (m_engine.isEmpty()) {
return;
}
m_dataEngineConsumer = new Plasma::DataEngineConsumer();
Plasma::DataEngine *engine = dataEngine(m_engine);
if (!engine) {
qWarning() << "DataEngine" << m_engine << "not found";
return;
}
// qDebug() << "Engine loaed .. . " << m_engine << m_dataEngineConsumer;
if (engine != m_dataEngine) {
if (m_dataEngine) {
m_dataEngine->disconnect(this);
// Deleting the consumer triggers the reference counting
delete m_dataEngineConsumer;
m_dataEngineConsumer = 0;
}
/*
* It is due little explanation why this is a queued connection:
* If sourceAdded arrives immediately, in the case we have a datamodel
* with items at source level we connect too soon (before setData for
* all roles is done), having a dataupdated in the datamodel with only
* the first role, killing off the other roles.
* Besides causing a model reset more, unfortunately setRoleNames can be done a single time, so is not possible adding new roles after the
* first setRoleNames() is called.
* This fixes engines that have 1 item per source like the
* recommendations engine.
*/
m_dataEngine = engine;
connect(m_dataEngine, SIGNAL(sourceAdded(QString)), this, SIGNAL(sourcesChanged()), Qt::QueuedConnection);
connect(m_dataEngine, SIGNAL(sourceRemoved(QString)), this, SIGNAL(sourcesChanged()));
connect(m_dataEngine, SIGNAL(sourceAdded(QString)), this, SIGNAL(sourceAdded(QString)), Qt::QueuedConnection);
connect(m_dataEngine, SIGNAL(sourceRemoved(QString)), this, SLOT(removeSource(QString)));
connect(m_dataEngine, SIGNAL(sourceRemoved(QString)), this, SIGNAL(sourceRemoved(QString)));
}
foreach (const QString &source, m_connectedSources) {
m_dataEngine->connectSource(source, this, m_interval);
m_dataEngine->connectSource(source, this, m_interval, m_intervalAlignment);
emit sourceConnected(source);
}
}
@ -210,7 +238,7 @@ void DataSource::connectSource(const QString &source)
m_connectedSources.append(source);
if (m_dataEngine) {
m_dataEngine->connectSource(source, this, m_interval);
m_dataEngine->connectSource(source, this, m_interval, m_intervalAlignment);
emit sourceConnected(source);
emit connectedSourcesChanged();
}
@ -226,4 +254,17 @@ void DataSource::disconnectSource(const QString &source)
}
}
void DataSource::updateSources()
{
QStringList sources;
if (m_dataEngine) {
sources = m_dataEngine->sources();
}
if (sources != m_sources) {
m_sources = sources;
emit sourcesChanged();
}
}
}

View File

@ -26,6 +26,7 @@
#include <QObject>
#include <QtQml>
#include <QQmlPropertyMap>
#include <QQmlParserStatus>
#include <Plasma/DataEngineConsumer>
#include <Plasma/DataEngine>
@ -40,9 +41,11 @@ class DataEngine;
* @class DataSource
* @short Provides data from a range of plugins
*/
class DataSource : public QObject, DataEngineConsumer
class DataSource : public QObject, public QQmlParserStatus, DataEngineConsumer
{
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
public:
enum Change {
NoChange = 0,
@ -54,6 +57,10 @@ public:
typedef QMap<QString, QVariant> Data;
DataSource(QObject *parent = 0);
void classBegin();
void componentComplete();
/**
* true if the connection to the Plasma DataEngine is valid
*/
@ -73,6 +80,16 @@ public:
}
void setInterval(const int interval);
/**
* The interval to align polling to
*/
Q_PROPERTY(Plasma::Types::IntervalAlignment intervalAlignment READ intervalAlignment WRITE setIntervalAlignment NOTIFY intervalAlignmentChanged)
Plasma::Types::IntervalAlignment intervalAlignment() const
{
return m_intervalAlignment;
}
void setIntervalAlignment(Plasma::Types::IntervalAlignment intervalAlignment);
/**
* Plugin name of the Plasma DataEngine
*/
@ -100,11 +117,7 @@ public:
Q_PROPERTY(QStringList sources READ sources NOTIFY sourcesChanged)
QStringList sources() const
{
if (m_dataEngine) {
return m_dataEngine->sources();
} else {
return QStringList();
}
return m_sources;
}
/**
@ -151,6 +164,7 @@ public Q_SLOTS:
protected Q_SLOTS:
void removeSource(const QString &source);
void setupData();
void updateSources();
Q_SIGNALS:
void newData(const QString &sourceName, const QVariantMap &data);
@ -159,19 +173,23 @@ Q_SIGNALS:
void sourceConnected(const QString &source);
void sourceDisconnected(const QString &source);
void intervalChanged();
void intervalAlignmentChanged();
void engineChanged();
void dataChanged();
void connectedSourcesChanged();
void sourcesChanged();
private:
bool m_ready;
QString m_id;
int m_interval;
Plasma::Types::IntervalAlignment m_intervalAlignment;
QString m_engine;
QQmlPropertyMap *m_data;
QQmlPropertyMap *m_models;
Plasma::DataEngine *m_dataEngine;
Plasma::DataEngineConsumer *m_dataEngineConsumer;
QStringList m_sources;
QStringList m_connectedSources;
QStringList m_oldSources;
QStringList m_newSources;