Sophie

Sophie

distrib > Mandriva > 2010.1 > i586 > media > main-testing-src > by-pkgid > 357e0466909645e33fa8bfa6e2222a8a > files > 16

kdebase4-runtime-4.4.5-0.1mdv2010.2.src.rpm

diff -Nru kdebase-runtime-4.3.2/nepomuk/kioslaves/search/CMakeLists.txt kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/CMakeLists.txt
--- kdebase-runtime-4.3.2/nepomuk/kioslaves/search/CMakeLists.txt	2009-07-21 17:18:35.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/CMakeLists.txt	2009-10-26 09:52:22.000000000 +0100
@@ -12,7 +12,7 @@
   ${nepomuk_SOURCE_DIR}/libnepomukquery
 )
 
-add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
+add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS} -DDISABLE_NEPOMUK_LEGACY)
 
 set(kio_nepomuksearch_PART_SRCS
   kio_nepomuksearch.cpp
@@ -25,16 +25,29 @@
   ${nepomuk_SOURCE_DIR}/libnepomukquery/dbusoperators.cpp
 )
 
-soprano_add_ontology(kio_nepomuksearch_PART_SRCS
-  ${nepomukontologies_SOURCE_DIR}/nfo.trig
-  "NFO"
-  "Nepomuk::Vocabulary"
-  "trig")
-soprano_add_ontology(kio_nepomuksearch_PART_SRCS
-  ${nepomukontologies_SOURCE_DIR}/nie.trig
-  "NIE"
-  "Nepomuk::Vocabulary"
-  "trig")
+# find the nfo.trig file from the kdebase installation
+#find_file(NIE_TRIG_SOURCE 
+#  nie.trig
+#  PATHS "${KDE4_DATA_INSTALL_DIR}/.." "${KDE4_DATA_INSTALL_DIR}" ENV XDG_DATA_DIRS
+#  PATH_SUFFIXES "apps/nepomuk/ontologies"
+#  NO_DEFAULT_PATH
+#  )
+#find_file(NFO_TRIG_SOURCE 
+#  nfo.trig
+#  PATHS "${KDE4_DATA_INSTALL_DIR}/.." "${KDE4_DATA_INSTALL_DIR}" ENV XDG_DATA_DIRS
+#  PATH_SUFFIXES "apps/nepomuk/ontologies"
+#  NO_DEFAULT_PATH
+#  )
+#find_file(PIMO_TRIG_SOURCE 
+#  pimo.trig
+#  PATHS "${KDE4_DATA_INSTALL_DIR}/.." "${KDE4_DATA_INSTALL_DIR}" ENV XDG_DATA_DIRS
+#  PATH_SUFFIXES "apps/nepomuk/ontologies"
+#  NO_DEFAULT_PATH
+#  )
+
+soprano_add_ontology(kio_nepomuksearch_PART_SRCS ${nepomukontologies_SOURCE_DIR}/nfo.trig "NFO" "Nepomuk::Vocabulary" "trig")
+soprano_add_ontology(kio_nepomuksearch_PART_SRCS ${nepomukontologies_SOURCE_DIR}/nie.trig "NIE" "Nepomuk::Vocabulary" "trig")
+soprano_add_ontology(kio_nepomuksearch_PART_SRCS ${nepomukontologies_SOURCE_DIR}/pimo.trig "PIMO" "Nepomuk::Vocabulary" "trig")
 
 set_source_files_properties(
   ../../interfaces/org.kde.nepomuk.QueryService.xml
diff -Nru kdebase-runtime-4.3.2/nepomuk/kioslaves/search/kio_nepomuksearch.cpp kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/kio_nepomuksearch.cpp
--- kdebase-runtime-4.3.2/nepomuk/kioslaves/search/kio_nepomuksearch.cpp	2009-08-27 10:17:34.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/kio_nepomuksearch.cpp	2009-10-26 10:35:59.000000000 +0100
@@ -1,5 +1,5 @@
 /*
-   Copyright (C) 2008-2009 by Sebastian Trueg <trueg at kde.org>
+   Copyright (C) 2008 by Sebastian Trueg <trueg at kde.org>
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -20,6 +20,8 @@
 #include "searchfolder.h"
 #include "nfo.h"
 #include "nie.h"
+#include "pimo.h"
+#include "queryserviceclient.h"
 
 #include <QtCore/QFile>
 
@@ -27,10 +29,13 @@
 #include <KDebug>
 #include <KAboutData>
 #include <KApplication>
+#include <KConfig>
+#include <KConfigGroup>
 #include <KCmdLineArgs>
 #include <kio/global.h>
 #include <kio/job.h>
 #include <KMimeType>
+#include <KStandardDirs>
 
 #include <Nepomuk/Resource>
 #include <Nepomuk/ResourceManager>
@@ -38,7 +43,10 @@
 #include "queryparser.h"
 
 #include <Soprano/Vocabulary/RDF>
-#include <Soprano/Vocabulary/Xesam>
+#include <Soprano/Vocabulary/RDFS>
+#include <Soprano/Vocabulary/NRL>
+#include <Soprano/Vocabulary/NAO>
+#include <Soprano/Vocabulary/XMLSchema>
 
 #include <sys/types.h>
 #include <unistd.h>
@@ -55,6 +63,53 @@
         return uds;
     }
 
+
+    //if type != 0, also retreives the type of the query and stores it into type
+    QString queryNameFromURL( const KUrl& url, Nepomuk::Search::Query::Type* type = 0 ) {
+        if(url.queryItems().contains( "sparql" ) ) {
+            if( type ) {
+                *type = Nepomuk::Search::Query::SPARQLQuery;
+            }
+            return url.queryItem( "sparql" );
+        }
+        else if(url.queryItems().contains( "query" ) ) {
+            if( type ) {
+                *type = Nepomuk::Search::Query::PlainQuery;
+            }
+            return url.queryItem( "query" );
+        }
+        else {
+            if( type ) {
+                *type = Nepomuk::Search::Query::PlainQuery;
+            }
+            return url.path().section( '/', 0, 0, QString::SectionSkipEmpty );
+        }
+    }
+
+    /**
+     * Empty if the path only contains the query.
+     */
+    QString fileNameFromUrl( const KUrl& url ) {
+        QString fn;
+        if ( url.hasQueryItem( QLatin1String( "sparql" ) ) ||
+             url.hasQueryItem( QLatin1String( "query" ) ) ||
+             url.directory() != QLatin1String( "/" ) ) {
+            return url.fileName();
+        }
+        else {
+            return QString();
+        }
+    }
+
+    Nepomuk::Search::Query createQuery( const QString& name, Nepomuk::Search::Query::Type type ) {
+        if( type == Nepomuk::Search::Query::PlainQuery ) {
+            return Nepomuk::Search::QueryParser::parseQuery( name );
+        }
+        else /*type == Search::Query::SPARQLQuery*/ {
+            return Nepomuk::Search::Query( name );
+        }
+    }
+
     // do not cache more than SEARCH_CACHE_MAX search folders at the same time
     const int SEARCH_CACHE_MAX = 5;
 }
@@ -63,26 +118,21 @@
 Nepomuk::SearchProtocol::SearchProtocol( const QByteArray& poolSocket, const QByteArray& appSocket )
     : KIO::ForwardingSlaveBase( "nepomuksearch", poolSocket, appSocket )
 {
-    // FIXME: load default searches from config
-    // FIXME: allow icons
+    // FIXME: trueg: install a file watch on this file and update it whenever the queries change.
+    // FIXME: trueg: also emit a KDirNotify signal to inform KIO about that change
+    KConfig config("kionepomukuserqueriesrc" );
+
+    foreach( QString search, config.group("Searches").readEntry("All searches", QStringList() ) )
+    {
+        search = search.simplified();
+        KConfigGroup grp = config.group(search);
+        KUrl url( QUrl( QString("nepomuksearch:/") + grp.readEntry("Query",QString() ) ) );
+
+        Search::Query::Type type;
+        QString name = queryNameFromURL(url, &type );
 
-    // all music files
-    Search::Term musicOrTerm;
-    musicOrTerm.setType( Search::Term::OrTerm );
-    musicOrTerm.addSubTerm( Search::Term( Soprano::Vocabulary::RDF::type(),
-                                          Soprano::Vocabulary::Xesam::Music() ) );
-    musicOrTerm.addSubTerm( Search::Term( Soprano::Vocabulary::RDF::type(),
-                                          Nepomuk::Vocabulary::NFO::Audio() ) );
-    addDefaultSearch( i18n( "All Music Files" ), musicOrTerm );
-
-    // select the 10 most recent files:
-    addDefaultSearch( i18n( "Recent Files" ),
-                      Search::Query( QString( "select distinct ?r where { "
-                                              "?r a %1 . "
-                                              "?r %2 ?date . "
-                                              "} ORDER BY DESC(?date) LIMIT 10" )
-                                     .arg(Soprano::Node::resourceToN3( Nepomuk::Vocabulary::NFO::FileDataObject() ))
-                                     .arg(Soprano::Node::resourceToN3( Nepomuk::Vocabulary::NFO::fileLastModified() )) ) );
+        addDefaultSearch(search, createQuery( name, type ) );
+    }
 }
 
 
@@ -91,10 +141,25 @@
 }
 
 
+bool Nepomuk::SearchProtocol::ensureNepomukRunning()
+{
+    if ( Nepomuk::ResourceManager::instance()->init() ) {
+        error( KIO::ERR_SLAVE_DEFINED, i18n( "The Nepomuk system is not activated. Unable to answer queries without it." ) );
+        return false;
+    }
+    else if ( !Nepomuk::Search::QueryServiceClient::serviceAvailable() ) {
+        error( KIO::ERR_SLAVE_DEFINED, i18n( "The Nepomuk query service is not running. Unable to answer queries without it." ) );
+        return false;
+    }
+    else {
+        return true;
+    }
+}
+
+
 void Nepomuk::SearchProtocol::addDefaultSearch( const QString& name, const Search::Query& q )
 {
     Search::Query query( q );
-    query.addRequestProperty( Soprano::Vocabulary::Xesam::url(), true );
     query.addRequestProperty( Nepomuk::Vocabulary::NIE::url(), true );
     m_defaultSearches.insert( name, query );
 }
@@ -102,13 +167,14 @@
 
 Nepomuk::SearchFolder* Nepomuk::SearchProtocol::extractSearchFolder( const KUrl& url )
 {
-    QString name = url.path().section( '/', 0, 0, QString::SectionSkipEmpty );
+    Search::Query::Type type;
+    QString name = queryNameFromURL( url, &type );
     kDebug() << url << name;
     if ( SearchFolder* sf = getDefaultQueryFolder( name ) ) {
         kDebug() << "-----> is default search folder";
         return sf;
     }
-    else if ( SearchFolder* sf = getQueryResults( name ) ) {
+    else if ( SearchFolder* sf = getQueryResults( name, type ) ) {
         kDebug() << "-----> is on-the-fly search folder";
         return sf;
     }
@@ -121,7 +187,12 @@
 
 void Nepomuk::SearchProtocol::listDir( const KUrl& url )
 {
-    kDebug() << url;
+    Search::Query::Type type;
+    QString name = queryNameFromURL( url, &type );
+    kDebug() << url << name;
+
+    if ( !ensureNepomukRunning() )
+        return;
 
     //
     // Root dir: * list default searches: "all music files", "recent files"
@@ -134,17 +205,16 @@
     //           * Look for a default search and execute that
     //
 
-    if ( url.path() == "/" ) {
+    if ( name.isEmpty() ) {
         listRoot();
     }
-    else if ( url.directory() == "/" &&
-              m_defaultSearches.contains( url.fileName() ) ) {
+    else if ( m_defaultSearches.contains( name ) ) {
         // the default search name is the folder name
-        listDefaultSearch( url.fileName() );
+        listDefaultSearch( name );
     }
     else {
         // lets create an on-the-fly search
-        listQuery( url.fileName() );
+        listQuery( name, type );
     }
 }
 
@@ -152,6 +222,10 @@
 void Nepomuk::SearchProtocol::get( const KUrl& url )
 {
     kDebug() << url;
+
+    if ( !ensureNepomukRunning() )
+        return;
+
     ForwardingSlaveBase::get( url );
 }
 
@@ -159,6 +233,10 @@
 void Nepomuk::SearchProtocol::put( const KUrl& url, int permissions, KIO::JobFlags flags )
 {
     kDebug() << url << permissions << flags;
+
+    if ( !ensureNepomukRunning() )
+        return;
+
     // this will work only for existing files (ie. overwrite to allow saving of opened files)
     ForwardingSlaveBase::put( url, permissions, flags );
 }
@@ -168,6 +246,9 @@
 {
     kDebug() << url;
 
+    if ( !ensureNepomukRunning() )
+        return;
+
     if ( url.path() == "/" ) {
         mimeType( QString::fromLatin1( "inode/directory" ) );
         finished();
@@ -187,52 +268,84 @@
 {
     kDebug() << url;
 
-    if ( url.path() == "/" ) {
-        if ( url.queryItems().isEmpty() ) {
-            kDebug() << "/";
-            //
-            // stat the root path
-            //
-            KIO::UDSEntry uds;
-            uds.insert( KIO::UDSEntry::UDS_NAME, QString::fromLatin1( "/" ) );
-            uds.insert( KIO::UDSEntry::UDS_ICON_NAME, QString::fromLatin1( "nepomuk" ) );
-            uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
-            uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
+    Search::Query::Type type;
+    QString name = queryNameFromURL( url, &type );
+    kDebug() << url << name;
 
-            statEntry( uds );
-            finished();
-        }
-        else {
-            kDebug() << "query folder:" << url.queryItemValue("query");
+    if ( !ensureNepomukRunning() )
+        return;
+
+    //
+    // Root dir: * list default searches: "all music files", "recent files"
+    //           * list configuration entries: "create new default search"
+    //
+    // Root dir with query:
+    //           * execute the query (cached) and list its results
+    //
+    // some folder:
+    //           * Look for a default search and execute that
+    //
 
-            //
-            // stat a query folder
-            //
-            KIO::UDSEntry uds;
-            uds.insert( KIO::UDSEntry::UDS_NAME, url.fileName() );
-            uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
-            uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
+    if ( name.isEmpty() ) {
+        kDebug() << "Stating root" << url;
+        //
+        // stat the root path
+        //
+        KIO::UDSEntry uds;
+        uds.insert( KIO::UDSEntry::UDS_NAME, QString::fromLatin1( "/" ) );
+        uds.insert( KIO::UDSEntry::UDS_ICON_NAME, QString::fromLatin1( "nepomuk" ) );
+        uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
+        uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
 
-            statEntry( uds );
-            finished();
-        }
+        statEntry( uds );
+        finished();
     }
-    else if ( url.directory() == "/" ) {
-        if ( SearchFolder* sf = extractSearchFolder( url ) ) {
-            KIO::UDSEntry uds = statDefaultSearchFolder( sf->name() );
-            Q_ASSERT( !uds.stringValue( KIO::UDSEntry::UDS_NAME ).isEmpty() );
-            statEntry( uds );
+    else if ( m_defaultSearches.contains( name ) ) {
+        kDebug() << "Stating default search" << url;
+        statEntry( statDefaultSearchFolder( name ) );
+        finished();
+    }
+    else if ( fileNameFromUrl(url).isEmpty() ) {
+        kDebug() << "Stating search folder" << url;
+        statEntry( statDefaultSearchFolder( name ) );
+        finished();
+    }
+    else {
+        kDebug() << "Stating file" << url;
+        ForwardingSlaveBase::stat(url);
+    }
+}
+
+
+void Nepomuk::SearchProtocol::del(const KUrl& url, bool isFile)
+{
+    if ( !ensureNepomukRunning() )
+        return;
+
+    Nepomuk::SearchFolder* folder = extractSearchFolder( url );
+
+    if (folder) {
+        if ( SearchEntry* entry = folder->findEntry( url.fileName() ) ) {
+            kDebug() << "findEntry returned something";
+
+            if ( entry->isFile() ) {
+                kDebug() << entry->resource() << "is file";
+                KIO::ForwardingSlaveBase::del(entry->entry().stringValue( KIO::UDSEntry::UDS_TARGET_URL ), isFile);
+            }
+            else {
+                kDebug() << entry->resource() << "is non file";
+                Nepomuk::Resource(entry->resource()).remove();
+            }
             finished();
         }
         else {
-            error( KIO::ERR_DOES_NOT_EXIST, url.url() );
+            kDebug() << "findEntry returned nothing";
+            error( KIO::ERR_DOES_NOT_EXIST, url.fileName() ); // not in m_entries
         }
     }
-    else if ( SearchFolder* folder = extractSearchFolder( url ) ) {
-        folder->stat( url.fileName() );
-    }
     else {
-        error( KIO::ERR_DOES_NOT_EXIST, url.url() );
+        kDebug() << "ERROR : extractSearchFolder returned NOTHING";
+        error( KIO::ERR_DOES_NOT_EXIST, url.fileName() );
     }
 }
 
@@ -244,7 +357,7 @@
     if ( SearchFolder* folder = extractSearchFolder( url ) ) {
         if ( SearchEntry* entry = folder->findEntry( url.fileName() ) ) {
             QString localPath = entry->entry().stringValue( KIO::UDSEntry::UDS_LOCAL_PATH );
-            if ( localPath.isEmpty() ) {
+            if ( !localPath.isEmpty() ) {
                 newURL = localPath;
             }
             else {
@@ -276,7 +389,7 @@
 }
 
 
-Nepomuk::SearchFolder* Nepomuk::SearchProtocol::getQueryResults( const QString& query )
+Nepomuk::SearchFolder* Nepomuk::SearchProtocol::getQueryResults( const QString& query, Search::Query::Type type )
 {
     if ( m_searchCache.contains( query ) ) {
         return m_searchCache[query];
@@ -287,8 +400,8 @@
             delete m_searchCache.take( oldestQuery );
         }
 
-        Search::Query q = Nepomuk::Search::QueryParser::parseQuery( query );
-        q.addRequestProperty( Soprano::Vocabulary::Xesam::url(), true );
+        Search::Query q = createQuery( query, type );
+
         q.addRequestProperty( Nepomuk::Vocabulary::NIE::url(), true );
         SearchFolder* folder = new SearchFolder( query, q, this );
         m_searchCacheNameQueue.enqueue( query );
@@ -314,10 +427,10 @@
 }
 
 
-void Nepomuk::SearchProtocol::listQuery( const QString& query )
+void Nepomuk::SearchProtocol::listQuery( const QString& query, Search::Query::Type type )
 {
     kDebug() << query;
-    getQueryResults( query )->list();
+    getQueryResults( query, type )->list();
 }
 
 
@@ -350,11 +463,6 @@
         KComponentData comp( "kio_nepomuksearch" );
         QCoreApplication app( argc, argv );
 
-        if ( Nepomuk::ResourceManager::instance()->init() ) {
-            kError() << "Unable to initialized Nepomuk.";
-            return -1;
-        }
-
         kDebug(7102) << "Starting nepomuksearch slave " << getpid();
 
         Nepomuk::SearchProtocol slave( argv[2], argv[3] );
diff -Nru kdebase-runtime-4.3.2/nepomuk/kioslaves/search/kio_nepomuksearch.h kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/kio_nepomuksearch.h
--- kdebase-runtime-4.3.2/nepomuk/kioslaves/search/kio_nepomuksearch.h	2008-09-26 16:55:58.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/kio_nepomuksearch.h	2009-10-26 09:52:22.000000000 +0100
@@ -40,7 +40,7 @@
         virtual ~SearchProtocol();
 
         /**
-         * 
+         *
          */
         void listDir( const KUrl& url );
 
@@ -66,6 +66,11 @@
          */
         void stat( const KUrl& url );
 
+        /**
+         * Delete resources
+         */
+        void del(const KUrl&, bool);
+
     protected:
         /**
          * reimplemented from ForwardingSlaveBase
@@ -73,8 +78,9 @@
         bool rewriteUrl( const KUrl& url, KUrl& newURL );
 
     private:
+        bool ensureNepomukRunning();
         void listRoot();
-        void listQuery( const QString& query );
+        void listQuery( const QString& query, Search::Query::Type type );
         void listActions();
         void listDefaultSearches();
         void listDefaultSearch( const QString& path );
@@ -85,7 +91,7 @@
         /**
          * Get (possibly cached) query results
          */
-        SearchFolder* getQueryResults( const QString& query );
+        SearchFolder* getQueryResults( const QString& query, Search::Query::Type type );
         SearchFolder* getDefaultQueryFolder( const QString& name );
 
         // the default search folders
diff -Nru kdebase-runtime-4.3.2/nepomuk/kioslaves/search/nepomuksearch.protocol kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/nepomuksearch.protocol
--- kdebase-runtime-4.3.2/nepomuk/kioslaves/search/nepomuksearch.protocol	2008-09-26 16:55:58.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/nepomuksearch.protocol	2009-10-26 09:52:22.000000000 +0100
@@ -5,7 +5,7 @@
 output=filesystem
 reading=true
 writing=false
-deleting=false
+deleting=true
 linking=false
 makedir=false
 moving=false
diff -Nru kdebase-runtime-4.3.2/nepomuk/kioslaves/search/searchfolder.cpp kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/searchfolder.cpp
--- kdebase-runtime-4.3.2/nepomuk/kioslaves/search/searchfolder.cpp	2009-08-27 10:17:34.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/searchfolder.cpp	2009-10-26 09:52:22.000000000 +0100
@@ -19,6 +19,7 @@
 #include "searchfolder.h"
 #include "nfo.h"
 #include "nie.h"
+#include "pimo.h"
 
 #include "queryserviceclient.h"
 
@@ -37,6 +38,7 @@
 #include <KIO/NetAccess>
 #include <KUser>
 #include <kdirnotify.h>
+#include <kdeversion.h>
 
 
 namespace {
@@ -59,9 +61,11 @@
 
 
 Nepomuk::SearchEntry::SearchEntry( const QUrl& res,
-                                   const KIO::UDSEntry& uds )
+                                   bool isFile,
+                                   const KIO::UDSEntry& uds)
     : m_resource( res ),
-      m_entry( uds )
+      m_entry( uds ),
+      m_isFile(isFile)
 {
 }
 
@@ -427,6 +431,19 @@
             uds.insert( KIO::UDSEntry::UDS_USER, KUser().loginName() );
 //        uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, "application/x-nepomuk-resource" );
         }
+#if KDE_IS_VERSION( 4, 3, 61 )
+        //
+        // We always want the display type, even for pimo thing linked files, in the
+        // end showing "Invoice" or "Letter" is better than "text file"
+        // However, mimetypes are better than generic stuff like pimo:Thing and pimo:Document
+        //
+        Nepomuk::Types::Class type( res.pimoThing().isValid() ? res.pimoThing().resourceType() : res.resourceType() );
+        if ( !isPimoThingLinkedFile ||
+             type.uri() != Nepomuk::Vocabulary::PIMO::Thing() ) {
+            if (!type.label().isEmpty())
+                uds.insert( KIO::UDSEntry::UDS_DISPLAY_TYPE, type.label() );
+        }
+#endif
 
         //
         // Although in KDE 4.3 the target url is sort of deprecated, we still set it.
@@ -461,7 +478,7 @@
         uds.insert( KIO::UDSEntry::UDS_NAME, name );
         uds.insert( KIO::UDSEntry::UDS_DISPLAY_NAME, name );
 
-        SearchEntry* entry = new SearchEntry( result.resourceUri(), uds );
+        SearchEntry* entry = new SearchEntry( result.resourceUri(), isFile, uds );
         m_entries.insert( name, entry );
         m_resourceNameMap.insert( result.resourceUri(), name );
 
diff -Nru kdebase-runtime-4.3.2/nepomuk/kioslaves/search/searchfolder.h kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/searchfolder.h
--- kdebase-runtime-4.3.2/nepomuk/kioslaves/search/searchfolder.h	2009-08-27 10:17:34.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/kioslaves/search/searchfolder.h	2009-10-26 09:52:22.000000000 +0100
@@ -48,14 +48,17 @@
     {
     public:
         SearchEntry( const QUrl& uri,
+                     bool isFile,
                      const KIO::UDSEntry& = KIO::UDSEntry() );
 
         QUrl resource() const { return m_resource; }
         KIO::UDSEntry entry() const { return m_entry; }
+        bool isFile() const  { return m_isFile; }
 
     private:
         QUrl m_resource;
         KIO::UDSEntry m_entry;
+        bool m_isFile;
 
         friend class SearchFolder;
     };
diff -Nru kdebase-runtime-4.3.2/nepomuk/libnepomukquery/dbusoperators.cpp kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/dbusoperators.cpp
--- kdebase-runtime-4.3.2/nepomuk/libnepomukquery/dbusoperators.cpp	2008-11-28 16:33:44.000000000 +0100
+++ kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/dbusoperators.cpp	2009-10-26 09:52:22.000000000 +0100
@@ -99,8 +99,9 @@
 QDBusArgument& operator<<( QDBusArgument& arg, const Nepomuk::Search::Term& term )
 {
     //
-    // Signature: (ii(isss)sss)
+    // Signature: (ibi(isss)sss)
     // i      -> type
+    // b      -> positive/negative term
     // i      -> comparator type
     // (isss) -> Soprano::LiteralValue encoded as a Soprano::Node for simplicity
     // s      -> resource
@@ -110,6 +111,7 @@
 
     arg.beginStructure();
     arg << ( int )term.type()
+        << term.positive()
         << ( int )term.comparator()
         << Soprano::Node( term.value() )
         << QString::fromAscii( term.resource().toEncoded() )
@@ -124,8 +126,9 @@
 const QDBusArgument& operator>>( const QDBusArgument& arg, Nepomuk::Search::Term& term )
 {
     //
-    // Signature: (ii(isss)sss)
+    // Signature: (ibi(isss)sss)
     // i      -> type
+    // b      -> positive/negative term
     // i      -> comparator type
     // (isss) -> Soprano::LiteralValue encoded as a Soprano::Node for simplicity
     // s      -> resource
@@ -135,16 +138,19 @@
 
     arg.beginStructure();
     int type = Nepomuk::Search::Term::InvalidTerm;
+    bool positive = true;
     int comparator = Nepomuk::Search::Term::Equal;
     Soprano::Node valueNode;
     QString resource, field, property;
     arg >> type
+        >> positive
         >> comparator
         >> valueNode
         >> resource
         >> field
         >> property;
     term.setType( Nepomuk::Search::Term::Type( type ) );
+    term.setPositive( positive );
     term.setComparator( Nepomuk::Search::Term::Comparator( comparator ) );
     if ( valueNode.isLiteral() )
         term.setValue( valueNode.literal() );
@@ -183,13 +189,14 @@
 QDBusArgument& operator<<( QDBusArgument& arg, const Nepomuk::Search::Query& query )
 {
     //
-    // Signature: (isa(ii(isss)sss)a{iai}ia{sb})
+    // Signature: (isa(ii(isss)sss)a{iai}ia{sb}a{s})
     // i      -> type
     // s      -> sparql query
     // a(ii(isss)sss)    -> array of terms (first is root term)
     // a{iai} -> hash of term relations
     // i      -> limit
     // a{sb}  -> request properties
+    // a{sb}   -> folder limits
     //
 
     arg.beginStructure();
@@ -222,6 +229,15 @@
         arg.endMapEntry();
     }
     arg.endMap();
+    
+    arg.beginMap( QVariant::String, QVariant::Bool );
+    QList<Nepomuk::Search::Query::FolderLimit> folderLimits = query.folderLimits();
+    foreach( const Nepomuk::Search::Query::FolderLimit& fl, folderLimits ) {
+        arg.beginMapEntry();
+        arg << QString::fromAscii( fl.first.toEncoded() ) << fl.second;
+        arg.endMapEntry();
+    }
+    arg.endMap();
 
     arg.endStructure();
 
@@ -244,13 +260,14 @@
 const QDBusArgument& operator>>( const QDBusArgument& arg, Nepomuk::Search::Query& query )
 {
     //
-    // Signature: (isa(ii(isss)sss)a{iai}ia{sb})
+    // Signature: (isa(ii(isss)sss)a{iai}ia{sb}a{s})
     // i      -> type
     // s      -> sparql query
     // a(ii(isss)sss)    -> array of terms (first is root term)
     // a{iai} -> hash of term relations
     // i      -> limit
     // a{sb}  -> request properties
+    // a{sb}   -> folder limits
     //
 
     arg.beginStructure();
@@ -288,6 +305,17 @@
         query.addRequestProperty( QUrl::fromEncoded( prop.toAscii() ), optional );
     }
     arg.endMap();
+    
+    arg.beginMap();
+    while( !arg.atEnd() ) {
+        QString prop;
+        bool include = true;
+        arg.beginMapEntry();
+        arg >> prop >> include;
+        arg.endMapEntry();
+        query.addFolderLimit( QUrl::fromEncoded( prop.toAscii() ), include );
+    }
+    arg.endMap();
 
     arg.endStructure();
 
diff -Nru kdebase-runtime-4.3.2/nepomuk/libnepomukquery/query.cpp kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/query.cpp
--- kdebase-runtime-4.3.2/nepomuk/libnepomukquery/query.cpp	2008-09-26 16:55:58.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/query.cpp	2009-10-26 09:52:22.000000000 +0100
@@ -38,6 +38,7 @@
     int limit;
 
     QList<RequestProperty> requestProperties;
+    QList<FolderLimit> folderLimits;
 };
 
 
@@ -145,14 +146,15 @@
 
 
 namespace {
-    bool compareRequestProperties( const QList<Nepomuk::Search::Query::RequestProperty>& rp1, const QList<Nepomuk::Search::Query::RequestProperty>& rp2 ) {
+    template<typename T>
+    bool compareQList( const QList<T>& rp1, const QList<T>& rp2 ) {
         // brute force
-        foreach( const Nepomuk::Search::Query::RequestProperty& rp, rp1 ) {
+        foreach( const T& rp, rp1 ) {
             if ( !rp2.contains( rp ) ) {
                 return false;
             }
         }
-        foreach( const Nepomuk::Search::Query::RequestProperty& rp, rp2 ) {
+        foreach( const T& rp, rp2 ) {
             if ( !rp1.contains( rp ) ) {
                 return false;
             }
@@ -167,11 +169,13 @@
          d->limit == other.d->limit ) {
         if ( d->type == SPARQLQuery ) {
             return( d->sparqlQuery == other.d->sparqlQuery &&
-                    compareRequestProperties( d->requestProperties, other.d->requestProperties ) );
+                    compareQList( d->requestProperties, other.d->requestProperties ) &&
+                    compareQList( d->folderLimits, other.d->folderLimits ) );
         }
         else {
             return( d->term == other.d->term &&
-                    compareRequestProperties( d->requestProperties, other.d->requestProperties ) );
+                    compareQList( d->requestProperties, other.d->requestProperties ) &&
+                    compareQList( d->folderLimits, other.d->folderLimits ) );
         }
     }
 
@@ -179,6 +183,24 @@
 }
 
 
+void Nepomuk::Search::Query::addFolderLimit( const QUrl& folder, bool include )
+{
+    d->folderLimits.append( qMakePair( folder, include ) );
+}
+
+
+void Nepomuk::Search::Query::clearFolderLimits()
+{
+    d->folderLimits.clear();
+}
+
+
+QList<Nepomuk::Search::Query::FolderLimit> Nepomuk::Search::Query::folderLimits() const
+{
+    return d->folderLimits;
+}
+
+
 QDebug operator<<( QDebug dbg, const Nepomuk::Search::Query& query )
 {
     dbg << "(Query" << query.term() << query.limit() << ")";
diff -Nru kdebase-runtime-4.3.2/nepomuk/libnepomukquery/query.h kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/query.h
--- kdebase-runtime-4.3.2/nepomuk/libnepomukquery/query.h	2008-09-26 16:55:58.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/query.h	2009-10-26 09:52:22.000000000 +0100
@@ -107,6 +107,20 @@
             QList<RequestProperty> requestProperties() const;
 
             bool operator==( const Query& ) const;
+            
+            /**
+             * Add a folder to the search space. If no folder limits are set, will
+             * search the entire Nepomuk database
+             * \param folder the folder to search
+             * \param include true if we should search this folder, false
+             * if we should exclude this folder from search results
+             */
+            void addFolderLimit( const QUrl& folder, bool include );
+            void clearFolderLimits();
+            
+            typedef QPair<QUrl, bool> FolderLimit;
+            
+            QList<FolderLimit> folderLimits() const;
 
         private:
             class Private;
diff -Nru kdebase-runtime-4.3.2/nepomuk/libnepomukquery/queryparser.cpp kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/queryparser.cpp
--- kdebase-runtime-4.3.2/nepomuk/libnepomukquery/queryparser.cpp	2009-02-04 19:18:10.000000000 +0100
+++ kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/queryparser.cpp	2009-10-26 09:52:22.000000000 +0100
@@ -121,6 +121,17 @@
             return Soprano::LiteralValue( d );
         return s;
     }
+    
+    bool positiveTerm( const QString& s) {
+        if(s.isEmpty())
+            return true;
+        else if(s == "+")
+            return true;
+        else if(s == "-")
+            return false;
+        else //unrecognized capture
+            return true;
+    }
 }
 
 
@@ -164,6 +175,7 @@
     // TODO: a "real" parser which can handle all of the Xesam user language
     //       This one for example does not handle nesting at all.
 
+    Nepomuk::Search::Query final;
     QList<Term> terms;
 
     bool inOrBlock = false;
@@ -181,15 +193,15 @@
 
         if ( pos < query.length() ) {
             if ( s_resourceRx.indexIn( query, pos ) == pos ) {
-                // FIXME: honour the +-
                 kDebug() << "matched resource term at" << pos << s_resourceRx.cap( 0 );
                 term = Term( tryToBeIntelligentAboutParsingUrl( s_resourceRx.cap( 2 ) ),
-                             tryToBeIntelligentAboutParsingUrl( s_resourceRx.cap( 3 ) ) );
+                             tryToBeIntelligentAboutParsingUrl( s_resourceRx.cap( 3 ) ),
+                             positiveTerm(s_resourceRx.cap( 1 ) ) );
                 pos += s_resourceRx.matchedLength();
             }
             else if ( s_propertyRx.indexIn( query, pos ) == pos ) {
-                // FIXME: honour the +-
                 kDebug() << "matched property term at" << pos << s_propertyRx.cap( 0 );
+                term.setPositive( positiveTerm(s_propertyRx.cap( 1 ) ) );
                 term.setProperty( tryToBeIntelligentAboutParsingUrl( s_propertyRx.cap( 2 ) ) );
                 term.addSubTerm( Term( createLiteral( stripQuotes( s_propertyRx.cap( 4 ) ) ) ) );
                 QString comparator = s_propertyRx.cap( 3 );
@@ -213,17 +225,24 @@
                 pos += s_fieldFieldRx.matchedLength();
             }
             else if ( s_fieldRx.indexIn( query, pos ) == pos ) {
-                // FIXME: honour the +-
                 kDebug() << "matched field term at" << pos << s_fieldRx.cap( 0 ) << s_fieldRx.cap( 2 ) << s_fieldRx.cap( 4 ) << s_fieldRx.cap( 5 );
-                term.setField( stripQuotes( s_fieldRx.cap( 2 ) ) );
-                term.addSubTerm( Term( createLiteral( stripQuotes( s_fieldRx.cap( 5 ) ) ) ) );
-                QString comparator = s_fieldRx.cap( 4 );
-                term.setType( Term::ComparisonTerm );
-                term.setComparator( fieldTypeRelationFromString( comparator ) );
-                pos += s_fieldRx.matchedLength();
+                if( stripQuotes ( s_fieldRx.cap( 2 ) ).compare( QString( "inFolder" ), Qt::CaseInsensitive ) == 0 ) {
+                    QUrl path = QUrl::fromLocalFile( s_fieldRx.cap( 5 ) );
+                    kDebug() << "found include path" << path;
+                    final.addFolderLimit( path, positiveTerm( s_fieldRx.cap( 1 ) ) );
+                    pos += s_fieldRx.matchedLength();
+                }
+                else {
+                    term.setField( stripQuotes( s_fieldRx.cap( 2 ) ) );
+                    term.setPositive( positiveTerm( s_fieldRx.cap( 1 ) ) );
+                    term.addSubTerm( Term( createLiteral( stripQuotes( s_fieldRx.cap( 5 ) ) ) ) );
+                    QString comparator = s_fieldRx.cap( 4 );
+                    term.setType( Term::ComparisonTerm );
+                    term.setComparator( fieldTypeRelationFromString( comparator ) );
+                    pos += s_fieldRx.matchedLength();
+                }
             }
             else if ( s_plainTermRx.indexIn( query, pos ) == pos ) {
-                // FIXME: honour the +-
                 QString value = stripQuotes( s_plainTermRx.cap( 2 ) );
                 if ( d->orKeywords.contains( value.toLower() ) ) {
                     inOrBlock = true;
@@ -233,7 +252,7 @@
                 }
                 else {
                     kDebug() << "matched literal at" << pos << value;
-                    term = Term( Soprano::LiteralValue( value ) );
+                    term = Term( Soprano::LiteralValue( value ), positiveTerm(s_plainTermRx.cap( 1 ) ) );
                 }
                 pos += s_plainTermRx.matchedLength();
             }
@@ -265,15 +284,17 @@
     }
 
     if ( terms.count() == 1 ) {
-        return terms[0];
+        final.setTerm( terms[0] );
+        return final;
     }
     else if ( terms.count() > 0 ) {
         Term t;
         t.setType( Term::AndTerm );
         t.setSubTerms( terms );
-        return t;
+        final.setTerm( t );
+        return final;
     }
     else {
-        return Term();
+        return final;
     }
 }
diff -Nru kdebase-runtime-4.3.2/nepomuk/libnepomukquery/term.cpp kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/term.cpp
--- kdebase-runtime-4.3.2/nepomuk/libnepomukquery/term.cpp	2009-02-04 19:18:10.000000000 +0100
+++ kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/term.cpp	2009-10-26 09:52:22.000000000 +0100
@@ -28,12 +28,14 @@
 class Nepomuk::Search::Term::Private : public QSharedData
 {
 public:
-    Private( Type t = InvalidTerm, Comparator c = Equal )
+    Private( Type t = InvalidTerm, bool p = true, Comparator c = Equal )
         : type( t ),
+          positive( p ),
           comparator( c ) {
     }
 
     Type type;
+    bool positive;
     Comparator comparator;
     Soprano::LiteralValue value;
     QUrl resource;
@@ -55,8 +57,8 @@
 }
 
 
-Nepomuk::Search::Term::Term( const Soprano::LiteralValue& value )
-    : d( new Private( LiteralTerm ) )
+Nepomuk::Search::Term::Term( const Soprano::LiteralValue& value, bool isPositive )
+    : d( new Private( LiteralTerm, isPositive ) )
 {
     d->value = value;
 }
@@ -69,24 +71,24 @@
 }
 
 
-Nepomuk::Search::Term::Term( const QString& field, const Soprano::LiteralValue& value, Comparator c )
-    : d( new Private( ComparisonTerm, c ) )
+Nepomuk::Search::Term::Term( const QString& field, const Soprano::LiteralValue& value, bool isPositive, Comparator c )
+    : d( new Private( ComparisonTerm, isPositive, c ) )
 {
     d->field = field;
     d->subTerms.append( Term( value ) );
 }
 
 
-Nepomuk::Search::Term::Term( const QUrl& field, const Soprano::LiteralValue& value, Comparator c )
-    : d( new Private( ComparisonTerm, c ) )
+Nepomuk::Search::Term::Term( const QUrl& field, const Soprano::LiteralValue& value, bool isPositive, Comparator c )
+    : d( new Private( ComparisonTerm, isPositive, c ) )
 {
     d->property = field;
     d->subTerms.append( Term( value ) );
 }
 
 
-Nepomuk::Search::Term::Term( const QUrl& field, const QUrl& resource )
-    : d( new Private( ComparisonTerm ) )
+Nepomuk::Search::Term::Term( const QUrl& field, const QUrl& resource, bool isPositive )
+    : d( new Private( ComparisonTerm, isPositive ) )
 {
     d->property = field;
     d->subTerms.append( Term( resource ) );
@@ -139,6 +141,12 @@
 }
 
 
+bool Nepomuk::Search::Term::positive() const
+{
+    return d->positive;
+}
+
+
 Nepomuk::Search::Term::Type Nepomuk::Search::Term::type() const
 {
     return d->type;
@@ -181,6 +189,12 @@
 }
 
 
+void Nepomuk::Search::Term::setPositive( bool positive )
+{
+    d->positive = positive;
+}
+
+
 void Nepomuk::Search::Term::setType( Type type )
 {
     d->type = type;
@@ -312,6 +326,8 @@
         default:
             break;
         }
+        if( !term.positive() )
+            dbg << "( negative )";
         if ( term.type() == Nepomuk::Search::Term::ComparisonTerm ) {
             if ( term.property().isValid() ) {
                 dbg << "Property" << term.property();
@@ -340,12 +356,13 @@
 {
     switch( term.type() ) {
     case Nepomuk::Search::Term::LiteralTerm:
-        return qHash( term.value().toString() );
+        return( qHash( term.value().toString() )<<8 | ( uint )term.positive() );
 
     case Nepomuk::Search::Term::ComparisonTerm:
-        return( qHash( term.property().isValid() ?  term.property().toString() : term.field() )<<16 |
-                qHash( term.subTerms().first() )<<8 |
-                ( uint )term.comparator() );
+        return( qHash( term.property().isValid() ?  term.property().toString() : term.field() )<<24 |
+                qHash( term.subTerms().first() )<<16 |
+                ( uint )term.comparator()<<8  |
+                ( uint )term.positive() );
 
     case Nepomuk::Search::Term::AndTerm:
     case Nepomuk::Search::Term::OrTerm: {
diff -Nru kdebase-runtime-4.3.2/nepomuk/libnepomukquery/term.h kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/term.h
--- kdebase-runtime-4.3.2/nepomuk/libnepomukquery/term.h	2008-10-30 15:13:02.000000000 +0100
+++ kdebase-runtime-4.3.2-new/nepomuk/libnepomukquery/term.h	2009-10-26 09:52:22.000000000 +0100
@@ -107,7 +107,7 @@
             /**
              * Construct a literal term.
              */
-            Term( const Soprano::LiteralValue& value );
+            Term( const Soprano::LiteralValue& value, bool isPositive = true );
 
             /**
              * Construct a resource term.
@@ -121,7 +121,7 @@
              *        types are converted to string.
              * \param comparator The Comparator to use
              */
-            Term( const QString& field, const Soprano::LiteralValue& value, Comparator c = Contains );
+            Term( const QString& field, const Soprano::LiteralValue& value, bool isPositive = true, Comparator c = Contains );
 
             /**
              * Construct a Contains ComparisonTerm term.
@@ -130,14 +130,14 @@
              *        types are converted to string.
              * \param comparator The Comparator to use
              */
-            Term( const QUrl& field, const Soprano::LiteralValue& value, Comparator c = Contains );
+            Term( const QUrl& field, const Soprano::LiteralValue& value, bool isPositive = true, Comparator c = Contains );
 
             /**
              * Construct an EqualityTerm term.
              * \param field The exact field to match
              * \param value The resource that should be matched.
              */
-            Term( const QUrl& field, const QUrl& resource );
+            Term( const QUrl& field, const QUrl& resource, bool isPositive = true );
 
             /**
              * Destructor
@@ -158,6 +158,11 @@
              * \return \p true if the Term is valid.
              */
             bool isValid() const;
+            
+            /**
+            * \return \p true is the Term is positive
+            */
+            bool positive() const;
 
             /**
              * \return the Term type.
@@ -208,6 +213,11 @@
              * \sa setSubTerms, addSubTerm
              */
             QList<Term> subTerms() const;
+            
+            /**
+             * Sets whether or not this term is positive
+             */
+            void setPositive( bool );
 
             /**
              * Set the type of the Term
diff -Nru kdebase-runtime-4.3.2/nepomuk/services/queryservice/CMakeLists.txt kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/CMakeLists.txt
--- kdebase-runtime-4.3.2/nepomuk/services/queryservice/CMakeLists.txt	2009-07-21 17:18:36.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/CMakeLists.txt	2009-10-26 09:52:22.000000000 +0100
@@ -2,8 +2,6 @@
 
 include(SopranoAddOntology)
 
-add_definitions(-DKDE_DEFAULT_DEBUG_AREA=300104)
-
 include_directories(
   ${QT_INCLUDES}
   ${KDE4_INCLUDES}
@@ -17,6 +15,7 @@
   searchthread.cpp
   folder.cpp
   folderconnection.cpp
+  dateparser.cpp
   ${nepomuk_SOURCE_DIR}/libnepomukquery/result.cpp
   ${nepomuk_SOURCE_DIR}/libnepomukquery/query.cpp
   ${nepomuk_SOURCE_DIR}/libnepomukquery/term.cpp
@@ -24,6 +23,12 @@
   ${nepomuk_SOURCE_DIR}/libnepomukquery/dbusoperators.cpp
 )
 
+#find_file(NFO_TRIG_SOURCE 
+#  nfo.trig
+#  PATHS "${KDE4_DATA_INSTALL_DIR}/.." "${KDE4_DATA_INSTALL_DIR}" ENV XDG_DATA_DIRS
+#  PATH_SUFFIXES "apps/nepomuk/ontologies"
+#  NO_DEFAULT_PATH
+#  )
 soprano_add_ontology(queryservice_SRCS
   ${nepomukontologies_SOURCE_DIR}/nfo.trig
   "NFO"
diff -Nru kdebase-runtime-4.3.2/nepomuk/services/queryservice/dateparser.cpp kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/dateparser.cpp
--- kdebase-runtime-4.3.2/nepomuk/services/queryservice/dateparser.cpp	1970-01-01 01:00:00.000000000 +0100
+++ kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/dateparser.cpp	2009-10-26 09:52:22.000000000 +0100
@@ -0,0 +1,356 @@
+/*
+* This file is part of the Nepomuk KDE project.
+* Copyright (c) 2009 Adam Kidder <thekidder@gmail.com>
+* Copyright (c) 2009 Sebastian Trueg <trueg@kde.org>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public License
+* along with this library; see the file COPYING.LIB.  If not, write to
+* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+* Boston, MA 02110-1301, USA.
+*/
+
+#include "dateparser.h"
+
+#include <KDebug>
+
+#include <QtCore/QLocale>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVector>
+
+
+namespace {
+    //represents a time difference from the current time, to represent relative dates
+    struct time_difference
+    {
+        time_difference() : seconds(0), minutes(0), hours(0), days(0), weeks(0), months(0), years(0) {}
+        int seconds, minutes, hours, days, weeks, months, years;
+    };
+
+    struct format
+    {
+        format() : pos(0) {}
+        format(const QRegExp& r, const QStringList& f) : regex(r), pos(0), useRelativeDate(false), formats(f) {}
+        format(const QRegExp& r, const time_difference& d, bool dr = false) : regex(r), pos(0), useRelativeDate(true), difference(d), dynamicRelative(dr) {}
+        QRegExp regex;
+        int pos;
+
+        bool useRelativeDate;
+        time_difference difference;
+        bool dynamicRelative;
+        QStringList formats;
+    };
+
+    struct date_string
+    {
+        QDate date;
+        unsigned int pos;
+        unsigned int length;
+    };
+}
+
+class Nepomuk::Search::DateParser::Private
+{
+public:
+    Private(const QString& text, unsigned int flags) :
+        m_text(text), m_locale(QLocale::English), m_flags(flags) {
+        //TODO: we are english-only here!
+        QStringList longMonthNames;
+        QStringList shortMonthNames;
+        for ( int i = 1; i <= 12; ++i ) {
+            longMonthNames << m_locale.monthName( i, QLocale::LongFormat );
+            shortMonthNames << m_locale.monthName( i, QLocale::ShortFormat );
+        }
+
+        // DD.MM.YYYY
+        format date1( QRegExp( "\\b\\d{1,2}\\.\\d{1,2}\\.\\d{4,4}\\b" ), QStringList("d.M.yyyy") );
+
+        // DD.MM.YY
+        format date2( QRegExp( "\\b\\d{1,2}\\.\\d{1,2}\\.\\d{2,2}\\b" ), QStringList("d.M.yy") );
+
+        // MM/DD/YYYY
+        format date3( QRegExp( "\\b\\d{1,2}/\\d{1,2}/\\d{4,4}\\b" ), QStringList("M/d/yyyy") );
+
+        // YYYY-MM-DD
+        format date13(QRegExp( "\\b\\d{4,4}-\\d{1,2}-\\d{1,2}\\b" ), QStringList("yyyy-M-d") );
+
+        // MM/DD/YY
+        format date4( QRegExp( "\\b\\d{1,2}/\\d{1,2}/\\d{2,2}\\b" ), QStringList("M/d/yy") );
+
+        // January MM [YYYY] (no word boundry at the end for 'st' or 'nd' or 'th') (also excluding ranges)
+        format date5( QRegExp( QString( "\\b(%1)\\s\\d{1,2}(?!(\\d|\\s?-\\s?\\d))(\\s\\d{4,4})?" ).arg( longMonthNames.join( "|" ) ) ),
+            QStringList("MMMM d") << QString("MMMM d yyyy") );
+
+        // January, MM [YYYY] (no word boundry at the end for 'st' or 'nd' or 'th') (also excluding ranges)
+        format date6( QRegExp( QString( "\\b(%1),\\s?\\d{1,2}(?!(\\d|\\s?-\\s?\\d))(\\s\\d{4,4})?" ).arg( longMonthNames.join( "|" ) ) ),
+            QStringList("MMMM, d") << QString("MMMM,d") << QString("MMMM, d yyyy") << QString("MMMM,d yyyy") );
+
+        // FIXME: trueg: IMHO something like "yesterday" should result in a range if not used with < or >.
+
+        //TODO: english only again!
+        time_difference days;
+        days.days = -1;
+        format date7( QRegExp( QString( "\\b(yesterday)\\b" ) ), days );
+
+        format date8( QRegExp( QString( "\\b(\\d{1,3}) (day)s? ago\\b" ) ), days, true );
+
+        time_difference weeks;
+        weeks.weeks = -1;
+        format date9( QRegExp( QString( "\\ba week ago\\b" ) ), weeks );
+
+        format date10( QRegExp( QString( "\\b(\\d{1,3}) (week)s? ago\\b" ) ), weeks, true );
+
+        time_difference months;
+        months.months = -1;
+        format date11( QRegExp( QString( "\\ba month ago\\b" ) ), months );
+
+        format date12( QRegExp( QString( "\\b(\\d{1,3}) (month)s? ago\\b" ) ), months, true );
+
+        m_regexes.push_back( date1 );
+        m_regexes.push_back( date2 );
+        m_regexes.push_back( date3 );
+        m_regexes.push_back( date4 );
+        m_regexes.push_back( date5 );
+        m_regexes.push_back( date6 );
+        m_regexes.push_back( date7 );
+        m_regexes.push_back( date8 );
+        m_regexes.push_back( date9 );
+        m_regexes.push_back( date10);
+        m_regexes.push_back( date11);
+        m_regexes.push_back( date12);
+        m_regexes.push_back( date13);
+    }
+
+
+    bool hasDate() {
+        if(!m_dates.empty()) return true;
+
+        while(m_dates.empty() && !finishedParsing())
+        {
+            parseAllRegexes();
+        }
+
+        if(!m_dates.empty()) return true;
+        return false;
+    }
+
+
+    QDate getDate() {
+        if( !m_dates.isEmpty() )
+            return m_dates.first().date;
+        else
+            return QDate();
+    }
+
+    void next() {
+        m_dates.pop_front();
+    }
+
+    unsigned int length() const {
+        if( !m_dates.isEmpty() )
+            return m_dates.first().length;
+        else
+            return 0;
+    }
+
+    unsigned int pos() const {
+        if( !m_dates.isEmpty() )
+            return m_dates.first().pos;
+        else
+            return 0;
+    }
+    int dateObject;
+
+private:
+    bool finishedParsing() {
+        foreach(format r, m_regexes) {
+            if(r.pos != -1) return false;
+        }
+        return true;
+    }
+
+
+    void parseAllRegexes() {
+        QVector<format>::iterator it ;
+        for(it = m_regexes.begin(); it != m_regexes.end(); ++it) {
+            it->pos = it->regex.indexIn(m_text, it->pos);
+            if( it->pos == -1 )
+                continue;
+            if( !it->useRelativeDate && (m_flags & AbsoluteDates) ) {
+                foreach(QString format, it->formats) {
+                    QDate date = m_locale.toDate( it->regex.cap( 0 ), format );
+                    if(date.isValid()) {
+                        if(!format.contains( "yy" ) )
+                            date.setDate( QDate::currentDate().year(), date.month(), date.day() );
+                        kDebug() << "Found absolute date:" << date;
+                        date_string dateObject;
+                        dateObject.date = date;
+                        dateObject.pos = it->pos;
+                        dateObject.length = it->regex.matchedLength();
+                        m_dates.append( dateObject );
+                        break;
+                    }
+                }
+            }
+            else if( m_flags & RelativeDates) {
+                int amount = 1;
+                if( it->dynamicRelative ) {
+                    amount = it->regex.cap( 1 ).toInt();
+                    kDebug() << "dynamic relative date, amount is" << amount << it->regex.cap( 1 );
+                }
+                QDate current( QDate::currentDate() );
+                current = current.addDays( it->difference.days * amount );
+                current = current.addDays( it->difference.weeks * 7 * amount );
+                current = current.addMonths( it->difference.months * amount );
+                current = current.addYears( it->difference.years * amount );
+
+                kDebug() << "Found relative date:" << current << it->regex.pattern();
+                date_string dateObject;
+                dateObject.date = current;
+                dateObject.pos = it->pos;
+                dateObject.length = it->regex.matchedLength();
+                m_dates.append( dateObject );
+            }
+        }
+    }
+
+
+    const QString& m_text;
+    QLocale m_locale;
+    QVector<format> m_regexes;
+    QList<date_string> m_dates;
+    unsigned int m_flags;
+};
+
+
+
+Nepomuk::Search::DateParser::DateParser(const QString& text, unsigned int flags) :
+    d( new Private(text, flags) ) {
+}
+
+
+Nepomuk::Search::DateParser::~DateParser() {
+    delete d;
+}
+
+bool Nepomuk::Search::DateParser::hasDate() {
+    return d->hasDate();
+}
+
+QDate Nepomuk::Search::DateParser::getDate() {
+    return d->getDate();
+}
+
+void Nepomuk::Search::DateParser::next() {
+    d->next();
+}
+
+unsigned int Nepomuk::Search::DateParser::pos() const {
+    return d->pos();
+}
+
+unsigned int Nepomuk::Search::DateParser::length() const {
+    return d->length();
+}
+
+class Nepomuk::Search::TimeParser::Private
+{
+public:
+    Private(const QString& text) : m_text(text), m_locale(QLocale::English) {
+        // hh:mm[pm|am]
+        format time1( QRegExp( "\\b\\d{1,2}\\:\\d{2,2}\\s?(pm|am|AM|PM)?\\b" ), QStringList("h:map") << QString("h:m ap") );
+
+        // hh:mm
+        format time2( QRegExp( "\\b\\d{1,2}\\:\\d{2,2}\\b(?!\\s?(pm|am|AM|PM))\\b" ), QStringList("h:m") );
+
+        m_regexes.push_back( time1 );
+        m_regexes.push_back( time2 );
+    }
+
+
+    bool hasTime() {
+        if(!m_times.empty()) return true;
+
+        while(m_times.empty() && !finishedParsing())
+        {
+            parseAllRegexes();
+        }
+
+        if(!m_times.empty()) return true;
+        return false;
+    }
+
+
+    QTime next() {
+        return m_times.takeFirst();
+    }
+private:
+    bool finishedParsing() {
+        foreach(format r, m_regexes) {
+            if(r.pos != -1) return false;
+        }
+        return true;
+    }
+
+
+    void parseAllRegexes() {
+        QVector<format>::iterator it ;
+        for(it = m_regexes.begin(); it != m_regexes.end(); ++it) {
+            it->pos = it->regex.indexIn(m_text, it->pos);
+            if( !it->useRelativeDate ) {
+                foreach(QString format, it->formats) {
+                    QTime time = m_locale.toTime( it->regex.cap( 0 ), format );
+                    if(time.isValid()) {
+                        kDebug() << "Found time:" << time;
+                        m_times.append( time );
+                        break;
+                    }
+                }
+            }
+            else {
+                QTime current( QTime::currentTime() );
+                current.addSecs( it->difference.seconds );
+                current.addSecs( it->difference.minutes * 60 );
+                current.addSecs( it->difference.hours * 60 * 60 );
+
+                kDebug() << "Found time:" << current;
+                m_times.append( current );
+                break;
+            }
+        }
+    }
+
+
+    const QString& m_text;
+    QLocale m_locale;
+    QVector<format> m_regexes;
+    QList<QTime> m_times;
+};
+
+
+
+Nepomuk::Search::TimeParser::TimeParser(const QString& text) : d( new Private(text) ) {
+}
+
+
+Nepomuk::Search::TimeParser::~TimeParser() {
+    delete d;
+}
+
+bool Nepomuk::Search::TimeParser::hasTime() {
+    return d->hasTime();
+}
+
+QTime Nepomuk::Search::TimeParser::next() {
+    return d->next();
+}
diff -Nru kdebase-runtime-4.3.2/nepomuk/services/queryservice/dateparser.h kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/dateparser.h
--- kdebase-runtime-4.3.2/nepomuk/services/queryservice/dateparser.h	1970-01-01 01:00:00.000000000 +0100
+++ kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/dateparser.h	2009-10-26 09:52:22.000000000 +0100
@@ -0,0 +1,83 @@
+/*
+* This file is part of the Nepomuk KDE project.
+* Copyright (c) 2009 Adam Kidder <thekidder@gmail.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public License
+* along with this library; see the file COPYING.LIB.  If not, write to
+* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+* Boston, MA 02110-1301, USA.
+*/
+
+#include <QtCore/QDate>
+#include <QtCore/QTime>
+
+
+namespace Nepomuk {
+    namespace Search {
+        /*DateTimeParser parses a string to extract QDateTime object(s). It is (will be) capable of extracting:
+          * fully qualified date times
+          * times qualified using a specified date
+          * dates qualified with a specified time
+        */
+        class DateTimeParser 
+        {
+        public:
+            DateTimeParser(const QString& dateTimeString);
+            
+            
+        private:
+            const QString& text;
+        };
+        
+        
+        class DateParser
+        {
+        public:
+            //flags
+            const static unsigned int AbsoluteDates = 0x1;
+            const static unsigned int RelativeDates = 0x2;
+
+            DateParser(const QString& dateString, unsigned int flags = AbsoluteDates | RelativeDates);
+            ~DateParser();
+            
+            //true if another date has been found
+            bool hasDate();
+            //advances to the next date
+            void next();
+            
+            //next 3 functions only valid if hasDate()
+            QDate getDate();
+            //position of current extracted date
+            unsigned int pos() const;
+            //length of current extracted date string
+            unsigned int length() const;
+        private:
+            class Private;
+            Private* const d;
+        };
+        
+        //FIXME: code duplication in DateParser and TimeParser
+        class TimeParser
+        {
+        public:
+            TimeParser(const QString& timeString);
+            ~TimeParser();
+            
+            bool hasTime();
+            QTime next();
+        private:
+            class Private;
+            Private* const d;
+        };
+    }
+}
\ No newline at end of file
diff -Nru kdebase-runtime-4.3.2/nepomuk/services/queryservice/searchcore.cpp kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/searchcore.cpp
--- kdebase-runtime-4.3.2/nepomuk/services/queryservice/searchcore.cpp	2009-08-27 10:17:34.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/searchcore.cpp	2009-10-26 09:52:22.000000000 +0100
@@ -31,7 +31,7 @@
 {
 public:
     Private()
-        : cutOffScore( 0.0 ),
+        : cutOffScore( 0.0 ), // TODO: make this configurable through the service API
           active( false ),
           canceled( false ) {
     }
diff -Nru kdebase-runtime-4.3.2/nepomuk/services/queryservice/searchcore.h kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/searchcore.h
--- kdebase-runtime-4.3.2/nepomuk/services/queryservice/searchcore.h	2009-08-27 10:17:34.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/searchcore.h	2009-10-26 09:52:22.000000000 +0100
@@ -54,7 +54,7 @@
 
         public Q_SLOTS:
             void query( const Query& query );
-            
+
             void cancel();
 
             /**
diff -Nru kdebase-runtime-4.3.2/nepomuk/services/queryservice/searchthread.cpp kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/searchthread.cpp
--- kdebase-runtime-4.3.2/nepomuk/services/queryservice/searchthread.cpp	2009-07-21 17:18:36.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/searchthread.cpp	2009-10-26 09:52:22.000000000 +0100
@@ -17,6 +17,7 @@
   Boston, MA 02110-1301, USA.
 */
 
+#include "dateparser.h"
 #include "searchthread.h"
 #include "term.h"
 #include "nfo.h"
@@ -43,9 +44,12 @@
 #include <Soprano/Vocabulary/Xesam>
 
 #include <KDebug>
+#include <KDateTime>
 #include <KRandom>
 
 #include <QtCore/QTime>
+#include <QLatin1String>
+#include <QStringList>
 
 
 
@@ -94,6 +98,24 @@
         return es;
     }
 
+    QString createFolderFilterStringSparql( const Nepomuk::Search::SearchNode& node, const QString& varName = QString( "?r" ) )
+    {
+        QStringList positive, negative;
+        QString filter;
+
+        QList<Nepomuk::Search::Query::FolderLimit>::const_iterator it;
+        for( it = node.folderLimits.constBegin(); it != node.folderLimits.constEnd(); ++it ) {
+            QStringList& ref = it->second ? positive : negative;
+            ref.append( QString::fromAscii( it->first.toEncoded( QUrl::StripTrailingSlash ) ) );
+        }
+
+        if( !positive.isEmpty() )
+            filter += QString( " FILTER(REGEX(STR(%1), \"^%2/\")) ." ).arg( varName ).arg( positive.join( "|" ) );
+        if( !negative.isEmpty() )
+            filter += QString( " FILTER(!REGEX(STR(%1), \"^%2/\")) ." ).arg( varName ).arg( negative.join( "|" ) );
+        return filter;
+    }
+
     QString luceneQueryEscape( const QUrl& s ) {
         return luceneQueryEscape( QString::fromAscii( s.toEncoded() ) );
     }
@@ -107,12 +129,35 @@
         }
     }
 
+    QString createFolderFilterStringLucene( const Nepomuk::Search::SearchNode& node )
+    {
+        QStringList positive, negative;
+        QString filter;
+
+        QList<Nepomuk::Search::Query::FolderLimit>::const_iterator it;
+        for( it = node.folderLimits.constBegin(); it != node.folderLimits.constEnd(); ++it ) {
+            QStringList& ref = it->second ? positive : negative;
+            QString notTerm = it->second ? QString() : QString( "NOT" );
+            ref.append( QString( "%1 id:%2/*" ).arg( notTerm ).arg( luceneQueryEscape( it->first ) ) );
+        }
+
+        if( !positive.isEmpty() )
+            filter += QString( " AND ( %1) " ).arg( positive.join( " OR " ) );
+        if( !negative.isEmpty() )
+            filter += QString( " AND %1 " ).arg( negative.join( " AND " ) );
+        return filter;
+    }
+
     QString createLuceneQuery( const Nepomuk::Search::SearchNode& node ) {
+        const QString notTerm = node.term.positive() ? QLatin1String("") : QLatin1String( "NOT " );
+
+        QString filterString = createFolderFilterStringLucene( node );
+
         if ( node.term.type() == Nepomuk::Search::Term::LiteralTerm ) {
-            return createLuceneLiteralQuery( luceneQueryEscape( node.term.value().toString() ) );
+            return notTerm + createLuceneLiteralQuery( luceneQueryEscape( node.term.value().toString() ) ) + filterString;
         }
         else if ( node.term.type() == Nepomuk::Search::Term::ComparisonTerm ) {
-            return luceneQueryEscape( node.term.property() ) + ':' + createLuceneLiteralQuery( luceneQueryEscape( node.term.subTerms().first().value().toString() ) );
+            return notTerm + luceneQueryEscape( node.term.property() ) + ':' + createLuceneLiteralQuery( luceneQueryEscape( node.term.subTerms().first().value().toString() ) ) + filterString;
         }
         else {
             Q_ASSERT( node.term.type() == Nepomuk::Search::Term::AndTerm ||
@@ -151,6 +196,24 @@
     }
 
 
+    Nepomuk::Search::Term::Comparator oppositeComparator( Nepomuk::Search::Term::Comparator c ) {
+        switch( c ) {
+            case Nepomuk::Search::Term::Greater:
+                return Nepomuk::Search::Term::SmallerOrEqual;
+            case Nepomuk::Search::Term::Smaller:
+                return Nepomuk::Search::Term::GreaterOrEqual;
+            case Nepomuk::Search::Term::GreaterOrEqual:
+                return Nepomuk::Search::Term::Smaller;
+            case Nepomuk::Search::Term::SmallerOrEqual:
+                return Nepomuk::Search::Term::Greater;
+            default:
+                kDebug() << "Unknown or invalid comparator:" << comparatorString(c);
+                //to remove warnings we return Contains as default
+                return Nepomuk::Search::Term::Contains;
+        }
+    }
+
+
     bool isNumberLiteralValue( const Soprano::LiteralValue& value ) {
         return value.isInt() || value.isInt64() || value.isUnsignedInt() || value.isUnsignedInt64() || value.isDouble();
     }
@@ -168,11 +231,14 @@
 
     QString createGraphPattern( const Nepomuk::Search::SearchNode& node, int& varCnt, const QString& varName = QString( "?r" ) )
     {
+        //TODO: ugly code, refactor :(
         switch( node.term.type() ) {
         case Nepomuk::Search::Term::ComparisonTerm: {
 
             Nepomuk::Search::Term subTerm( node.term.subTerms().first() );
 
+            QString filterString = createFolderFilterStringSparql( node );
+
             //
             // is the subterm (we only support one ATM) a final term (no further subterms)
             // -> actually match the literal or resource
@@ -180,11 +246,12 @@
             if ( subTerm.type() == Nepomuk::Search::Term::ResourceTerm ||
                  subTerm.type() == Nepomuk::Search::Term::LiteralTerm ) {
                 if( node.term.comparator() != Nepomuk::Search::Term::Equal ) {
+                    Nepomuk::Search::Term::Comparator c = node.term.positive() ? node.term.comparator() : oppositeComparator( node.term.comparator() );
                     // For numbers there is no need for quotes + this way we can handle all the xsd decimal types
                     // FIXME: it may be necessary to escape stuff
                     QString filter = QString( "?var%1 %2 " )
                                      .arg( ++varCnt )
-                                     .arg( comparatorString( node.term.comparator() ) );
+                                     .arg( comparatorString( c ) );
                     if ( isNumberLiteralValue( subTerm.value() ) ) {
                         filter += subTerm.value().toString();
                     }
@@ -195,19 +262,31 @@
                             filter += QString( "^^<%1>" ).arg( prop.literalRangeType().dataTypeUri().toString() );
                     }
 
-                    return wrapInInstanceBaseGraphQuery( QString( "%1 <%2> ?var%3 . FILTER(%4) . " )
+                    return wrapInInstanceBaseGraphQuery( QString( "%1 <%2> ?var%3 . FILTER(%4) . %5" )
                                                          .arg( varName )
                                                          .arg( QString::fromAscii( node.term.property().toEncoded() ) )
                                                          .arg( varCnt )
-                                                         .arg( filter ) );
+                                                         .arg( filter )
+                                                         .arg( filterString ) );
                 }
                 else {
                     if ( subTerm.type() == Nepomuk::Search::Term::ResourceTerm ) {
-                        return wrapInInstanceBaseGraphQuery( QString( "%1 <%2> <%3> . " )
-                                                             .arg( varName )
-                                                             .arg( QString::fromAscii( node.term.property().toEncoded() ) )
-                                                             .arg( QString::fromAscii( subTerm.resource().toEncoded() ) ) );
+                        QString resourceLiteral( QString::fromAscii( subTerm.resource().toEncoded() ) );
+                        QString resource = node.term.positive() ? Soprano::Node::resourceToN3( resourceLiteral ) : QString( "?v" );
+                        QString baseTerm = QString( "%1 <%2> %3 . %4" )
+                                           .arg( varName )
+                                           .arg( QString::fromAscii( node.term.property().toEncoded() ) )
+                                           .arg( resource )
+                                           .arg( filterString );
+                        if( node.term.positive() )
+                            return wrapInInstanceBaseGraphQuery( baseTerm );
+                        else {
+                            return QString( " %1 OPTIONAL { %2 } FILTER(!BOUND(?v))" )
+                                   .arg( wrapInInstanceBaseGraphQuery( QString ( "%1 a ?type . " ).arg( varName ) ) )
+                                   .arg( wrapInInstanceBaseGraphQuery( baseTerm + QString(" FILTER(?v = <%1>) . ").arg( resourceLiteral ) ) );
+                        }
                     }
+                    //TODO: negation, folder filters here
                     else if ( Nepomuk::Types::Property( node.term.property() ).range().isValid() ) {
                         return wrapInInstanceBaseGraphQuery( QString( "%1 %2 ?x . " )
                                                              .arg( varName )
@@ -230,13 +309,14 @@
                         // property is defined to range to a plain one.
                         //
                         Nepomuk::Types::Property p( node.term.property() );
-                        return wrapInInstanceBaseGraphQuery( QString( "%1 <%2> \"%3\"^^<%4> . " )
+                        return wrapInInstanceBaseGraphQuery( QString( "%1 <%2> \"%3\"^^<%4> . %5" )
                                                              .arg( varName )
                                                              .arg( QString::fromAscii( node.term.property().toEncoded() ) )
                                                              .arg( subTerm.value().toString() )
                                                              .arg( p.literalRangeType().dataTypeUri() == Soprano::Vocabulary::RDFS::Literal()
                                                                    ? Soprano::Vocabulary::XMLSchema::string().toString()
-                                                                   : p.literalRangeType().dataTypeUri().toString() ) );
+                                                                   : p.literalRangeType().dataTypeUri().toString() )
+                                                             .arg( filterString ) );
                     }
                 }
             }
@@ -279,6 +359,57 @@
 
         return QString();
     }
+
+
+    QDateTime parseDateTime( const Soprano::LiteralValue& literal ) {
+        //TODO: change to DateTime parser once complete
+        Nepomuk::Search::DateParser date( literal.toString() );
+        if( date.hasDate() )
+            return QDateTime( date.getDate() );
+        else
+        {
+            Nepomuk::Search::TimeParser time( literal.toString() );
+            if(time.hasTime() )
+                return QDateTime(QDate::currentDate(), time.next() );
+            else
+                return QDateTime(); //return invalid datetime
+        }
+    }
+
+
+    Soprano::LiteralValue parseSizeType( const Soprano::LiteralValue& literal ) {
+        const double KiB = 1024.0;
+        const double MiB = KiB * 1024.0;
+        const double GiB = MiB * 1024.0;
+        const double TiB = GiB * 1024.0;
+
+        const double KB = 1000.0;
+        const double MB = KB * 1000.0;
+        const double GB = MB * 1000.0;
+        const double TB = GB * 1000.0;
+
+        QHash<QString, double> sizes;
+        sizes.insert( "KiB", KiB );
+        sizes.insert( "MiB", MiB );
+        sizes.insert( "GiB", GiB );
+        sizes.insert( "TiB", TiB );
+        sizes.insert( "KB", KB );
+        sizes.insert( "MB", MB );
+        sizes.insert( "GB", GB );
+        sizes.insert ("TB", TB );
+
+        QHash<QString, double>::const_iterator i;
+        for (i = sizes.constBegin(); i != sizes.constEnd(); ++i) {
+            QRegExp cur( QString("^([\\d]+.?[\\d]*)[\\s]*%1$").arg( i.key() ) );
+            if( cur.indexIn( literal.toString() ) != -1 ) {
+                double value = cur.cap( 1 ).toDouble();
+                double newValue = value * i.value();
+                kDebug() << "Found value" << value << i.key() << "->" << newValue;
+                return Soprano::LiteralValue( newValue );
+            }
+        }
+        return literal;
+    }
 }
 
 
@@ -331,12 +462,14 @@
         t = optimize( t );
         kDebug() << "Optimized query:" << t;
 
-        search( splitLuceneSparql( t ) /*optimize( resolveValues( resolveFields( m_searchTerm ) ) )*/, 1.0, true );
+        Nepomuk::Search::SearchNode temp =  splitLuceneSparql( t, m_searchTerm.folderLimits() );
+
+        search( temp /*optimize( resolveValues( resolveFields( m_searchTerm ) ) )*/, 1.0, true );
     }
     else {
         // FIXME: once we have the Soprano query API it should be simple to add the requestProperties here
         // for now we do it the hacky way
-        QString query = m_searchTerm.sparqlQuery();
+        QString query = tuneQuery( m_searchTerm.sparqlQuery() );
         int pos = query.indexOf( QLatin1String( "where" ) );
         if ( pos > 0 ) {
             query.insert( pos, buildRequestPropertyVariableList() + ' ' );
@@ -346,6 +479,15 @@
             }
         }
 
+        //do relative date parsing here
+        DateParser date(query, DateParser::RelativeDates);
+        while( date.hasDate() ) {
+            //TODO: this will likely not work with multiple dates in a query due to changing string length
+            QString replaced = Soprano::Node::literalToN3( QDateTime(date.getDate()) );
+            query.replace( date.pos(), date.length(), replaced );
+            date.next();
+        }
+
         sparqlQuery( query, 1.0, true );
     }
 
@@ -480,7 +622,7 @@
                     QUrl hit = hits.binding( 0 ).uri();
                     if ( prop.range().uri() == Soprano::Vocabulary::RDFS::Resource() ||
                          Nepomuk::Resource( hit ).hasType( prop.range().uri() ) ) {
-                        orTerm.addSubTerm( Term( term.property(), hit ) );
+                        orTerm.addSubTerm( Term( term.property(), hit, term.positive() ) );
                         if ( orTerm.subTerms().count() == MAX_RESOURCES ) {
                             break;
                         }
@@ -504,11 +646,43 @@
             }
         }
 
-        // non-literal term or non-contains term -> handled in SPARQL query
+
         else {
-            Term newTerm( term );
-            newTerm.setSubTerms( QList<Term>() << resolveValues( term.subTerms().first() ) );
-            return newTerm;
+            //modify the value for specific ranges
+            QString dateTimeRange = QString("ASK {%1 %2 %3}")
+                                   .arg( Soprano::Node::resourceToN3( term.property().toString() ) )
+                                   .arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::RDFS::range().toString() ) )
+                                   .arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::XMLSchema::dateTime().toString() ) );
+            QString integerRange  = QString("ASK {%1 %2 %3}")
+                                   .arg( Soprano::Node::resourceToN3( term.property().toString() ) )
+                                   .arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::RDFS::range().toString() ) )
+                                   .arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::XMLSchema::integer().toString() ) );
+
+            Soprano::QueryResultIterator dtRange  = ResourceManager::instance()->mainModel()->executeQuery( dateTimeRange, Soprano::Query::QUERY_LANGUAGE_SPARQL );
+            Soprano::QueryResultIterator intRange = ResourceManager::instance()->mainModel()->executeQuery( integerRange , Soprano::Query::QUERY_LANGUAGE_SPARQL );
+            //look for date properties to parse
+            if( dtRange.boolValue() ) {
+                QDateTime dateTime = parseDateTime( term.subTerms().first().value() );
+                kDebug() << "datetime is" << dateTime;
+                Term newTerm( term.property(), dateTime, term.positive(), term.comparator() );
+                if( dateTime.isValid() )
+                    return newTerm;
+                else {
+                    Term newTerm( term );
+                    newTerm.setSubTerms( QList<Term>() << resolveValues( term.subTerms().first() ) );
+                    return newTerm;
+                }
+            }
+            //check for sizes
+            else if( intRange.boolValue() ) {
+                return Term( term.property(), parseSizeType( term.subTerms().first().value() ), term.positive(), term.comparator() );
+            }
+            // non-literal term or non-contains term -> handled in SPARQL query
+            else {
+                Term newTerm( term );
+                newTerm.setSubTerms( QList<Term>() << resolveValues( term.subTerms().first() ) );
+                return newTerm;
+            }
         }
     }
 
@@ -549,7 +723,8 @@
 }
 
 
-Nepomuk::Search::SearchNode Nepomuk::Search::SearchThread::splitLuceneSparql( const Term& term )
+Nepomuk::Search::SearchNode Nepomuk::Search::SearchThread::splitLuceneSparql( const Nepomuk::Search::Term& term,
+                                                                              const QList<Nepomuk::Search::Query::FolderLimit>& folderLimits )
 {
     // Goal: separate the terms into 2 groups: literal and resource which are
     // merged with only one AND or OR action. Is that possible?
@@ -562,18 +737,18 @@
 
     switch( term.type() ) {
     case Term::LiteralTerm:
-        return SearchNode( term, SearchNode::Lucene );
+        return SearchNode( term, SearchNode::Lucene, folderLimits );
 
     case Term::ComparisonTerm:
         if ( term.comparator() == Term::Contains &&
              term.subTerms().first().type() == Term::LiteralTerm ) {
             // no need for subnides here - we only use the subterm's value
-            return SearchNode( term, SearchNode::Lucene );
+            return SearchNode( term, SearchNode::Lucene, folderLimits );
         }
         else {
             // all subnodes are resolved and can be handled in a SPARQL query
-            SearchNode node( term, SearchNode::Sparql );
-            node.subNodes += splitLuceneSparql( term.subTerms().first() );
+            SearchNode node( term, SearchNode::Sparql, folderLimits );
+            node.subNodes += splitLuceneSparql( term.subTerms().first(), folderLimits );
             return node;
         }
 
@@ -585,7 +760,7 @@
         QList<Term>::const_iterator end( subTerms.constEnd() );
         for ( QList<Term>::const_iterator it = subTerms.constBegin();
               it != end; ++it ) {
-            SearchNode node = splitLuceneSparql( *it );
+            SearchNode node = splitLuceneSparql( *it, folderLimits );
             if ( node.type == SearchNode::Lucene ) {
                 luceneNodes += node;
             }
@@ -598,24 +773,24 @@
         }
 
         if ( luceneNodes.count() && !sparqlNodes.count() && !unknownNodes.count() ) {
-            return SearchNode( term, SearchNode::Lucene, luceneNodes );
+            return SearchNode( term, SearchNode::Lucene, folderLimits, luceneNodes );
         }
         else if ( !luceneNodes.count() && sparqlNodes.count() && !unknownNodes.count() ) {
-            return SearchNode( term, SearchNode::Sparql, sparqlNodes );
+            return SearchNode( term, SearchNode::Sparql, folderLimits, sparqlNodes );
         }
         else if ( !luceneNodes.count() && !sparqlNodes.count() && unknownNodes.count() ) {
-            return SearchNode( term, SearchNode::Unknown, unknownNodes );
+            return SearchNode( term, SearchNode::Unknown, folderLimits, unknownNodes );
         }
         else {
             Term newTerm;
             newTerm.setType( term.type() );
             SearchNode andNode( newTerm );
             if ( luceneNodes.count() )
-                andNode.subNodes += SearchNode( term, SearchNode::Lucene, luceneNodes );
+                andNode.subNodes += SearchNode( term, SearchNode::Lucene, folderLimits, luceneNodes );
             if ( sparqlNodes.count() )
-                andNode.subNodes += SearchNode( term, SearchNode::Sparql, sparqlNodes );
+                andNode.subNodes += SearchNode( term, SearchNode::Sparql, folderLimits, sparqlNodes );
             if ( unknownNodes.count() )
-                andNode.subNodes += SearchNode( term, SearchNode::Unknown, unknownNodes );
+                andNode.subNodes += SearchNode( term, SearchNode::Unknown, folderLimits, unknownNodes );
             return andNode;
         }
     }
@@ -755,9 +930,10 @@
             //        we do not search the data itself and do not have to filter
             // BUT: What about inference?
 
-            query = QString( "select ?p where { "
+            query = QString( "select distinct ?p where { "
                              "?p <%1> <%2> . "
                              "?p <%3> ?label . "
+                             "?x ?p ?y . "
                              "FILTER(REGEX(STR(?label),'%4','i')) . }" )
                     .arg( Soprano::Vocabulary::RDF::type().toString() )
                     .arg( Soprano::Vocabulary::RDF::Property().toString() )
@@ -775,8 +951,9 @@
 
 
         if ( results.isEmpty() ) {
-            query = QString( "select ?p where { "
+            query = QString( "select distinct ?p where { "
                              "?p <%1> <%2> . "
+                             "?x ?p ?y . "
                              "FILTER(REGEX(STR(?p),'%3','i')) . }" )
                     .arg( Soprano::Vocabulary::RDF::type().toString() )
                     .arg( Soprano::Vocabulary::RDF::Property().toString() )
@@ -799,7 +976,7 @@
 QString Nepomuk::Search::SearchThread::createSparqlQuery( const Nepomuk::Search::SearchNode& node )
 {
     int varCnt = 0;
-    return QString( "select distinct ?r %1 where { %3 %4 }" )
+    return QString( "select distinct ?r %1 where { %3 %2 }" )
         .arg( buildRequestPropertyVariableList() )
         .arg( createGraphPattern( node, varCnt ) )
         .arg( buildRequestPropertyPatterns() );
@@ -965,4 +1142,55 @@
     }
 }
 
+
+void Nepomuk::Search::SearchThread::buildPrefixMap()
+{
+    // fixed prefixes
+    m_prefixes.insert( "rdf", Soprano::Vocabulary::RDF::rdfNamespace() );
+    m_prefixes.insert( "rdfs", Soprano::Vocabulary::RDFS::rdfsNamespace() );
+    m_prefixes.insert( "xsd", Soprano::Vocabulary::XMLSchema::xsdNamespace() );
+
+    // get prefixes from nepomuk
+    Soprano::QueryResultIterator it =
+        ResourceManager::instance()->mainModel()->executeQuery( QString( "select ?ns ?ab where { "
+                                                                         "?g %1 ?ns . "
+                                                                         "?g %2 ?ab . }" )
+                                                                .arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::NAO::hasDefaultNamespace() ) )
+                                                                .arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::NAO::hasDefaultNamespaceAbbreviation() ) ),
+                                                                Soprano::Query::QueryLanguageSparql );
+    while ( it.next() ) {
+        QString ab = it["ab"].toString();
+        QUrl ns = it["ns"].toString();
+        if ( !m_prefixes.contains( ab ) ) {
+            m_prefixes.insert( ab, ns );
+        }
+    }
+}
+
+
+QString Nepomuk::Search::SearchThread::tuneQuery( const QString& query_ )
+{
+    QString query( query_ );
+
+    buildPrefixMap();
+
+    for ( QHash<QString, QUrl>::const_iterator it = m_prefixes.constBegin();
+          it != m_prefixes.constEnd(); ++it ) {
+        QString prefix = it.key();
+        QUrl ns = it.value();
+
+        // very stupid check for the prefix usage
+        if ( query.contains( prefix + ':' ) ) {
+            // if the prefix is not defined add it
+            if ( !query.contains( QRegExp( QString( "[pP][rR][eE][fF][iI][xX]\\s*%1\\s*:\\s*<%2>" )
+                                           .arg( prefix )
+                                           .arg( QRegExp::escape( ns.toString() ) ) ) ) ) {
+                query.prepend( QString( "prefix %1: <%2> " ).arg( prefix ).arg( ns.toString() ) );
+            }
+        }
+    }
+
+    return query;
+}
+
 #include "searchthread.moc"
diff -Nru kdebase-runtime-4.3.2/nepomuk/services/queryservice/searchthread.h kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/searchthread.h
--- kdebase-runtime-4.3.2/nepomuk/services/queryservice/searchthread.h	2008-09-18 14:25:44.000000000 +0200
+++ kdebase-runtime-4.3.2-new/nepomuk/services/queryservice/searchthread.h	2009-10-26 09:52:22.000000000 +0100
@@ -47,14 +47,19 @@
                 Sparql
             };
 
-            SearchNode( const Term& t, Type tt = Unknown, const QList<SearchNode>& sub = QList<SearchNode>() )
+            SearchNode( const Term& t,
+                        Type tt = Unknown,
+                        const QList<Nepomuk::Search::Query::FolderLimit>& l = QList<Nepomuk::Search::Query::FolderLimit>(),
+                        const QList<SearchNode>& sub = QList<SearchNode>() )
                 : term(t),
                 type(tt),
+                folderLimits(l),
                 subNodes(sub) {
             }
-            
+
             Term term;
             Type type;
+            QList<Nepomuk::Search::Query::FolderLimit> folderLimits;
             QList<SearchNode> subNodes;
         };
 
@@ -112,7 +117,7 @@
              * Try to split the query into two (or more) subqueries, one of which will be
              * executed against the lucene index and one against the soprano store.
              */
-            SearchNode splitLuceneSparql( const Term& term );
+            SearchNode splitLuceneSparql( const Term& term, const QList<Nepomuk::Search::Query::FolderLimit>& folderLimits );
 
             QList<QUrl> matchFieldName( const QString& field );
             QHash<QUrl, Result> search( const SearchNode& node, double baseScore, bool reportResults = false );
@@ -128,12 +133,25 @@
 
             QString createSparqlQuery( const SearchNode& node );
 
+            /**
+             * Fill m_prefixes with values from the Nepomuk db.
+             */
+            void buildPrefixMap();
+
+            /**
+             * Insert missing prefix statements into the query.
+             */
+            QString tuneQuery( const QString& query_ );
+
             Query m_searchTerm;
             double m_cutOffScore;
 
             // status
             int m_numResults;
             bool m_canceled;
+
+            // cache of all prefixes that are supported
+            QHash<QString, QUrl> m_prefixes;
         };
     }
 }