50
QStringList convertUris(const QList<QUrl>& uris) {
53
template<typename T> QVariantList nodeListToVariantList(const T &nodes) {
55
list.reserve(nodes.size());
56
foreach( const Soprano::Node &n, nodes ) {
57
list << nodeToVariant(n).variant();
63
QString convertUri(const QUrl& uri) {
64
return KUrl(uri).url();
67
template<typename T> QStringList convertUris(const T& uris) {
52
69
foreach(const QUrl& uri, uris)
53
sl << KUrl(uri).url();
70
sl << convertUri(uri);
74
QUrl convertUri(const QString& s) {
57
78
QList<QUrl> convertUris(const QStringList& uris) {
59
80
foreach(const QString& uri, uris)
81
sl << convertUri(uri);
65
Nepomuk::ResourceWatcherManager::ResourceWatcherManager(QObject* parent)
86
* Returns true if the given hash contains at least one of the possible combinations of con and "c in candidates".
88
bool hashContainsAtLeastOneOf(Nepomuk::ResourceWatcherConnection* con, const QSet<QUrl>& candidates, const QMultiHash<QUrl, Nepomuk::ResourceWatcherConnection*>& hash) {
89
for(QSet<QUrl>::const_iterator it = candidates.constBegin();
90
it != candidates.constEnd(); ++it) {
91
if(hash.contains(*it, con)) {
100
Nepomuk::ResourceWatcherManager::ResourceWatcherManager(DataManagementModel* parent)
66
101
: QObject(parent),
67
103
m_connectionCount(0)
69
105
QDBusConnection::sessionBus().registerObject("/resourcewatcher", this, QDBusConnection::ExportScriptableSlots);
84
120
void Nepomuk::ResourceWatcherManager::addStatement(const Soprano::Statement& st)
86
addProperty( st.subject(), st.predicate().uri(), st.object() );
123
//addProperty( st.subject(), st.predicate().uri(), QList<Soprano::Node>() << st.object() );
89
void Nepomuk::ResourceWatcherManager::addProperty(const Soprano::Node res, const QUrl& property, const Soprano::Node& value)
127
void Nepomuk::ResourceWatcherManager::changeProperty(const QUrl &res, const QUrl &property, const QList<Soprano::Node> &addedValues, const QList<Soprano::Node> &removedValues)
91
typedef ResourceWatcherConnection RWC;
93
// FIXME: take care of duplicate signals!
129
kDebug() << res << property << addedValues << removedValues;
132
// We only need the resource types if any connections are watching types.
135
if(!m_typeHash.isEmpty()) {
136
types = getTypes(res);
141
// special case: rdf:type
143
if(property == RDF::type()) {
144
QSet<QUrl> addedTypes, removedTypes;
145
for(QList<Soprano::Node>::const_iterator it = addedValues.constBegin();
146
it != addedValues.constEnd(); ++it) {
147
addedTypes << it->uri();
149
for(QList<Soprano::Node>::const_iterator it = removedValues.constBegin();
150
it != removedValues.constEnd(); ++it) {
151
removedTypes << it->uri();
153
changeTypes(res, types, addedTypes, removedTypes);
157
// first collect all the connections we need to emit the signals for
158
QSet<ResourceWatcherConnection*> connections;
96
161
// Emit signals for all the connections that are only watching specific resources
98
QSet<RWC*> resConnections;
99
QList<RWC*> connections = m_resHash.values( res.uri() );
100
foreach( RWC* con, connections ) {
101
if( !con->hasProperties() ) {
102
emit con->propertyAdded( KUrl(res.uri()).url(),
104
nodeToVariant(value) );
107
resConnections << con;
163
foreach( ResourceWatcherConnection* con, m_resHash.values( res ) ) {
164
if( m_propHash.contains(property, con) ||
165
!m_propHash.values().contains(con) ) {
112
172
// Emit signals for the connections that are watching specific resources and properties
114
QList<RWC*> propConnections = m_propHash.values( property );
115
foreach( RWC* con, propConnections ) {
116
QSet<RWC*>::const_iterator it = resConnections.constFind( con );
117
if( it != resConnections.constEnd() ) {
118
emit con->propertyAdded( KUrl(res.uri()).url(),
120
nodeToVariant(value) );
125
// Emit type + property signals
127
//TODO: Implement me! ( How? )
174
foreach( ResourceWatcherConnection* con, m_propHash.values( property ) ) {
176
// Emit for those connections which watch the property and either no
177
// type or once of the types of the resource.
178
// Only query the types if we have any type watching connections.
180
bool conIsWatchingResType = !m_typeHash.values().contains(con);
181
foreach(const QUrl& type, types) {
182
if(m_typeHash.contains(type, con)) {
183
conIsWatchingResType = true;
188
if( !m_resHash.values().contains(con) && conIsWatchingResType ) {
196
// Emit signals for all connections which watch one of the types of the resource
197
// but no properties (that is handled above).
199
foreach(const QUrl& type, types) {
200
foreach(ResourceWatcherConnection* con, m_typeHash.values(type)) {
201
if(!m_propHash.values(property).contains(con)) {
209
// Finally emit the signals for all connections
211
foreach(ResourceWatcherConnection* con, connections) {
212
emit con->propertyChanged( convertUri(res),
213
convertUri(property),
214
nodeListToVariantList(addedValues),
215
nodeListToVariantList(removedValues) );
216
if(!addedValues.isEmpty()) {
217
emit con->propertyAdded(convertUri(res),
218
convertUri(property),
219
nodeListToVariantList(addedValues));
221
if(!removedValues.isEmpty()) {
222
emit con->propertyRemoved(convertUri(res),
223
convertUri(property),
224
nodeListToVariantList(removedValues));
130
void Nepomuk::ResourceWatcherManager::removeProperty(const Soprano::Node res, const QUrl& property, const Soprano::Node& value)
229
void Nepomuk::ResourceWatcherManager::changeProperty(const QMultiHash< QUrl, Soprano::Node >& oldValues,
230
const QUrl& property,
231
const QList<Soprano::Node>& nodes)
132
typedef ResourceWatcherConnection RWC;
135
// Emit signals for all the connections that are only watching specific resources
137
QSet<RWC*> resConnections;
138
QList<RWC*> connections = m_resHash.values( res.uri() );
139
foreach( RWC* con, connections ) {
140
if( !con->hasProperties() ) {
141
emit con->propertyRemoved( KUrl(res.uri()).url(),
143
nodeToVariant(value) );
146
resConnections << con;
151
// Emit signals for the conn2ections that are watching specific resources and properties
153
QList<RWC*> propConnections = m_propHash.values( property );
154
foreach( RWC* con, propConnections ) {
155
QSet<RWC*>::const_iterator it = resConnections.constFind( con );
156
if( it != resConnections.constEnd() ) {
157
emit con->propertyRemoved( KUrl(res.uri()).url(),
159
nodeToVariant(value) );
233
QList<QUrl> uniqueKeys = oldValues.keys();
234
foreach( const QUrl resUri, uniqueKeys ) {
235
const QList<Soprano::Node> old = oldValues.values( resUri );
236
changeProperty(resUri, property, old, nodes);
251
327
removeConnectionFromHash( m_typeHash, con );
330
void Nepomuk::ResourceWatcherManager::setResources(Nepomuk::ResourceWatcherConnection *conn, const QStringList &resources)
332
const QSet<QUrl> newRes = convertUris(resources).toSet();
333
const QSet<QUrl> oldRes = m_resHash.keys(conn).toSet();
335
foreach(const QUrl& res, newRes - oldRes) {
336
m_resHash.insert(res, conn);
338
foreach(const QUrl& res, oldRes - newRes) {
339
m_resHash.remove(res, conn);
343
void Nepomuk::ResourceWatcherManager::addResource(Nepomuk::ResourceWatcherConnection *conn, const QString &resource)
345
m_resHash.insert(convertUri(resource), conn);
348
void Nepomuk::ResourceWatcherManager::removeResource(Nepomuk::ResourceWatcherConnection *conn, const QString &resource)
350
m_resHash.remove(convertUri(resource), conn);
353
void Nepomuk::ResourceWatcherManager::setProperties(Nepomuk::ResourceWatcherConnection *conn, const QStringList &properties)
355
const QSet<QUrl> newprop = convertUris(properties).toSet();
356
const QSet<QUrl> oldprop = m_propHash.keys(conn).toSet();
358
foreach(const QUrl& prop, newprop - oldprop) {
359
m_propHash.insert(prop, conn);
361
foreach(const QUrl& prop, oldprop - newprop) {
362
m_propHash.remove(prop, conn);
366
void Nepomuk::ResourceWatcherManager::addProperty(Nepomuk::ResourceWatcherConnection *conn, const QString &property)
368
m_propHash.insert(convertUri(property), conn);
371
void Nepomuk::ResourceWatcherManager::removeProperty(Nepomuk::ResourceWatcherConnection *conn, const QString &property)
373
m_propHash.remove(convertUri(property), conn);
376
void Nepomuk::ResourceWatcherManager::setTypes(Nepomuk::ResourceWatcherConnection *conn, const QStringList &types)
378
const QSet<QUrl> newtype = convertUris(types).toSet();
379
const QSet<QUrl> oldtype = m_typeHash.keys(conn).toSet();
381
foreach(const QUrl& type, newtype - oldtype) {
382
m_typeHash.insert(type, conn);
384
foreach(const QUrl& type, oldtype - newtype) {
385
m_typeHash.remove(type, conn);
389
void Nepomuk::ResourceWatcherManager::addType(Nepomuk::ResourceWatcherConnection *conn, const QString &type)
391
m_typeHash.insert(convertUri(type), conn);
394
void Nepomuk::ResourceWatcherManager::removeType(Nepomuk::ResourceWatcherConnection *conn, const QString &type)
396
m_typeHash.remove(convertUri(type), conn);
399
QSet<QUrl> Nepomuk::ResourceWatcherManager::getTypes(const Soprano::Node &res) const
402
Soprano::StatementIterator it = m_model->listStatements(res, RDF::type(), Soprano::Node());
404
types.insert(it.current().object().uri());
409
// FIXME: also take super-classes into account
410
void Nepomuk::ResourceWatcherManager::changeTypes(const QUrl &res, const QSet<QUrl>& resTypes, const QSet<QUrl> &addedTypes, const QSet<QUrl> &removedTypes)
412
// first collect all the connections we need to emit the signals for
413
QSet<ResourceWatcherConnection*> addConnections, removeConnections;
415
// all connections watching the resource and not a special property
416
// and no special type or one of the changed types
417
foreach( ResourceWatcherConnection* con, m_resHash.values( res ) ) {
418
if( m_propHash.contains(RDF::type(), con) ||
419
!m_propHash.values().contains(con) ) {
420
if(!addedTypes.isEmpty() &&
421
connectionWatchesOneType(con, addedTypes)) {
422
addConnections << con;
424
if(!removedTypes.isEmpty() &&
425
connectionWatchesOneType(con, removedTypes)) {
426
removeConnections << con;
431
// all connections watching one of the types and no special resource or property
432
if(!addedTypes.isEmpty()) {
433
foreach(const QUrl& type, addedTypes + resTypes) {
434
foreach(ResourceWatcherConnection* con, m_typeHash.values(type)) {
435
if(!m_resHash.values().contains(con) &&
436
!m_propHash.values().contains(con)) {
437
addConnections << con;
442
if(!removedTypes.isEmpty()) {
443
foreach(const QUrl& type, removedTypes + resTypes) {
444
foreach(ResourceWatcherConnection* con, m_typeHash.values(type)) {
445
if(!m_resHash.values().contains(con) &&
446
!m_propHash.values().contains(con)) {
447
removeConnections << con;
453
// all connections watching rdf:type
454
foreach(ResourceWatcherConnection* con, m_propHash.values(RDF::type())) {
455
if(!m_resHash.values().contains(con) ) {
456
if(connectionWatchesOneType(con, addedTypes + resTypes)) {
457
addConnections << con;
459
if(connectionWatchesOneType(con, removedTypes + resTypes)) {
460
removeConnections << con;
465
// finally emit the actual signals
466
if(!addedTypes.isEmpty()) {
467
foreach(ResourceWatcherConnection* con, addConnections) {
468
emit con->resourceTypesAdded(convertUri(res),
469
convertUris(addedTypes));
472
if(!removedTypes.isEmpty()) {
473
foreach(ResourceWatcherConnection* con, removeConnections) {
474
emit con->resourceTypesRemoved(convertUri(res),
475
convertUris(removedTypes));
480
bool Nepomuk::ResourceWatcherManager::connectionWatchesOneType(Nepomuk::ResourceWatcherConnection *con, const QSet<QUrl> &types) const
482
return !m_typeHash.values().contains(con) || hashContainsAtLeastOneOf(con, types, m_typeHash);
254
485
#include "resourcewatchermanager.moc"