add more spacing
[personal-kdebase.git] / runtime / nepomuk / kioslaves / search / kio_nepomuksearch.cpp
blob96e494810daad446505c816b8a312d419185f643
1 /*
2 Copyright (C) 2008 by Sebastian Trueg <trueg at kde.org>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "kio_nepomuksearch.h"
20 #include "searchfolder.h"
22 #include <QtCore/QFile>
24 #include <KUser>
25 #include <KDebug>
26 #include <KAboutData>
27 #include <KApplication>
28 #include <KCmdLineArgs>
29 #include <kio/global.h>
30 #include <kio/job.h>
31 #include <KMimeType>
33 #include <Nepomuk/Resource>
34 #include <Nepomuk/ResourceManager>
35 #include <Nepomuk/Variant>
36 #include "queryparser.h"
38 #include <Soprano/Vocabulary/RDF>
39 #include <Soprano/Vocabulary/Xesam>
41 #include <sys/types.h>
42 #include <unistd.h>
45 namespace {
46 KIO::UDSEntry statDefaultSearchFolder( const QString& name ) {
47 KIO::UDSEntry uds;
48 uds.insert( KIO::UDSEntry::UDS_NAME, name );
49 uds.insert( KIO::UDSEntry::UDS_ACCESS, 0700 );
50 uds.insert( KIO::UDSEntry::UDS_USER, KUser().loginName() );
51 uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
52 uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
53 return uds;
56 // do not cache more than SEARCH_CACHE_MAX search folders at the same time
57 const int SEARCH_CACHE_MAX = 5;
61 Nepomuk::SearchProtocol::SearchProtocol( const QByteArray& poolSocket, const QByteArray& appSocket )
62 : KIO::ForwardingSlaveBase( "nepomuksearch", poolSocket, appSocket )
64 // FIXME: load default searches from config
65 // FIXME: allow icons
67 // all music files
68 addDefaultSearch( i18n( "All Music Files" ), Search::Term( Soprano::Vocabulary::RDF::type(),
69 Soprano::Vocabulary::Xesam::Music() ) );
71 // today's files
72 Search::Term term;
73 QDateTime today( QDate::currentDate(), QTime(), Qt::UTC );
74 term.setType( Search::Term::AndTerm );
75 term.addSubTerm( Search::Term( Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::Xesam::File() ) );
76 term.addSubTerm( Search::Term( Soprano::Vocabulary::Xesam::sourceModified(), today, Search::Term::GreaterOrEqual ) );
77 addDefaultSearch( i18n( "Today's Files" ), term );
79 // yesterday's files
80 term = Search::Term();
81 term.setType( Search::Term::AndTerm );
82 term.addSubTerm( Search::Term( Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::Xesam::File() ) );
83 QDateTime yesterday( today );
84 yesterday.addDays( -1 );
85 term.addSubTerm( Search::Term( Soprano::Vocabulary::Xesam::sourceModified(), yesterday, Search::Term::GreaterOrEqual ) );
86 term.addSubTerm( Search::Term( Soprano::Vocabulary::Xesam::sourceModified(), today, Search::Term::Smaller ) );
87 addDefaultSearch( i18n( "Yesterday's Files" ), term );
89 // select the 10 most recent files:
90 addDefaultSearch( i18n( "Recent Files" ),
91 Search::Query( "select distinct ?r where { "
92 "?r a <http://freedesktop.org/standards/xesam/1.0/core#File> . ?r "
93 "<http://freedesktop.org/standards/xesam/1.0/core#sourceModified> ?date . "
94 "} ORDER BY DESC(?date) LIMIT 10" ) );
98 Nepomuk::SearchProtocol::~SearchProtocol()
103 void Nepomuk::SearchProtocol::addDefaultSearch( const QString& name, const Search::Query& q )
105 Search::Query query( q );
106 query.addRequestProperty( Soprano::Vocabulary::Xesam::url(), true );
107 m_defaultSearches.insert( name, query );
111 Nepomuk::SearchFolder* Nepomuk::SearchProtocol::extractSearchFolder( const KUrl& url )
113 QString name = url.path().section( '/', 0, 0, QString::SectionSkipEmpty );
114 kDebug() << url << name;
115 if ( SearchFolder* sf = getDefaultQueryFolder( name ) ) {
116 kDebug() << "-----> is default search folder";
117 return sf;
119 else if ( SearchFolder* sf = getQueryResults( name ) ) {
120 kDebug() << "-----> is on-the-fly search folder";
121 return sf;
123 else {
124 kDebug() << "-----> does not exist.";
125 return 0;
130 void Nepomuk::SearchProtocol::listDir( const KUrl& url )
132 kDebug() << url;
135 // Root dir: * list default searches: "all music files", "recent files"
136 // * list configuration entries: "create new default search"
138 // Root dir with query:
139 // * execute the query (cached) and list its results
141 // some folder:
142 // * Look for a default search and execute that
145 if ( url.path() == "/" ) {
146 listRoot();
148 else if ( url.directory() == "/" &&
149 m_defaultSearches.contains( url.fileName() ) ) {
150 // the default search name is the folder name
151 listDefaultSearch( url.fileName() );
153 else {
154 // lets create an on-the-fly search
155 listQuery( url.fileName() );
160 void Nepomuk::SearchProtocol::get( const KUrl& url )
162 kDebug() << url;
163 ForwardingSlaveBase::get( url );
167 void Nepomuk::SearchProtocol::put( const KUrl& url, int permissions, KIO::JobFlags flags )
169 kDebug() << url << permissions << flags;
170 // this will work only for existing files (ie. overwrite to allow saving of opened files)
171 ForwardingSlaveBase::put( url, permissions, flags );
175 void Nepomuk::SearchProtocol::mimetype( const KUrl& url )
177 kDebug() << url;
179 if ( url.path() == "/" ) {
180 mimeType( QString::fromLatin1( "inode/directory" ) );
181 finished();
183 else if ( url.directory() == "/" &&
184 m_defaultSearches.contains( url.fileName() ) ) {
185 mimeType( QString::fromLatin1( "inode/directory" ) );
186 finished();
188 else {
189 ForwardingSlaveBase::mimetype( url );
194 void Nepomuk::SearchProtocol::stat( const KUrl& url )
196 kDebug() << url;
198 if ( url.path() == "/" ) {
199 if ( url.queryItems().isEmpty() ) {
200 kDebug() << "/";
202 // stat the root path
204 KIO::UDSEntry uds;
205 uds.insert( KIO::UDSEntry::UDS_NAME, QString::fromLatin1( "/" ) );
206 uds.insert( KIO::UDSEntry::UDS_ICON_NAME, QString::fromLatin1( "nepomuk" ) );
207 uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
208 uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
210 statEntry( uds );
211 finished();
213 else {
214 kDebug() << "query folder:" << url.queryItemValue("query");
217 // stat a query folder
219 KIO::UDSEntry uds;
220 uds.insert( KIO::UDSEntry::UDS_NAME, url.fileName() );
221 uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
222 uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
224 statEntry( uds );
225 finished();
228 else if ( url.directory() == "/" ) {
229 if ( SearchFolder* sf = extractSearchFolder( url ) ) {
230 KIO::UDSEntry uds = statDefaultSearchFolder( sf->name() );
231 Q_ASSERT( !uds.stringValue( KIO::UDSEntry::UDS_NAME ).isEmpty() );
232 statEntry( uds );
233 finished();
235 else {
236 error( KIO::ERR_DOES_NOT_EXIST, url.url() );
239 else if ( SearchFolder* folder = extractSearchFolder( url ) ) {
240 folder->stat( url.fileName() );
242 else {
243 error( KIO::ERR_DOES_NOT_EXIST, url.url() );
248 bool Nepomuk::SearchProtocol::rewriteUrl( const KUrl& url, KUrl& newURL )
250 kDebug() << url << newURL;
252 if ( SearchFolder* folder = extractSearchFolder( url ) ) {
253 if ( SearchEntry* entry = folder->findEntry( url.fileName() ) ) {
254 QString localPath = entry->entry().stringValue( KIO::UDSEntry::UDS_LOCAL_PATH );
255 if ( localPath.isEmpty() ) {
256 newURL = localPath;
258 else {
259 newURL = entry->resource();
261 return true;
265 return false;
269 void Nepomuk::SearchProtocol::listRoot()
271 kDebug();
273 listDefaultSearches();
274 listActions();
276 listEntry( KIO::UDSEntry(), true );
277 finished();
281 void Nepomuk::SearchProtocol::listActions()
283 // FIXME: manage default searches
287 Nepomuk::SearchFolder* Nepomuk::SearchProtocol::getQueryResults( const QString& query )
289 if ( m_searchCache.contains( query ) ) {
290 return m_searchCache[query];
292 else {
293 if ( m_searchCache.count() >= SEARCH_CACHE_MAX ) {
294 QString oldestQuery = m_searchCacheNameQueue.dequeue();
295 delete m_searchCache.take( oldestQuery );
298 Search::Query q = Nepomuk::Search::QueryParser::parseQuery( query );
299 q.addRequestProperty( Soprano::Vocabulary::Xesam::url(), true );
300 SearchFolder* folder = new SearchFolder( query, q, this );
301 m_searchCacheNameQueue.enqueue( query );
302 m_searchCache.insert( query, folder );
303 return folder;
308 Nepomuk::SearchFolder* Nepomuk::SearchProtocol::getDefaultQueryFolder( const QString& name )
310 if ( m_defaultSearchCache.contains( name ) ) {
311 return m_defaultSearchCache[name];
313 else if ( m_defaultSearches.contains( name ) ) {
314 SearchFolder* folder = new SearchFolder( name, m_defaultSearches[name], this );
315 m_defaultSearchCache.insert( name, folder );
316 return folder;
318 else {
319 return 0;
324 void Nepomuk::SearchProtocol::listQuery( const QString& query )
326 kDebug() << query;
327 getQueryResults( query )->list();
331 void Nepomuk::SearchProtocol::listDefaultSearches()
333 for ( QHash<QString, Nepomuk::Search::Query>::const_iterator it = m_defaultSearches.constBegin();
334 it != m_defaultSearches.constEnd(); ++it ) {
335 listEntry( statDefaultSearchFolder( it.key() ), false );
340 void Nepomuk::SearchProtocol::listDefaultSearch( const QString& name )
342 kDebug() << name;
343 if ( m_defaultSearches.contains( name ) ) {
344 getDefaultQueryFolder( name )->list();
346 else {
347 error( KIO::ERR_CANNOT_ENTER_DIRECTORY, "Unknown default search: " + name );
348 finished();
352 extern "C"
354 KDE_EXPORT int kdemain( int argc, char **argv )
356 // necessary to use other kio slaves
357 KComponentData( "kio_nepomuksearch" );
358 QCoreApplication app( argc, argv );
360 if ( Nepomuk::ResourceManager::instance()->init() ) {
361 kError() << "Unable to initialized Nepomuk.";
362 return -1;
365 kDebug(7102) << "Starting nepomuksearch slave " << getpid();
367 Nepomuk::SearchProtocol slave( argv[2], argv[3] );
368 slave.dispatchLoop();
370 kDebug(7102) << "Nepomuksearch slave Done";
372 return 0;
376 #include "kio_nepomuksearch.moc"