00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kio_nepomuksearch.h"
00020 #include "searchfolder.h"
00021
00022 #include <QtCore/QFile>
00023
00024 #include <KUser>
00025 #include <KDebug>
00026 #include <KAboutData>
00027 #include <KApplication>
00028 #include <KCmdLineArgs>
00029 #include <kio/global.h>
00030 #include <kio/job.h>
00031 #include <KMimeType>
00032
00033 #include <Nepomuk/Resource>
00034 #include <Nepomuk/ResourceManager>
00035 #include <Nepomuk/Variant>
00036 #include "queryparser.h"
00037
00038 #include <Soprano/Vocabulary/RDF>
00039 #include <Soprano/Vocabulary/Xesam>
00040
00041 #include <sys/types.h>
00042 #include <unistd.h>
00043
00044
00045 namespace {
00046 KIO::UDSEntry statDefaultSearchFolder( const QString& name ) {
00047 KIO::UDSEntry uds;
00048 uds.insert( KIO::UDSEntry::UDS_NAME, name );
00049 uds.insert( KIO::UDSEntry::UDS_ACCESS, 0700 );
00050 uds.insert( KIO::UDSEntry::UDS_USER, KUser().loginName() );
00051 uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
00052 uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
00053 return uds;
00054 }
00055
00056
00057 const int SEARCH_CACHE_MAX = 5;
00058 }
00059
00060
00061 Nepomuk::SearchProtocol::SearchProtocol( const QByteArray& poolSocket, const QByteArray& appSocket )
00062 : KIO::ForwardingSlaveBase( "nepomuksearch", poolSocket, appSocket )
00063 {
00064
00065
00066
00067
00068 addDefaultSearch( i18n( "All Music Files" ), Search::Term( Soprano::Vocabulary::RDF::type(),
00069 Soprano::Vocabulary::Xesam::Music() ) );
00070
00071
00072 Search::Term term;
00073 QDateTime today( QDate::currentDate(), QTime(), Qt::UTC );
00074 term.setType( Search::Term::AndTerm );
00075 term.addSubTerm( Search::Term( Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::Xesam::File() ) );
00076 term.addSubTerm( Search::Term( Soprano::Vocabulary::Xesam::sourceModified(), today, Search::Term::GreaterOrEqual ) );
00077 addDefaultSearch( i18n( "Today's Files" ), term );
00078
00079
00080 term = Search::Term();
00081 term.setType( Search::Term::AndTerm );
00082 term.addSubTerm( Search::Term( Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::Xesam::File() ) );
00083 QDateTime yesterday( today );
00084 yesterday.addDays( -1 );
00085 term.addSubTerm( Search::Term( Soprano::Vocabulary::Xesam::sourceModified(), yesterday, Search::Term::GreaterOrEqual ) );
00086 term.addSubTerm( Search::Term( Soprano::Vocabulary::Xesam::sourceModified(), today, Search::Term::Smaller ) );
00087 addDefaultSearch( i18n( "Yesterday's Files" ), term );
00088
00089
00090 addDefaultSearch( i18n( "Recent Files" ),
00091 Search::Query( "select distinct ?r where { "
00092 "?r a <http://freedesktop.org/standards/xesam/1.0/core#File> . ?r "
00093 "<http://freedesktop.org/standards/xesam/1.0/core#sourceModified> ?date . "
00094 "} ORDER BY DESC(?date) LIMIT 10" ) );
00095 }
00096
00097
00098 Nepomuk::SearchProtocol::~SearchProtocol()
00099 {
00100 }
00101
00102
00103 void Nepomuk::SearchProtocol::addDefaultSearch( const QString& name, const Search::Query& q )
00104 {
00105 Search::Query query( q );
00106 query.addRequestProperty( Soprano::Vocabulary::Xesam::url(), true );
00107 m_defaultSearches.insert( name, query );
00108 }
00109
00110
00111 Nepomuk::SearchFolder* Nepomuk::SearchProtocol::extractSearchFolder( const KUrl& url )
00112 {
00113 QString name = url.path().section( '/', 0, 0, QString::SectionSkipEmpty );
00114 kDebug() << url << name;
00115 if ( SearchFolder* sf = getDefaultQueryFolder( name ) ) {
00116 kDebug() << "-----> is default search folder";
00117 return sf;
00118 }
00119 else if ( SearchFolder* sf = getQueryResults( name ) ) {
00120 kDebug() << "-----> is on-the-fly search folder";
00121 return sf;
00122 }
00123 else {
00124 kDebug() << "-----> does not exist.";
00125 return 0;
00126 }
00127 }
00128
00129
00130 void Nepomuk::SearchProtocol::listDir( const KUrl& url )
00131 {
00132 kDebug() << url;
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 if ( url.path() == "/" ) {
00146 listRoot();
00147 }
00148 else if ( url.directory() == "/" &&
00149 m_defaultSearches.contains( url.fileName() ) ) {
00150
00151 listDefaultSearch( url.fileName() );
00152 }
00153 else {
00154
00155 listQuery( url.fileName() );
00156 }
00157 }
00158
00159
00160 void Nepomuk::SearchProtocol::get( const KUrl& url )
00161 {
00162 kDebug() << url;
00163 ForwardingSlaveBase::get( url );
00164 }
00165
00166
00167 void Nepomuk::SearchProtocol::put( const KUrl& url, int permissions, KIO::JobFlags flags )
00168 {
00169 kDebug() << url << permissions << flags;
00170
00171 ForwardingSlaveBase::put( url, permissions, flags );
00172 }
00173
00174
00175 void Nepomuk::SearchProtocol::mimetype( const KUrl& url )
00176 {
00177 kDebug() << url;
00178
00179 if ( url.path() == "/" ) {
00180 mimeType( QString::fromLatin1( "inode/directory" ) );
00181 finished();
00182 }
00183 else if ( url.directory() == "/" &&
00184 m_defaultSearches.contains( url.fileName() ) ) {
00185 mimeType( QString::fromLatin1( "inode/directory" ) );
00186 finished();
00187 }
00188 else {
00189 ForwardingSlaveBase::mimetype( url );
00190 }
00191 }
00192
00193
00194 void Nepomuk::SearchProtocol::stat( const KUrl& url )
00195 {
00196 kDebug() << url;
00197
00198 if ( url.path() == "/" ) {
00199 if ( url.queryItems().isEmpty() ) {
00200 kDebug() << "/";
00201
00202
00203
00204 KIO::UDSEntry uds;
00205 uds.insert( KIO::UDSEntry::UDS_NAME, QString::fromLatin1( "/" ) );
00206 uds.insert( KIO::UDSEntry::UDS_ICON_NAME, QString::fromLatin1( "nepomuk" ) );
00207 uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
00208 uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
00209
00210 statEntry( uds );
00211 finished();
00212 }
00213 else {
00214 kDebug() << "query folder:" << url.queryItemValue("query");
00215
00216
00217
00218
00219 KIO::UDSEntry uds;
00220 uds.insert( KIO::UDSEntry::UDS_NAME, url.fileName() );
00221 uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
00222 uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
00223
00224 statEntry( uds );
00225 finished();
00226 }
00227 }
00228 else if ( url.directory() == "/" ) {
00229 if ( SearchFolder* sf = extractSearchFolder( url ) ) {
00230 KIO::UDSEntry uds = statDefaultSearchFolder( sf->name() );
00231 Q_ASSERT( !uds.stringValue( KIO::UDSEntry::UDS_NAME ).isEmpty() );
00232 statEntry( uds );
00233 finished();
00234 }
00235 else {
00236 error( KIO::ERR_DOES_NOT_EXIST, url.url() );
00237 }
00238 }
00239 else if ( SearchFolder* folder = extractSearchFolder( url ) ) {
00240 folder->stat( url.fileName() );
00241 }
00242 else {
00243 error( KIO::ERR_DOES_NOT_EXIST, url.url() );
00244 }
00245 }
00246
00247
00248 bool Nepomuk::SearchProtocol::rewriteUrl( const KUrl& url, KUrl& newURL )
00249 {
00250 kDebug() << url << newURL;
00251
00252 if ( SearchFolder* folder = extractSearchFolder( url ) ) {
00253 if ( SearchEntry* entry = folder->findEntry( url.fileName() ) ) {
00254 QString localPath = entry->entry().stringValue( KIO::UDSEntry::UDS_LOCAL_PATH );
00255 if ( localPath.isEmpty() ) {
00256 newURL = localPath;
00257 }
00258 else {
00259 newURL = entry->resource();
00260 }
00261 return true;
00262 }
00263 }
00264
00265 return false;
00266 }
00267
00268
00269 void Nepomuk::SearchProtocol::listRoot()
00270 {
00271 kDebug();
00272
00273 listDefaultSearches();
00274 listActions();
00275
00276 listEntry( KIO::UDSEntry(), true );
00277 finished();
00278 }
00279
00280
00281 void Nepomuk::SearchProtocol::listActions()
00282 {
00283
00284 }
00285
00286
00287 Nepomuk::SearchFolder* Nepomuk::SearchProtocol::getQueryResults( const QString& query )
00288 {
00289 if ( m_searchCache.contains( query ) ) {
00290 return m_searchCache[query];
00291 }
00292 else {
00293 if ( m_searchCache.count() >= SEARCH_CACHE_MAX ) {
00294 QString oldestQuery = m_searchCacheNameQueue.dequeue();
00295 delete m_searchCache.take( oldestQuery );
00296 }
00297
00298 Search::Query q = Nepomuk::Search::QueryParser::parseQuery( query );
00299 q.addRequestProperty( Soprano::Vocabulary::Xesam::url(), true );
00300 SearchFolder* folder = new SearchFolder( query, q, this );
00301 m_searchCacheNameQueue.enqueue( query );
00302 m_searchCache.insert( query, folder );
00303 return folder;
00304 }
00305 }
00306
00307
00308 Nepomuk::SearchFolder* Nepomuk::SearchProtocol::getDefaultQueryFolder( const QString& name )
00309 {
00310 if ( m_defaultSearchCache.contains( name ) ) {
00311 return m_defaultSearchCache[name];
00312 }
00313 else if ( m_defaultSearches.contains( name ) ) {
00314 SearchFolder* folder = new SearchFolder( name, m_defaultSearches[name], this );
00315 m_defaultSearchCache.insert( name, folder );
00316 return folder;
00317 }
00318 else {
00319 return 0;
00320 }
00321 }
00322
00323
00324 void Nepomuk::SearchProtocol::listQuery( const QString& query )
00325 {
00326 kDebug() << query;
00327 getQueryResults( query )->list();
00328 }
00329
00330
00331 void Nepomuk::SearchProtocol::listDefaultSearches()
00332 {
00333 for ( QHash<QString, Nepomuk::Search::Query>::const_iterator it = m_defaultSearches.constBegin();
00334 it != m_defaultSearches.constEnd(); ++it ) {
00335 listEntry( statDefaultSearchFolder( it.key() ), false );
00336 }
00337 }
00338
00339
00340 void Nepomuk::SearchProtocol::listDefaultSearch( const QString& name )
00341 {
00342 kDebug() << name;
00343 if ( m_defaultSearches.contains( name ) ) {
00344 getDefaultQueryFolder( name )->list();
00345 }
00346 else {
00347 error( KIO::ERR_CANNOT_ENTER_DIRECTORY, "Unknown default search: " + name );
00348 finished();
00349 }
00350 }
00351
00352 extern "C"
00353 {
00354 KDE_EXPORT int kdemain( int argc, char **argv )
00355 {
00356
00357 KComponentData( "kio_nepomuksearch" );
00358 QCoreApplication app( argc, argv );
00359
00360 if ( Nepomuk::ResourceManager::instance()->init() ) {
00361 kError() << "Unable to initialized Nepomuk.";
00362 return -1;
00363 }
00364
00365 kDebug(7102) << "Starting nepomuksearch slave " << getpid();
00366
00367 Nepomuk::SearchProtocol slave( argv[2], argv[3] );
00368 slave.dispatchLoop();
00369
00370 kDebug(7102) << "Nepomuksearch slave Done";
00371
00372 return 0;
00373 }
00374 }
00375
00376 #include "kio_nepomuksearch.moc"