• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

Nepomuk-Core

  • sources
  • kde-4.12
  • kdelibs
  • nepomuk-core
  • services
  • storage
  • query
folder.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2008-2012 Sebastian Trueg <trueg@kde.org>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License version 2 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Library General Public License for more details.
12 
13  You should have received a copy of the GNU Library General Public License
14  along with this library; see the file COPYING.LIB. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 */
18 
19 #include "folder.h"
20 #include "folderconnection.h"
21 #include "queryservice.h"
22 #include "countqueryrunnable.h"
23 #include "searchrunnable.h"
24 
25 #include "resource.h"
26 #include "resourcemanager.h"
27 
28 #include "andterm.h"
29 #include "orterm.h"
30 #include "resourcetypeterm.h"
31 #include "optionalterm.h"
32 #include "comparisonterm.h"
33 #include "negationterm.h"
34 #include "resourcewatcher.h"
35 
36 #include <Soprano/Model>
37 
38 #include <KDebug>
39 
40 #include <QtCore/QThreadPool>
41 #include <QtCore/QMutexLocker>
42 #include <QtDBus/QDBusConnection>
43 
44 
45 Nepomuk2::Query::Folder::Folder( Soprano::Model* model, const Query& query, QObject* parent )
46  : QObject( parent ),
47  m_isSparqlQueryFolder( false ),
48  m_query( query ),
49  m_model( model ),
50  m_currentSearchRunnable( 0 ),
51  m_currentCountQueryRunnable( 0 )
52 {
53  init();
54 }
55 
56 
57 Nepomuk2::Query::Folder::Folder( Soprano::Model* model, const QString& query,
58  const RequestPropertyMap& requestProps, QObject* parent )
59  : QObject( parent ),
60  m_isSparqlQueryFolder( true ),
61  m_sparqlQuery( query ),
62  m_requestProperties( requestProps ),
63  m_model( model ),
64  m_currentSearchRunnable( 0 ),
65  m_currentCountQueryRunnable( 0 )
66 {
67  init();
68 }
69 
70 namespace {
71  using namespace Nepomuk2::Query;
72  using namespace Nepomuk2;
73 
74  void initWatcherForGroupTerms(ResourceWatcher* watcher, const GroupTerm& groupTerm, bool& emptyProperty);
75 
76  void initWatcherForTerm(ResourceWatcher* watcher, const Term& term, bool &emptyProperty ) {
77  if( term.isAndTerm() )
78  initWatcherForGroupTerms( watcher, term.toAndTerm(), emptyProperty );
79  else if( term.isOrTerm() )
80  initWatcherForGroupTerms( watcher, term.toOrTerm(), emptyProperty );
81  else if( term.isOptionalTerm() )
82  initWatcherForTerm( watcher, term.toOptionalTerm().subTerm(), emptyProperty );
83  else if( term.isNegationTerm() )
84  initWatcherForTerm( watcher, term.toNegationTerm().subTerm(), emptyProperty );
85  //if( term.isResourceTypeTerm() ) is not managed: we continue to watch all types.
86  else if( term.isComparisonTerm() ) {
87  const QUrl prop = term.toComparisonTerm().property().uri();
88  if( prop.isEmpty() ) {
89  emptyProperty = true;
90  }
91  else {
92  watcher->addProperty( term.toComparisonTerm().property().uri() );
93  }
94  }
95  }
96 
97  void initWatcherForGroupTerms(ResourceWatcher* watcher, const GroupTerm& groupTerm, bool &emptyProperty) {
98  QList<Term> terms = groupTerm.subTerms();
99  foreach(const Term& term, terms) {
100  initWatcherForTerm( watcher, term, emptyProperty );
101  }
102  }
103 
104  void initWatcherForQuery(ResourceWatcher* watcher, const Nepomuk2::Query::Query& query) {
105  // The empty property is for comparison terms which do not have a property
106  // in that case we want to monitor all properties
107  bool emptyProperty = false;
108  initWatcherForTerm( watcher, query.term(), emptyProperty );
109  if( emptyProperty )
110  watcher->setProperties( QList<Types::Property>() );
111  }
112 }
113 
114 
115 void Nepomuk2::Query::Folder::init()
116 {
117  m_resultCount = -1;
118  m_initialListingDone = false;
119  m_storageChanged = false;
120 
121  m_updateTimer.setSingleShot( true );
122  m_updateTimer.setInterval( 2000 );
123 
124  ResourceWatcher* watcher = new ResourceWatcher( this );
125  initWatcherForQuery( watcher, m_query );
126 
127  connect( watcher, SIGNAL(propertyAdded(Nepomuk2::Resource,Nepomuk2::Types::Property,QVariant)),
128  this, SLOT(slotStorageChanged()) );
129  connect( watcher, SIGNAL(propertyRemoved(Nepomuk2::Resource,Nepomuk2::Types::Property,QVariant)),
130  this, SLOT(slotStorageChanged()) );
131  connect( watcher, SIGNAL(resourceCreated(Nepomuk2::Resource,QList<QUrl>)),
132  this, SLOT(slotStorageChanged()) );
133  connect( watcher, SIGNAL(resourceRemoved(QUrl,QList<QUrl>)),
134  this, SLOT(slotStorageChanged()) );
135  connect( watcher, SIGNAL(resourceTypeAdded(Nepomuk2::Resource,Nepomuk2::Types::Class)),
136  this, SLOT(slotStorageChanged()) );
137  connect( watcher, SIGNAL(resourceTypeRemoved(Nepomuk2::Resource,Nepomuk2::Types::Class)),
138  this, SLOT(slotStorageChanged()) );
139  watcher->start();
140 
141  connect( &m_updateTimer, SIGNAL( timeout() ),
142  this, SLOT( slotUpdateTimeout() ) );
143 }
144 
145 
146 Nepomuk2::Query::Folder::~Folder()
147 {
148  if( m_currentSearchRunnable ){
149  m_currentSearchRunnable->cancel();
150  //Zero the pointers in case we somehow end up here again
151  m_currentSearchRunnable = 0;
152  }
153  if( m_currentCountQueryRunnable ){
154  m_currentCountQueryRunnable->cancel();
155  m_currentCountQueryRunnable = 0;
156  }
157 
158  // cannot use qDeleteAll since deleting a connection changes m_connections
159  while ( !m_connections.isEmpty() )
160  delete m_connections.first();
161 }
162 
163 
164 void Nepomuk2::Query::Folder::update()
165 {
166  if ( !m_currentSearchRunnable ) {
167  m_currentSearchRunnable = new SearchRunnable( m_model, sparqlQuery(), requestPropertyMap() );
168  // Enforcing queued connections cause the SearchRunnable will be running in its own thread
169  connect( m_currentSearchRunnable, SIGNAL(newResult(Nepomuk2::Query::Result)),
170  this, SLOT(addResult(Nepomuk2::Query::Result)), Qt::QueuedConnection );
171  connect( m_currentSearchRunnable, SIGNAL(listingFinished()),
172  this, SLOT(listingFinished()), Qt::QueuedConnection );
173 
174  QueryService::searchThreadPool()->start( m_currentSearchRunnable, 1 );
175 
176  // we only need the count for initialListingDone
177  // count with a limit is pointless since Virtuoso will ignore the limit
178  if ( !m_initialListingDone &&
179  !m_isSparqlQueryFolder &&
180  m_query.limit() == 0 ) {
181  m_currentCountQueryRunnable = new CountQueryRunnable( m_model, query() );
182  connect( m_currentCountQueryRunnable, SIGNAL(countQueryFinished(int)),
183  this, SLOT(countQueryFinished(int)), Qt::QueuedConnection );
184 
185  QueryService::searchThreadPool()->start( m_currentCountQueryRunnable, 0 );
186  }
187  }
188 }
189 
190 
191 QList<Nepomuk2::Query::Result> Nepomuk2::Query::Folder::entries() const
192 {
193  return m_results.values();
194 }
195 
196 
197 bool Nepomuk2::Query::Folder::initialListingDone() const
198 {
199  return m_initialListingDone;
200 }
201 
202 
203 QString Nepomuk2::Query::Folder::sparqlQuery() const
204 {
205  if ( !m_isSparqlQueryFolder )
206  return m_query.toSparqlQuery();
207  else
208  return m_sparqlQuery;
209 }
210 
211 
212 Nepomuk2::Query::RequestPropertyMap Nepomuk2::Query::Folder::requestPropertyMap() const
213 {
214  if ( !m_isSparqlQueryFolder )
215  return m_query.requestPropertyMap();
216  else
217  return m_requestProperties;
218 }
219 
220 
221 void Nepomuk2::Query::Folder::addResult(const Result& result)
222 {
223  const QUrl resUri = result.resource().uri();
224  m_newResults.insert( resUri, result );
225 
226  if ( !m_results.contains( resUri ) ) {
227  emit newEntries( QList<Result>() << result );
228  }
229 }
230 
231 
232 void Nepomuk2::Query::Folder::listingFinished()
233 {
234  m_currentSearchRunnable = 0;
235 
236  // inform about removed items
237  QList<Result> removedResults;
238 
239  // legacy removed results
240  foreach( const Result& result, m_results ) {
241  if ( !m_newResults.contains( result.resource().uri() ) ) {
242  removedResults << result;
243  emit entriesRemoved( QList<QUrl>() << KUrl(result.resource().uri()).url() );
244  }
245  }
246 
247  // new removed results which include all the details to be used for optimizations
248  if( !removedResults.isEmpty() ) {
249  emit entriesRemoved( removedResults );
250  }
251 
252  // reset
253  m_results = m_newResults;
254  m_newResults.clear();
255 
256  if ( !m_initialListingDone ) {
257  kDebug() << "Listing done. Total:" << m_results.count();
258  m_initialListingDone = true;
259  emit finishedListing();
260  }
261 
262  // make sure we do not update again right away
263  // but we need to do it from the main thread but this
264  // method is called sync from the SearchRunnable
265  QMetaObject::invokeMethod( &m_updateTimer, "start", Qt::QueuedConnection );
266 }
267 
268 
269 void Nepomuk2::Query::Folder::slotStorageChanged()
270 {
271  m_updateTimer.start();
272  m_storageChanged = true;
273 }
274 
275 
276 void Nepomuk2::Query::Folder::slotUpdateTimeout()
277 {
278  if ( m_storageChanged && !m_currentSearchRunnable ) {
279  m_storageChanged = false;
280  update();
281  }
282 }
283 
284 
285 void Nepomuk2::Query::Folder::countQueryFinished( int count )
286 {
287  m_currentCountQueryRunnable = 0;
288 
289  m_resultCount = count;
290  kDebug() << m_resultCount;
291  if( count >= 0 )
292  emit resultCount( m_resultCount );
293 }
294 
295 
296 void Nepomuk2::Query::Folder::addConnection( FolderConnection* conn )
297 {
298  Q_ASSERT( conn != 0 );
299  Q_ASSERT( !m_connections.contains( conn ) );
300 
301  m_connections.append( conn );
302 }
303 
304 
305 void Nepomuk2::Query::Folder::removeConnection( FolderConnection* conn )
306 {
307  Q_ASSERT( conn != 0 );
308  Q_ASSERT( m_connections.contains( conn ) );
309 
310  m_connections.removeAll( conn );
311 
312  if ( m_connections.isEmpty() ) {
313  kDebug() << "Folder unused. Deleting.";
314  emit aboutToBeDeleted( this );
315  deleteLater();
316  }
317 }
318 
319 
320 QList<Nepomuk2::Query::FolderConnection*> Nepomuk2::Query::Folder::openConnections() const
321 {
322  return m_connections;
323 }
324 
325 
326 uint Nepomuk2::Query::qHash( const Result& result )
327 {
328  // we only use this to ensure that we do not emit duplicates
329  return qHash(result.resource().uri());
330 }
331 
332 #include "folder.moc"
andterm.h
Nepomuk2::Query::Term::isOptionalTerm
bool isOptionalTerm() const
Definition: term.cpp:181
Nepomuk2::Query::Term::isComparisonTerm
bool isComparisonTerm() const
Definition: term.cpp:199
Nepomuk2::Query::Term::toOptionalTerm
OptionalTerm toOptionalTerm() const
Interpret this term as a OptionalTerm.
Definition: term.cpp:239
Nepomuk2::ResourceWatcher::setProperties
void setProperties(const QList< Types::Property > &properties_)
Set the properties to be watched.
Definition: resourcewatcher.cpp:275
Nepomuk2::Query::Term::isOrTerm
bool isOrTerm() const
Definition: term.cpp:193
Nepomuk2::Types::Entity::uri
QUrl uri() const
The URI of the resource.
Definition: entity.cpp:175
Nepomuk2::Query::Term
The base class for all term types.
Definition: term.h:64
Nepomuk2::Query::GroupTerm
Abstract base class for AndTerm and OrTerm which maintains a list of sub-terms.
Definition: groupterm.h:41
Nepomuk2::ResourceWatcher::addProperty
void addProperty(const Types::Property &property)
Add a property to be watched.
Definition: resourcewatcher.cpp:176
Nepomuk2::Query::Term::isAndTerm
bool isAndTerm() const
Definition: term.cpp:187
Nepomuk2::Query::SearchRunnable
Definition: searchrunnable.h:40
Nepomuk2::Query::Query::term
Term term() const
The root term of the query.
Definition: query.cpp:293
Nepomuk2::Query::SimpleTerm::subTerm
Term subTerm() const
The sub term to match against.
Definition: simpleterm.cpp:52
negationterm.h
Nepomuk2::Query::Folder::sparqlQuery
QString sparqlQuery() const
Definition: folder.cpp:203
QObject
Nepomuk2::Query::GroupTerm::subTerms
QList< Term > subTerms() const
The sub terms that are combined in this group.
Definition: groupterm.cpp:94
Nepomuk2::Query::Folder::entries
QList< Result > entries() const
Definition: folder.cpp:191
Nepomuk2::Query::qHash
uint qHash(const Nepomuk2::Query::Query &)
Definition: query.cpp:738
Nepomuk2::Query::Folder::openConnections
QList< FolderConnection * > openConnections() const
Definition: folder.cpp:320
Nepomuk2::Query::Term::isNegationTerm
bool isNegationTerm() const
Definition: term.cpp:175
Nepomuk2::Query::Term::toComparisonTerm
ComparisonTerm toComparisonTerm() const
Interpret this term as a ComparisonTerm.
Definition: term.cpp:266
Nepomuk2::Query::Folder::Folder
Folder(Soprano::Model *model, const Query &query, QObject *parent=0)
Definition: folder.cpp:45
Nepomuk2::Query::RequestPropertyMap
QHash< QString, Nepomuk2::Types::Property > RequestPropertyMap
Convinience definition for request property mappings as used in QueryServiceClient::sparqlQuery() and...
Definition: query.h:41
Nepomuk2::Query::Folder::initialListingDone
bool initialListingDone() const
Definition: folder.cpp:197
queryservice.h
Nepomuk2::ResourceWatcher::start
bool start()
Start the signalling of changes.
Definition: resourcewatcher.cpp:89
Nepomuk2::Query::Term::toOrTerm
OrTerm toOrTerm() const
Interpret this term as a OrTerm.
Definition: term.cpp:257
Nepomuk2::Query::Query
A Nepomuk desktop query.
Definition: query.h:76
Nepomuk2::Types::Class
A Class is a resource of type rdf:Class.
Definition: class.h:49
resource.h
Nepomuk2::Types::Property
A property is a resource of type rdf:Property which relates a domain with a range.
Definition: libnepomukcore/types/property.h:52
Nepomuk2::Query::CountQueryRunnable
Definition: countqueryrunnable.h:34
Nepomuk2::Query::FolderConnection
Definition: folderconnection.h:35
countqueryrunnable.h
resourcemanager.h
Nepomuk2::ResourceWatcher
Selectively monitor the nepomuk repository for changes.
Definition: resourcewatcher.h:81
resourcetypeterm.h
folder.h
Nepomuk2::Query::Result
A single search result.
Definition: result.h:57
comparisonterm.h
Nepomuk2::Query::Folder::~Folder
~Folder()
Definition: folder.cpp:146
Nepomuk2::Query::Term::toAndTerm
AndTerm toAndTerm() const
Interpret this term as a AndTerm.
Definition: term.cpp:248
folderconnection.h
Nepomuk2::Resource
Resource is the central object type in Nepomuk.
Definition: resource.h:93
resourcewatcher.h
orterm.h
optionalterm.h
Nepomuk2::Query::Result::resource
Resource resource() const
The result resource.
Definition: result.cpp:81
Nepomuk2::Resource::uri
QUrl uri() const
The URI of the resource, uniquely identifying it.
Definition: resource.cpp:166
Nepomuk2::Query::QueryService::searchThreadPool
static QThreadPool * searchThreadPool()
Definition: queryservice.cpp:90
Nepomuk2::Query::Folder::requestPropertyMap
RequestPropertyMap requestPropertyMap() const
Definition: folder.cpp:212
searchrunnable.h
Nepomuk2::Query::ComparisonTerm::property
Types::Property property() const
A property used for ComparisonTerm Terms.
Definition: comparisonterm.cpp:467
Nepomuk2::Query::Term::toNegationTerm
NegationTerm toNegationTerm() const
Interpret this term as a NegationTerm.
Definition: term.cpp:230
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Nepomuk-Core

Skip menu "Nepomuk-Core"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal