Sophie

Sophie

distrib > Mandriva > 2009.0 > i586 > by-pkgid > f3998c8fc85cdd48c5141e7080e23f35 > files > 6

kdebase4-runtime-4.1.2-3mdv2009.0.src.rpm

diff -Naur nepomuk/CMakeLists.txt nepomuk/CMakeLists.txt
--- nepomuk/CMakeLists.txt	2008-06-10 13:41:01.000000000 +0200
+++ nepomuk/CMakeLists.txt	2008-09-01 14:33:17.000000000 +0200
@@ -16,7 +16,6 @@
 endif(CLucene_FOUND AND SopranoIndex_FOUND)
 # -----------------------------
 
-add_subdirectory(common)
 add_subdirectory(server)
 add_subdirectory(kcm)
 add_subdirectory(services)
diff -Naur nepomuk/common/CMakeLists.txt nepomuk/common/CMakeLists.txt
--- nepomuk/common/CMakeLists.txt	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/common/CMakeLists.txt	1970-01-01 01:00:00.000000000 +0100
@@ -1,4 +0,0 @@
-project(nepomukcommon)
-
-configure_file(nepomukstrigi-config.h.cmake
-  ${CMAKE_CURRENT_BINARY_DIR}/nepomukstrigi-config.h)
diff -Naur nepomuk/common/nepomukstrigi-config.h.cmake nepomuk/common/nepomukstrigi-config.h.cmake
--- nepomuk/common/nepomukstrigi-config.h.cmake	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/common/nepomukstrigi-config.h.cmake	1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-#cmakedefine HAVE_STRIGI_SOPRANO_BACKEND
diff -Naur nepomuk/common/strigiconfigfile.cpp nepomuk/common/strigiconfigfile.cpp
--- nepomuk/common/strigiconfigfile.cpp	2008-05-07 11:05:22.000000000 +0200
+++ nepomuk/common/strigiconfigfile.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,380 +0,0 @@
-/*
- * This file is part of the Nepomuk KDE project.
- * Copyright (C) 2006-2007 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 "strigiconfigfile.h"
-#include "nepomukstrigi-config.h"
-
-#include <QtCore/QFile>
-#include <QtCore/QTextStream>
-#include <QtCore/QDir>
-#include <QtXml/QDomDocument>
-#include <QtXml/QDomElement>
-
-#include <KDebug>
-#include <KStandardDirs>
-
-
-namespace {
-    bool convertBooleanXsdValue( const QString& value ) {
-        return(  value.toLower() == QLatin1String( "true" ) ||
-                 value.toLower() == QLatin1String( "1" ) );
-    }
-}
-
-
-Nepomuk::StrigiConfigFile::StrigiConfigFile()
-{
-    reset();
-}
-
-
-Nepomuk::StrigiConfigFile::StrigiConfigFile( const QString& filename )
-{
-    reset();
-    setFilename( filename );
-}
-
-
-Nepomuk::StrigiConfigFile::~StrigiConfigFile()
-{
-}
-
-
-void Nepomuk::StrigiConfigFile::setFilename( const QString& filename )
-{
-    m_filename = filename;
-}
-
-
-void Nepomuk::StrigiConfigFile::reset()
-{
-    m_useDBus = true;
-    m_repositories.clear();
-    m_excludeFilters.clear();
-    m_includeFilters.clear();
-}
-
-
-bool Nepomuk::StrigiConfigFile::load()
-{
-    kDebug() << m_filename;
-
-    QFile file( m_filename );
-    if ( file.open( QIODevice::ReadOnly ) ) {
-        QDomDocument doc;
-        if ( doc.setContent( &file ) ) {
-            return readConfig( doc.documentElement() );
-        }
-        else {
-            kDebug() << "Failed to parse" << m_filename;
-            return false;
-        }
-    }
-    else {
-        kDebug() << "Could not open file" << m_filename;
-        return false;
-    }
-}
-
-
-bool Nepomuk::StrigiConfigFile::readConfig( const QDomElement& rootElement )
-{
-    if ( rootElement.tagName() != "strigiDaemonConfiguration" ) {
-        kDebug() << "Invalid configuration root tag:" << rootElement.tagName();
-        return false;
-    }
-
-    m_useDBus = convertBooleanXsdValue( rootElement.attribute( "useDBus", QLatin1String( "1" ) ) );
-
-    // read repository
-    QDomElement repoElem = rootElement.firstChildElement( "repository" );
-    while ( !repoElem.isNull() ) {
-        Repository repo = readRepositoryConfig( repoElem );
-        if ( repo.isValid() )
-            addRepository( repo );
-        repoElem = repoElem.nextSiblingElement( "repository" );
-    }
-
-    // read filters
-    return readFilterConfig( rootElement.firstChildElement( "filters" ) );
-}
-
-
-Nepomuk::StrigiConfigFile::Repository Nepomuk::StrigiConfigFile::readRepositoryConfig( const QDomElement& repositoryElement )
-{
-    Repository repo;
-
-    QDomNamedNodeMap attributes = repositoryElement.attributes();
-
-    // read repository configuration
-    for ( int i = 0; i < attributes.size(); ++i ) {
-        QDomNode attributeNode = attributes.item( i );
-        QString attributeName = attributeNode.nodeName();
-        QString attributeValue = attributeNode.nodeValue();
-        if ( attributeName == "type" ) {
-            repo.setType( attributeValue );
-        }
-        else if ( attributeName == "name" ) {
-            repo.setName( attributeValue );
-        }
-        else if ( attributeName == "indexdir" ) {
-            repo.setIndexDir( attributeValue );
-        }
-        else if ( attributeName == "writeable" ) {
-            repo.setWriteable( convertBooleanXsdValue( attributeValue ) );
-        }
-        else if ( attributeName == "urlbase" ) {
-            repo.setUrlBase( attributeValue );
-        }
-        else if ( attributeName == "pollingInterval" ) {
-            repo.setPollingInterval( attributeValue.toInt() );
-        }
-        else {
-            kDebug() << "Unknown config entry" << attributeName;
-        }
-    }
-
-    // read indexed dirs
-    QDomElement pathElement = repositoryElement.firstChildElement( "path" );
-    while ( !pathElement.isNull() ) {
-        QString path = pathElement.attribute( "path" );
-        if ( !path.isEmpty() )
-            repo.addIndexedDirectory( path );
-        pathElement = pathElement.nextSiblingElement( "path" );
-    }
-
-    return repo;
-}
-
-
-bool Nepomuk::StrigiConfigFile::readFilterConfig( const QDomElement& filtersElement )
-{
-    QDomElement filterElement = filtersElement.firstChildElement( "filter" );
-
-    while ( !filterElement.isNull() ) {
-        QString pattern = filterElement.attribute( "pattern" );
-        QString inExclude = filterElement.attribute( "include" );
-        if ( !pattern.isEmpty() && !inExclude.isEmpty() ) {
-            if ( convertBooleanXsdValue( inExclude ) )
-                m_includeFilters << pattern;
-            else
-                m_excludeFilters << pattern;
-        }
-        else {
-            kDebug() << "Invalid filter rule.";
-            return false;
-        }
-
-        filterElement = filterElement.nextSiblingElement( "filter" );
-    }
-
-    return true;
-}
-
-
-bool Nepomuk::StrigiConfigFile::save()
-{
-    kDebug() << m_filename;
-
-    QDomDocument doc;
-    QDomElement rootElement = doc.createElement( "strigiDaemonConfiguration" );
-    rootElement.setAttribute( "useDBus", useDBus() ? QLatin1String( "1" ) : QLatin1String( "0" ) );
-    doc.appendChild( rootElement );
-
-    // save repositories
-    foreach( const Repository &repo, m_repositories ) {
-        QDomElement repoElem = doc.createElement( "repository" );
-        repoElem.setAttribute( "name", repo.name() );
-        repoElem.setAttribute( "type", repo.type() );
-        repoElem.setAttribute( "indexdir", repo.indexDir() );
-        repoElem.setAttribute( "writeable", repo.writeable() ? QLatin1String( "1" ) : QLatin1String( "0" ) );
-        repoElem.setAttribute( "urlbase", repo.urlBase() );
-        repoElem.setAttribute( "pollingInterval", QString::number( repo.pollingInterval() ) );
-
-        // add paths
-        foreach( const QString &path, repo.indexedDirectories() ) {
-            QDomElement pathElem = doc.createElement( "path" );
-            pathElem.setAttribute( "path", path );
-            repoElem.appendChild( pathElem );
-        }
-
-        rootElement.appendChild( repoElem );
-    }
-
-    // save filters
-    QDomElement filtersElem = doc.createElement( "filters" );
-    rootElement.appendChild( filtersElem );
-    foreach( const QString &filter, m_includeFilters ) {
-        QDomElement filterElem = doc.createElement( "filter" );
-        filterElem.setAttribute( "pattern", filter );
-        filterElem.setAttribute( "include", "1" );
-        filtersElem.appendChild( filterElem );
-    }
-    foreach( const QString &filter, m_excludeFilters ) {
-        QDomElement filterElem = doc.createElement( "filter" );
-        filterElem.setAttribute( "pattern", filter );
-        filterElem.setAttribute( "include", "0" );
-        filtersElem.appendChild( filterElem );
-    }
-
-    // save to file
-    KStandardDirs::makeDir( m_filename.section( '/', 0, -2 ) );
-    QFile f( m_filename );
-    if ( f.open( QIODevice::WriteOnly ) ) {
-        QTextStream s( &f );
-        s << doc;
-        return true;
-    }
-    else {
-        kDebug() << "Could not open" << m_filename << "for writing";
-        return false;
-    }
-}
-
-
-bool Nepomuk::StrigiConfigFile::useDBus() const
-{
-    return m_useDBus;
-}
-
-
-QStringList Nepomuk::StrigiConfigFile::excludeFilters() const
-{
-    return m_excludeFilters;
-}
-
-
-QStringList Nepomuk::StrigiConfigFile::includeFilters() const
-{
-    return m_includeFilters;
-}
-
-
-QList<Nepomuk::StrigiConfigFile::Repository> Nepomuk::StrigiConfigFile::repositories() const
-{
-    return m_repositories;
-}
-
-
-Nepomuk::StrigiConfigFile::Repository& Nepomuk::StrigiConfigFile::defaultRepository()
-{
-    if ( m_repositories.isEmpty() ) {
-        Repository repo;
-        repo.setName( "localhost" ); // the default repository
-        repo.setWriteable( true );
-        repo.setPollingInterval( 180 ); // default value copied from Strigi sources
-#ifdef HAVE_STRIGI_SOPRANO_BACKEND
-        repo.setType( "sopranobackend" ); // our default
-#else
-        repo.setType( "clucene" );
-        repo.setIndexDir( QDir::homePath() + "/.strigi/clucene" );
-#endif
-        repo.addIndexedDirectory( QDir::homePath() );
-        repo.addIndexedDirectory( QDir::homePath() + "/.kde" );
-        addRepository( repo );
-
-        // in case there are no repositories and no filters we also create
-        // default filters
-        if ( m_includeFilters.isEmpty() && m_excludeFilters.isEmpty() ) {
-            // exclude hidden dirs and files
-            m_excludeFilters << ".*/" << ".*" << "*~" << "*.part";
-        }
-    }
-
-    return m_repositories.first();
-}
-
-
-const Nepomuk::StrigiConfigFile::Repository& Nepomuk::StrigiConfigFile::defaultRepository() const
-{
-    return const_cast<StrigiConfigFile*>( this )->defaultRepository();
-}
-
-
-void Nepomuk::StrigiConfigFile::setUseDBus( bool b )
-{
-    m_useDBus = b;
-}
-
-void Nepomuk::StrigiConfigFile::setExcludeFilters( const QStringList& filters )
-{
-    m_excludeFilters = filters;
-}
-
-
-void Nepomuk::StrigiConfigFile::addExcludeFilter( const QString& filter )
-{
-    m_excludeFilters << filter;
-}
-
-
-void Nepomuk::StrigiConfigFile::setIncludeFilters( const QStringList& filters )
-{
-    m_includeFilters = filters;
-}
-
-
-void Nepomuk::StrigiConfigFile::addInludeFilter( const QString& filter )
-{
-    m_includeFilters << filter;
-}
-
-void Nepomuk::StrigiConfigFile::setRepositories( const QList<Repository>& repos )
-{
-    m_repositories = repos;
-}
-
-
-void Nepomuk::StrigiConfigFile::addRepository( const Repository& repo )
-{
-    m_repositories << repo;
-}
-
-
-QString Nepomuk::StrigiConfigFile::defaultStrigiConfigFilePath()
-{
-    return QDir::homePath() + "/.strigi/daemon.conf";
-}
-
-
-QTextStream& operator<<( QTextStream& s, const Nepomuk::StrigiConfigFile& scf )
-{
-    s << "useDBus: " << scf.useDBus() << endl
-      << "repositories:" << endl;
-    foreach( const Nepomuk::StrigiConfigFile::Repository &repo, scf.repositories() ) {
-        s << "   " << repo.name() << ":" << endl
-          << "      " << "type: " << repo.type() << endl
-          << "      " << "indexdir: " << repo.indexDir() << endl
-          << "      " << "writeable: " << repo.writeable() << endl
-          << "      " << "urlbase: " << repo.urlBase() << endl
-          << "      " << "paths: " << repo.indexedDirectories().join( ":" ) << endl;
-    }
-    s << "include filters:" << endl;
-    foreach( const QString &filter, scf.includeFilters() ) {
-        s << "   " << filter << endl;
-    }
-    s << "exclude filters:" << endl;
-    foreach( const QString &filter, scf.excludeFilters() ) {
-        s << "   " << filter << endl;
-    }
-    return s;
-}
-
-#include "strigiconfigfile.moc"
diff -Naur nepomuk/common/strigiconfigfile.h nepomuk/common/strigiconfigfile.h
--- nepomuk/common/strigiconfigfile.h	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/common/strigiconfigfile.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,135 +0,0 @@
-/*
- * This file is part of the Nepomuk KDE project.
- * Copyright (C) 2006-2007 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.
- */
-
-#ifndef _NEPOMUK_STRIGI_CONFIG_H_
-#define _NEPOMUK_STRIGI_CONFIG_H_
-
-#include <QtCore/QObject>
-#include <QtCore/QStringList>
-
-class QDomElement;
-class QTextStream;
-
-namespace Nepomuk {
-    /**
-     * Parser and writer class for Strigidaemon config
-     * files.
-     *
-     * The default Strigi config file can be found at
-     * ~/.strigi/daemon.conf.
-     */
-    class StrigiConfigFile : public QObject
-    {
-        Q_OBJECT
-
-    public:
-        StrigiConfigFile();
-        StrigiConfigFile( const QString& filename );
-        ~StrigiConfigFile();
-
-        void setFilename( const QString& filename );
-
-        bool load();
-        bool save();
-
-        /**
-         * A Strigi repository. Normally there is only one.
-         */
-        class Repository {
-        public:
-            QString name() const { return m_name; }
-            QString type() const { return m_type; }
-            QString indexDir() const { return m_indexDir; }
-            bool writeable() const { return m_writeable; }
-            QString urlBase() const { return m_urlBase; }
-            QStringList indexedDirectories() const { return m_indexedDirectories; }
-            int pollingInterval() const { return m_pollingInterval; }
-
-            bool isValid() const { return !m_type.isEmpty(); }
-
-            void setType( const QString& type ) { m_type = type; }
-            void setName( const QString& name ) { m_name = name; }
-            void setIndexDir( const QString& dir ) { m_indexDir = dir; }
-            void setWriteable( bool writeable ) { m_writeable = writeable; }
-            void setUrlBase( const QString& urlBase ) { m_urlBase = urlBase; }
-            void addIndexedDirectory( const QString& dir ) { m_indexedDirectories << dir; }
-            void setIndexedDirectories( const QStringList& dirs ) { m_indexedDirectories = dirs; }
-            void setPollingInterval( int pollingInterval ) { m_pollingInterval = pollingInterval; }
-            
-        private:
-            QString m_name;
-            QString m_type;
-            QString m_indexDir;
-            bool m_writeable;
-            QString m_urlBase;
-            QStringList m_indexedDirectories;
-            int m_pollingInterval;
-        };
-
-        bool useDBus() const;
-        QStringList excludeFilters() const;
-        QStringList includeFilters() const;
-        QList<Repository> repositories() const;
-
-        /**
-         * In most cases (or even always) there is only
-         * one repository. This method will return the 
-         * first repository in the list or create a default
-         * one and insert it if the list is empty.
-         *
-         * This will also create default filters if none are
-         * specified AND no repository is configured.
-         */
-        Repository& defaultRepository();
-        const Repository& defaultRepository() const;
-
-        /**
-         * ~/.strigi/daemon.conf
-         */
-        static QString defaultStrigiConfigFilePath();
-
-    public Q_SLOTS:
-        void reset();
-
-        void setUseDBus( bool b );
-        void setExcludeFilters( const QStringList& filters );
-        void addExcludeFilter( const QString& filter );
-        void setIncludeFilters( const QStringList& filters );
-        void addInludeFilter( const QString& filter );
-        void setRepositories( const QList<Repository>& repos );
-        void addRepository( const Repository& repo );
-
-    private:
-        bool readConfig( const QDomElement& );
-        Repository readRepositoryConfig( const QDomElement& );
-        bool readFilterConfig( const QDomElement& filterElement );
-
-        QString m_filename;
-
-        bool m_useDBus;
-        QStringList m_excludeFilters;
-        QStringList m_includeFilters;
-        QList<Repository> m_repositories;
-    };
-}
-
-QTextStream& operator<<( QTextStream& s, const Nepomuk::StrigiConfigFile& scf );
-
-#endif
diff -Naur nepomuk/interfaces/CMakeLists.txt nepomuk/interfaces/CMakeLists.txt
--- nepomuk/interfaces/CMakeLists.txt	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/interfaces/CMakeLists.txt	2008-09-01 14:33:17.000000000 +0200
@@ -2,5 +2,8 @@
   org.kde.NepomukServer.xml
   org.kde.nepomuk.ServiceControl.xml
   org.kde.nepomuk.ServiceManager.xml
+  org.kde.nepomuk.Strigi.xml
+  org.kde.nepomuk.OntologyManager.xml
+  org.kde.nepomuk.Storage.xml
   DESTINATION ${DBUS_INTERFACES_INSTALL_DIR}
   )
diff -Naur nepomuk/interfaces/org.kde.nepomuk.OntologyManager.xml nepomuk/interfaces/org.kde.nepomuk.OntologyManager.xml
--- nepomuk/interfaces/org.kde.nepomuk.OntologyManager.xml	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/interfaces/org.kde.nepomuk.OntologyManager.xml	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,21 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+         "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+  <interface name="org.kde.nepomuk.OntologyManager">
+    <method name="findOntologyContext">
+      <arg name="uri" type="s" direction="in" />
+      <arg type="s" direction="out" />
+    </method>
+    <method name="importOntology">
+      <arg name="uri" type="s" direction="in" />
+    </method>
+    <method name="updateLocalOntologies" />
+    <signal name="ontologyUpdated">
+      <arg name="uri" type="s" />
+    </signal>
+    <signal name="ontologyUpdateFailed">
+      <arg name="uri" type="s" />
+      <arg name="errorString" type="s" />
+    </signal>
+  </interface>
+</node>
diff -Naur nepomuk/interfaces/org.kde.nepomuk.Storage.xml nepomuk/interfaces/org.kde.nepomuk.Storage.xml
--- nepomuk/interfaces/org.kde.nepomuk.Storage.xml	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/interfaces/org.kde.nepomuk.Storage.xml	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,12 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+         "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+  <interface name="org.kde.nepomuk.Storage">
+    <method name="optimize">
+      <arg name="repoName" type="s" direction="in" />
+    </method>
+    <method name="usedSopranoBackend">
+      <arg name="backendName" type="s" direction="out" />
+    </method>
+  </interface>
+</node>
diff -Naur nepomuk/interfaces/org.kde.nepomuk.Strigi.xml nepomuk/interfaces/org.kde.nepomuk.Strigi.xml
--- nepomuk/interfaces/org.kde.nepomuk.Strigi.xml	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/interfaces/org.kde.nepomuk.Strigi.xml	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,32 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+         "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+  <interface name="org.kde.nepomuk.Strigi">
+    <method name="isIndexing">
+      <arg type="b" direction="out" />
+    </method>
+    <method name="isSuspended">
+      <arg type="b" direction="out" />
+    </method>
+    <method name="currentFolder">
+      <arg type="s" direction="out" />
+    </method>
+    <method name="suspend" />
+    <method name="resume" />
+    <method name="analyzeResource" >
+      <arg name="uri" direction="in" type="s" />
+      <arg name="lastModificationDate" direction="in" type="u" />
+      <arg name="data" direction="in" type="ay" />
+    </method>
+    <method name="analyzeResourceFromTempFileAndDeleteTempFile" >
+      <arg name="uri" direction="in" type="s" />
+      <arg name="lastModificationDate" direction="in" type="u" />
+      <arg name="tmpFileName" direction="in" type="s" />
+    </method>
+    <signal name="indexingStarted" />
+    <signal name="indexingStopped" />
+    <signal name="indexingFolder">
+      <arg name="path" type="s" />
+    </method>
+  </interface>
+</node>
diff -Naur nepomuk/kcm/CMakeLists.txt nepomuk/kcm/CMakeLists.txt
--- nepomuk/kcm/CMakeLists.txt	2008-05-21 10:33:02.000000000 +0200
+++ nepomuk/kcm/CMakeLists.txt	2008-09-01 14:33:17.000000000 +0200
@@ -6,15 +6,15 @@
   ${SOPRANO_INCLUDE_DIR}
   ${CMAKE_SOURCE_DIR}
   ${NEPOMUK_INCLUDE_DIR}
-  ${nepomukcommon_BINARY_DIR}
   )
 
 set(kcmnepomuk_SRCS
-  ../common/strigiconfigfile.cpp
   nepomukserverkcm.cpp
+  folderselectionmodel.cpp
   )
 
 qt4_add_dbus_interface(kcmnepomuk_SRCS ../interfaces/org.kde.NepomukServer.xml nepomukserverinterface)
+qt4_add_dbus_interface(kcmnepomuk_SRCS ../interfaces/org.kde.nepomuk.Strigi.xml strigiserviceinterface)
 
 kde4_add_ui_files(kcmnepomuk_SRCS
   nepomukconfigwidget.ui)
@@ -22,9 +22,9 @@
 kde4_add_plugin(kcm_nepomuk ${kcmnepomuk_SRCS})
 
 target_link_libraries(kcm_nepomuk
-  ${STRIGI_STRIGIQTDBUSCLIENT_LIBRARY}
   ${KDE4_KDEUI_LIBS}
   ${KDE4_KIO_LIBS}
+  ${SOPRANO_LIBRARIES}
   )
 # -----------------------------
 
diff -Naur nepomuk/kcm/folderselectionmodel.cpp nepomuk/kcm/folderselectionmodel.cpp
--- nepomuk/kcm/folderselectionmodel.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/kcm/folderselectionmodel.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,156 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
+
+   Based on CollectionSetup.cpp from the Amarok project
+   (C) 2003 Scott Wheeler <wheeler@kde.org>
+   (C) 2004 Max Howell <max.howell@methylblue.com>
+   (C) 2004 Mark Kretschmann <markey@web.de>
+   (C) 2008 Seb Ruiz <ruiz@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 version 2 as published by the Free Software Foundation.
+
+   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 "folderselectionmodel.h"
+
+#include <QtCore/QDir>
+
+
+FolderSelectionModel::FolderSelectionModel( QObject* parent )
+    : QFileSystemModel( parent ),
+      m_recursive( true )
+{
+    setFilter( QDir::AllDirs | QDir::NoDotAndDotDot );
+}
+
+
+FolderSelectionModel::~FolderSelectionModel()
+{
+}
+
+
+Qt::ItemFlags FolderSelectionModel::flags( const QModelIndex &index ) const
+{
+    Qt::ItemFlags flags = QFileSystemModel::flags( index );
+    const QString path = filePath( index );
+    if( ( recursive() && ancestorChecked( path ) ) || isForbiddenPath( path ) )
+        flags ^= Qt::ItemIsEnabled; //disabled!
+
+    flags |= Qt::ItemIsUserCheckable;
+
+    return flags;
+}
+
+
+QVariant FolderSelectionModel::data( const QModelIndex& index, int role ) const
+{
+    if( index.isValid() && index.column() == 0 && role == Qt::CheckStateRole )
+    {
+        const QString path = filePath( index );
+        if( recursive() && ancestorChecked( path ) )
+            return Qt::Checked; // always set children of recursively checked parents to checked
+        if( isForbiddenPath( path ) )
+            return Qt::Unchecked; // forbidden paths can never be checked
+        if ( !m_checked.contains( path ) && descendantChecked( path ) )
+            return Qt::PartiallyChecked;
+        return m_checked.contains( path ) ? Qt::Checked : Qt::Unchecked;
+    }
+    return QFileSystemModel::data( index, role );
+}
+
+
+bool FolderSelectionModel::setData( const QModelIndex& index, const QVariant& value, int role )
+{
+    if( index.isValid() && index.column() == 0 && role == Qt::CheckStateRole )
+    {
+        QString path = filePath( index );
+        // store checked paths, remove unchecked paths
+        if( value.toInt() == Qt::Checked )
+            m_checked.insert( path );
+        else
+            m_checked.remove( path );
+        return true;
+    }
+    return QFileSystemModel::setData( index, value, role );
+}
+
+
+void FolderSelectionModel::setFolders( const QStringList &dirs )
+{
+    m_checked.clear();
+    foreach( const QString& dir, dirs ) {
+        m_checked.insert( dir );
+    }
+}
+
+
+QStringList FolderSelectionModel::folders() const
+{
+    QStringList dirs = m_checked.toList();
+
+    qSort( dirs.begin(), dirs.end() );
+
+    // we need to remove any children of selected items as
+    // they are redundant when recursive mode is chosen
+    if( recursive() ) {
+        foreach( const QString& dir, dirs ) {
+            if( ancestorChecked( dir ) )
+                dirs.removeAll( dir );
+        }
+    }
+
+    return dirs;
+}
+
+
+inline bool FolderSelectionModel::isForbiddenPath( const QString& path ) const
+{
+    // we need the trailing slash otherwise we could forbid "/dev-music" for example
+    QString _path = path.endsWith( "/" ) ? path : path + "/";
+    return _path.startsWith( "/proc/" ) || _path.startsWith( "/dev/" ) || _path.startsWith( "/sys/" );
+}
+
+
+bool FolderSelectionModel::ancestorChecked( const QString& path ) const
+{
+    foreach( const QString& element, m_checked ) {
+        if( path.startsWith( element ) && element != path )
+            return true;
+    }
+    return false;
+}
+
+
+bool FolderSelectionModel::descendantChecked( const QString& path ) const
+{
+    foreach( const QString& element, m_checked ) {
+        if ( element.startsWith( path ) && element != path )
+            return true;
+    }
+    return false;
+}
+
+
+bool FolderSelectionModel::recursive() const
+{
+    return m_recursive;
+}
+
+
+void FolderSelectionModel::setRecursive( bool r )
+{
+    m_recursive = r;
+}
+
+#include "folderselectionmodel.moc"
diff -Naur nepomuk/kcm/folderselectionmodel.h nepomuk/kcm/folderselectionmodel.h
--- nepomuk/kcm/folderselectionmodel.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/kcm/folderselectionmodel.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,61 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
+
+   Based on CollectionSetup.h from the Amarok project
+   (C) 2003 Scott Wheeler <wheeler@kde.org>
+   (C) 2004 Max Howell <max.howell@methylblue.com>
+   (C) 2004 Mark Kretschmann <markey@web.de>
+   (C) 2008 Seb Ruiz <ruiz@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 version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef _FOLDER_SELECTION_MODEL_H_
+#define _FOLDER_SELECTION_MODEL_H_
+
+#include <QtGui/QFileSystemModel>
+#include <QtCore/QSet>
+
+
+class FolderSelectionModel : public QFileSystemModel
+{
+    Q_OBJECT
+
+public:
+    FolderSelectionModel( QObject* parent = 0 );
+    virtual ~FolderSelectionModel();
+
+    Qt::ItemFlags flags( const QModelIndex &index ) const;
+    QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
+    bool setData( const QModelIndex& index, const QVariant& value, int role = Qt::EditRole );
+
+    void setFolders( const QStringList &dirs ); // will clear m_checked before inserting new directories
+    QStringList folders() const;
+
+    int columnCount( const QModelIndex& ) const { return 1; }
+
+    bool recursive() const;
+    void setRecursive( bool r );
+
+private:
+    bool ancestorChecked( const QString& path ) const;
+    bool descendantChecked( const QString& path ) const;
+    bool isForbiddenPath( const QString& path ) const;
+
+    QSet<QString> m_checked;
+    bool m_recursive;
+};
+
+#endif
diff -Naur nepomuk/kcm/kcm_nepomuk.desktop nepomuk/kcm/kcm_nepomuk.desktop
--- nepomuk/kcm/kcm_nepomuk.desktop	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/kcm/kcm_nepomuk.desktop	2008-09-01 14:33:17.000000000 +0200
@@ -8,16 +8,27 @@
 X-KDE-ParentApp=kcontrol
 X-KDE-System-Settings-Parent-Category=advanced-user-settings
 
-Name=Nepomuk
-Name[ar]=مشروع Nepomuk
-Name[gu]=નેપોમુક
-Name[ml]=നെപ്പോമുക്
-Name[pa]=ਨਿਪੋਮੁਕ
-Name[sr]=Непомук
-Name[x-test]=xxNepomukxx
+Name=Desktop Search
+Name[et]=Töölauaotsing
+Name[ga]=Cuardach Deisce
+Name[gl]=Procura do escritorio
+Name[gu]=ડેસ્કટોપ શોધ
+Name[hr]=Pager na radnoj površini
+Name[ja]=デスクトップ検索
+Name[km]=ស្វែងរក​ផ្ទៃតុ
+Name[nb]=Skrivebordssøk
+Name[nds]=Schriefdischsöök
+Name[nn]=Skrivebordsøk
+Name[pt]=Pesquisa no Ambiente de Trabalho
+Name[pt_BR]=Pesquisa no Ambiente de Trabalho
+Name[sl]=Namizno iskanje
+Name[sv]=Skrivbordssökning
+Name[te]=డెస్‍క్ టాప్ శోధన
+Name[tr]=Masaüstü Araması
+Name[uk]=Стільничний пошук
+Name[zh_TW]=桌面搜尋
 Comment=Nepomuk/Strigi Server Configuration
 Comment[af]=Nepomuk/Strigi bedienerkonfigurasie
-Comment[ar]=اعداد خدمة Nepomuk/Strigi
 Comment[bg]=Настройване на Nepomuk/Strigi
 Comment[bn_IN]=Nepomuk/Strigi সার্ভার কনফিগারেশন
 Comment[ca]=Configuració del servidor Nepomuk/Strigi
@@ -63,6 +74,7 @@
 Comment[sr]=Постава сервера Непомука/Стригија
 Comment[sr@latin]=Postava servera Nepomuka/Strigija
 Comment[sv]=Tjänstinställning av Nepomuk- och Strigiserver
+Comment[te]=Nepomuk/Strigi సేవిక ఆకృతీకరణ
 Comment[tg]=Танзимоти хидматгоҳи Nepomuk/Strigi
 Comment[th]=ปรับแต่งเซิร์ฟเวอร์ Nepomuk/Strigi
 Comment[tr]=Nepomuk/Strigi Sunucu Yapılandırması
diff -Naur nepomuk/kcm/nepomukconfigwidget.ui nepomuk/kcm/nepomukconfigwidget.ui
--- nepomuk/kcm/nepomukconfigwidget.ui	2008-04-23 17:51:26.000000000 +0200
+++ nepomuk/kcm/nepomukconfigwidget.ui	2008-09-01 14:33:17.000000000 +0200
@@ -2,14 +2,6 @@
  <author>Sebastian Trueg</author>
  <class>NepomukConfigWidget</class>
  <widget class="QWidget" name="NepomukConfigWidget" >
-  <property name="geometry" >
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>366</width>
-    <height>300</height>
-   </rect>
-  </property>
   <layout class="QVBoxLayout" >
    <item>
     <widget class="QTabWidget" name="tabWidget" >
@@ -20,7 +12,7 @@
       <attribute name="title" >
        <string>Basic Settings</string>
       </attribute>
-      <layout class="QVBoxLayout" >
+      <layout class="QVBoxLayout" name="verticalLayout_2" >
        <item>
         <widget class="QGroupBox" name="groupBox_2" >
          <property name="title" >
@@ -30,7 +22,7 @@
           <item>
            <widget class="QLabel" name="label_3" >
             <property name="text" >
-             <string>Nepomuk Semantic Desktop enables tagging and rating of files integrated with the Strigi Desktop Search.</string>
+             <string>Nepomuk Semantic Desktop enables tagging and rating of files integrated with the Desktop Search.</string>
             </property>
             <property name="wordWrap" >
              <bool>true</bool>
@@ -50,9 +42,9 @@
        <item>
         <widget class="QGroupBox" name="groupBox" >
          <property name="title" >
-          <string>Strigi Desktop Search</string>
+          <string>Strigi Desktop File Indexer</string>
          </property>
-         <layout class="QVBoxLayout" >
+         <layout class="QVBoxLayout" name="verticalLayout" >
           <item>
            <widget class="QLabel" name="label_2" >
             <property name="text" >
@@ -64,46 +56,49 @@
            </widget>
           </item>
           <item>
-           <layout class="QHBoxLayout" >
-            <item>
-             <widget class="QCheckBox" name="m_checkEnableStrigi" >
-              <property name="text" >
-               <string>Enable Strigi Desktop Search</string>
-              </property>
-             </widget>
-            </item>
+           <widget class="QCheckBox" name="m_checkEnableStrigi" >
+            <property name="text" >
+             <string>Enable Strigi Desktop File Indexer</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout" >
             <item>
-             <spacer>
+             <spacer name="horizontalSpacer" >
               <property name="orientation" >
                <enum>Qt::Horizontal</enum>
               </property>
-              <property name="sizeHint" >
+              <property name="sizeType" >
+               <enum>QSizePolicy::Fixed</enum>
+              </property>
+              <property name="sizeHint" stdset="0" >
                <size>
-                <width>20</width>
-                <height>40</height>
+                <width>40</width>
+                <height>1</height>
                </size>
               </property>
              </spacer>
             </item>
             <item>
-             <layout class="QHBoxLayout" >
-              <item>
-               <widget class="KLed" native="1" name="m_strigiStatus" />
-              </item>
-              <item>
-               <widget class="QLabel" name="m_strigiStatusLabel" >
-                <property name="sizePolicy" >
-                 <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
-                  <horstretch>1</horstretch>
-                  <verstretch>0</verstretch>
-                 </sizepolicy>
-                </property>
-                <property name="text" >
-                 <string>Strigi not running</string>
-                </property>
-               </widget>
-              </item>
-             </layout>
+             <widget class="KSqueezedTextLabel" name="m_labelStrigiStatus" >
+              <property name="sizePolicy" >
+               <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+                <horstretch>1</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="font" >
+               <font>
+                <weight>75</weight>
+                <italic>true</italic>
+                <bold>true</bold>
+               </font>
+              </property>
+              <property name="text" >
+               <string>KSqueezedTextLabel</string>
+              </property>
+             </widget>
             </item>
            </layout>
           </item>
@@ -115,7 +110,7 @@
          <property name="orientation" >
           <enum>Qt::Vertical</enum>
          </property>
-         <property name="sizeHint" >
+         <property name="sizeHint" stdset="0" >
           <size>
            <width>20</width>
            <height>40</height>
@@ -129,21 +124,27 @@
       <attribute name="title" >
        <string>Advanced Settings</string>
       </attribute>
-      <layout class="QVBoxLayout" >
+      <layout class="QHBoxLayout" name="horizontalLayout_2" >
        <item>
-        <widget class="KEditListBox" name="m_editStrigiFolders" >
-         <property name="toolTip" >
-          <string>The folders Strigi scans for indexable files</string>
-         </property>
-         <property name="whatsThis" >
-          <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
-p, li { white-space: pre-wrap; }
-&lt;/style>&lt;/head>&lt;body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
-&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select the folders that Strigi should scan for files to index. The files in these folders will be searchable through Strigi Desktop Search.&lt;/p>&lt;/body>&lt;/html></string>
-         </property>
+        <widget class="QGroupBox" name="groupBox_3" >
          <property name="title" >
           <string>Strigi Index Folders</string>
          </property>
+         <layout class="QVBoxLayout" name="verticalLayout_3" >
+          <item>
+           <widget class="QLabel" name="label" >
+            <property name="text" >
+             <string>Select the local folders that contain files to be indexed for fast desktop searches</string>
+            </property>
+            <property name="wordWrap" >
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QTreeView" name="m_viewIndexFolders" />
+          </item>
+         </layout>
         </widget>
        </item>
        <item>
@@ -159,19 +160,6 @@
          </property>
         </widget>
        </item>
-       <item>
-        <spacer>
-         <property name="orientation" >
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" >
-          <size>
-           <width>20</width>
-           <height>40</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
       </layout>
      </widget>
     </widget>
@@ -186,15 +174,14 @@
    <container>1</container>
   </customwidget>
   <customwidget>
-   <class>KLed</class>
-   <extends>QWidget</extends>
-   <header>kled.h</header>
+   <class>KSqueezedTextLabel</class>
+   <extends>QLabel</extends>
+   <header>ksqueezedtextlabel.h</header>
   </customwidget>
  </customwidgets>
  <tabstops>
   <tabstop>tabWidget</tabstop>
   <tabstop>m_checkEnableNepomuk</tabstop>
-  <tabstop>m_checkEnableStrigi</tabstop>
  </tabstops>
  <resources/>
  <connections>
diff -Naur nepomuk/kcm/nepomukserverkcm.cpp nepomuk/kcm/nepomukserverkcm.cpp
--- nepomuk/kcm/nepomukserverkcm.cpp	2008-06-10 13:41:01.000000000 +0200
+++ nepomuk/kcm/nepomukserverkcm.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -18,7 +18,7 @@
 
 #include "nepomukserverkcm.h"
 #include "nepomukserverinterface.h"
-#include "../common/strigiconfigfile.h"
+#include "folderselectionmodel.h"
 
 #include <KPluginFactory>
 #include <KPluginLoader>
@@ -26,18 +26,31 @@
 #include <KSharedConfig>
 #include <KLed>
 #include <KMessageBox>
-#include <KUrlRequester>
 
-#include <strigi/qtdbus/strigiclient.h>
+#include <QtGui/QTreeView>
+
+#include <Soprano/PluginManager>
 
 
 K_PLUGIN_FACTORY( NepomukConfigModuleFactory, registerPlugin<Nepomuk::ServerConfigModule>(); )
 K_EXPORT_PLUGIN( NepomukConfigModuleFactory("kcm_nepomuk", "nepomuk") )
 
 
+namespace {
+    QStringList defaultFolders() {
+        return QStringList() << QDir::homePath();
+    }
+
+    QStringList defaultExcludeFilters() {
+        return QStringList() << ".*/" << ".*" << "*~" << "*.part";
+    }
+}
+
+
 Nepomuk::ServerConfigModule::ServerConfigModule( QWidget* parent, const QVariantList& args )
     : KCModule( NepomukConfigModuleFactory::componentData(), parent, args ),
-      m_serverInterface( "org.kde.NepomukServer", "/nepomukserver", QDBusConnection::sessionBus() )
+      m_serverInterface( "org.kde.NepomukServer", "/nepomukserver", QDBusConnection::sessionBus() ),
+      m_strigiInterface( "org.kde.nepomuk.services.nepomukstrigiservice", "/nepomukstrigiservice", QDBusConnection::sessionBus() )
 {
     KAboutData *about = new KAboutData(
         "kcm_nepomuk", 0, ki18n("Nepomuk Configuration Module"),
@@ -48,20 +61,29 @@
     setButtons(Apply|Default);
     setupUi( this );
 
-    KUrlRequester* urlReq = new KUrlRequester( m_editStrigiFolders );
-    urlReq->setMode( KFile::Directory|KFile::LocalOnly|KFile::ExistingOnly );
-    KEditListBox::CustomEditor ce( urlReq, urlReq->lineEdit() );
-    m_editStrigiFolders->setCustomEditor( ce );
+    m_folderModel = new FolderSelectionModel( m_viewIndexFolders );
+    m_viewIndexFolders->setModel( m_folderModel );
+    m_viewIndexFolders->setHeaderHidden( true );
+    m_viewIndexFolders->setRootIsDecorated( true );
+    m_viewIndexFolders->setAnimated( true );
+    m_viewIndexFolders->setRootIndex( m_folderModel->setRootPath( QDir::rootPath() ) );
 
     connect( m_checkEnableStrigi, SIGNAL( toggled(bool) ),
              this, SLOT( changed() ) );
     connect( m_checkEnableNepomuk, SIGNAL( toggled(bool) ),
              this, SLOT( changed() ) );
-    connect( m_editStrigiFolders, SIGNAL( changed() ),
+    connect( m_folderModel, SIGNAL( dataChanged(const QModelIndex&, const QModelIndex&) ),
              this, SLOT( changed() ) );
     connect( m_editStrigiExcludeFilters, SIGNAL( changed() ),
              this, SLOT( changed() ) );
 
+    connect( &m_strigiInterface, SIGNAL( indexingStarted() ),
+             this, SLOT( slotUpdateStrigiStatus() ) );
+    connect( &m_strigiInterface, SIGNAL( indexingStopped() ),
+             this, SLOT( slotUpdateStrigiStatus() ) );
+    connect( &m_strigiInterface, SIGNAL( indexingFolder(QString) ),
+             this, SLOT( slotUpdateStrigiStatus() ) );
+
     load();
 }
 
@@ -73,7 +95,16 @@
 
 void Nepomuk::ServerConfigModule::load()
 {
-    if ( m_serverInterface.isValid() ) {
+    bool sopranoBackendAvailable = !Soprano::PluginManager::instance()->allBackends().isEmpty();
+
+    m_checkEnableNepomuk->setEnabled( sopranoBackendAvailable );
+
+    if ( !sopranoBackendAvailable ) {
+        KMessageBox::sorry( this,
+                            i18n( "No Soprano Database backend available. Please check your installation." ),
+                            i18n( "Nepomuk cannot be started" ) );
+    }
+    else if ( m_serverInterface.isValid() ) {
         m_checkEnableStrigi->setChecked( m_serverInterface.isStrigiEnabled().value() );
         m_checkEnableNepomuk->setChecked( m_serverInterface.isNepomukEnabled().value() );
     }
@@ -85,30 +116,20 @@
 
         KConfig config( "nepomukserverrc" );
         m_checkEnableNepomuk->setChecked( config.group( "Basic Settings" ).readEntry( "Start Nepomuk", true ) );
-        m_checkEnableStrigi->setChecked( config.group( "Service-nepomukstrigiservice" ).readEntry( "autostart", false ) );
+        m_checkEnableStrigi->setChecked( config.group( "Service-nepomukstrigiservice" ).readEntry( "autostart", true ) );
     }
 
-    if ( isStrigiRunning() ) {
-        StrigiClient strigiClient;
-        m_editStrigiFolders->setItems( strigiClient.getIndexedDirectories() );
-        QList<QPair<bool, QString> > filters = strigiClient.getFilters();
-        m_editStrigiExcludeFilters->clear();
-        for( QList<QPair<bool, QString> >::const_iterator it = filters.constBegin();
-             it != filters.constEnd(); ++it ) {
-            if ( !it->first ) {
-                m_editStrigiExcludeFilters->insertItem( it->second );
-            }
-            // else: we simply drop include filters for now
-        }
-    }
-    else {
-        StrigiConfigFile strigiConfig( StrigiConfigFile::defaultStrigiConfigFilePath() );
-        strigiConfig.load();
-        m_editStrigiFolders->setItems( strigiConfig.defaultRepository().indexedDirectories() );
-        m_editStrigiExcludeFilters->setItems( strigiConfig.excludeFilters() );
+    KConfig strigiConfig( "nepomukstrigirc" );
+    m_folderModel->setFolders( strigiConfig.group( "General" ).readPathEntry( "folders", defaultFolders() ) );
+    m_editStrigiExcludeFilters->setItems( strigiConfig.group( "General" ).readEntry( "exclude filters", defaultExcludeFilters() ) );
+
+    // make sure that the tree is expanded to show all selected items
+    foreach( const QString& dir, m_folderModel->folders() ) {
+        QModelIndex index = m_folderModel->index( dir );
+        m_viewIndexFolders->scrollTo( index, QAbstractItemView::EnsureVisible );
     }
 
-    updateStrigiStatus();
+    slotUpdateStrigiStatus();
 }
 
 
@@ -121,17 +142,9 @@
 
 
     // 2. update Strigi config
-    StrigiConfigFile strigiConfig( StrigiConfigFile::defaultStrigiConfigFilePath() );
-    strigiConfig.load();
-    if ( m_checkEnableNepomuk->isChecked() ) {
-        strigiConfig.defaultRepository().setType( "sopranobackend" );
-    }
-    else {
-        strigiConfig.defaultRepository().setType( "clucene" );
-    }
-    strigiConfig.defaultRepository().setIndexedDirectories( m_editStrigiFolders->items() );
-    strigiConfig.setExcludeFilters( m_editStrigiExcludeFilters->items() );
-    strigiConfig.save();
+    KConfig strigiConfig( "nepomukstrigirc" );
+    strigiConfig.group( "General" ).writePathEntry( "folders", m_folderModel->folders() );
+    strigiConfig.group( "General" ).writeEntry( "exclude filters", m_editStrigiExcludeFilters->items() );
 
 
     // 3. update the current state of the nepomuk server
@@ -146,66 +159,36 @@
                             i18n( "Nepomuk server not running" ) );
     }
 
-
-    // 4. update values in the running Strigi instance
-    // TODO: there should be a dbus method to re-read the config
-    // -----------------------------
-    if ( m_checkEnableStrigi->isChecked() ) {
-        // give strigi some time to start
-        QTimer::singleShot( 2000, this, SLOT( updateStrigiSettingsInRunningInstance() ) );
-    }
-
-    // give strigi some time to start
-    QTimer::singleShot( 2000, this, SLOT( updateStrigiStatus() ) );
+    slotUpdateStrigiStatus();
 }
 
 
 void Nepomuk::ServerConfigModule::defaults()
 {
-    m_checkEnableStrigi->setChecked( false );
+    m_checkEnableStrigi->setChecked( true );
     m_checkEnableNepomuk->setChecked( true );
-    // create Strigi default config
-    StrigiConfigFile defaultConfig;
-    m_editStrigiFolders->setItems( defaultConfig.defaultRepository().indexedDirectories() );
-    m_editStrigiExcludeFilters->setItems( defaultConfig.excludeFilters() );
+    m_editStrigiExcludeFilters->setItems( defaultExcludeFilters() );
+    m_folderModel->setFolders( defaultFolders() );
 }
 
 
-void Nepomuk::ServerConfigModule::updateStrigiStatus()
+void Nepomuk::ServerConfigModule::slotUpdateStrigiStatus()
 {
-    if ( isStrigiRunning() ) {
-        m_strigiStatus->on();
-        m_strigiStatusLabel->setText( i18n( "Strigi is running" ) );
+    if ( m_strigiInterface.isValid() ) {
+        bool indexing = m_strigiInterface.isIndexing();
+        bool suspended = m_strigiInterface.isSuspended();
+        QString folder = m_strigiInterface.currentFolder();
+
+        if ( suspended )
+            m_labelStrigiStatus->setText( i18n( "File indexer is suspended" ) );
+        else if ( indexing )
+            m_labelStrigiStatus->setText( i18n( "Strigi is currently indexing files in folder %1", folder ) );
+        else
+            m_labelStrigiStatus->setText( i18n( "File indexer is idle" ) );
     }
     else {
-        m_strigiStatus->off();
-        m_strigiStatusLabel->setText( i18n( "Strigi not running" ) );
+        m_labelStrigiStatus->setText( i18n( "Strigi service not running." ) );
     }
 }
 
-
-void Nepomuk::ServerConfigModule::updateStrigiSettingsInRunningInstance()
-{
-    if ( isStrigiRunning() ) {
-        StrigiClient strigiClient;
-        strigiClient.setIndexedDirectories( m_editStrigiFolders->items() );
-
-        // FIXME: there should be a rereadConfig method in strigi
-        StrigiConfigFile strigiConfig( StrigiConfigFile::defaultStrigiConfigFilePath() );
-        strigiConfig.load();
-
-        QList<QPair<bool, QString> > filters;
-        foreach( const QString &filter, strigiConfig.excludeFilters() ) {
-            filters.append( qMakePair( false, filter ) );
-        }
-        strigiClient.setFilters( filters );
-    }
-}
-
-
-bool Nepomuk::ServerConfigModule::isStrigiRunning()
-{
-    return QDBusConnection::sessionBus().interface()->isServiceRegistered( "vandenoever.strigi" ).value();
-}
-
 #include "nepomukserverkcm.moc"
diff -Naur nepomuk/kcm/nepomukserverkcm.h nepomuk/kcm/nepomukserverkcm.h
--- nepomuk/kcm/nepomukserverkcm.h	2008-04-02 14:18:20.000000000 +0200
+++ nepomuk/kcm/nepomukserverkcm.h	2008-09-01 14:33:17.000000000 +0200
@@ -22,6 +22,9 @@
 #include <KCModule>
 #include "ui_nepomukconfigwidget.h"
 #include "nepomukserverinterface.h"
+#include "strigiserviceinterface.h"
+
+class FolderSelectionModel;
 
 namespace Nepomuk {
     class ServerConfigModule : public KCModule, private Ui::NepomukConfigWidget
@@ -38,13 +41,13 @@
         void defaults();
 
     private Q_SLOTS:
-        void updateStrigiStatus();
-        void updateStrigiSettingsInRunningInstance();
+        void slotUpdateStrigiStatus();
 
     private:
-        bool isStrigiRunning();
-
         org::kde::NepomukServer m_serverInterface;
+        org::kde::nepomuk::Strigi m_strigiInterface;
+
+        FolderSelectionModel* m_folderModel;
     };
 }
 
diff -Naur nepomuk/server/main.cpp nepomuk/server/main.cpp
--- nepomuk/server/main.cpp	2008-07-03 07:05:21.000000000 +0200
+++ nepomuk/server/main.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -38,6 +38,7 @@
         switch( signal ) {
         case SIGHUP:
         case SIGQUIT:
+        case SIGTERM:
         case SIGINT:
             if ( qApp ) {
                 qApp->quit();
@@ -54,6 +55,7 @@
         sigaction( SIGHUP, &sa, 0 );
         sigaction( SIGINT, &sa, 0 );
         sigaction( SIGQUIT, &sa, 0 );
+        sigaction( SIGTERM, &sa, 0 );
 #endif
     }
 }
diff -Naur nepomuk/server/nepomukserver.desktop nepomuk/server/nepomukserver.desktop
--- nepomuk/server/nepomukserver.desktop	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/server/nepomukserver.desktop	2008-09-01 14:33:17.000000000 +0200
@@ -5,7 +5,6 @@
 OnlyShowIn=KDE;
 X-KDE-autostart-phase=0
 Name=Nepomuk Server
-Name[ar]=خادم Nepomuk
 Name[bg]=Сървър Nepomuk
 Name[bn_IN]=Nepomuk সার্ভার
 Name[ca]=Servidor Nepomuk
@@ -24,6 +23,7 @@
 Name[ga]=Freastalaí Nepomuk
 Name[gl]=Servidor Nepomuk
 Name[gu]=નેપોમુક સર્વર
+Name[he]=שרת Nepomuk
 Name[hr]=Poslužitelj Nepomuk
 Name[hu]=Nepomuk szolgáltatás
 Name[is]=Nepomuk miðlari
@@ -52,6 +52,7 @@
 Name[sr]=Сервер Непомука
 Name[sr@latin]=Server Nepomuka
 Name[sv]=Nepomuk-server
+Name[te]=Nepomuk సేవిక
 Name[tg]=Хидматгоҳи Nepomuk
 Name[th]=เซิร์ฟเวอร์ Nepomuk
 Name[tr]=Nepomuk Sunucu
@@ -63,7 +64,6 @@
 Name[zh_CN]=Nepomuk 服务器
 Name[zh_TW]=Nepomuk 伺服器
 Comment=The Nepomuk Server providing Storage services and strigi controlling
-Comment[ar]=Nepomuk  مزود اقوى الخدمات وادوات التحكم 
 Comment[bg]=Сървърът Nepomuk предлага контрол на strigi и съхранение
 Comment[ca]=El servidor Nepomuk proporciona serveis d'emmagatzematge i de control de l'Strigi
 Comment[csb]=Serwer Nepomuk dôwô kòntrolã nad strigi ë zôpisowné ùsłëżnotë
@@ -103,6 +103,7 @@
 Comment[sr]=Сервер Непомука даје уређаје за складиштење и контролу Стригија
 Comment[sr@latin]=Server Nepomuka daje uređaje za skladištenje i kontrolu Strigija
 Comment[sv]=Nepomuk-server som tillhandahåller lagringstjänster och styrning av Strigi
+Comment[te]=Nepomuk సేవిక నిల్వ సేవలను మరియు strigi నింయత్రణను అందిస్తుంది
 Comment[th]=เซิร์ฟเวอร์ Nepomuk จะให้บริการจัดเก็บและการควบคุม strigi
 Comment[tr]=Nepomuk Sunucusu Depolama servislerini ve Strigi uygulamasının kontrolünü sağlar
 Comment[uk]=Сервер Nepomuk надає служби збереження і керування strigi
diff -Naur nepomuk/server/nepomukservice.desktop nepomuk/server/nepomukservice.desktop
--- nepomuk/server/nepomukservice.desktop	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/server/nepomukservice.desktop	2008-09-01 14:33:17.000000000 +0200
@@ -3,7 +3,6 @@
 X-KDE-ServiceType=NepomukService
 Comment=Nepomuk Service
 Comment[af]=Nepomuk diens
-Comment[ar]=خادم Nepomuk
 Comment[bg]=Услуга Nepomuk
 Comment[bn_IN]=Nepomuk পরিসেবা
 Comment[ca]=Servei Nepomuk
@@ -45,6 +44,7 @@
 Comment[sr]=Сервис Непомука
 Comment[sr@latin]=Servis Nepomuka
 Comment[sv]=Nepomuk-tjänst
+Comment[te]=Nepomuk సేవ
 Comment[tg]=Хидматҳои Nepomuk
 Comment[th]=บริการ Neomuk
 Comment[tr]=Nepomuk Servisi
diff -Naur nepomuk/server/servicecontroller.cpp nepomuk/server/servicecontroller.cpp
--- nepomuk/server/servicecontroller.cpp	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/server/servicecontroller.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -42,8 +42,9 @@
     Private()
         : processControl( 0 ),
           serviceControlInterface( 0 ),
-          attached(false),
-          initialized( false ) {
+          attached( false ),
+          initialized( false ),
+          failedToInitialize( false ) {
     }
 
     KService::Ptr service;
@@ -59,6 +60,7 @@
     bool attached;
 
     bool initialized;
+    bool failedToInitialize;
 
     // list of loops waiting for the service to become initialized
     QList<QEventLoop*> loops;
@@ -154,6 +156,7 @@
     }
 
     d->initialized = false;
+    d->failedToInitialize = false;
 
     // check if the service is already running, ie. has been started by someone else or by a crashed instance of the server
     // we cannot rely on the auto-restart feature of ProcessControl here. So we handle that completely in slotServiceOwnerChanged
@@ -195,7 +198,9 @@
             d->processControl->setCrashPolicy( ProcessControl::StopOnCrash );
         }
 
-        if ( waitForInitialized( 2000 ) ) {
+        if ( d->serviceControlInterface ||
+             ( !QCoreApplication::closingDown() &&
+               waitForInitialized( 2000 ) ) ) {
             d->serviceControlInterface->shutdown();
         }
 
@@ -230,7 +235,7 @@
         return false;
     }
 
-    if( !d->initialized ) {
+    if( !d->initialized && !d->failedToInitialize ) {
         QEventLoop loop;
         d->loops.append( &loop );
         if ( timeout > 0 ) {
@@ -300,14 +305,21 @@
 void Nepomuk::ServiceController::slotServiceInitialized( bool success )
 {
     if ( !d->initialized ) {
-        kDebug() << "Service" << name() << "initialized:" << success;
-        d->initialized = true;
-        emit serviceInitialized( this );
-
-        if ( runOnce() ) {
-            // we have been run once. Do not autostart next time
-            KConfigGroup cg( Server::self()->config(), QString("Service-%1").arg(name()) );
-            cg.writeEntry( "autostart", false );
+        if ( success ) {
+            kDebug() << "Service" << name() << "initialized";
+            d->initialized = true;
+            emit serviceInitialized( this );
+
+            if ( runOnce() ) {
+                // we have been run once. Do not autostart next time
+                KConfigGroup cg( Server::self()->config(), QString("Service-%1").arg(name()) );
+                cg.writeEntry( "autostart", false );
+            }
+        }
+        else {
+            d->failedToInitialize = true;
+            kDebug() << "Failed to initialize service" << name();
+            stop();
         }
     }
 
diff -Naur nepomuk/services/filewatch/nepomukfilewatch.desktop nepomuk/services/filewatch/nepomukfilewatch.desktop
--- nepomuk/services/filewatch/nepomukfilewatch.desktop	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/services/filewatch/nepomukfilewatch.desktop	2008-09-01 14:33:17.000000000 +0200
@@ -5,7 +5,6 @@
 X-KDE-Nepomuk-autostart=true
 X-KDE-Nepomuk-start-on-demand=false
 Name=NepomukFileWatch
-Name[ar]=البحث في ملفات Nepomuk
 Name[de]=NepomukDateiMonitor
 Name[es]=MonitorDeArchivosNepomuk
 Name[et]=Nepomuki failijälgija
@@ -18,11 +17,10 @@
 Name[sr]=Непомуков надзор фајлова
 Name[sr@latin]=Nepomukov nadzor fajlova
 Name[sv]=Nepomuk-filövervakning
-Name[x-test]=xxNepomukFileWatchxx
+Name[te]=Nepomukఫైల్ వాచ్
 Name[zh_CN]=Nepomuk 文件监视
 Name[zh_TW]=Nepomuk 檔案監控
 Comment=The Nepomuk file watch service for monitoring file changes
-Comment[ar]=مراقب تغير ملفات Nepomuk
 Comment[bg]=Услугата NepomukFileWatch  следи за промяна във файловете
 Comment[ca]=El servei de control de fitxers del Nepomuk per fer un seguiment dels canvis en fitxers
 Comment[csb]=Ùsłëżnota Nepomùka mònitorëjącô zjinaczi lopków
@@ -40,10 +38,8 @@
 Comment[ja]=ファイルの変更を監視する Nepomuk サービス
 Comment[km]=ឯកសារ​របស់ Nepomuk មើល​សេវា​សម្រាប់​ត្រួតពិនិត្យ​កា​រផ្លាស់ប្ដូរ​ឯកសារ
 Comment[ko]=파일 변화를 감시하는 Nepumuk 파일 감시 서비스
-Comment[lv]=Nepomuk failu novērošanas serviss, kas novēro izmaiņas failos
 Comment[nb]=Nepomuk filovervåkning for å detektere filendringer
 Comment[nds]=Nepomuk sien Dateibeluurdeenst, de Ännern an Dateien vermeldt
-Comment[nl]=NepomukFileWatch volgt uw systeem op bestandswijzigingen
 Comment[nn]=Filovervakingstenesta Nepomuk tilbyr overvaking av endringar i filer
 Comment[pl]=Usługa Nepomuka do monitorowania zmian w plikach
 Comment[pt]=O serviço de vigilância de ficheiros para vigiar as alterações dos ficheiros
@@ -52,8 +48,9 @@
 Comment[sr]=Непомуков сервис за надгледање измена над фајловима
 Comment[sr@latin]=Nepomukov servis za nadgledanje izmena nad fajlovima
 Comment[sv]=Nepomuks filövervakningstjänst för att bevaka filändringar
+Comment[te]=ఫైల్ మార్పులను మానిటరింగ్ చేయుటకొరకు Nepomuk ఫైల్ వాచ్ సేవ
 Comment[th]=บริการของ Nepomuk สำหรับคอยตรวจจับความเปลี่ยนแปลงของแฟ้ม
+Comment[tr]=Dosya değişikliklerini izlemek için Nepomuk dosya izleme servisi
 Comment[uk]=Служба Nepomuk для спостереження за змінами в файлах
-Comment[x-test]=xxThe Nepomuk file watch service for monitoring file changesxx
 Comment[zh_CN]=用于监视文件变更的 Nepomuk 服务
 Comment[zh_TW]=Nepomuk 檔案監控服務,監視檔案變化
diff -Naur nepomuk/services/migration1/nepomukmigration1.desktop nepomuk/services/migration1/nepomukmigration1.desktop
--- nepomuk/services/migration1/nepomukmigration1.desktop	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/services/migration1/nepomukmigration1.desktop	2008-09-01 14:33:17.000000000 +0200
@@ -6,7 +6,6 @@
 X-KDE-Nepomuk-start-on-demand=false
 X-KDE-Nepomuk-run-once=true
 Comment=Nepomuk Data Migration Level 1
-Comment[ar]=معلومات هجرة Nepomuk المرحلة 1
 Comment[ca]=Nivell 1 de migració de dades del Nepomuk
 Comment[csb]=Migracëjô pòdôwków Nepomuk, równiô 1
 Comment[da]=Nepomuk datamigrering niveau 1
@@ -37,6 +36,7 @@
 Comment[sr]=Непомукова миграција података нивоа 1
 Comment[sr@latin]=Nepomukova migracija podataka nivoa 1
 Comment[sv]=Nepomuk-datamigration nivå 1
+Comment[te]=Nepomuk డాటా వలస స్థాయి 1
 Comment[th]=ตัวปรับรุ่นข้อมูลระดับ 1 ของ Nepomuk
 Comment[tr]=Nepomuk Veri Taşıma Seviyesi 1
 Comment[uk]=Міграція даних Nepomuk - рівень 1
diff -Naur nepomuk/services/ontologyloader/CMakeLists.txt nepomuk/services/ontologyloader/CMakeLists.txt
--- nepomuk/services/ontologyloader/CMakeLists.txt	2008-05-21 10:33:02.000000000 +0200
+++ nepomuk/services/ontologyloader/CMakeLists.txt	2008-09-01 14:33:17.000000000 +0200
@@ -9,13 +9,20 @@
 set(ontologyloader_SRCS
   ontologyloader.cpp
   ontologymanagermodel.cpp
+  graphretriever.cpp
   )
 
+qt4_add_dbus_adaptor(ontologyloader_SRCS
+  ../../interfaces/org.kde.nepomuk.OntologyManager.xml
+  ontologyloader.h
+  Nepomuk::OntologyLoader)
+
 kde4_add_plugin(nepomukontologyloader ${ontologyloader_SRCS})
 
 target_link_libraries(nepomukontologyloader
   ${SOPRANO_LIBRARIES}
   ${KDE4_KDECORE_LIBS}
+  ${KDE4_KIO_LIBS}
   ${NEPOMUK_LIBRARIES}
   )
 
diff -Naur nepomuk/services/ontologyloader/graphretriever.cpp nepomuk/services/ontologyloader/graphretriever.cpp
--- nepomuk/services/ontologyloader/graphretriever.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/ontologyloader/graphretriever.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,173 @@
+/*  This file is part of the KDE semantic clipboard
+    Copyright (C) 2008 Tobias Wolf <twolf@access.unizh.ch>
+    Copyright (C) 2008 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 "graphretriever.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QEventLoop>
+#include <QtCore/QHash>
+#include <QtCore/QPair>
+#include <QtCore/QString>
+#include <QtCore/QTextStream>
+#include <QtCore/QUrl>
+
+#include <Soprano/Model>
+#include <Soprano/Global>
+#include <Soprano/Parser>
+#include <Soprano/PluginManager>
+#include <Soprano/StatementIterator>
+
+#include <KDebug>
+#include <KLocale>
+#include <kio/job.h>
+
+
+class Nepomuk::GraphRetriever::Private
+{
+public:
+    Private( Nepomuk::GraphRetriever* qq );
+
+    void get( const QUrl& url );
+
+    Nepomuk::GraphRetriever*   q;
+
+    QUrl url;
+    QHash<int, QByteArray>     m_data;
+    unsigned int               m_idleCount;
+    unsigned int               m_timeoutThreshold;
+};
+
+
+Nepomuk::GraphRetriever::Private::Private( Nepomuk::GraphRetriever* qq )
+    : q(qq),
+      m_idleCount( 0 )
+{
+}
+
+
+void Nepomuk::GraphRetriever::Private::get( const QUrl& url )
+{
+    KIO::StoredTransferJob* job = KIO::storedGet( url, KIO::Reload, KIO::HideProgressInfo );
+    job->addMetaData( "accept",
+                        QString( "%1;q=0.2, %2" )
+                        .arg( Soprano::serializationMimeType( Soprano::SerializationRdfXml ) )
+                        .arg( Soprano::serializationMimeType( Soprano::SerializationTrig ) ) );
+    job->addMetaData( "Charsets", "utf-8" );
+
+    connect( job, SIGNAL(result(KJob*)),
+             q, SLOT(httpRequestFinished(KJob*)));
+}
+
+
+Nepomuk::GraphRetriever::GraphRetriever( QObject* parent )
+    : KJob( parent ),
+      d( new Private(this) )
+{
+}
+
+
+Nepomuk::GraphRetriever::~GraphRetriever()
+{
+    delete d;
+}
+
+
+void Nepomuk::GraphRetriever::setUrl( const QUrl& url )
+{
+    d->url = url;
+}
+
+
+QUrl Nepomuk::GraphRetriever::url() const
+{
+    return d->url;
+}
+
+
+void Nepomuk::GraphRetriever::start()
+{
+    d->get( d->url );
+}
+
+
+Soprano::Model* Nepomuk::GraphRetriever::model() const
+{
+    Soprano::Model* result = Soprano::createModel();
+    Soprano::StatementIterator it = statements();
+    while ( it.next() ) {
+        result->addStatement( *it );
+    }
+    return result;
+}
+
+
+Soprano::StatementIterator Nepomuk::GraphRetriever::statements() const
+{
+    QByteArray data;
+    Soprano::RdfSerialization serialization = Soprano::SerializationRdfXml;
+    if ( d->m_data.contains( ( int )Soprano::SerializationTrig ) ) {
+        serialization = Soprano::SerializationTrig;
+        data = d->m_data[( int )Soprano::SerializationTrig];
+    }
+    else {
+        serialization = Soprano::SerializationRdfXml;
+        data = d->m_data[( int )Soprano::SerializationRdfXml];
+    }
+
+    QTextStream stream( data );
+    if ( const Soprano::Parser* parser =
+         Soprano::PluginManager::instance()->discoverParserForSerialization( serialization ) ) {
+        return parser->parseStream( stream, d->url, serialization );
+    }
+    else {
+        return Soprano::StatementIterator();
+    }
+}
+
+
+void Nepomuk::GraphRetriever::httpRequestFinished( KJob* job )
+{
+    KIO::StoredTransferJob* tj = static_cast<KIO::StoredTransferJob*>( job );
+
+    // reset idle counter every time a request is finished
+    d->m_idleCount = 0;
+
+    QString mimetype = tj->mimetype();
+    Soprano::RdfSerialization serialization = Soprano::mimeTypeToSerialization( mimetype );
+    if ( serialization == Soprano::SerializationUser &&
+         mimetype.contains( "xml", Qt::CaseInsensitive ) ) {
+        serialization = Soprano::SerializationRdfXml;
+    }
+    if ( serialization != Soprano::SerializationUser )
+        d->m_data[( int )serialization] = tj->data();
+
+    emitResult();
+}
+
+
+Nepomuk::GraphRetriever* Nepomuk::GraphRetriever::retrieve( const QUrl& uri )
+{
+    GraphRetriever* gr = new GraphRetriever();
+    gr->setUrl( uri );
+    gr->start();
+    return gr;
+}
+
+#include "graphretriever.moc"
diff -Naur nepomuk/services/ontologyloader/graphretriever.h nepomuk/services/ontologyloader/graphretriever.h
--- nepomuk/services/ontologyloader/graphretriever.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/ontologyloader/graphretriever.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,108 @@
+/*  This file is part of the KDE semantic clipboard
+    Copyright (C) 2008 Tobias Wolf <twolf@access.unizh.ch>
+    Copyright (C) 2008 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.
+*/
+
+#ifndef _NEPOMUK_GRAPHRETRIEVER_H_
+#define _NEPOMUK_GRAPHRETRIEVER_H_
+
+#include <KJob>
+
+class QString;
+class QUrl;
+
+namespace Soprano {
+    class Model;
+    class StatementIterator;
+}
+namespace KIO {
+    class Job;
+}
+
+namespace Nepomuk
+{
+
+    /**
+     * \class GraphRetriever graphretriever.h <nepomuk/graphretriever.h>
+     *
+     * \brief Utility class for retrieving RDF graphs from Web locations.
+     *
+     * GraphRetriever allows retrieval of multiple RDF graph fragments from
+     * the Web using HTTP GET. Target HTTP servers should support the RDF+XML
+     * request MIME type for this to work.
+     *
+     * Clients can queue multiple get requests and must follow the last get
+     * request with a call to either model() or serialization().
+     *
+     * \author Tobias Wolf <twolf@access.unizh.ch>
+     */
+    class GraphRetriever : public KJob
+    {
+        Q_OBJECT
+
+    public:
+        /**
+         * Custom and default constructor.
+         *
+         * @param parent The parent QObject.
+         */
+        GraphRetriever( QObject* parent = 0 );
+
+        /**
+         * Default destructor.
+         */
+        ~GraphRetriever();
+
+        static GraphRetriever* retrieve( const QUrl& uri );
+
+        void setUrl( const QUrl& url );
+
+        QUrl url() const;
+
+        /**
+         * Adds a get request for the given URL.
+         *
+         * @param url An URL specifying the location of a graph fragment to get.
+         * @return True if the get request was accepted, false otherwise.
+         */
+        void start();
+
+        /**
+         * Returns a new Soprano model constructed from the retrieved graph fragments. The
+         * client takes over ownership of the returned model.
+         *
+         * @return A new Soprano model constructed from the merged fragments.
+         */
+        Soprano::Model* model() const;
+
+        Soprano::StatementIterator statements() const;
+
+    private Q_SLOTS:
+        /**
+         * @internal
+         */
+        void httpRequestFinished( KJob* );
+
+    private:
+        class Private;
+        Private* const d;
+    };
+
+}
+
+#endif
diff -Naur nepomuk/services/ontologyloader/nepomukontologyloader.desktop nepomuk/services/ontologyloader/nepomukontologyloader.desktop
--- nepomuk/services/ontologyloader/nepomukontologyloader.desktop	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/services/ontologyloader/nepomukontologyloader.desktop	2008-09-01 14:33:17.000000000 +0200
@@ -6,7 +6,6 @@
 X-KDE-Nepomuk-start-on-demand=false
 X-KDE-Nepomuk-dependencies=nepomukstorage
 Name=Nepomuk Ontology Loader
-Name[ar]=محمل معلومات الانشاء Nepomuk
 Name[ca]=Carregador d'ontologies del Nepomuk
 Name[csb]=Ladowanié òntogiji Nepomuka
 Name[da]=Nepomuk ontologi-indlæser
@@ -38,6 +37,7 @@
 Name[sr]=Непомуков учитавач онтологија
 Name[sr@latin]=Nepomukov učitavač ontologija
 Name[sv]=Nepomuk-ontologiladdning
+Name[te]=Nepomuk ఆన్‌టోలజి లోడర్
 Name[th]=ตัวโหลด Ontology ของ Nepomuk
 Name[tr]=Nepomuk Ontoloji Yükleyici
 Name[uk]=Завантажувач онтології Nepomuk
@@ -46,7 +46,6 @@
 Name[zh_CN]=Nepomuk 本体装载器
 Name[zh_TW]=Nepomuk Ontology 載入器
 Comment=Nepomuk Service which maintains the ontologies installed on the system
-Comment[ar]=Nepomuk المحافظة على معلومات الانشاء المثبتة علىالنظام
 Comment[bg]=Услуга, която поддържа инсталираните на компютъра онтологии
 Comment[ca]=Servei del Nepomuk que manté les ontologies instal·lades en el sistema
 Comment[csb]=Ùsłëżnota Nepomuka, jakô sprôwiô òntologijama winstalowónëmi w systemie
@@ -79,6 +78,7 @@
 Comment[sr]=Сервис Непомука за одржавање онтологија присутних на систему
 Comment[sr@latin]=Servis Nepomuka za održavanje ontologija prisutnih na sistemu
 Comment[sv]=Nepomuk-tjänst som hanterar ontologier installerade i systemet
+Comment[te]=సిస్టమ్ నందు సంస్థాపించిన ఆన్‌టాలజీస్‌ను నిర్వహించే Nepomuk సేవ
 Comment[th]=บริการของ Nepomuk สำหรับดูแล ontologies ที่ติดตั้งไว้บนระบบ
 Comment[tr]=Sistemde yüklü olan ontolojileri yürüten Nepomuk servisi
 Comment[uk]=Служба Nepomuk, яка здійснює супровід всіх онтологій встановлених у системі
diff -Naur nepomuk/services/ontologyloader/ontologyloader.cpp nepomuk/services/ontologyloader/ontologyloader.cpp
--- nepomuk/services/ontologyloader/ontologyloader.cpp	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/services/ontologyloader/ontologyloader.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -18,6 +18,8 @@
 
 #include "ontologyloader.h"
 #include "ontologymanagermodel.h"
+#include "ontologymanageradaptor.h"
+#include "graphretriever.h"
 
 #include <Soprano/Global>
 #include <Soprano/Node>
@@ -31,6 +33,8 @@
 #include <KDebug>
 #include <KGlobal>
 #include <KStandardDirs>
+#include <KLocale>
+#include <KDirWatch>
 
 #include <QtCore/QFileInfo>
 #include <QtCore/QTimer>
@@ -47,12 +51,14 @@
 {
 public:
     Private( OntologyLoader* p )
-        : q( p ) {
+        : forceOntologyUpdate( false ),
+          q( p ) {
     }
 
     OntologyManagerModel* model;
 
     QTimer updateTimer;
+    bool forceOntologyUpdate;
     QStringList desktopFilesToUpdate;
 
     void updateOntology( const QString& filename );
@@ -62,16 +68,81 @@
 };
 
 
+void Nepomuk::OntologyLoader::Private::updateOntology( const QString& filename )
+{
+    KDesktopFile df( filename );
+
+    // only update if the modification date of the ontology file changed (not the desktop file).
+    // ------------------------------------
+    QFileInfo ontoFileInf( df.readPath() );
+    QDateTime ontoLastModified = model->ontoModificationDate( df.readUrl() );
+    bool update = false;
+
+    if ( ontoLastModified < ontoFileInf.lastModified() ) {
+        kDebug() << "Ontology" << df.readUrl() << "needs updating.";
+        update = true;
+    }
+    else {
+        kDebug() << "Ontology" << df.readUrl() << "up to date.";
+    }
+
+    if( !update && forceOntologyUpdate ) {
+        kDebug() << "Ontology update forced.";
+        update = true;
+    }
+
+    if( update ) {
+        QString mimeType = df.desktopGroup().readEntry( "MimeType", QString() );
+
+        const Soprano::Parser* parser
+            = Soprano::PluginManager::instance()->discoverParserForSerialization( Soprano::mimeTypeToSerialization( mimeType ),
+                                                                                  mimeType );
+        if ( !parser ) {
+            kDebug() << "No parser to handle" << df.readName() << "(" << mimeType << ")";
+            return;
+        }
+
+        kDebug() << "Parsing" << df.readPath();
+
+        Soprano::StatementIterator it = parser->parseFile( df.readPath(),
+                                                           df.readUrl(),
+                                                           Soprano::mimeTypeToSerialization( mimeType ),
+                                                           mimeType );
+        if ( !parser->lastError() ) {
+            model->updateOntology( it, df.readUrl() );
+            emit q->ontologyUpdated( df.readUrl() );
+        }
+        else {
+            emit q->ontologyUpdateFailed( df.readUrl(), i18n( "Parsing of file %1 failed (%2)", df.readPath(), parser->lastError().message() ) );
+        }
+    }
+}
+
+
+
 Nepomuk::OntologyLoader::OntologyLoader( QObject* parent, const QList<QVariant>& )
     : Service( parent ),
       d( new Private(this) )
 {
+    ( void )new OntologyManagerAdaptor( this );
+
     d->model = new OntologyManagerModel( mainModel(), this );
     connect( &d->updateTimer, SIGNAL(timeout()), this, SLOT(updateNextOntology()) );
-    updateAllOntologies();
 
-    // FIXME: install watches for changed or newly installed ontologies
-//    QStringList dirs = KGlobal::dirs()->findDirs( "data", "nepomuk/ontologies" );
+    // only update changed ontologies
+    updateLocalOntologies();
+
+    // watch both the global and local ontology folder for changes
+    KDirWatch* dirWatch = KDirWatch::self();
+    connect( dirWatch, SIGNAL( dirty(QString) ),
+             this, SLOT( updateLocalOntologies() ) );
+    connect( dirWatch, SIGNAL( created(QString) ),
+             this, SLOT( updateLocalOntologies() ) );
+    foreach( const QString& dir, KGlobal::dirs()->findDirs( "data", QString() ) ) {
+        // we only add the suffix here to make sure to also watch the non-existing local dir
+        kDebug() << "watching" << ( dir + "nepomuk/ontologies/" );
+        dirWatch->addDir( dir + "nepomuk/ontologies/", KDirWatch::WatchFiles );
+    }
 }
 
 
@@ -81,62 +152,60 @@
 }
 
 
-void Nepomuk::OntologyLoader::updateAllOntologies()
+void Nepomuk::OntologyLoader::updateLocalOntologies()
 {
-    if ( !d->model ) {
-        kDebug() << "No Nepomuk Model. Cannot update ontologies.";
-        return;
-    }
-
-    // update all installed ontologies
     d->desktopFilesToUpdate = KGlobal::dirs()->findAllResources( "data", "nepomuk/ontologies/*.desktop" );
     d->updateTimer.start(0);
 }
 
 
+void Nepomuk::OntologyLoader::updateAllLocalOntologies()
+{
+    d->forceOntologyUpdate = true;
+    updateLocalOntologies();
+}
+
+
 void Nepomuk::OntologyLoader::updateNextOntology()
 {
     if( !d->desktopFilesToUpdate.isEmpty() ) {
         d->updateOntology( d->desktopFilesToUpdate.takeFirst() );
     }
     else {
+        d->forceOntologyUpdate = false;
         d->updateTimer.stop();
     }
 }
 
 
-void Nepomuk::OntologyLoader::Private::updateOntology( const QString& filename )
+QString Nepomuk::OntologyLoader::findOntologyContext( const QString& uri )
 {
-    KDesktopFile df( filename );
-
-    // only update if the modification date of the ontology file changed (not the desktop file).
-    // ------------------------------------
-    QFileInfo ontoFileInf( df.readPath() );
-    QDateTime ontoLastModified = model->ontoModificationDate( df.readUrl() );
-    if ( ontoLastModified < ontoFileInf.lastModified() ) {
+    return QString::fromAscii( d->model->findOntologyContext( QUrl::fromEncoded( uri.toAscii() ) ).toEncoded() );
+}
 
-        kDebug() << "Ontology" << df.readUrl() << "needs updating.";
 
-        QString mimeType = df.desktopGroup().readEntry( "MimeType", QString() );
-
-        const Soprano::Parser* parser
-            = Soprano::PluginManager::instance()->discoverParserForSerialization( Soprano::mimeTypeToSerialization( mimeType ),
-                                                                                  mimeType );
-        if ( !parser ) {
-            kDebug() << "No parser to handle" << df.readName() << "(" << mimeType << ")";
-            return;
-        }
+void Nepomuk::OntologyLoader::importOntology( const QString& url )
+{
+    connect( GraphRetriever::retrieve( url ), SIGNAL( result( KJob* ) ),
+             this, SLOT( slotGraphRetrieverResult( KJob* ) ) );
+}
 
-        kDebug() << "Parsing" << df.readPath();
 
-        model->updateOntology( parser->parseFile( df.readPath(),
-                                                  df.readUrl(),
-                                                  Soprano::mimeTypeToSerialization( mimeType ),
-                                                  mimeType ),
-                                  df.readUrl() );
+void Nepomuk::OntologyLoader::slotGraphRetrieverResult( KJob* job )
+{
+    GraphRetriever* graphRetriever = static_cast<GraphRetriever*>( job );
+    if ( job->error() ) {
+        emit ontologyUpdateFailed( QString::fromAscii( graphRetriever->url().toEncoded() ), graphRetriever->errorString() );
     }
     else {
-        kDebug() << "Ontology" << df.readUrl() << "up to date.";
+        // TODO: find a way to check if the imported version of the ontology
+        // is newer than the already installed one
+        if ( d->model->updateOntology( graphRetriever->statements(), graphRetriever->url() ) ) {
+            emit ontologyUpdated( QString::fromAscii( graphRetriever->url().toEncoded() ) );
+        }
+        else {
+            emit ontologyUpdateFailed( QString::fromAscii( graphRetriever->url().toEncoded() ), d->model->lastError().message() );
+        }
     }
 }
 
diff -Naur nepomuk/services/ontologyloader/ontologyloader.h nepomuk/services/ontologyloader/ontologyloader.h
--- nepomuk/services/ontologyloader/ontologyloader.h	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/services/ontologyloader/ontologyloader.h	2008-09-01 14:33:17.000000000 +0200
@@ -26,12 +26,14 @@
     class Model;
 }
 
+class KJob;
 
+
+// Hint: Using QString instead of QUrl for URIs since this API will be exported via DBus and not used otherwise
 namespace Nepomuk {
     class OntologyLoader : public Nepomuk::Service
     {
         Q_OBJECT
-        Q_CLASSINFO( "D-Bus Interface", "org.kde.nepomuk.OntologyManager" )
 
     public:
         OntologyLoader( QObject* parent = 0, const QList<QVariant>& args = QList<QVariant>() );
@@ -39,19 +41,49 @@
 
     public Q_SLOTS:
         /**
-         * Update all installed ontologies and install dir watches
-         * to monitor newly installed and changed ontologies.
-         *
-         * This should also be called for initialization
+         * Tries to find the ontology \p uri in the local Nepomuk store.
+         * \return The context (named graph) storing the ontology's statements
+         * or an invalid URI if the ontology could not be found.
+         */
+        QString findOntologyContext( const QString& uri );
+
+        /**
+         * Update all installed ontologies that changed since the last update.
          */
-        Q_SCRIPTABLE void updateAllOntologies();
+        void updateLocalOntologies();
 
-        // FIXME: add methods (exported on DBus) like:
-        // void importOntology( const QUrl& url... )
+        /**
+         * Update all installed ontologies, independant of their status.
+         */
+        void updateAllLocalOntologies();
+
+        /**
+         * Try to retrieve an ontology from the web.
+         * On success ontologyUpdated will be emitted. If the
+         * retrieval failed, ontologyUpdateFailed will be
+         * emitted.
+         */
+        void importOntology( const QString& url );
+
+    Q_SIGNALS:
+        /**
+         * Emitted once an ontology has been updated. This holds for both
+         * locally installed ontology files (which are read automaticall)
+         * and those retrieved from the web via importOntology
+         */
+        void ontologyUpdated( const QString& uri );
+
+        /**
+         * Emitted if updating an ontology failed. This holds for both
+         * locally installed ontology files (parsing may fail) and for
+         * those imported via importOntology.
+         */
+        void ontologyUpdateFailed( const QString& uri, const QString& error );
 
     private Q_SLOTS:
         // a little async updating
         void updateNextOntology();
+        void slotGraphRetrieverResult( KJob* job );
 
     private:
         class Private;
diff -Naur nepomuk/services/ontologyloader/ontologymanagermodel.cpp nepomuk/services/ontologyloader/ontologymanagermodel.cpp
--- nepomuk/services/ontologyloader/ontologymanagermodel.cpp	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/services/ontologyloader/ontologymanagermodel.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -193,10 +193,19 @@
 }
 
 
+void Nepomuk::OntologyManagerModel::setParentModel( Soprano::Model* parentModel )
+{
+    FilterModel::setParentModel( parentModel );
+}
+
+
 bool Nepomuk::OntologyManagerModel::updateOntology( Soprano::StatementIterator data, const QUrl& ns )
 {
     clearError();
 
+    QTime timer;
+    timer.start();
+
     // Create temp memory model
     // ------------------------------------
     const Soprano::Backend* backend = Soprano::PluginManager::instance()->discoverBackendByFeatures( Soprano::BackendFeatureStorageMemory );
@@ -290,7 +299,7 @@
             }
         }
 
-        kDebug() << "Successfully updated ontology" << ontoUri;
+        kDebug() << "Successfully updated ontology" << ontoUri << QString("(%1ms)").arg(timer.elapsed());
         return true;
     }
     else {
@@ -340,4 +349,16 @@
     }
 }
 
+
+QUrl Nepomuk::OntologyManagerModel::findOntologyContext( const QUrl& uri )
+{
+    QUrl dataGraphUri, metaDataGraphUri;
+    if ( findGraphUris( parentModel(), uri, dataGraphUri, metaDataGraphUri ) ) {
+        return dataGraphUri;
+    }
+    else {
+        return QUrl();
+    }
+}
+
 #include "ontologymanagermodel.moc"
diff -Naur nepomuk/services/ontologyloader/ontologymanagermodel.h nepomuk/services/ontologyloader/ontologymanagermodel.h
--- nepomuk/services/ontologyloader/ontologymanagermodel.h	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/services/ontologyloader/ontologymanagermodel.h	2008-09-01 14:33:17.000000000 +0200
@@ -46,6 +46,11 @@
          * Destructor
          */
         ~OntologyManagerModel();
+
+        /**
+         * Reimplemented from FilterModel. The API is not affected.
+         */
+        void setParentModel( Soprano::Model* parentModel );
         
         /**
          * Update an ontology.
@@ -83,6 +88,13 @@
          */
         QDateTime ontoModificationDate( const QUrl& uri );
 
+        /**
+         * Tries to find the ontology \p uri in the local Nepomuk store.
+         * \return The context (named graph) storing the ontology's statements
+         * or an invalid URI if the ontology could not be found.
+         */
+        QUrl findOntologyContext( const QUrl& uri );
+
     private:
         class Private;
         Private* const d;
diff -Naur nepomuk/services/storage/nepomukcore.cpp nepomuk/services/storage/nepomukcore.cpp
--- nepomuk/services/storage/nepomukcore.cpp	2008-07-08 11:26:02.000000000 +0200
+++ nepomuk/services/storage/nepomukcore.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -127,4 +127,11 @@
     }
 }
 
+
+void Nepomuk::Core::optimize( const QString& name )
+{
+    if ( m_repositories.contains( name ) )
+        m_repositories[name]->optimize();
+}
+
 #include "nepomukcore.moc"
diff -Naur nepomuk/services/storage/nepomukcore.h nepomuk/services/storage/nepomukcore.h
--- nepomuk/services/storage/nepomukcore.h	2008-04-10 11:30:07.000000000 +0200
+++ nepomuk/services/storage/nepomukcore.h	2008-09-01 14:33:17.000000000 +0200
@@ -51,6 +51,9 @@
          */
         bool initialized() const;
 
+    public Q_SLOTS:
+        void optimize( const QString& repoName );
+
     Q_SIGNALS:
         void initializationDone( bool success );
 
diff -Naur nepomuk/services/storage/nepomukstorage.desktop nepomuk/services/storage/nepomukstorage.desktop
--- nepomuk/services/storage/nepomukstorage.desktop	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/services/storage/nepomukstorage.desktop	2008-09-01 14:33:17.000000000 +0200
@@ -5,7 +5,6 @@
 X-KDE-Nepomuk-autostart=true
 X-KDE-Nepomuk-start-on-demand=true
 Name=Nepomuk Data Storage
-Name[ar]=مخزن بياناتNepomuk
 Name[bg]=Хранилище Nepomuk
 Name[bn_IN]=Nepomuk ডাটা সংরক্ষণব্যবস্থা
 Name[ca]=Emmagatzematge de dades del Nepomuk
@@ -44,6 +43,7 @@
 Name[sr]=Непомуково складиште
 Name[sr@latin]=Nepomukovo skladište
 Name[sv]=Nepomuk-datalagring
+Name[te]=Nepomuk డాటా నిల్వ
 Name[tg]=Захирагоҳи Nepomuk
 Name[th]=ที่จัดเก็บข้อมูลของ Nepomuk
 Name[tr]=Nepomuk Veri Depolama
@@ -53,7 +53,6 @@
 Name[zh_CN]=Nepomuk 数据存储
 Name[zh_TW]=Nepomuk 資料儲存
 Comment=The Core Nepomuk data storage service
-Comment[ar]=مخزن Nepomuk الاساسي للخدمات والبيانات
 Comment[bg]=Основното място, където се съхраняват данните на Nepomuk
 Comment[ca]=El servei d'emmagatzematge de dades del nucli del Nepomuk
 Comment[csb]=Spòdlowô ùsłëżnota Nepomuka do trzëmaniô pòdôwków
@@ -88,6 +87,7 @@
 Comment[sr]=Језгарни сервис Непомука за складиштење података
 Comment[sr@latin]=Jezgarni servis Nepomuka za skladištenje podataka
 Comment[sv]=Nepomuk-datalagringstjänstens kärna
+Comment[te]=ఆధార Nepomuk డాటా నిల్వ సేవ
 Comment[th]=บริการจัดเก็บข้อมูล Core Nepomik
 Comment[tr]=Nepomuk Ana veri depolama servisi
 Comment[uk]=Ядро служби збереження даних Nepomuk
diff -Naur nepomuk/services/storage/repository.cpp nepomuk/services/storage/repository.cpp
--- nepomuk/services/storage/repository.cpp	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/services/storage/repository.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -26,6 +26,7 @@
 #include <Soprano/StorageModel>
 #include <Soprano/Error/Error>
 #include <Soprano/Vocabulary/Xesam>
+#include <Soprano/Vocabulary/RDF>
 
 #ifdef HAVE_SOPRANO_INDEX
 #include <Soprano/Index/IndexFilterModel>
@@ -38,6 +39,8 @@
 #include <KSharedConfig>
 #include <KLocale>
 
+#include <QtCore/QTimer>
+
 
 namespace {
     QString createStoragePath( const QString& repositoryId )
@@ -273,6 +276,22 @@
 }
 
 
+void Nepomuk::Repository::optimize()
+{
+    QTimer::singleShot( 0, this, SLOT( slotDoOptimize() ) );
+}
+
+
+void Nepomuk::Repository::slotDoOptimize()
+{
+#ifdef HAVE_SOPRANO_INDEX
+#if SOPRANO_IS_VERSION(2,1,60)
+    m_index->optimize();
+#endif
+#endif
+}
+
+
 const Soprano::Backend* Nepomuk::Repository::activeSopranoBackend()
 {
     QString backendName = KSharedConfig::openConfig( "nepomukserverrc" )->group( "Basic Settings" ).readEntry( "Soprano Backend", "sesame2" );
diff -Naur nepomuk/services/storage/repository.h nepomuk/services/storage/repository.h
--- nepomuk/services/storage/repository.h	2008-05-15 20:37:14.000000000 +0200
+++ nepomuk/services/storage/repository.h	2008-09-01 14:33:17.000000000 +0200
@@ -18,17 +18,7 @@
 #include <QtCore/QString>
 #include <QtCore/QMap>
 
-#include <soprano/version.h>
-
-#ifndef SOPRANO_IS_VERSION
-#define SOPRANO_IS_VERSION(a,b,c) false
-#endif
-
-#if SOPRANO_IS_VERSION(2,0,90)
 #include <Soprano/Util/SignalCacheModel>
-#else
-#include <Soprano/FilterModel>
-#endif
 
 
 namespace Soprano {
@@ -46,12 +36,7 @@
 
     class CLuceneAnalyzer;
 
-    class Repository : public
-#if SOPRANO_IS_VERSION(2,0,90)
-        Soprano::Util::SignalCacheModel
-#else
-        Soprano::FilterModel
-#endif
+    class Repository : public Soprano::Util::SignalCacheModel
     {
         Q_OBJECT
 
@@ -79,11 +64,17 @@
 
         void close();
 
+        /**
+         * Calls slotDoOptimize via timer for instant return.
+         */
+        void optimize();
+
     Q_SIGNALS:
         void opened( Repository*, bool success );
 
     private Q_SLOTS:
         void copyFinished( KJob* job );
+        void slotDoOptimize();
 
     private:
         QString m_name;
diff -Naur nepomuk/services/storage/storage.cpp nepomuk/services/storage/storage.cpp
--- nepomuk/services/storage/storage.cpp	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/services/storage/storage.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -26,6 +26,8 @@
 #include <KGlobal>
 #include <KStandardDirs>
 
+#include <Soprano/Backend>
+
 #include <kpluginfactory.h>
 #include <kpluginloader.h>
 
@@ -70,4 +72,18 @@
     setServiceInitialized( success );
 }
 
+
+void Nepomuk::Storage::optimize( const QString& repo )
+{
+    m_core->optimize( repo );
+}
+
+
+QString Nepomuk::Storage::usedSopranoBackend() const
+{
+    // FIXME: this is only partly true. It is perfectly possible to change the backend only
+    //        for the main repo in the config file
+    return Repository::activeSopranoBackend()->pluginName();
+}
+
 #include "storage.moc"
diff -Naur nepomuk/services/storage/storage.h nepomuk/services/storage/storage.h
--- nepomuk/services/storage/storage.h	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/services/storage/storage.h	2008-09-01 14:33:17.000000000 +0200
@@ -28,12 +28,16 @@
     class Storage : public Service
     {
         Q_OBJECT
-//        Q_CLASSINFO( "D-Bus Interface", "org.kde.nepomuk.Storage" )
+        Q_CLASSINFO( "D-Bus Interface", "org.kde.nepomuk.Storage" )
 
     public:
         Storage( QObject* parent, const QList<QVariant>& args = QList<QVariant>() );
         ~Storage();
 
+    public Q_SLOTS:
+        Q_SCRIPTABLE void optimize( const QString& repo );
+        Q_SCRIPTABLE QString usedSopranoBackend() const;
+
     private Q_SLOTS:
         void slotNepomukCoreInitialized( bool success );
 
diff -Naur nepomuk/services/strigi/CMakeLists.txt nepomuk/services/strigi/CMakeLists.txt
--- nepomuk/services/strigi/CMakeLists.txt	2008-06-26 03:33:08.000000000 +0200
+++ nepomuk/services/strigi/CMakeLists.txt	2008-09-01 14:33:17.000000000 +0200
@@ -1,25 +1,41 @@
-project(strigiservice)
+project(nepomukstrigiservice)
 
 include_directories(
   ${SOPRANO_INCLUDE_DIR}
   ${CMAKE_SOURCE_DIR}
   ${NEPOMUK_INCLUDE_DIR}
-  ${nepomukcommon_BINARY_DIR}
+  ${STRIGI_INCLUDE_DIR}
+  ${nepomukstrigiservice_BUILD_DIR}
   )
 
 set(strigiservice_SRCS
   strigiservice.cpp
-  strigicontroller.cpp
-  ../../common/strigiconfigfile.cpp
+  strigiserviceadaptor.cpp
+  indexscheduler.cpp
+  priority.cpp
+  config.cpp
+  eventmonitor.cpp
+  systray.cpp
+  statuswidget.cpp
+  filesystemwatcher.cpp
   )
 
+qt4_add_dbus_interface(strigiservice_SRCS ../../interfaces/org.kde.nepomuk.Storage.xml nepomukstorageinterface)
+
+kde4_add_ui_files(strigiservice_SRCS
+  statuswidget.ui)
+
 kde4_add_plugin(nepomukstrigiservice ${strigiservice_SRCS})
 
 target_link_libraries(nepomukstrigiservice
-  ${STRIGI_STRIGIQTDBUSCLIENT_LIBRARY}
+  ${STRIGI_STREAMANALYZER_LIBRARY}
+  ${STRIGI_STREAMS_LIBRARY}
   ${KDE4_KDEUI_LIBS}
+  ${KDE4_KIO_LIBS}
+  ${KDE4_SOLID_LIBS}
+  ${KDE4_KUTILS_LIBS}
   ${NEPOMUK_LIBRARIES}
-  ${QT_QTXML_LIBRARY}
+  ${SOPRANO_LIBRARIES}
   )
 
 install(
@@ -27,6 +43,10 @@
   DESTINATION ${SERVICES_INSTALL_DIR})
 
 install(
+  FILES nepomukstrigiservice.notifyrc
+  DESTINATION ${DATA_INSTALL_DIR}/nepomukstrigiservice)
+
+install(
   TARGETS nepomukstrigiservice
   DESTINATION ${PLUGIN_INSTALL_DIR})
 # -----------------------------
diff -Naur nepomuk/services/strigi/config.cpp nepomuk/services/strigi/config.cpp
--- nepomuk/services/strigi/config.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/config.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,110 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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 "config.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QDir>
+
+#include <kdirwatch.h>
+#include <kstandarddirs.h>
+#include <kconfiggroup.h>
+
+
+Nepomuk::Config::Config()
+    : QObject(),
+      m_config( "nepomukstrigirc" )
+{
+    KDirWatch* dirWatch = KDirWatch::self();
+    connect( dirWatch, SIGNAL( dirty( const QString& ) ),
+             this, SLOT( slotConfigDirty() ) );
+    connect( dirWatch, SIGNAL( created( const QString& ) ),
+             this, SLOT( slotConfigDirty() ) );
+    dirWatch->addFile( KStandardDirs::locateLocal( "config", m_config.name() ) );
+}
+
+
+Nepomuk::Config::~Config()
+{
+    m_config.group( "General" ).writeEntry( "first run", false );
+}
+
+
+Nepomuk::Config* Nepomuk::Config::self()
+{
+    K_GLOBAL_STATIC( Config, _self );
+    return _self;
+}
+
+
+QStringList Nepomuk::Config::folders() const
+{
+    return m_config.group( "General" ).readPathEntry( "folders", QStringList() << QDir::homePath() );
+}
+
+
+bool Nepomuk::Config::recursive() const
+{
+    return m_config.group( "General" ).readEntry( "recursive", true );
+}
+
+
+QStringList Nepomuk::Config::excludeFilters() const
+{
+    return m_config.group( "General" ).readEntry( "exclude filters", QStringList() << ".*/" << ".*" << "*~" << "*.part" );
+}
+
+
+QStringList Nepomuk::Config::includeFilters() const
+{
+    return m_config.group( "General" ).readEntry( "include filters", QStringList() );
+}
+
+
+KIO::filesize_t Nepomuk::Config::minDiskSpace() const
+{
+    // default: 200 MB
+    return m_config.group( "General" ).readEntry( "min disk space", KIO::filesize_t( 200*1024*1024 ) );
+}
+
+
+void Nepomuk::Config::slotConfigDirty()
+{
+    m_config.reparseConfiguration();
+    emit configChanged();
+}
+
+
+bool Nepomuk::Config::showGui() const
+{
+    return m_config.group( "General" ).readEntry( "show gui", true );
+}
+
+
+void Nepomuk::Config::setShowGui( bool showGui )
+{
+    m_config.group( "General" ).writeEntry( "show gui", showGui );
+}
+
+
+bool Nepomuk::Config::isInitialRun() const
+{
+    return m_config.group( "General" ).readEntry( "first run", true );
+}
+
+#include "config.moc"
diff -Naur nepomuk/services/strigi/config.h nepomuk/services/strigi/config.h
--- nepomuk/services/strigi/config.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/config.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,82 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef _NEPOMUK_STRIGI_CONFIG_H_
+#define _NEPOMUK_STRIGI_CONFIG_H_
+
+#include <QtCore/QObject>
+
+#include <kconfig.h>
+#include <kio/global.h>
+
+
+namespace Nepomuk {
+    /**
+     * Active config class which emits signals if the config
+     * was changed, for example if the KCM saved the config file.
+     */
+    class Config : public QObject
+    {
+        Q_OBJECT
+
+    public:
+        ~Config();
+        static Config* self();
+
+        /**
+         * The folders to search for files to analyse
+         */
+        QStringList folders() const;
+
+        /**
+         * Recurse into subdirs
+         */
+        bool recursive() const;
+        
+        QStringList excludeFilters() const;
+        QStringList includeFilters() const;
+
+        bool showGui() const;
+        void setShowGui( bool showGui );
+
+        /**
+         * The minimal available disk space. If it drops below
+         * indexing will be suspended.
+         */
+        KIO::filesize_t minDiskSpace() const;
+
+        /**
+         * true the first time the service is run (or after manually
+         * tampering with the config.
+         */
+        bool isInitialRun() const;
+
+    Q_SIGNALS:
+        void configChanged();
+
+    private Q_SLOTS:
+        void slotConfigDirty();
+
+    private:
+        Config();
+
+        KConfig m_config;
+    };
+}
+
+#endif
diff -Naur nepomuk/services/strigi/eventmonitor.cpp nepomuk/services/strigi/eventmonitor.cpp
--- nepomuk/services/strigi/eventmonitor.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/eventmonitor.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,178 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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 "eventmonitor.h"
+#include "config.h"
+#include "indexscheduler.h"
+#include "filesystemwatcher.h"
+
+#include <KDebug>
+#include <KPassivePopup>
+#include <KLocale>
+#include <KDiskFreeSpaceInfo>
+#include <KStandardDirs>
+#include <KNotification>
+#include <KIcon>
+
+#include <Solid/PowerManagement>
+
+#include <QtDBus/QDBusInterface>
+
+
+namespace {
+    void sendEvent( const QString& event, const QString& text, const QString& iconName ) {
+        KNotification::event( event, text, KIcon( iconName ).pixmap( 32, 32 ) );
+    }
+}
+
+
+Nepomuk::EventMonitor::EventMonitor( IndexScheduler* scheduler, QObject* parent )
+    : QObject( parent ),
+      m_indexScheduler( scheduler ),
+      m_pauseState( NotPaused )
+{
+    // monitor the file system
+    m_fsWatcher = new FileSystemWatcher( this );
+    connect( m_fsWatcher, SIGNAL( dirty( QString ) ),
+             m_indexScheduler, SLOT( updateDir( QString ) ) );
+
+    // update the watches if the config changes
+    connect( Config::self(), SIGNAL( configChanged() ),
+             this, SLOT( updateWatches() ) );
+
+    // start watching the index folders
+    updateWatches();
+
+    // FileSystemWatcher does not catch changes to files, only new and removed files
+    // thus, we also do periodic updates of the whole index every half hour
+    connect( &m_periodicUpdateTimer, SIGNAL( timeout() ),
+             m_indexScheduler, SLOT( updateAll() ) );
+    m_periodicUpdateTimer.setInterval( 30*60*1000 );
+
+    // monitor the powermanagement to not drain the battery
+    connect( Solid::PowerManagement::notifier(), SIGNAL( appShouldConserveResourcesChanged( bool ) ),
+             this, SLOT( slotPowerManagementStatusChanged( bool ) ) );
+
+    // setup the avail disk usage monitor
+    connect( &m_availSpaceTimer, SIGNAL( timeout() ),
+             this, SLOT( slotCheckAvailableSpace() ) );
+    m_availSpaceTimer.start( 20*1000 ); // every 20 seconds should be enough
+
+    if ( Config::self()->isInitialRun() ) {
+        // TODO: add actions to this notification
+
+        m_initialIndexTime.start();
+
+        // inform the user about the initial indexing
+        sendEvent( "initialIndexingStarted",
+                   i18n( "Strigi file indexing started. Indexing all files for fast desktop searches may take a while." ),
+                   "nepomuk" );
+
+        // connect to get the end of initial indexing
+        connect( m_indexScheduler, SIGNAL( indexingStopped() ),
+                 this, SLOT( slotIndexingStopped() ) );
+    }
+    else {
+        m_periodicUpdateTimer.start();
+    }
+}
+
+
+Nepomuk::EventMonitor::~EventMonitor()
+{
+}
+
+
+void Nepomuk::EventMonitor::updateWatches()
+{
+    // the hard way since the KDirWatch API is too simple
+    QStringList folders = Config::self()->folders();
+    if ( folders != m_fsWatcher->folders() ||
+         Config::self()->recursive() != m_fsWatcher->watchRecursively() ) {
+        m_fsWatcher->setFolders( Config::self()->folders() );
+        m_fsWatcher->setWatchRecursively( Config::self()->recursive() );
+        m_fsWatcher->setInterval( 2*60 ); // check every 2 minutes
+        m_fsWatcher->start();
+    }
+}
+
+
+void Nepomuk::EventMonitor::slotPowerManagementStatusChanged( bool conserveResources )
+{
+    if ( !conserveResources && m_pauseState == PausedDueToPowerManagement ) {
+        kDebug() << "Resuming indexer due to power management";
+        m_pauseState = NotPaused;
+        m_indexScheduler->resume();
+        sendEvent( "indexingResumed", i18n("Resuming Strigi file indexing."), "solid" );
+    }
+    else if ( m_indexScheduler->isRunning() &&
+              !m_indexScheduler->isSuspended() ) {
+        kDebug() << "Pausing indexer due to power management";
+        m_pauseState = PausedDueToPowerManagement;
+        m_indexScheduler->suspend();
+        sendEvent( "indexingSuspended", i18n("Suspending Strigi file indexing to preserve resources."), "solid" );
+    }
+}
+
+
+void Nepomuk::EventMonitor::slotCheckAvailableSpace()
+{
+    KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( KStandardDirs::locateLocal( "data", "nepomuk/repository/", false ) );
+    if ( info.isValid() ) {
+        if ( info.available() <= Config::self()->minDiskSpace() ) {
+            if ( m_indexScheduler->isRunning() &&
+                !m_indexScheduler->isSuspended() ) {
+                m_pauseState = PausedDueToAvailSpace;
+                m_indexScheduler->suspend();
+                sendEvent( "indexingSuspended",
+                           i18n("Local disk space is running low (%1 left). Suspending Strigi file indexing.",
+                                KIO::convertSize( info.available() ) ),
+                           "drive-harddisk" );
+            }
+        }
+        else if ( m_pauseState == PausedDueToAvailSpace ) {
+            kDebug() << "Resuming indexer due to disk space";
+            m_pauseState = NotPaused;
+            m_indexScheduler->resume();
+            sendEvent( "indexingResumed", i18n("Resuming Strigi file indexing."), "drive-harddisk" );
+        }
+    }
+    else {
+        // if it does not work once, it will probably never work
+        m_availSpaceTimer.stop();
+    }
+}
+
+
+void Nepomuk::EventMonitor::slotIndexingStopped()
+{
+    // inform the user about the end of initial indexing. This will only be called once
+    if ( !m_indexScheduler->isSuspended() ) {
+        kDebug() << "initial indexing took" << m_initialIndexTime.elapsed();
+        sendEvent( "initialIndexingFinished", i18n( "Strigi file indexing finished. Elapsed time: %1", m_initialIndexTime.toString() ), "nepomuk" );
+        m_indexScheduler->disconnect( this );
+
+        // after this much index work, it makes sense to optimize the full text index in the main model
+        QDBusInterface( "org.kde.nepomuk.services.nepomukstorage", "/nepomukstorage", "org.kde.nepomuk.Storage" ).call( "optimize", "main" );
+
+
+        m_periodicUpdateTimer.start();
+    }
+}
+
+#include "eventmonitor.moc"
diff -Naur nepomuk/services/strigi/eventmonitor.h nepomuk/services/strigi/eventmonitor.h
--- nepomuk/services/strigi/eventmonitor.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/eventmonitor.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,69 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef _NEPOMUK_STRIGI_EVENT_MONITOR_H_
+#define _NEPOMUK_STRIGI_EVENT_MONITOR_H_
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QTimer>
+#include <QtCore/QTime>
+
+class KDiskFreeSpace;
+class FileSystemWatcher;
+
+namespace Nepomuk {
+
+    class IndexScheduler;
+
+    class EventMonitor : public QObject
+    {
+        Q_OBJECT
+
+    public:
+        EventMonitor( IndexScheduler* scheduler, QObject* parent );
+        ~EventMonitor();
+
+    private Q_SLOTS:
+        void slotPowerManagementStatusChanged( bool conserveResources );
+        void updateWatches();
+        void slotCheckAvailableSpace();
+        void slotIndexingStopped();
+
+    private:
+        enum {
+            NotPaused,
+            PausedDueToPowerManagement,
+            PausedDueToAvailSpace
+        };
+
+        IndexScheduler* m_indexScheduler;
+        int m_pauseState;
+
+        FileSystemWatcher* m_fsWatcher;
+
+        // timer used to periodically check for available space
+        QTimer m_availSpaceTimer;
+
+        QTime m_initialIndexTime;
+
+        QTimer m_periodicUpdateTimer;
+    };
+}
+
+#endif
diff -Naur nepomuk/services/strigi/filesystemwatcher.cpp nepomuk/services/strigi/filesystemwatcher.cpp
--- nepomuk/services/strigi/filesystemwatcher.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/filesystemwatcher.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,212 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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 "filesystemwatcher.h"
+
+#include <QtCore/QTimer>
+#include <QtCore/QHash>
+#include <QtCore/QDateTime>
+#include <QtCore/QStringList>
+#include <QtCore/QDirIterator>
+#include <QtCore/QFileInfo>
+
+#include <KDebug>
+
+
+namespace {
+    // small class to keep mem usage low
+    class FolderEntry
+    {
+    public:
+        FolderEntry() {
+        }
+
+        FolderEntry( int m )
+            : mTime( m ) {
+        }
+
+        uint mTime;
+        QHash<QString, FolderEntry> children;
+    };
+}
+
+class FileSystemWatcher::Private
+{
+public:
+    Private( FileSystemWatcher* parent )
+        : recursive( true ),
+          interval( 10*60 ),
+          q( parent ) {
+    }
+
+    QStringList folders;
+    QHash<QString, FolderEntry> cache;
+    bool recursive;
+    int interval;
+
+    QTimer timer;
+
+    void buildFolderCache( uint mTime );
+    void checkFolders();
+
+private:
+    void updateChildrenCache( const QString& parentPath, FolderEntry& parentEntry, bool signalNewEntries );
+    void checkFolder( const QString& path, FolderEntry& folder );
+
+    FileSystemWatcher* q;
+};
+
+
+void FileSystemWatcher::Private::buildFolderCache( uint mTime )
+{
+    cache.clear();
+
+    foreach( QString folder, folders ) {
+        if ( folder.endsWith( '/' ) )
+            folder.truncate( folder.length()-1 );
+        FolderEntry entry( mTime );
+        if ( recursive ) {
+            updateChildrenCache( folder, entry, false );
+        }
+        cache.insert( folder, entry );
+    }
+}
+
+
+void FileSystemWatcher::Private::updateChildrenCache( const QString& parentPath, FolderEntry& parentEntry, bool signalNewEntries )
+{
+    QDirIterator dirIt( parentPath, QDir::NoDotAndDotDot|QDir::Readable|QDir::Dirs|QDir::NoSymLinks );
+    while ( dirIt.hasNext() ) {
+        dirIt.next();
+        if ( !parentEntry.children.contains( dirIt.fileName() ) ) {
+            FolderEntry entry( parentEntry.mTime );
+            parentEntry.children.insert( dirIt.fileName(), entry );
+            if ( signalNewEntries ) {
+                emit q->dirty( dirIt.filePath() );
+            }
+        }
+    }
+
+    for( QHash<QString, FolderEntry>::iterator it = parentEntry.children.begin();
+         it != parentEntry.children.end(); ++it ) {
+        updateChildrenCache( parentPath + '/' + it.key(), it.value(), signalNewEntries );
+    }
+}
+
+
+void FileSystemWatcher::Private::checkFolders()
+{
+    for( QHash<QString, FolderEntry>::iterator it = cache.begin();
+         it != cache.end(); ++it ) {
+        checkFolder( it.key(), it.value() );
+    }
+}
+
+
+void FileSystemWatcher::Private::checkFolder( const QString& path, FolderEntry& entry )
+{
+    QFileInfo info( path );
+    if ( info.exists() ) {
+        // check if anything changed in the folder
+        bool dirty = false;
+        if ( info.lastModified().toTime_t() > entry.mTime ) {
+            entry.mTime = info.lastModified().toTime_t();
+            emit q->dirty( path );
+            dirty = true;
+        }
+
+        // check if any subfolder changed
+        for( QHash<QString, FolderEntry>::iterator it = entry.children.begin();
+             it != entry.children.end(); ++it ) {
+            checkFolder( path + '/' + it.key(), it.value() );
+        }
+
+        // update in case folders have been created
+        if ( dirty ) {
+            updateChildrenCache( path, entry, true );
+        }
+    }
+    // else -> FIXME: do we need to signal this or is it handled by the parent folder
+}
+
+
+FileSystemWatcher::FileSystemWatcher( QObject* parent )
+    : QObject( parent ),
+      d( new Private( this ) )
+{
+    connect( &d->timer, SIGNAL( timeout() ),
+             this, SLOT( checkFolders() ) );
+}
+
+
+FileSystemWatcher::~FileSystemWatcher()
+{
+    delete d;
+}
+
+
+void FileSystemWatcher::start( const QDateTime& startTime )
+{
+    stop();
+    d->buildFolderCache( startTime.toTime_t() );
+    d->timer.start( d->interval*1000 );
+}
+
+
+void FileSystemWatcher::stop()
+{
+    d->timer.stop();
+}
+
+
+QStringList FileSystemWatcher::folders() const
+{
+    return d->folders;
+}
+
+
+bool FileSystemWatcher::watchRecursively() const
+{
+    return d->recursive;
+}
+
+
+int FileSystemWatcher::interval() const
+{
+    return d->interval;
+}
+
+
+void FileSystemWatcher::setFolders( const QStringList& folders )
+{
+    d->folders = folders;
+}
+
+
+void FileSystemWatcher::setWatchRecursively( bool r )
+{
+    d->recursive = r;
+}
+
+
+void FileSystemWatcher::setInterval( int seconds )
+{
+    d->interval = seconds;
+}
+
+#include "filesystemwatcher.moc"
diff -Naur nepomuk/services/strigi/filesystemwatcher.h nepomuk/services/strigi/filesystemwatcher.h
--- nepomuk/services/strigi/filesystemwatcher.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/filesystemwatcher.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,78 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef _FILE_SYSTEM_WATCHER_H_
+#define _FILE_SYSTEM_WATCHER_H_
+
+#include <QtCore/QObject>
+#include <QtCore/QDateTime>
+
+
+/**
+ * Watches a file system by periodically checking the
+ * folder modification date.
+ */
+class FileSystemWatcher : public QObject
+{
+    Q_OBJECT
+
+public:
+    FileSystemWatcher( QObject* parent = 0 );
+    ~FileSystemWatcher();
+
+    QStringList folders() const;
+    bool watchRecursively() const;
+    int interval() const;
+
+public Q_SLOTS:
+    void setFolders( const QStringList& folders );
+
+    /**
+     * Enabled by default.
+     */
+    void setWatchRecursively( bool );
+
+    void setInterval( int seconds );
+
+    /**
+     * Actually start checking the folders. Once the FileSystemWatcher
+     * is started it will check the configured folders every \p interval()
+     * seconds.
+     *
+     * Be aware that changing the settings on a started FileSystemWatcher
+     * will have no effect until it is restarted.
+     */
+    void start( const QDateTime& startTime = QDateTime::currentDateTime() );
+
+    void stop();
+
+Q_SIGNALS:
+    /**
+     * Emitted if a folder is dirty, i.e. its contents
+     * changed.
+     */
+    void dirty( const QString& folder );
+
+private:
+    class Private;
+    Private* const d;
+
+    Q_PRIVATE_SLOT( d, void checkFolders() )
+};
+
+#endif
diff -Naur nepomuk/services/strigi/indexscheduler.cpp nepomuk/services/strigi/indexscheduler.cpp
--- nepomuk/services/strigi/indexscheduler.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/indexscheduler.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,431 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
+
+   Parts of this file are based on code from Strigi
+   Copyright (C) 2006-2007 Jos van den Oever <jos@vandenoever.info>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License version 2 as published by the Free Software Foundation.
+
+   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 "indexscheduler.h"
+#include "config.h"
+
+#include <QtCore/QMutexLocker>
+#include <QtCore/QList>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDirIterator>
+#include <QtCore/QDateTime>
+#include <QtCore/QByteArray>
+#include <QtCore/QUrl>
+
+#include <KDebug>
+#include <KTemporaryFile>
+
+#include <map>
+#include <vector>
+
+#include <strigi/indexwriter.h>
+#include <strigi/indexmanager.h>
+#include <strigi/indexreader.h>
+#include <strigi/analysisresult.h>
+#include <strigi/fileinputstream.h>
+#include <strigi/analyzerconfiguration.h>
+
+
+class StoppableConfiguration : public Strigi::AnalyzerConfiguration {
+public:
+    StoppableConfiguration()
+        : m_stop(false) {
+    }
+
+    bool indexMore() const {
+        return !m_stop;
+    }
+
+    bool addMoreText() const {
+        return !m_stop;
+    }
+
+    void setStop( bool s ) {
+        m_stop = s;
+    }
+
+private:
+    bool m_stop;
+};
+
+
+Nepomuk::IndexScheduler::IndexScheduler( Strigi::IndexManager* manager, QObject* parent )
+    : QThread( parent ),
+      m_suspended( false ),
+      m_stopped( false ),
+      m_indexing( false ),
+      m_indexManager( manager )
+{
+    m_analyzerConfig = new StoppableConfiguration;
+
+    connect( Config::self(), SIGNAL( configChanged() ),
+             this, SLOT( readConfig() ) );
+}
+
+
+Nepomuk::IndexScheduler::~IndexScheduler()
+{
+    delete m_analyzerConfig;
+}
+
+
+void Nepomuk::IndexScheduler::suspend()
+{
+    if ( isRunning() ) {
+        QMutexLocker locker( &m_resumeStopMutex );
+        m_suspended = true;
+    }
+}
+
+
+void Nepomuk::IndexScheduler::resume()
+{
+    if ( isRunning() ) {
+        QMutexLocker locker( &m_resumeStopMutex );
+        m_suspended = false;
+        m_resumeStopWc.wakeAll();
+    }
+}
+
+
+void Nepomuk::IndexScheduler::setSuspended( bool suspended )
+{
+    if ( suspended )
+        suspend();
+    else
+        resume();
+}
+
+
+void Nepomuk::IndexScheduler::stop()
+{
+    if ( isRunning() ) {
+        QMutexLocker locker( &m_resumeStopMutex );
+        m_stopped = true;
+        m_suspended = false;
+        m_analyzerConfig->setStop( true );
+        m_dirsToUpdateWc.wakeAll();
+        m_resumeStopWc.wakeAll();
+    }
+}
+
+
+bool Nepomuk::IndexScheduler::isSuspended() const
+{
+    return isRunning() && m_suspended;
+}
+
+
+bool Nepomuk::IndexScheduler::isIndexing() const
+{
+    return m_indexing;
+}
+
+
+QString Nepomuk::IndexScheduler::currentFolder() const
+{
+    return m_currentFolder;
+}
+
+
+void Nepomuk::IndexScheduler::setIndexingStarted( bool started )
+{
+    if ( started != m_indexing ) {
+        m_indexing = started;
+        if ( m_indexing )
+            emit indexingStarted();
+        else
+            emit indexingStopped();
+    }
+}
+
+
+void Nepomuk::IndexScheduler::run()
+{
+    // set lowest priority for this thread
+    setPriority( QThread::IdlePriority );
+
+    // initialization
+    m_suspended = false;
+    m_stopped = false;
+    m_analyzerConfig->setStop( false );
+    readConfig();
+
+    Strigi::StreamAnalyzer analyzer( *m_analyzerConfig );
+    analyzer.setIndexWriter( *m_indexManager->indexWriter() );
+
+    setIndexingStarted( true );
+
+    // do the actual indexing
+    m_dirsToUpdate.clear();
+    foreach( const QString& f, Config::self()->folders() )
+        m_dirsToUpdate << qMakePair( f, Config::self()->recursive() );
+
+    m_startedRecursive = Config::self()->recursive();
+
+    while ( 1 ) {
+        // wait for more dirs to analyze in case the initial
+        // indexing is done
+        if ( m_dirsToUpdate.isEmpty() ) {
+            setIndexingStarted( false );
+
+            m_dirsToUpdateMutex.lock();
+            m_dirsToUpdateWc.wait( &m_dirsToUpdateMutex );
+            m_dirsToUpdateMutex.unlock();
+
+            if ( !m_stopped )
+                setIndexingStarted( true );
+        }
+
+        // wait for resume or stop (or simply continue)
+        if ( !waitForContinue() ) {
+            break;
+        }
+
+        // get the next folder
+        m_dirsToUpdateMutex.lock();
+        QPair<QString, bool> dir = *m_dirsToUpdate.begin();
+        m_dirsToUpdate.erase( m_dirsToUpdate.begin() );
+        m_dirsToUpdateMutex.unlock();
+
+        // update until stopped
+        if ( !updateDir( dir.first, &analyzer, dir.second ) ) {
+            break;
+        }
+        m_currentFolder.clear();
+    }
+
+    setIndexingStarted( false );
+}
+
+
+// this method should be thread-safe ("should" because of the indexreader and -writer)
+bool Nepomuk::IndexScheduler::updateDir( const QString& dir, Strigi::StreamAnalyzer* analyzer, bool recursive )
+{
+//    kDebug() << dir << analyzer << recursive;
+
+    m_currentFolder = dir;
+
+    // get a map of all indexed files from the dir including their stored mtime
+    std::map<std::string, time_t> filesInStore;
+    m_indexManager->indexReader()->getChildren( QFile::encodeName( dir ).data(), filesInStore );
+    std::map<std::string, time_t>::const_iterator filesInStoreEnd = filesInStore.end();
+
+    QList<QFileInfo> filesToIndex;
+    QList<QString> subFolders;
+    std::vector<std::string> filesToDelete;
+
+    // iterate over all files in the dir
+    // and select the ones we need to add or delete from the store
+    QDirIterator dirIt( dir, QDir::NoDotAndDotDot|QDir::Readable|QDir::Files|QDir::Dirs );
+    while ( dirIt.hasNext() ) {
+        QString path = dirIt.next();
+
+        QFileInfo fileInfo = dirIt.fileInfo();
+
+        // check if this file is new by looking it up in the store
+        std::map<std::string, time_t>::iterator filesInStoreIt = filesInStore.find( QFile::encodeName( path ).data() );
+        bool newFile = ( filesInStoreIt == filesInStoreEnd );
+
+        // do we need to update? Did the file change?
+        bool fileChanged = !newFile && fileInfo.lastModified().toTime_t() != filesInStoreIt->second;
+
+        if ( newFile || fileChanged )
+            filesToIndex << fileInfo;
+
+        if ( !newFile && fileChanged )
+            filesToDelete.push_back( filesInStoreIt->first );
+
+        // cleanup a bit for faster lookups
+        if ( !newFile )
+            filesInStore.erase( filesInStoreIt );
+
+        if ( recursive && fileInfo.isDir() && !fileInfo.isSymLink() )
+            subFolders << path;
+    }
+
+    // all the files left in filesInStore are not in the current
+    // directory and should be deleted
+    for ( std::map<std::string, time_t>::const_iterator it = filesInStore.begin();
+          it != filesInStoreEnd; ++it ) {
+        filesToDelete.push_back( it->first );
+    }
+
+    // inform interested clients
+    if ( !filesToIndex.isEmpty() || !filesToDelete.empty() )
+        emit indexingFolder( dir );
+
+    // remove all files that need updating or have been removed
+    m_indexManager->indexWriter()->deleteEntries( filesToDelete );
+
+    // analyse all files that are new or need updating
+    foreach( const QFileInfo& file, filesToIndex ) {
+
+        analyzeFile( file, analyzer );
+
+        // wait if we are suspended or return if we are stopped
+        if ( !waitForContinue() )
+            return false;
+    }
+
+    // recurse into subdirs (we do this in a separate loop to always keep a proper state:
+    // compare m_currentFolder)
+    if ( recursive ) {
+        foreach( const QString& folder, subFolders ) {
+            if ( !updateDir( folder, analyzer, true ) )
+                return false;
+        }
+    }
+
+    return true;
+}
+
+
+void Nepomuk::IndexScheduler::analyzeFile( const QFileInfo& file, Strigi::StreamAnalyzer* analyzer )
+{
+//    kDebug() << file.filePath();
+
+    Strigi::AnalysisResult analysisresult( QFile::encodeName( file.filePath() ).data(),
+                                           file.lastModified().toTime_t(),
+                                           *m_indexManager->indexWriter(),
+                                           *analyzer,
+                                           QFile::encodeName( file.path() ).data() );
+    if ( file.isFile() && !file.isSymLink() ) {
+        Strigi::FileInputStream stream( QFile::encodeName( file.filePath() ) );
+        analysisresult.index( &stream );
+    }
+    else {
+        analysisresult.index(0);
+    }
+}
+
+
+bool Nepomuk::IndexScheduler::waitForContinue()
+{
+    QMutexLocker locker( &m_resumeStopMutex );
+    if ( m_suspended ) {
+        setIndexingStarted( false );
+        m_resumeStopWc.wait( &m_resumeStopMutex );
+        setIndexingStarted( true );
+    }
+
+    return !m_stopped;
+}
+
+
+void Nepomuk::IndexScheduler::updateDir( const QString& path )
+{
+    QMutexLocker lock( &m_dirsToUpdateMutex );
+    m_dirsToUpdate << qMakePair( path, false );
+    m_dirsToUpdateWc.wakeAll();
+}
+
+
+void Nepomuk::IndexScheduler::updateAll()
+{
+    QMutexLocker lock( &m_dirsToUpdateMutex );
+    foreach( const QString& f, Config::self()->folders() )
+        m_dirsToUpdate << qMakePair( f, true );
+    m_dirsToUpdateWc.wakeAll();
+}
+
+
+void Nepomuk::IndexScheduler::readConfig()
+{
+    // load Strigi configuration
+    std::vector<std::pair<bool, std::string> > filters;
+    QStringList excludeFilters = Config::self()->excludeFilters();
+    QStringList includeFilters = Config::self()->includeFilters();
+    foreach( const QString& filter, excludeFilters ) {
+        filters.push_back( std::make_pair<bool, std::string>( false, filter.toUtf8().data() ) );
+    }
+    foreach( const QString& filter, includeFilters ) {
+        filters.push_back( std::make_pair<bool, std::string>( true, filter.toUtf8().data() ) );
+    }
+    m_analyzerConfig->setFilters(filters);
+
+    // if the recursion setting changed, update everything again
+    // FIXME: this does not really help if the new value is false!
+    if ( m_startedRecursive != Config::self()->recursive() ) {
+        QMutexLocker lock( &m_dirsToUpdateMutex );
+        foreach( const QString& f, Config::self()->folders() )
+            m_dirsToUpdate << qMakePair( f, Config::self()->recursive() );
+        m_dirsToUpdateWc.wakeAll();
+    }
+}
+
+
+namespace {
+    class QDataStreamStrigiBufferedStream : public Strigi::BufferedStream<char>
+    {
+    public:
+        QDataStreamStrigiBufferedStream( QDataStream& stream )
+            : m_stream( stream ) {
+        }
+
+        int32_t fillBuffer( char* start, int32_t space ) {
+            int r = m_stream.readRawData( start, space );
+            if ( r == 0 ) {
+                // Strigi's API is so weird!
+                return -1;
+            }
+            else if ( r < 0 ) {
+                // Again: weird API. m_status is a protected member of StreamBaseBase (yes, 2x Base)
+                m_status = Strigi::Error;
+                return -1;
+            }
+            else {
+                return r;
+            }
+        }
+
+    private:
+        QDataStream& m_stream;
+    };
+}
+
+
+void Nepomuk::IndexScheduler::analyzeResource( const QUrl& uri, const QDateTime& modificationTime, QDataStream& data )
+{
+    QDateTime existingMTime = QDateTime::fromTime_t( m_indexManager->indexReader()->mTime( uri.toEncoded().data() ) );
+    if ( existingMTime < modificationTime ) {
+        // remove the old data
+        std::vector<std::string> entries;
+        entries.push_back( uri.toEncoded().data() );
+        m_indexManager->indexWriter()->deleteEntries( entries );
+
+        // create the new
+        Strigi::StreamAnalyzer analyzer( *m_analyzerConfig );
+        analyzer.setIndexWriter( *m_indexManager->indexWriter() );
+        Strigi::AnalysisResult analysisresult( uri.toEncoded().data(),
+                                               modificationTime.toTime_t(),
+                                               *m_indexManager->indexWriter(),
+                                               analyzer );
+        QDataStreamStrigiBufferedStream stream( data );
+        analysisresult.index( &stream );
+    }
+    else {
+        kDebug() << uri << "up to date";
+    }
+}
+
+#include "indexscheduler.moc"
diff -Naur nepomuk/services/strigi/indexscheduler.h nepomuk/services/strigi/indexscheduler.h
--- nepomuk/services/strigi/indexscheduler.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/indexscheduler.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,140 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef _NEPOMUK_STRIGI_INDEX_SCHEDULER_H_
+#define _NEPOMUK_STRIGI_INDEX_SCHEDULER_H_
+
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtCore/QWaitCondition>
+#include <QtCore/QSet>
+
+
+namespace Strigi {
+    class StreamAnalyzer;
+    class IndexManager;
+}
+
+class StoppableConfiguration;
+class QFileInfo;
+class QUrl;
+class QDateTime;
+class QByteArray;
+
+
+namespace Nepomuk {
+    /**
+     * The IndexScheduler performs the normal indexing,
+     * ie. the initial indexing and the timed updates
+     * of all files.
+     *
+     * Events are not handled.
+     */
+    class IndexScheduler : public QThread
+    {
+        Q_OBJECT
+
+    public:
+        IndexScheduler( Strigi::IndexManager* manager, QObject* parent );
+        ~IndexScheduler();
+
+        bool isSuspended() const;
+        bool isIndexing() const;
+
+        /**
+         * The folder currently being indexed. Empty if not indexing.
+         * If suspended the folder might still be set!
+         */
+        QString currentFolder() const;
+
+    public Q_SLOTS:
+        void suspend();
+        void resume();
+        void stop();
+
+        void setSuspended( bool );
+
+        /**
+         * Slot to connect to certain event systems like KDirNotify
+         * or KDirWatch
+         *
+         * Updates a complete folder (non-recursively). Makes sense for
+         * signals like KDirWatch::dirty.
+         */
+        void updateDir( const QString& path );
+
+        /**
+         * Updates all configured folders.
+         */
+        void updateAll();
+
+        /**
+         * Analyze a resource that is not read from the local harddisk.
+         *
+         * \param uri The resource URI to identify the resource.
+         * \param modificationTime The modification date of the resource. Used to determine if
+         *        an actual update is necessary.
+         * \data The data to analyze, ie. the contents of the resource.
+         */
+        void analyzeResource( const QUrl& uri, const QDateTime& modificationTime, QDataStream& data );
+
+    Q_SIGNALS:
+        void indexingStarted();
+        void indexingStopped();
+        void indexingFolder( const QString& );
+
+    private Q_SLOTS:
+        void readConfig();
+
+    private:
+        void run();
+
+        bool waitForContinue();
+        bool updateDir( const QString& dir, Strigi::StreamAnalyzer* analyzer, bool recursive );
+        void analyzeFile( const QFileInfo& file, Strigi::StreamAnalyzer* analyzer );
+        
+        // emits indexingStarted or indexingStopped based on parameter. Makes sure
+        // no signal is emitted twice
+        void setIndexingStarted( bool started );
+
+        bool m_suspended;
+        bool m_stopped;
+        bool m_indexing;
+
+        // true if recursion was configured at start
+        // if this differs from the new value when the
+        // config changes, all folders are updated again
+        bool m_startedRecursive;
+
+        QMutex m_resumeStopMutex;
+        QWaitCondition m_resumeStopWc;
+
+        StoppableConfiguration* m_analyzerConfig;
+        Strigi::IndexManager* m_indexManager;
+
+        // set of folders to update (+recursive flag) - changed by updateDir
+        QSet<QPair<QString, bool> > m_dirsToUpdate;
+
+        QMutex m_dirsToUpdateMutex;
+        QWaitCondition m_dirsToUpdateWc;
+
+        QString m_currentFolder;
+    };
+}
+
+#endif
diff -Naur nepomuk/services/strigi/nepomukstrigiservice.desktop nepomuk/services/strigi/nepomukstrigiservice.desktop
--- nepomuk/services/strigi/nepomukstrigiservice.desktop	2008-08-28 10:07:16.000000000 +0200
+++ nepomuk/services/strigi/nepomukstrigiservice.desktop	2008-09-01 14:33:17.000000000 +0200
@@ -2,11 +2,10 @@
 Type=Service
 X-KDE-ServiceTypes=NepomukService
 X-KDE-Library=nepomukstrigiservice
-X-KDE-Nepomuk-autostart=false
+X-KDE-Nepomuk-autostart=true
 X-KDE-Nepomuk-start-on-demand=false
 Name=Nepomuk Strigi Service
 Name[af]=Nepomuk Strigi diens
-Name[ar]=Nepomuk خدمة بحث سطح المكتب
 Name[bg]=Услуга Nepomuk Strigi
 Name[bn_IN]=Nepomuk Strigi পরিসেবা
 Name[ca]=Servei Strigi del Nepomuk
@@ -47,6 +46,7 @@
 Name[sr]=Непомуков сервис Стригија
 Name[sr@latin]=Nepomukov servis Strigija
 Name[sv]=Nepomuk-Strigitjänst
+Name[te]=Nepomuk Strigi సేవ
 Name[tg]=Хидматҳои Nepomuk Strigi
 Name[th]=บริการ Nepomuk Strigi
 Name[tr]=Nepomuk Strigi Servisi
@@ -58,7 +58,6 @@
 Name[zh_CN]=Nepomuk Strigi 服务
 Name[zh_TW]=Nepomuk Strigi 服務
 Comment=Nepomuk Service which controls the strigidaemon, i.e. indexes files on the desktop
-Comment[ar]=خدمة Nepomuk للبحث على سطح المكتب
 Comment[bg]=Услуга, която контролира демона на Strigi, напр. файлове с индекси
 Comment[ca]=Servei del Nepomuk que controla el strigidaemon, p.ex. indexa els fitxers de l'escriptori
 Comment[csb]=Ùsłëznota Nepomuka, jakô sprôwiô demonã strigi, to òznôczô: indeksëje lopczi na pùlce
@@ -92,6 +91,7 @@
 Comment[sr]=Сервис Непомука за управљање демоном Стригија, тј. индексирање фајлова
 Comment[sr@latin]=Servis Nepomuka za upravljanje demonom Strigija, tj. indeksiranje fajlova
 Comment[sv]=Nepomuk-tjänst som styr Strigi-demonen, dvs. indexerar filer på skrivbordet
+Comment[te]=Nepomuk సేవ strigidaemon ను నియత్రిస్తుంది, అంటే. డెస్‍క్‌టాప్ పైన దస్త్రములను క్రమపరుస్తుంది
 Comment[th]=บริการของ Nepomuk สำหรับสำหรับควบคุมดีมอน strigidaemon ที่ทำหน้าที่ เช่น สร้างดัชนีแฟ้มสำหรับพื้นที่ทำงาน เป็นต้น
 Comment[tr]=Strigidaemon uygulamasını yöneten Nepomuk servisi, masaüstünüzdeki dosyaları indeksleyen bir uygulama
 Comment[uk]=Служба Nepomuk, яка контролює фонову службу strigi, тобто, індексує файли на стільниці
diff -Naur nepomuk/services/strigi/nepomukstrigiservice.notifyrc nepomuk/services/strigi/nepomukstrigiservice.notifyrc
--- nepomuk/services/strigi/nepomukstrigiservice.notifyrc	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/nepomukstrigiservice.notifyrc	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,158 @@
+[Global]
+IconName=nepomuk
+Comment=The Nepomuk Strigi file indexer
+Comment[et]=Nepomuki Strigi failide indekseerija
+Comment[gl]=O indexador de ficheiros Strigi para Nepomuk
+Comment[gu]=નેપોમુક સ્ટ્રિગિ ફાઇલ ઇન્ડેક્સર
+Comment[km]=កម្មវិធី​បង្កើត​លិបិក្រម​ឯកសារ​របស់ Nepomuk Strigi
+Comment[nb]=Nepomuk Strigi filindekseringen
+Comment[nds]=De Nepomuk-Dateiindizeerdeenst Strigi
+Comment[nn]=Nepomuk Strigi – filindeksering
+Comment[pt]=O serviço de indexação de ficheiros Strigi para o Nepomuk
+Comment[pt_BR]=O serviço de indexação de ficheiros Strigi para o Nepomuk
+Comment[sl]=Indeksirnik datotek Nepomuk Strigi
+Comment[sv]=Nepomuk Strigi-filindexering
+Comment[te]=Nepomuk Strigi దస్త్ర విషయసూచకి
+Comment[tr]=Nepomuk Strigi dosya indeksleyici
+Comment[uk]=Служба Strigi Nepomuk для індексування файлів
+Comment[zh_TW]=Nepomuk Strigi 檔案索引服務
+
+[Event/initialIndexingStarted]
+Name=Initial Indexing started
+Name[et]=Esmaindekseerimine on käivitatud
+Name[gl]=Iniciouse a indexación inicial
+Name[gu]=શરૂઆતનું ઇન્ડેક્સીંગ શરૂ થયેલ છે
+Name[km]=បាន​ចាប់ផ្ដើម​ការ​បង្កើត​លិបិក្រម​​ដំបូង
+Name[nb]=Første indeksering har startet
+Name[nds]=Eerst Indizeren anfungen
+Name[nn]=Førsteindekseringa har starta
+Name[pt]=Início da primeira indexação
+Name[pt_BR]=Início da primeira indexação
+Name[sl]=Pričelo se je začetno indeksiranje
+Name[sv]=Inledande indexering startad
+Name[te]=ప్రాధమిక విషయవర్గీకరణ ప్రారంభమైంది
+Name[tr]=Temel İndeksleme başladı
+Name[uk]=Запущено початкове індексування
+Name[zh_TW]=初始化索引已開始
+Comment=Strigi started the initial indexing of local files for fast desktop searches
+Comment[et]=Strigi alustas kohalike failide esimest indekseerimist kiire töölauaotsingu võimaldamiseks
+Comment[gl]=Strigi comezou a indexación inicial dos ficheiros locais para facer procuras rápidas no escritorio
+Comment[gu]=સ્ટ્રીગીએ ઝડપી ડેસ્કટોપ શોધ માટે સ્થાનિક ફાઇલોનું શરૂઆતી ઇન્ડેક્સીંગ ચાલુ કર્યું છે
+Comment[km]=បាន​ចាប់ផ្ដើម​ការ​បង្កើត​លិបិក្រម​ដំបូង​របស់ Strigi នៃ​ឯកសារ​មូលដ្ឋាន​សម្រាប់​ការ​ស្វែងរក​ផ្ទៃតុ​រហ័ស
+Comment[nb]=Strigi startet den første indekseringen av lokale filer som vil gjøre søk raskere
+Comment[nds]=Strigi hett mit dat eerste Indizeren vun lokaal Dateien anfungen, dat hölp bi't gaue Söken op den Schriefdisch
+Comment[nn]=Strigi starta førsteindekseringa av lokale filer for snøgge skrivebordsøk
+Comment[pt]=O Strigi iniciou a primeira indexação dos ficheiros para pesquisas mais rápidas
+Comment[pt_BR]=O Strigi iniciou a primeira indexação dos ficheiros para pesquisas mais rápidas
+Comment[sl]=Strigi je pričel z začetnim indeksiranjem krajevnih datotek, da bo namizno iskanje hitro
+Comment[sv]=Strigi har startat den inledande indexeringen av lokala filer för snabb skrivbordssökning
+Comment[te]=వేగమైన డెస్‍క్‌ టాప్ శోధనలకొరకు Strigi స్థానిక దస్త్రముల ప్రాధమిక విషయవర్గీకరణను ప్రారంభించింది.
+Comment[tr]=Strigi hızlı masaüstü araması için yerel dosyaların temel indeksleme işlemine başladı
+Comment[uk]=Програма Strigi запустила початкове індексування локальних файлів для швидкого стільничного пошуку
+Comment[zh_TW]=Strigi 已開始初始化本地檔案的索引
+Action=Popup
+
+[Event/initialIndexingFinished]
+Name=Initial Indexing finished
+Name[et]=Esmaindekseerimine on lõpetatud
+Name[gl]=Rematou a indexación inicial
+Name[gu]=શરૂઆતનું ઇન્ડેક્સીંગ પૂર્ણ થયેલ છે
+Name[km]=បាន​បញ្ចប់​កា​របង្កើត​លិបិក្រម​ដំបូង
+Name[nb]=Første indeksering er ferdig
+Name[nds]=Eerst Indizeren afslaten
+Name[nn]=Førsteindekseringa er ferdig
+Name[pt]=Fim da primeira indexação
+Name[pt_BR]=Fim da primeira indexação
+Name[sl]=Začetno indeksiranje se je zaključilo
+Name[sv]=Inledande indexering klar
+Name[te]=ప్రాధమిక విషయవర్గీకరణ పూర్తైనది.
+Name[tr]=Temel İndeksleme tamamlandı
+Name[uk]=Початкове індексування закінчено
+Name[zh_TW]=初始化索引已完成
+Comment=Strigi finished the initial indexing of local files for fast desktop searches
+Comment[et]=Strigi lõpetas kohalike failide esimese indekseerimise kiire töölauaotsingu võimaldamiseks
+Comment[gl]=Strigi rematou a indexación inicial dos ficheiros locais para facer procuras rápidas no escritorio
+Comment[gu]=સ્ટ્રીગીએ ઝડપી ડેસ્કટોપ શોધ માટે સ્થાનિક ફાઇલોનું શરૂઆતી ઇન્ડેક્સીંગ પૂર્ણ કર્યું છે
+Comment[km]=បានបញ្ចប់​ក​ការ​បង្កើត​លិបិក្រម​របស់ Strigi នៃ​ឯកសារ​មូលដ្ឋាន​សម្រាប់​ការ​ស្វែងរក​ផ្ទៃតុ​រហ័ស
+Comment[nb]=Strigi gjorde ferdig første indeksering av lokale filer som vil gjøre søk raskere
+Comment[nds]=Strigi hett dat eerste Indizeren vun lokaal Dateien afslaten, dat hölp bi't gaue Söken op den Schriefdisch
+Comment[nn]=Strigi er ferdig med førsteindekseringa av lokale filer for snøgge skrivebordsøk
+Comment[pt]=O Strigi terminou a primeira indexação dos ficheiros para pesquisas mais rápidas
+Comment[pt_BR]=O Strigi terminou a primeira indexação dos ficheiros para pesquisas mais rápidas
+Comment[sl]=Strigi je zaključil z začetnim indeksiranjem krajevnih datotek za hitro namizno iskanje
+Comment[sv]=Strigi har gjort färdig den inledande indexeringen av lokala filer för snabb skrivbordssökning
+Comment[te]=వేగమైన డెస్‍క్ టాప్ శోధనలకొరకు Strigi స్థానిక దస్త్రములయొక్క విషయవర్గీకరణ పూర్తైనది
+Comment[tr]=Strigi hızlı masaüstü araması için yerel dosyaların temel indeksleme işlemini tamamladı
+Comment[uk]=Програма Strigi завершила початкове індексування локальних файлів для швидкого стільничного пошуку
+Comment[zh_TW]=Strigi 已完成本地端檔案的初始化索引
+Action=Popup
+
+[Event/indexingSuspended]
+Name=Indexing suspended
+Name[et]=Indekseerimine on peatatud
+Name[gl]=Suspendeuse a indexación
+Name[gu]=ઇન્ડેક્સીંગ બંધ કરવામાં આવ્યું
+Name[km]=បាន​ផ្អាក​ការ​ដាក់​លិបិក្រម
+Name[nb]=Indekseringen stoppet midleridig
+Name[nds]=Indizeren anhollen
+Name[nn]=Indekseringa vart stoppa
+Name[pt]=Indexação suspensa
+Name[pt_BR]=Indexação suspensa
+Name[sl]=Indeksiranje je zaustavljeno
+Name[sv]=Indexering tillfälligt stoppad
+Name[te]=విషయవర్దీకరణ సంస్పెండ్ చేయబడింది
+Name[tr]=İndeksleme beklemeye alındı
+Name[uk]=Пауза індексування
+Name[zh_TW]=索引暫停
+Comment=Strigi file indexing has been suspended
+Comment[et]=Strigi failide indekseerimine on peatatud
+Comment[gl]=A indexación de ficheiros con Strigi suspendeuse
+Comment[gu]=સ્ટ્રીગીએ ફાઇલ ઇન્ડેક્સીંગ બંધ કરવામાં આવ્યું છે
+Comment[km]=បានផ្អាក​ការ​បង្កើត​លិបិក្រម​​ឯកសារ​របស់ Strigi
+Comment[nb]=Strigi filindeksering har blitt stoppet midlertidig
+Comment[nds]=Strigi hett mit dat Indizeren vun Dateien anhollen
+Comment[nn]=Filindekseringa med Strigi vart stoppa
+Comment[pt]=A indexação de ficheiros do Strigi foi suspensa
+Comment[pt_BR]=A indexação de ficheiros do Strigi foi suspensa
+Comment[sl]=Indeksiranje datotek s Strigijem je zaustavljeno
+Comment[sv]=Strigi filindexering har tillfälligt stoppats
+Comment[te]=Strigi దస్త్రము విషయవర్గీకరణ సస్పెండ్ చేయబడింది
+Comment[tr]=Strigi dosya indeksleyici beklemeye alındı
+Comment[uk]=Пауза індексування файлів програмою Strigi
+Comment[zh_TW]=Strigi 檔案索引已被暫停
+Action=Popup
+
+[Event/indexingResumed]
+Name=Indexing resumed
+Name[et]=Indekseerimine jätkub
+Name[gl]=Continuouse a indexación
+Name[gu]=ઇન્ડેક્સીંગ પુન: શરૂ કરવામાં આવ્યું
+Name[km]=បាន​បន្ត​ការ​បង្កើត​លិបិក្រម
+Name[nb]=Indekseringen fortsetter
+Name[nds]=Indizeren geiht wieder
+Name[nn]=Indekseringa held fram
+Name[pt]=Indexação prosseguida
+Name[pt_BR]=Indexação prosseguida
+Name[sl]=Indeksiranje se nadaljuje
+Name[sv]=Indexering återupptagen
+Name[te]=విషయవర్గీకరణ తిరిగికొనసాగించబడింది
+Name[tr]=İndeksleme çalışmaya devam ettirildi
+Name[uk]=Продовження індексування
+Name[zh_TW]=索引回復
+Comment=Strigi file indexing has been resumed
+Comment[et]=Strigi failide indekseerimine jätkub
+Comment[gl]=Continúase a indexación de ficheiros con Strigi
+Comment[gu]=સ્ટ્રીગીએ ફાઇલ ઇન્ડેક્સીંગ પુન: શરૂ કરવામાં આવ્યું છે
+Comment[km]=បាន​បន្ត​ការ​បង្កើត​លិបិក្រម​ឯកសារ​របស់ Strigi
+Comment[nb]=Strigi filindeksering er gjenopptatt
+Comment[nds]=Strigi maakt mit dat Indizeren vun Dateien wieder
+Comment[nn]=Filindekseringa med Strigi held fram
+Comment[pt]=Prosseguiu-se com a indexação de ficheiros no Strigi
+Comment[pt_BR]=Prosseguiu-se com a indexação de ficheiros no Strigi
+Comment[sl]=Indeksiranje datotek s Strigijem se nadaljuje
+Comment[sv]=Strigi filindexering har återupptagits
+Comment[te]=Strigi దస్త్రము విషయవర్గీకరణ తిరిగికొనసాగించబడింది
+Comment[tr]=Strigi dosya indeksleyici çalışmaya devam ettirildi
+Comment[uk]=Strigi продовжує індексування файлів
+Comment[zh_TW]=Strigi 檔案索引已回復
+Action=Popup
diff -Naur nepomuk/services/strigi/priority.cpp nepomuk/services/strigi/priority.cpp
--- nepomuk/services/strigi/priority.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/priority.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,100 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
+
+   Parts of this file are based on code from Strigi
+   Copyright (C) 2006-2007 Jos van den Oever <jos@vandenoever.info>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License version 2 as published by the Free Software Foundation.
+
+   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 "priority.h"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <QtCore/QDebug>
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <errno.h>
+
+#include <sched.h>
+
+
+#ifdef SYS_ioprio_set
+namespace {
+#ifndef IOPRIO_CLASS_IDLE
+    enum {
+        IOPRIO_CLASS_NONE,
+        IOPRIO_CLASS_RT,
+        IOPRIO_CLASS_BE,
+        IOPRIO_CLASS_IDLE
+    };
+#endif
+
+#ifndef IOPRIO_WHO_PROCESS
+    enum {
+        IOPRIO_WHO_PROCESS = 1,
+        IOPRIO_WHO_PGRP,
+        IOPRIO_WHO_USER
+    };
+#endif
+
+#ifndef IOPRIO_CLASS_SHIFT
+    const int IOPRIO_CLASS_SHIFT = 13;
+#endif
+}
+#endif
+
+
+bool lowerIOPriority()
+{
+#ifdef SYS_ioprio_set
+    if ( syscall( SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0, IOPRIO_CLASS_IDLE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
+        qDebug( "cannot set io scheduling to idle (%s). Trying best effort.\n",  strerror( errno ));
+        if ( syscall( SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0, 7|IOPRIO_CLASS_BE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
+            qDebug( "cannot set io scheduling to best effort.\n");
+            return false;
+        }
+    }
+    return true;
+#else
+    return false;
+#endif
+}
+
+
+bool lowerPriority()
+{
+    return !setpriority( PRIO_PROCESS, 0, 19 );
+}
+
+
+// FIXME: is this really useful? Should we better use SCHED_IDLE?
+bool lowerSchedulingPriority()
+{
+#ifdef SCHED_BATCH
+    struct sched_param param;
+    memset( &param, 0, sizeof(param) );
+    param.sched_priority = 0;
+    return !sched_setscheduler( 0, SCHED_BATCH, &param );
+#else
+    return false;
+#endif
+}
diff -Naur nepomuk/services/strigi/priority.h nepomuk/services/strigi/priority.h
--- nepomuk/services/strigi/priority.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/priority.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,26 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef _NEPOMUK_LINUX_PRIO_H_
+#define _NEPOMUK_LINUX_PRIO_H_
+
+bool lowerIOPriority();
+bool lowerSchedulingPriority();
+bool lowerPriority();
+
+#endif
diff -Naur nepomuk/services/strigi/statuswidget.cpp nepomuk/services/strigi/statuswidget.cpp
--- nepomuk/services/strigi/statuswidget.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/statuswidget.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,209 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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 "statuswidget.h"
+#include "indexscheduler.h"
+
+#include <KCMultiDialog>
+#include <KIcon>
+#include <KLocale>
+#include <KTitleWidget>
+#include <KStandardDirs>
+#include <KIO/NetAccess>
+#include <kio/directorysizejob.h>
+
+#include <Soprano/Model>
+#include <Soprano/QueryResultIterator>
+#include <Soprano/Vocabulary/Xesam>
+
+#include <QtCore/QTimer>
+
+
+Nepomuk::StatusWidget::StatusWidget( Soprano::Model* model, IndexScheduler* scheduler, QWidget* parent )
+    : KDialog( parent ),
+      m_model( model ),
+      m_indexScheduler( scheduler ),
+      m_connected( false ),
+      m_updating( false ),
+      m_updateRequested( false )
+{
+    setupUi( mainWidget() );
+
+    setCaption( m_title->text() );
+    setButtons( Ok|User1 );
+    setDefaultButton( Ok );
+    setButtonGuiItem( User1, KGuiItem( i18n( "Configure" ), KIcon( "configure" ) ) );
+
+    m_title->setPixmap( KIcon( "nepomuk" ).pixmap( 32, 32 ) );
+
+    m_updateTimer.setSingleShot( true );
+    m_updateTimer.setInterval( 10*1000 ); // do not update multiple times in 10 seconds
+    connect( &m_updateTimer, SIGNAL( timeout() ),
+             this, SLOT( slotUpdateTimeout() ) );
+
+    connect( this, SIGNAL( user1Clicked() ),
+             this, SLOT( slotConfigure() ) );
+}
+
+
+Nepomuk::StatusWidget::~StatusWidget()
+{
+}
+
+
+void Nepomuk::StatusWidget::slotUpdateStrigiStatus()
+{
+    bool indexing = m_indexScheduler->isIndexing();
+    bool suspended = m_indexScheduler->isSuspended();
+    QString folder = m_indexScheduler->currentFolder();
+
+    if ( suspended )
+        m_labelStrigiState->setText( i18n( "File indexer is suspended" ) );
+    else if ( indexing )
+        m_labelStrigiState->setText( i18n( "Strigi is currently indexing files in folder %1", folder ) );
+    else
+        m_labelStrigiState->setText( i18n( "File indexer is idle" ) );
+}
+
+
+void Nepomuk::StatusWidget::slotUpdateStoreStatus()
+{
+    if ( !m_updating && !m_updateTimer.isActive() ) {
+        m_updating = true;
+
+        // update storage size
+        // ========================================
+        QString path = KStandardDirs::locateLocal( "data", "nepomuk/repository/main/", false );
+        KIO::DirectorySizeJob* job = KIO::directorySize( path );
+        if ( KIO::NetAccess::synchronousRun( job, this ) )
+            m_labelStoreSize->setText( KIO::convertSize( job->totalSize() ) );
+        else
+            m_labelStoreSize->setText( i18n( "Calculation failed" ) );
+
+
+        // update file count
+        // ========================================
+        Soprano::QueryResultIterator it = m_model->executeQuery( QString( "select distinct ?r where { ?r a <%1> . }" )
+                                                                 .arg( Soprano::Vocabulary::Xesam::File().toString() ),
+                                                                 Soprano::Query::QueryLanguageSparql );
+        int cnt = 0;
+        while ( it.next() ) {
+            // a bit of hacking to keep the GUI responsive
+            // TODO: if we don't get aggregate functions in SPARQL soon, use a thread
+            if ( cnt % 100 == 0 )
+                QApplication::processEvents();
+            ++cnt;
+        }
+        m_labelFileCount->setText( i18np( "1 file in index", "%1 files in index", cnt ) );
+
+        m_updating = false;
+
+        // start the timer to avoid too many updates
+        m_updateTimer.start();
+    }
+    else {
+        m_updateRequested = true;
+    }
+}
+
+
+void Nepomuk::StatusWidget::slotUpdateTimeout()
+{
+    if ( m_updateRequested ) {
+        m_updateRequested = false;
+        slotUpdateStoreStatus();
+    }
+}
+
+
+void Nepomuk::StatusWidget::slotConfigure()
+{
+    KCMultiDialog dlg;
+    dlg.addModule( "kcm_nepomuk" );
+    dlg.exec();
+}
+
+#include <QApplication>
+#include <QDesktopWidget>
+
+// from kdialog.cpp since KDialog::centerOnScreen will simply do nothing on X11!
+static QRect screenRect( QWidget *widget, int screen )
+{
+    QDesktopWidget *desktop = QApplication::desktop();
+    KConfig gc( "kdeglobals", KConfig::NoGlobals );
+    KConfigGroup cg(&gc, "Windows" );
+    if ( desktop->isVirtualDesktop() &&
+         cg.readEntry( "XineramaEnabled", true ) &&
+         cg.readEntry( "XineramaPlacementEnabled", true ) ) {
+
+        if ( screen < 0 || screen >= desktop->numScreens() ) {
+            if ( screen == -1 )
+                screen = desktop->primaryScreen();
+            else if ( screen == -3 )
+                screen = desktop->screenNumber( QCursor::pos() );
+            else
+                screen = desktop->screenNumber( widget );
+        }
+
+        return desktop->availableGeometry( screen );
+    } else
+        return desktop->geometry();
+}
+
+void Nepomuk::StatusWidget::showEvent( QShowEvent* event )
+{
+    if ( !m_connected ) {
+        connect( m_indexScheduler, SIGNAL( indexingStarted() ),
+                 this, SLOT( slotUpdateStrigiStatus() ) );
+        connect( m_indexScheduler, SIGNAL( indexingStopped() ),
+                 this, SLOT( slotUpdateStrigiStatus() ) );
+        connect( m_indexScheduler, SIGNAL( indexingFolder(QString) ),
+                 this, SLOT( slotUpdateStrigiStatus() ) );
+
+        connect( m_model, SIGNAL( statementsAdded() ),
+                 this, SLOT( slotUpdateStoreStatus() ) );
+        connect( m_model, SIGNAL( statementsRemoved() ),
+                 this, SLOT( slotUpdateStoreStatus() ) );
+
+        m_connected = true;
+    }
+
+    QTimer::singleShot( 0, this, SLOT( slotUpdateStoreStatus() ) );
+    QTimer::singleShot( 0, this, SLOT( slotUpdateStrigiStatus() ) );
+
+    KDialog::showEvent( event );
+
+    QRect rect = screenRect( this, -1 );
+    move( rect.center().x() - width() / 2,
+          rect.center().y() - height() / 2 );
+    //KDialog::centerOnScreen( this );
+}
+
+
+void Nepomuk::StatusWidget::hideEvent( QHideEvent* event )
+{
+    if ( m_connected ) {
+        m_indexScheduler->disconnect( this );
+        m_model->disconnect( this );
+        m_connected = false;
+    }
+
+    KDialog::hideEvent( event );
+}
+
+#include "statuswidget.moc"
diff -Naur nepomuk/services/strigi/statuswidget.h nepomuk/services/strigi/statuswidget.h
--- nepomuk/services/strigi/statuswidget.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/statuswidget.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,66 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef _STATUS_WIDGET_H_
+#define _STATUS_WIDGET_H_
+
+#include <KDialog>
+#include "ui_statuswidget.h"
+
+#include <QtCore/QTimer>
+
+class QShowEvent;
+class QHideEvent;
+
+namespace Soprano {
+    class Model;
+}
+
+namespace Nepomuk {
+
+    class IndexScheduler;
+
+    class StatusWidget : public KDialog, public Ui::StatusWidget
+    {
+        Q_OBJECT
+
+    public:
+        StatusWidget( Soprano::Model* model, IndexScheduler* scheduler, QWidget* parent = 0 );
+        ~StatusWidget();
+
+    private Q_SLOTS:
+        void slotConfigure();
+        void slotUpdateStrigiStatus();
+        void slotUpdateStoreStatus();
+        void slotUpdateTimeout();
+
+    private:
+        void showEvent( QShowEvent* event );
+        void hideEvent( QHideEvent* event );
+
+        Soprano::Model* m_model;
+        IndexScheduler* m_indexScheduler;
+
+        bool m_connected;
+        QTimer m_updateTimer;
+        bool m_updating;
+        bool m_updateRequested;
+    };
+}
+
+#endif
diff -Naur nepomuk/services/strigi/statuswidget.ui nepomuk/services/strigi/statuswidget.ui
--- nepomuk/services/strigi/statuswidget.ui	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/statuswidget.ui	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,102 @@
+<ui version="4.0" >
+ <author>Sebastian Trueg</author>
+ <class>StatusWidget</class>
+ <widget class="QWidget" name="StatusWidget" >
+  <layout class="QVBoxLayout" name="verticalLayout" >
+   <item>
+    <widget class="KTitleWidget" name="m_title" >
+     <property name="text" >
+      <string>Nepomuk Strigi File Indexing</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox" >
+     <property name="title" >
+      <string>Strigi Indexing State</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout" >
+      <item>
+       <widget class="KSqueezedTextLabel" name="m_labelStrigiState" >
+        <property name="font" >
+         <font>
+          <weight>75</weight>
+          <bold>true</bold>
+         </font>
+        </property>
+        <property name="text" >
+         <string>KSqueezedTextLabel</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_2" >
+     <property name="title" >
+      <string>Nepomuk Storage State</string>
+     </property>
+     <layout class="QFormLayout" name="formLayout" >
+      <item row="0" column="0" >
+       <widget class="QLabel" name="label" >
+        <property name="text" >
+         <string>Indexed files:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1" >
+       <widget class="QLabel" name="m_labelFileCount" >
+        <property name="font" >
+         <font>
+          <weight>75</weight>
+          <bold>true</bold>
+         </font>
+        </property>
+        <property name="text" >
+         <string>Calculating...</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0" >
+       <widget class="QLabel" name="label_2" >
+        <property name="text" >
+         <string>Nepomuk store size:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1" >
+       <widget class="QLabel" name="m_labelStoreSize" >
+        <property name="font" >
+         <font>
+          <weight>75</weight>
+          <bold>true</bold>
+         </font>
+        </property>
+        <property name="text" >
+         <string>Calculating...</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutfunction spacing="KDialog::spacingHint" margin="KDialog::marginHint" />
+ <customwidgets>
+  <customwidget>
+   <class>KSqueezedTextLabel</class>
+   <extends>QLabel</extends>
+   <header>ksqueezedtextlabel.h</header>
+  </customwidget>
+  <customwidget>
+   <class>KTitleWidget</class>
+   <extends>QWidget</extends>
+   <header>ktitlewidget.h</header>
+  </customwidget>
+ </customwidgets>
+ <includes/>
+ <resources/>
+ <connections/>
+</ui>
diff -Naur nepomuk/services/strigi/strigicontroller.cpp nepomuk/services/strigi/strigicontroller.cpp
--- nepomuk/services/strigi/strigicontroller.cpp	2008-04-24 14:27:53.000000000 +0200
+++ nepomuk/services/strigi/strigicontroller.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,167 +0,0 @@
-/* This file is part of the KDE Project
-   Copyright (c) 2007 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 version 2 as published by the Free Software Foundation.
-
-   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 "strigicontroller.h"
-
-#include <QtDBus/QDBusConnection>
-#include <QtDBus/QDBusMessage>
-#include <QtCore/QTimer>
-#include <QtCore/QFile>
-#include <QtCore/QDir>
-
-#include <strigi/qtdbus/strigiclient.h>
-
-#include <KDebug>
-#include <KProcess>
-#include <KStandardDirs>
-#include <KMessageBox>
-#include <KLocale>
-
-
-Nepomuk::StrigiController::StrigiController( QObject* parent )
-    : QObject( parent ),
-      m_strigiProcess( 0 ),
-      m_running5Minutes( false ),
-      m_state( Idle )
-{
-}
-
-
-Nepomuk::StrigiController::~StrigiController()
-{
-    shutdown();
-}
-
-
-Nepomuk::StrigiController::State Nepomuk::StrigiController::state() const
-{
-    return m_state;
-}
-
-
-bool Nepomuk::StrigiController::start()
-{
-    kDebug(300002) << "(Nepomuk::StrigiController::start)";
-    if ( !m_strigiProcess ) {
-        m_strigiProcess = new KProcess( this );
-        m_strigiProcess->setOutputChannelMode( KProcess::ForwardedChannels );
-        connect( m_strigiProcess, SIGNAL( finished( int, QProcess::ExitStatus) ),
-                 this, SLOT( slotProcessFinished( int, QProcess::ExitStatus) ) );
-    }
-
-    m_strigiProcess->clearProgram();
-    *m_strigiProcess << KStandardDirs::findExe( "strigidaemon" );
-
-    if ( m_strigiProcess->state() == QProcess::NotRunning ) {
-        m_running5Minutes = false;
-        m_state = StartingUp;
-        m_strigiProcess->start();
-        if ( m_strigiProcess->waitForStarted() ) {
-            m_state = Running;
-            QTimer::singleShot( 50000, this, SLOT( slotRunning5Minutes() ) );
-
-            kDebug(300002) << "Strigi started successfully.";
-
-            // Strigi might refuse to start properly for some reason (invalid config, lock file invalid, whatever.)
-            // In that case the dbus client would hang. Thus, we wait for 5 seconds before starting the indexing
-            // (Which is ugly anyway since Strigi should do that automatically)
-            QTimer::singleShot( 5000, this, SLOT( slotStartStrigiIndexing() ) );
-
-            return true;
-        }
-        else {
-            kDebug(300002) << "Failed to start strigidaemon.";
-            m_state = Idle;
-            return false;
-        }
-    }
-    else {
-        kDebug(300002) << "strigidaemon already running.";
-        return false;
-    }
-}
-
-
-void Nepomuk::StrigiController::shutdown()
-{
-    kDebug(300002) << "(Nepomuk::StrigiController::shutdown)";
-
-    StrigiClient strigiClient;
-
-    m_state = ShuttingDown;
-
-    if ( isRunning() ) {
-        strigiClient.stopDaemon();
-    }
-
-    if ( state() == Running ) {
-        kDebug(300002) << "We started Strigi ourselves. Trying to shut it down gracefully.";
-        if ( !m_strigiProcess->waitForFinished(60000) ) {
-            kDebug(300002) << "strigidaemon does not terminate properly. Killing process...";
-            m_strigiProcess->terminate();
-        }
-        m_state = Idle;
-    }
-}
-
-
-void Nepomuk::StrigiController::slotProcessFinished( int exitCode, QProcess::ExitStatus exitStatus )
-{
-    if ( m_state == Running ) {
-        kDebug(300002) << "strigidaemon shut down unexpectedly with exit code:" << exitCode;
-
-        m_state = Idle;
-
-        if ( exitStatus == QProcess::CrashExit ) {
-            kDebug(300002) << "strigidaemon crashed.";
-            if ( m_running5Minutes ) {
-                kDebug(300002) << "restarting strigidaemon...";
-                start();
-            }
-            else {
-                kDebug(300002) << "looks like a recurring crash!";
-                KMessageBox::error( 0,
-                                    i18n( "Strigi (the desktop file indexer) crashed repeatedly. It will not be started again." ),
-                                    i18n( "Strigi Desktop Search" ) );
-            }
-        }
-    }
-}
-
-
-void Nepomuk::StrigiController::slotRunning5Minutes()
-{
-    m_running5Minutes = true;
-}
-
-
-bool Nepomuk::StrigiController::isRunning()
-{
-    return QDBusConnection::sessionBus().interface()->isServiceRegistered( "vandenoever.strigi" );
-}
-
-
-void Nepomuk::StrigiController::slotStartStrigiIndexing()
-{
-    if ( isRunning() ) {
-        StrigiClient strigiClient;
-        strigiClient.startIndexing();
-    }
-}
-
-#include "strigicontroller.moc"
diff -Naur nepomuk/services/strigi/strigicontroller.h nepomuk/services/strigi/strigicontroller.h
--- nepomuk/services/strigi/strigicontroller.h	2008-04-23 17:51:26.000000000 +0200
+++ nepomuk/services/strigi/strigicontroller.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,62 +0,0 @@
-/* This file is part of the KDE Project
-   Copyright (c) 2007 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 version 2 as published by the Free Software Foundation.
-
-   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.
-*/
-
-#ifndef _NEPOMUK_STRIGI_CONTROLLER_H_
-#define _NEPOMUK_STRIGI_CONTROLLER_H_
-
-#include <QtCore/QObject>
-#include <KProcess>
-
-
-namespace Nepomuk {
-    class StrigiController : public QObject
-    {
-        Q_OBJECT
-
-    public:
-        StrigiController( QObject* parent = 0 );
-        ~StrigiController();
-
-        enum State {
-            Idle,
-            StartingUp,
-            Running,
-            ShuttingDown
-        };
-
-        State state() const;
-
-    public Q_SLOTS:
-        bool start();
-        void shutdown();
-
-        static bool isRunning();
-
-    private Q_SLOTS:
-        void slotProcessFinished( int exitCode, QProcess::ExitStatus exitStatus );
-        void slotRunning5Minutes();
-        void slotStartStrigiIndexing();
-
-    private:
-        KProcess* m_strigiProcess;
-        bool m_running5Minutes;
-        State m_state;
-    };
-}
-
-#endif
diff -Naur nepomuk/services/strigi/strigiservice.cpp nepomuk/services/strigi/strigiservice.cpp
--- nepomuk/services/strigi/strigiservice.cpp	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/services/strigi/strigiservice.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -17,31 +17,78 @@
 */
 
 #include "strigiservice.h"
-#include "strigicontroller.h"
-#include "../../common/strigiconfigfile.h"
+#include "strigiserviceadaptor.h"
+#include "priority.h"
+#include "indexscheduler.h"
+#include "eventmonitor.h"
+#include "systray.h"
+#include "config.h"
+#include "statuswidget.h"
+#include "nepomukstorageinterface.h"
 
-Nepomuk::StrigiService::StrigiService( QObject* parent, const QList<QVariant>& )
-    : Service( parent )
-{
+#include <KDebug>
 
-    m_strigiController = new StrigiController( this );
-    updateStrigiConfig();
-    m_strigiController->start();
-}
+#include <strigi/indexpluginloader.h>
+#include <strigi/indexmanager.h>
 
-Nepomuk::StrigiService::~StrigiService()
+
+Nepomuk::StrigiService::StrigiService( QObject* parent, const QList<QVariant>& )
+    : Service( parent, true )
 {
+    // lower process priority - we do not want to spoil KDE usage
+    // ==============================================================
+    if ( !lowerPriority() )
+        kDebug() << "Failed to lower priority.";
+    if ( !lowerSchedulingPriority() )
+        kDebug() << "Failed to lower scheduling priority.";
+    if ( !lowerIOPriority() )
+        kDebug() << "Failed to lower io priority.";
+
+    // Using Strigi with the redland backend is torture.
+    // Thus we simply fail initialization if it is used
+    // ==============================================================
+    if ( org::kde::nepomuk::Storage( "org.kde.NepomukStorage",
+                                     "/nepomukstorage",
+                                     QDBusConnection::sessionBus() )
+         .usedSopranoBackend().value() != QString::fromLatin1( "redland" ) ) {
+        // setup the actual index scheduler including strigi stuff
+        // ==============================================================
+        if ( ( m_indexManager = Strigi::IndexPluginLoader::createIndexManager( "sopranobackend", 0 ) ) ) {
+            m_indexScheduler = new IndexScheduler( m_indexManager, this );
+
+            ( void )new EventMonitor( m_indexScheduler, this );
+            ( void )new StrigiServiceAdaptor( m_indexScheduler, this );
+            StatusWidget* sw = new StatusWidget( mainModel(), m_indexScheduler );
+            ( new SystemTray( m_indexScheduler, sw ) )->show();
+
+            m_indexScheduler->start();
+        }
+        else {
+            kDebug() << "Failed to load sopranobackend Strigi index manager.";
+        }
+
+
+        // service initialization done if creating a strigi index manager was successful
+        // ==============================================================
+        setServiceInitialized( m_indexManager != 0 );
+    }
+    else {
+        kDebug() << "Will not start when using redland Soprano backend due to horrible performance.";
+        setServiceInitialized( false );
+    }
 }
 
 
-void Nepomuk::StrigiService::updateStrigiConfig()
+Nepomuk::StrigiService::~StrigiService()
 {
-    StrigiConfigFile strigiConfig ( StrigiConfigFile::defaultStrigiConfigFilePath() );
-    strigiConfig.load();
-    strigiConfig.defaultRepository().setType( "sopranobackend" );
-    strigiConfig.save();
+    if ( m_indexManager ) {
+        m_indexScheduler->stop();
+        m_indexScheduler->wait();
+        Strigi::IndexPluginLoader::deleteIndexManager( m_indexManager );
+    }
 }
 
+
 #include <kpluginfactory.h>
 #include <kpluginloader.h>
 
diff -Naur nepomuk/services/strigi/strigiservice.h nepomuk/services/strigi/strigiservice.h
--- nepomuk/services/strigi/strigiservice.h	2008-04-02 14:18:19.000000000 +0200
+++ nepomuk/services/strigi/strigiservice.h	2008-09-01 14:33:17.000000000 +0200
@@ -20,10 +20,15 @@
 #define _NEPOMUK_STRIGI_SERVICE_H_
 
 #include <Nepomuk/Service>
+#include <QtCore/QTimer>
+
+namespace Strigi {
+    class IndexManager;
+}
 
 namespace Nepomuk {
 
-    class StrigiController;
+    class IndexScheduler;
 
     /**
      * Service controlling the strigidaemon
@@ -39,7 +44,8 @@
     private:
         void updateStrigiConfig();
 
-        StrigiController* m_strigiController;
+        Strigi::IndexManager* m_indexManager;
+        IndexScheduler* m_indexScheduler;
     };
 }
 
diff -Naur nepomuk/services/strigi/strigiserviceadaptor.cpp nepomuk/services/strigi/strigiserviceadaptor.cpp
--- nepomuk/services/strigi/strigiserviceadaptor.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/strigiserviceadaptor.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,110 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
+
+   Based on code generated by dbusxml2cpp version 0.6
+   dbusxml2cpp is Copyright (C) 2006 Trolltech ASA. All rights reserved.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License version 2 as published by the Free Software Foundation.
+
+   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 "strigiserviceadaptor.h"
+#include "strigiservice.h"
+#include "indexscheduler.h"
+
+#include <QtCore/QUrl>
+#include <QtCore/QDateTime>
+#include <QtCore/QFile>
+#include <QtCore/QDataStream>
+
+#include <KDebug>
+
+
+Nepomuk::StrigiServiceAdaptor::StrigiServiceAdaptor( IndexScheduler* scheduler, StrigiService* parent )
+    : QDBusAbstractAdaptor(parent),
+      m_indexScheduler( scheduler )
+{
+    connect( m_indexScheduler, SIGNAL( indexingStarted() ),
+             this, SIGNAL( indexingStarted() ) );
+    connect( m_indexScheduler, SIGNAL( indexingStopped() ),
+             this, SIGNAL( indexingStopped() ) );
+    connect( m_indexScheduler, SIGNAL( indexingFolder(QString) ),
+             this, SIGNAL( indexingFolder(QString) ) );
+}
+
+
+Nepomuk::StrigiServiceAdaptor::~StrigiServiceAdaptor()
+{
+}
+
+
+bool Nepomuk::StrigiServiceAdaptor::isIndexing()
+{
+    // handle method call org.kde.nepomuk.Strigi.isIndexing
+    return m_indexScheduler->isIndexing();
+}
+
+
+bool Nepomuk::StrigiServiceAdaptor::isSuspended()
+{
+    // handle method call org.kde.nepomuk.Strigi.isSuspended
+    return m_indexScheduler->isSuspended();
+}
+
+
+QString Nepomuk::StrigiServiceAdaptor::currentFolder()
+{
+    return m_indexScheduler->currentFolder();
+}
+
+
+void Nepomuk::StrigiServiceAdaptor::resume()
+{
+    // handle method call org.kde.nepomuk.Strigi.resume
+    m_indexScheduler->resume();
+}
+
+
+void Nepomuk::StrigiServiceAdaptor::suspend()
+{
+    // handle method call org.kde.nepomuk.Strigi.suspend
+    m_indexScheduler->suspend();
+}
+
+
+void Nepomuk::StrigiServiceAdaptor::updateFolder( const QString& path )
+{
+    m_indexScheduler->updateDir( path );
+}
+
+
+void Nepomuk::StrigiServiceAdaptor::analyzeResource( const QString& uri, uint mTime, const QByteArray& data )
+{
+    QDataStream stream( data );
+    m_indexScheduler->analyzeResource( QUrl::fromEncoded( uri.toAscii() ), QDateTime::fromTime_t( mTime ), stream );
+}
+
+
+void Nepomuk::StrigiServiceAdaptor::analyzeResourceFromTempFileAndDeleteTempFile( const QString& uri, uint mTime, const QString& tmpFile )
+{
+    QFile file( tmpFile );
+    if ( file.open( QIODevice::ReadOnly ) ) {
+        QDataStream stream( &file );
+        m_indexScheduler->analyzeResource( QUrl::fromEncoded( uri.toAscii() ), QDateTime::fromTime_t( mTime ), stream );
+        file.remove();
+    }
+    else {
+        kDebug() << "Failed to open" << tmpFile;
+    }
+}
diff -Naur nepomuk/services/strigi/strigiserviceadaptor.h nepomuk/services/strigi/strigiserviceadaptor.h
--- nepomuk/services/strigi/strigiserviceadaptor.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/strigiserviceadaptor.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,94 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
+
+   Based on code generated by dbusxml2cpp version 0.6
+   dbusxml2cpp is Copyright (C) 2006 Trolltech ASA. All rights reserved.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef _STRIGISERVICE_ADAPTOR_H_
+#define _STRIGISERVICE_ADAPTOR_H_
+
+#include <QtDBus/QDBusAbstractAdaptor>
+
+namespace Nepomuk {
+
+    class IndexScheduler;
+    class StrigiService;
+
+    class StrigiServiceAdaptor: public QDBusAbstractAdaptor
+    {
+        Q_OBJECT
+        Q_CLASSINFO("D-Bus Interface", "org.kde.nepomuk.Strigi")
+        Q_CLASSINFO("D-Bus Introspection", ""
+                    "  <interface name=\"org.kde.nepomuk.Strigi\" >\n"
+                    "    <method name=\"isIndexing\" >\n"
+                    "      <arg direction=\"out\" type=\"b\" />\n"
+                    "    </method>\n"
+                    "    <method name=\"isSuspended\" >\n"
+                    "      <arg direction=\"out\" type=\"b\" />\n"
+                    "    </method>\n"
+                    "    <method name=\"currentFolder\" >\n"
+                    "      <arg direction=\"out\" type=\"s\" />\n"
+                    "    </method>\n"
+                    "    <method name=\"suspend\" />\n"
+                    "    <method name=\"resume\" />\n"
+                    "    <method name=\"updateFolder\" >\n"
+                    "      <arg name=\"path\" direction=\"in\" type=\"s\" />\n"
+                    "    </method>\n"
+                    "    <method name=\"analyzeResource\" >\n"
+                    "      <arg name=\"uri\" direction=\"in\" type=\"s\" />\n"
+                    "      <arg name=\"lastModificationDate\" direction=\"in\" type=\"u\" />\n"
+                    "      <arg name=\"data\" direction=\"in\" type=\"ay\" />\n"
+                    "    </method>\n"
+                    "    <method name=\"analyzeResourceFromTempFileAndDeleteTempFile\" >\n"
+                    "      <arg name=\"uri\" direction=\"in\" type=\"s\" />\n"
+                    "      <arg name=\"lastModificationDate\" direction=\"in\" type=\"u\" />\n"
+                    "      <arg name=\"tmpFileName\" direction=\"in\" type=\"s\" />\n"
+                    "    </method>\n"
+                    "    <signal name=\"indexingStarted\" />\n"
+                    "    <signal name=\"indexingStopped\" />\n"
+                    "    <signal name=\"indexingFolder\" >\n"
+                    "      <arg type=\"s\" name=\"path\" />\n"
+                    "    </signal>\n"
+                    "  </interface>\n"
+                    "")
+
+    public:
+        StrigiServiceAdaptor( IndexScheduler* scheduler, StrigiService* parent );
+        ~StrigiServiceAdaptor();
+
+    public Q_SLOTS:
+        bool isIndexing();
+        bool isSuspended();
+        QString currentFolder();
+        void resume();
+        void suspend();
+        void updateFolder( const QString& path );
+        void analyzeResource( const QString& uri, uint mTime, const QByteArray& data );
+        void analyzeResourceFromTempFileAndDeleteTempFile( const QString& uri, uint mTime, const QString& tmpFile );
+
+    Q_SIGNALS:
+        void indexingFolder( const QString& path );
+        void indexingStarted();
+        void indexingStopped();
+
+    private:
+        IndexScheduler* m_indexScheduler;
+    };
+}
+
+#endif
diff -Naur nepomuk/services/strigi/systray.cpp nepomuk/services/strigi/systray.cpp
--- nepomuk/services/strigi/systray.cpp	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/systray.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,92 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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 "systray.h"
+#include "indexscheduler.h"
+
+#include <KMenu>
+#include <KToggleAction>
+#include <KLocale>
+#include <KCMultiDialog>
+#include <KIcon>
+
+
+
+Nepomuk::SystemTray::SystemTray( IndexScheduler* scheduler, QWidget* parent )
+    : KSystemTrayIcon( "nepomuk", parent ),
+      m_indexScheduler( scheduler )
+{
+    KMenu* menu = new KMenu;
+    menu->addTitle( i18n( "Strigi File Indexing" ) );
+
+    m_suspendResumeAction = new KToggleAction( i18n( "Suspend Strigi Indexing" ), menu );
+    m_suspendResumeAction->setCheckedState( KGuiItem( i18n( "Resume Strigi Indexing" ) ) );
+    m_suspendResumeAction->setToolTip( i18n( "Suspend or resume the Strigi file indexer manually" ) );
+    connect( m_suspendResumeAction, SIGNAL( toggled( bool ) ),
+             m_indexScheduler, SLOT( setSuspended( bool ) ) );
+
+    KAction* configAction = new KAction( menu );
+    configAction->setText( i18n( "Configure Strigi" ) );
+    configAction->setIcon( KIcon( "configure" ) );
+    connect( configAction, SIGNAL( triggered() ),
+             this, SLOT( slotConfigure() ) );
+
+    menu->addAction( m_suspendResumeAction );
+    menu->addAction( configAction );
+
+    setContextMenu( menu );
+
+    connect( m_indexScheduler, SIGNAL( indexingStarted() ),
+             this, SLOT( slotUpdateStrigiStatus() ) );
+    connect( m_indexScheduler, SIGNAL( indexingStopped() ),
+             this, SLOT( slotUpdateStrigiStatus() ) );
+    connect( m_indexScheduler, SIGNAL( indexingFolder(QString) ),
+             this, SLOT( slotUpdateStrigiStatus() ) );
+}
+
+
+Nepomuk::SystemTray::~SystemTray()
+{
+}
+
+
+void Nepomuk::SystemTray::slotUpdateStrigiStatus()
+{
+    bool indexing = m_indexScheduler->isIndexing();
+    bool suspended = m_indexScheduler->isSuspended();
+    QString folder = m_indexScheduler->currentFolder();
+
+    if ( suspended )
+        setToolTip( i18n( "File indexer is suspended" ) );
+    else if ( indexing )
+        setToolTip( i18n( "Strigi is currently indexing files in folder %1", folder ) );
+    else
+        setToolTip( i18n( "File indexer is idle" ) );
+
+    m_suspendResumeAction->setChecked( suspended );
+}
+
+
+void Nepomuk::SystemTray::slotConfigure()
+{
+    KCMultiDialog dlg;
+    dlg.addModule( "kcm_nepomuk" );
+    dlg.exec();
+}
+
+#include "systray.moc"
diff -Naur nepomuk/services/strigi/systray.h nepomuk/services/strigi/systray.h
--- nepomuk/services/strigi/systray.h	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/services/strigi/systray.h	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,49 @@
+/* This file is part of the KDE Project
+   Copyright (c) 2008 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 version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef _NEPOMUK_STRIGI_SYSTRAY_H_
+#define _NEPOMUK_STRIGI_SYSTRAY_H_
+
+#include <KSystemTrayIcon>
+
+class KToggleAction;
+
+namespace Nepomuk {
+
+    class IndexScheduler;
+
+    class SystemTray : public KSystemTrayIcon
+    {
+        Q_OBJECT
+
+    public:
+        SystemTray( IndexScheduler* scheduler, QWidget* parent );
+        ~SystemTray();
+
+    private Q_SLOTS:
+        void slotUpdateStrigiStatus();
+        void slotConfigure();
+
+    private:
+        KToggleAction* m_suspendResumeAction;
+
+        IndexScheduler* m_indexScheduler;
+    };
+}
+
+#endif
diff -Naur nepomuk/servicestub/CMakeLists.txt nepomuk/servicestub/CMakeLists.txt
--- nepomuk/servicestub/CMakeLists.txt	2008-07-03 07:05:21.000000000 +0200
+++ nepomuk/servicestub/CMakeLists.txt	2008-09-01 14:33:17.000000000 +0200
@@ -25,8 +25,10 @@
 
 target_link_libraries(nepomukservicestub
   ${QT_QTCORE_LIBRARY}
+  ${QT_QTGUI_LIBRARY}
   ${QT_QTDBUS_LIBRARY}
   ${KDE4_KDECORE_LIBS}
+  ${KDE4_KDEUI_LIBS}
   ${NEPOMUK_LIBRARIES}
   ${SOPRANO_LIBRARIES}
   )
diff -Naur nepomuk/servicestub/main.cpp nepomuk/servicestub/main.cpp
--- nepomuk/servicestub/main.cpp	2008-07-03 07:05:21.000000000 +0200
+++ nepomuk/servicestub/main.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -23,10 +23,10 @@
 #include <KService>
 #include <KServiceTypeTrader>
 #include <KDebug>
-#include <Nepomuk/Service>
 
-#include <QtCore/QCoreApplication>
 #include <QtCore/QTextStream>
+#include <QtCore/QTimer>
+#include <QtGui/QApplication>
 #include <QtDBus/QDBusConnection>
 #include <QtDBus/QDBusConnectionInterface>
 
@@ -34,20 +34,8 @@
 #include <stdio.h>
 
 #include "servicecontrol.h"
-#include "servicecontroladaptor.h"
 
 namespace {
-    QString dbusServiceName( const QString& serviceName ) {
-        return QString("org.kde.nepomuk.services.%1").arg(serviceName);
-    }
-
-    enum Errors {
-        ErrorUnknownServiceName = -9,
-        ErrorServiceAlreadyRunning = -10,
-        ErrorFailedToStart = -11,
-        ErrorMissingDependency = -12
-    };
-
 #ifndef Q_OS_WIN
     void signalHandler( int signal )
     {
@@ -77,7 +65,7 @@
 {
     KAboutData aboutData( "nepomukservicestub", "nepomuk",
                           ki18n("Nepomuk Service Stub"),
-                          "0.1",
+                          "0.2",
                           ki18n("Nepomuk Service Stub"),
                           KAboutData::License_GPL,
                           ki18n("(c) 2008, Sebastian Trüg"),
@@ -91,9 +79,9 @@
 
     KCmdLineArgs::init( argc, argv, &aboutData );
 
-    QCoreApplication app( argc, argv );
+    QApplication app( argc, argv );
     installSignalHandler();
-    KComponentData compData( aboutData );
+    QApplication::setQuitOnLastWindowClosed( false );
 
     // FIXME: set the proper KConfig rc name using the service name
 
@@ -105,6 +93,12 @@
 
     QTextStream s( stderr );
 
+    QString serviceName = args->arg(0);
+    args->clear();
+
+    aboutData.setAppName( serviceName.toLocal8Bit() );
+    KComponentData compData( aboutData );
+
 
     // check if NepomukServer is running
     // ====================================
@@ -116,20 +110,19 @@
 
     // search the service
     // ====================================
-    QString serviceName = args->arg(0);
     KService::List services = KServiceTypeTrader::self()->query( "NepomukService", "DesktopEntryName == '" + serviceName + "'" );
     if( services.isEmpty() ) {
         s << i18n( "Unknown service name:") << " " <<  serviceName << endl;
-        return ErrorUnknownServiceName;
+        return Nepomuk::ServiceControl::ErrorUnknownServiceName;
     }
     KService::Ptr service = services.first();
 
 
     // Check if this service is already running
     // ====================================
-    if( QDBusConnection::sessionBus().interface()->isServiceRegistered( dbusServiceName( serviceName ) ) ) {
+    if( QDBusConnection::sessionBus().interface()->isServiceRegistered( Nepomuk::ServiceControl::dbusServiceName( serviceName ) ) ) {
         s << "Service " << serviceName << " already running." << endl;
-        return ErrorServiceAlreadyRunning;
+        return Nepomuk::ServiceControl::ErrorServiceAlreadyRunning;
     }
 
 
@@ -137,42 +130,21 @@
     // ====================================
     QStringList dependencies = service->property( "X-KDE-Nepomuk-dependencies", QVariant::StringList ).toStringList();
     foreach( const QString &dep, dependencies ) {
-        if( !QDBusConnection::sessionBus().interface()->isServiceRegistered( dbusServiceName( dep ) ) ) {
+        if( !QDBusConnection::sessionBus().interface()->isServiceRegistered( Nepomuk::ServiceControl::dbusServiceName( dep ) ) ) {
             s << "Missing dependency " << dep << endl;
-            return ErrorMissingDependency;
+            return Nepomuk::ServiceControl::ErrorMissingDependency;
         }
     }
 
 
     // register the service control
     // ====================================
-    Nepomuk::ServiceControl* control = new Nepomuk::ServiceControl( &app );
-    (void)new ServiceControlAdaptor( control );
-    if( !QDBusConnection::sessionBus().registerObject( "/servicecontrol", control ) ) {
-        s << "Failed to register dbus service " << dbusServiceName( serviceName ) << "." << endl;
-        return ErrorFailedToStart;
-    }
+    Nepomuk::ServiceControl* control = new Nepomuk::ServiceControl( serviceName, service, &app );
 
-    // start the service
-    // ====================================
-    Nepomuk::Service* module = service->createInstance<Nepomuk::Service>( control );
-    if( !module ) {
-        s << "Failed to start service " << serviceName << "." << endl;
-        return ErrorFailedToStart;
-    }
 
-    // register the service interface
+    // start the service (queued since we need an event loop)
     // ====================================
-    if( !QDBusConnection::sessionBus().registerService( dbusServiceName( serviceName ) ) ) {
-        s << "Failed to register dbus service " << dbusServiceName( serviceName ) << "." << endl;
-        return ErrorFailedToStart;
-    }
-
-    QDBusConnection::sessionBus().registerObject( '/' + serviceName,
-                                                  module,
-                                                  QDBusConnection::ExportScriptableSlots |
-                                                  QDBusConnection::ExportScriptableProperties |
-                                                  QDBusConnection::ExportAdaptors);
+    QTimer::singleShot( 0, control, SLOT( start() ) );
 
     return app.exec();
 }
diff -Naur nepomuk/servicestub/servicecontrol.cpp nepomuk/servicestub/servicecontrol.cpp
--- nepomuk/servicestub/servicecontrol.cpp	2008-04-02 14:18:21.000000000 +0200
+++ nepomuk/servicestub/servicecontrol.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -17,12 +17,18 @@
 */
 
 #include "servicecontrol.h"
+#include "servicecontroladaptor.h"
 
 #include <QtCore/QCoreApplication>
+#include <QtCore/QTextStream>
 
+#include <Nepomuk/Service>
 
-Nepomuk::ServiceControl::ServiceControl( QObject* parent )
+
+Nepomuk::ServiceControl::ServiceControl( const QString& serviceName, const KService::Ptr& service, QObject* parent )
     : QObject( parent ),
+      m_serviceName( serviceName ),
+      m_service( service ),
       m_initialized( false )
 {
 }
@@ -35,7 +41,7 @@
 
 void Nepomuk::ServiceControl::setServiceInitialized( bool success )
 {
-    m_initialized = true;
+    m_initialized = success;
     emit serviceInitialized( success );
 }
 
@@ -46,9 +52,56 @@
 }
 
 
+void Nepomuk::ServiceControl::start()
+{
+    QTextStream s( stderr );
+
+    // register the service interface
+    // We need to do this before creating the module to ensure that
+    // the server can catch the serviceInitialized signal
+    // ====================================
+    (void)new ServiceControlAdaptor( this );
+    if( !QDBusConnection::sessionBus().registerObject( "/servicecontrol", this ) ) {
+        s << "Failed to register dbus service " << dbusServiceName( m_serviceName ) << "." << endl;
+        qApp->exit( ErrorFailedToStart );
+        return;
+    }
+
+    if( !QDBusConnection::sessionBus().registerService( dbusServiceName( m_serviceName ) ) ) {
+        s << "Failed to register dbus service " << dbusServiceName( m_serviceName ) << "." << endl;
+        qApp->exit( ErrorFailedToStart );
+        return;
+    }
+
+
+    // start the service
+    // ====================================
+    Nepomuk::Service* module = m_service->createInstance<Nepomuk::Service>( this );
+    if( !module ) {
+        s << "Failed to start service " << m_serviceName << "." << endl;
+        qApp->exit( ErrorFailedToStart );
+        return;
+    }
+
+    // register the service
+    // ====================================
+    QDBusConnection::sessionBus().registerObject( '/' + m_serviceName,
+                                                  module,
+                                                  QDBusConnection::ExportScriptableSlots |
+                                                  QDBusConnection::ExportScriptableProperties |
+                                                  QDBusConnection::ExportAdaptors);
+}
+
+
 void Nepomuk::ServiceControl::shutdown()
 {
     QCoreApplication::quit();
 }
 
+
+QString Nepomuk::ServiceControl::dbusServiceName( const QString& serviceName )
+{
+    return QString("org.kde.nepomuk.services.%1").arg(serviceName);
+}
+
 #include "servicecontrol.moc"
diff -Naur nepomuk/servicestub/servicecontrol.h nepomuk/servicestub/servicecontrol.h
--- nepomuk/servicestub/servicecontrol.h	2008-04-02 14:18:21.000000000 +0200
+++ nepomuk/servicestub/servicecontrol.h	2008-09-01 14:33:17.000000000 +0200
@@ -21,6 +21,7 @@
 
 #include <QtCore/QObject>
 
+#include <KService>
 
 namespace Nepomuk {
     class ServiceControl : public QObject
@@ -28,18 +29,30 @@
         Q_OBJECT
 
     public:
-        ServiceControl( QObject* parent = 0 );
+        ServiceControl( const QString& serviceName, const KService::Ptr& service, QObject* parent = 0 );
         ~ServiceControl();
 
+        static QString dbusServiceName( const QString& serviceName );
+
+        enum Errors {
+            ErrorUnknownServiceName = -9,
+            ErrorServiceAlreadyRunning = -10,
+            ErrorFailedToStart = -11,
+            ErrorMissingDependency = -12
+        };
+
     Q_SIGNALS:
-        void serviceInitialized( bool );
+        void serviceInitialized( bool success );
 
     public Q_SLOTS:
-        void setServiceInitialized( bool );
+        void start();
+        void setServiceInitialized( bool success );
         bool isInitialized() const;
         void shutdown();
 
     private:
+        QString m_serviceName;
+        KService::Ptr m_service;
         bool m_initialized;
     };
 }
diff -Naur nepomuk/strigibackend/CMakeLists.txt nepomuk/strigibackend/CMakeLists.txt
--- nepomuk/strigibackend/CMakeLists.txt	2008-05-21 10:33:02.000000000 +0200
+++ nepomuk/strigibackend/CMakeLists.txt	2008-09-01 14:33:17.000000000 +0200
@@ -43,6 +43,7 @@
   ${SOPRANO_CLIENT_LIBRARIES}
   ${QT_QTCORE_LIBRARY}
   ${CLUCENE_LIBRARY}
+  ${KDE4_KDECORE_LIBS}
 )
 
 install(TARGETS sopranobackend LIBRARY DESTINATION ${LIB_INSTALL_DIR}/strigi)
diff -Naur nepomuk/strigibackend/nepomukmainmodel.cpp nepomuk/strigibackend/nepomukmainmodel.cpp
--- nepomuk/strigibackend/nepomukmainmodel.cpp	2008-04-18 09:21:46.000000000 +0200
+++ nepomuk/strigibackend/nepomukmainmodel.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -87,8 +87,6 @@
 
     // we may get disconnected from the server but we don't want to try
     // to connect every time the model is requested
-    // FIXME: I doubt that this will work since the client is created in another thread than the
-    //        connections and that is something Qt really does not like. :(
     if ( !m_socketConnectFailed && !m_localSocketClient.isConnected() ) {
         delete m_localSocketModel;
         QString socketName = nepomukServerSocketPath();
diff -Naur nepomuk/strigibackend/sopranoindexreader.cpp nepomuk/strigibackend/sopranoindexreader.cpp
--- nepomuk/strigibackend/sopranoindexreader.cpp	2008-07-03 07:05:21.000000000 +0200
+++ nepomuk/strigibackend/sopranoindexreader.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -59,6 +59,16 @@
 static lucene::search::Query* createMultiFieldQuery( const Strigi::Query& query );
 
 
+static QString luceneQueryEscape( const QString& s )
+{
+    /* Chars to escape: + - && || ! ( ) { } [ ] ^ " ~  : \ */
+
+    static QRegExp rx( "([\\-" + QRegExp::escape( "+&|!(){}[]^\"~:\\" ) + "])" );
+    QString es( s );
+    es.replace( rx, "\\\\1" );
+    return es;
+}
+
 static lucene::index::Term* createWildCardTerm( const TString& name,
                                                 const string& value )
 {
@@ -266,7 +276,7 @@
 
     lucene::search::Query* q = createQuery( query );
     ::Soprano::QueryResultIterator hits = d->repository->executeQuery( TString( q->toString(), true ),
-                                                                       ::Soprano::Query::QUERY_LANGUAGE_USER,
+                                                                       ::Soprano::Query::QueryLanguageUser,
                                                                        QLatin1String( "lucene" ) );
 //    Iterator< ::Soprano::Index::QueryHit> hits = d->repository->index()->search( q );
     int s = 0;
@@ -288,7 +298,7 @@
     qDebug() << "IndexReader::getHits in thread" << QThread::currentThread();
     lucene::search::Query* bq = createQuery( query );
     ::Soprano::QueryResultIterator hits = d->repository->executeQuery( TString( bq->toString(), true ),
-                                                                       ::Soprano::Query::QUERY_LANGUAGE_USER,
+                                                                       ::Soprano::Query::QueryLanguageUser,
                                                                        QLatin1String( "lucene" ) );
 //    Iterator< ::Soprano::Index::QueryHit> hits = d->repository->index()->search( bq );
 
@@ -339,7 +349,7 @@
     vector<IndexedDocument> results;
     lucene::search::Query* bq = createQuery( query );
     ::Soprano::QueryResultIterator hits = d->repository->executeQuery( TString( bq->toString(), true ),
-                                                                       ::Soprano::Query::QUERY_LANGUAGE_USER,
+                                                                       ::Soprano::Query::QueryLanguageUser,
                                                                        QLatin1String( "lucene" ) );
 //    Iterator< ::Soprano::Index::QueryHit> hits = d->repository->index()->search( bq );
 
@@ -374,15 +384,15 @@
 {
 //    qDebug() << "IndexReader::getChildren in thread" << QThread::currentThread();
     QString query = QString( "select distinct ?path ?mtime where { ?r <%1> \"%2\"^^<%3> . ?r <%4> ?mtime . ?r <%5> ?path . }")
-                    .arg( Util::fieldUri( FieldRegister::parentLocationFieldName ).toString() )
-                    .arg( escapeLiteralForSparqlQuery( QString::fromUtf8( parent.c_str() ) ) )
-                    .arg( Vocabulary::XMLSchema::string().toString() )
-                    .arg( Util::fieldUri( FieldRegister::mtimeFieldName ).toString() )
-                    .arg( Util::fieldUri( FieldRegister::pathFieldName ).toString() );
+                    .arg( Util::fieldUri( FieldRegister::parentLocationFieldName ).toString(),
+                          escapeLiteralForSparqlQuery( QString::fromUtf8( parent.c_str() ) ),
+                          Vocabulary::XMLSchema::string().toString(),
+                          Util::fieldUri( FieldRegister::mtimeFieldName ).toString(),
+                          Util::fieldUri( FieldRegister::pathFieldName ).toString() );
 
-    qDebug() << "running getChildren query:" << query;
+//    qDebug() << "running getChildren query:" << query;
 
-    QueryResultIterator result = d->repository->executeQuery( query, ::Soprano::Query::QUERY_LANGUAGE_SPARQL );
+    QueryResultIterator result = d->repository->executeQuery( query, ::Soprano::Query::QueryLanguageSparql );
 
     while ( result.next() ) {
         Node pathNode = result.binding( "path" );
@@ -427,14 +437,14 @@
 {
 //    qDebug() << "IndexReader::mTime in thread" << QThread::currentThread();
     QString query = QString( "select ?mtime where { ?r <%2> \"%3\"^^<%4> . ?r <%1> ?mtime . }" )
-                    .arg( Util::fieldUri( FieldRegister::mtimeFieldName ).toString() )
-                    .arg( Util::fieldUri( FieldRegister::pathFieldName ).toString() )
-                    .arg( escapeLiteralForSparqlQuery( QString::fromUtf8( uri.c_str() ) ) )
-                    .arg( Vocabulary::XMLSchema::string().toString() );
+                    .arg( Util::fieldUri( FieldRegister::mtimeFieldName ).toString(),
+                          Util::fieldUri( FieldRegister::pathFieldName ).toString(),
+                          escapeLiteralForSparqlQuery( QString::fromUtf8( uri.c_str() ) ),
+                          Vocabulary::XMLSchema::string().toString() );
 
     qDebug() << "mTime( " << uri.c_str() << ") query:" << query;
 
-    QueryResultIterator it = d->repository->executeQuery( query, ::Soprano::Query::QUERY_LANGUAGE_SPARQL );
+    QueryResultIterator it = d->repository->executeQuery( query, ::Soprano::Query::QueryLanguageSparql );
 
     time_t mtime = 0;
     if ( it.next() ) {
@@ -459,7 +469,7 @@
     // Our list of field names (the predicates) is probably awefully long.
 
     std::vector<std::string> fields;
-    QueryResultIterator it = d->repository->executeQuery( "select distinct ?p where { ?r ?p ?o . }", ::Soprano::Query::QUERY_LANGUAGE_SPARQL );
+    QueryResultIterator it = d->repository->executeQuery( "select distinct ?p where { ?r ?p ?o . }", ::Soprano::Query::QueryLanguageSparql );
     while ( it.next() ) {
         fields.push_back( Util::fieldName( it.binding("p").uri() ) );
     }
diff -Naur nepomuk/strigibackend/sopranoindexreader.h nepomuk/strigibackend/sopranoindexreader.h
--- nepomuk/strigibackend/sopranoindexreader.h	2008-05-07 11:05:22.000000000 +0200
+++ nepomuk/strigibackend/sopranoindexreader.h	2008-09-01 14:33:17.000000000 +0200
@@ -1,5 +1,5 @@
 /*
-   Copyright (C) 2007 Sebastian Trueg <trueg@kde.org>
+   Copyright (C) 2007-2008 Sebastian Trueg <trueg@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
@@ -34,41 +34,41 @@
     class Query;
 
     namespace Soprano {
-	class IndexReader : public Strigi::IndexReader
-	{
-	public:
-	    IndexReader( ::Soprano::Model* );
-	    ~IndexReader();
-
-	    int32_t countHits( const Query& query );
-	    std::vector<IndexedDocument> query( const Query&, int off, int max );
-	    void getHits( const Strigi::Query& query,
-			  const std::vector<std::string>& fields,
-			  const std::vector<Strigi::Variant::Type>& types,
-			  std::vector<std::vector<Strigi::Variant> >& result,
-			  int off, int max );
-
-	    void getChildren( const std::string& parent,
-			      std::map<std::string, time_t>& children );
-
-	    int32_t countDocuments();
-	    int32_t countWords();
-	    int64_t indexSize();
-	    time_t mTime( const std::string& uri );
-	    std::vector<std::string> fieldNames();
-	    std::vector<std::pair<std::string,uint32_t> > histogram( const std::string& query,
-								     const std::string& fieldname,
-								     const std::string& labeltype );
-	    int32_t countKeywords( const std::string& keywordprefix,
-				   const std::vector<std::string>& fieldnames);
-	    std::vector<std::string> keywords( const std::string& keywordmatch,
-					       const std::vector<std::string>& fieldnames,
-					       uint32_t max, uint32_t offset );
-
-	private:
-	    class Private;
-	    Private* d;
-	};
+        class IndexReader : public Strigi::IndexReader
+        {
+        public:
+            IndexReader( ::Soprano::Model* );
+            ~IndexReader();
+
+            int32_t countHits( const Query& query );
+            std::vector<IndexedDocument> query( const Query&, int off, int max );
+            void getHits( const Strigi::Query& query,
+                          const std::vector<std::string>& fields,
+                          const std::vector<Strigi::Variant::Type>& types,
+                          std::vector<std::vector<Strigi::Variant> >& result,
+                          int off, int max );
+
+            void getChildren( const std::string& parent,
+                              std::map<std::string, time_t>& children );
+
+            int32_t countDocuments();
+            int32_t countWords();
+            int64_t indexSize();
+            time_t mTime( const std::string& uri );
+            std::vector<std::string> fieldNames();
+            std::vector<std::pair<std::string,uint32_t> > histogram( const std::string& query,
+                                                                     const std::string& fieldname,
+                                                                     const std::string& labeltype );
+            int32_t countKeywords( const std::string& keywordprefix,
+                                   const std::vector<std::string>& fieldnames);
+            std::vector<std::string> keywords( const std::string& keywordmatch,
+                                               const std::vector<std::string>& fieldnames,
+                                               uint32_t max, uint32_t offset );
+
+        private:
+            class Private;
+            Private* d;
+        };
     }
 }
 
diff -Naur nepomuk/strigibackend/sopranoindexwriter.cpp nepomuk/strigibackend/sopranoindexwriter.cpp
--- nepomuk/strigibackend/sopranoindexwriter.cpp	2008-09-01 14:44:51.000000000 +0200
+++ nepomuk/strigibackend/sopranoindexwriter.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -37,6 +37,8 @@
 #include <QtCore/QThread>
 #include <QtCore/QDateTime>
 
+#include <KUrl>
+
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <string.h>
@@ -76,8 +78,13 @@
         // such as tar:/ or zip:/
         // Here we try to use KDE-compatible URIs for these indexed files the best we can
         // everything else defaults to file:/
+        QUrl uri;
         QString path = QFile::decodeName( idx->path().c_str() );
-        QUrl url = QUrl::fromLocalFile( QFileInfo( path ).absoluteFilePath() );
+        if ( KUrl::isRelativeUrl( path ) )
+            uri = QUrl::fromLocalFile( QFileInfo( path ).absoluteFilePath() );
+        else
+            uri = KUrl( path ); // try to support http and other URLs
+
         if ( idx->depth() > 0 ) {
             QString archivePath = findArchivePath( path );
             if ( QFile::exists( archivePath ) ) {
@@ -85,20 +92,20 @@
                      archivePath.endsWith( QLatin1String( ".tar.gz" ) ) ||
                      archivePath.endsWith( QLatin1String( ".tar.bz2" ) ) ||
                      archivePath.endsWith( QLatin1String( ".tar.lzma" ) ) ) {
-                    url.setScheme( "tar" );
+                    uri.setScheme( "tar" );
                 }
                 else if ( archivePath.endsWith( QLatin1String( ".zip" ) ) ) {
-                    url.setScheme( "zip" );
+                    uri.setScheme( "zip" );
                 }
             }
         }
 
         // fallback for all
-        if ( url.scheme().isEmpty() ) {
-            url.setScheme( "file" );
+        if ( uri.scheme().isEmpty() ) {
+            uri.setScheme( "file" );
         }
 
-        return url;
+        return uri;
     }
 
     class FileMetaData
@@ -156,9 +163,13 @@
         if ( type == QVariant::DateTime ) { // dataTime is stored as integer in strigi!
             return LiteralValue( QDateTime::fromTime_t( value.toUInt() ) );
         }
-        else {
+        else if ( type != QVariant::Invalid ) {
             return LiteralValue::fromString( value, type );
         }
+        else {
+            // we default to string
+            return LiteralValue( value );
+        }
     }
 
 //    ::Soprano::Index::IndexFilterModel* repository;
@@ -176,6 +187,7 @@
 //    qDebug() << "IndexWriter::IndexWriter in thread" << QThread::currentThread();
     d = new Private;
     d->repository = model;
+    Util::storeStrigiMiniOntology( d->repository );
 //    qDebug() << "IndexWriter::IndexWriter done in thread" << QThread::currentThread();
 }
 
@@ -205,14 +217,14 @@
                         .arg( path )
                         .arg( Vocabulary::XMLSchema::string().toString() );
 
-        qDebug() << "deleteEntries query:" << query;
+//        qDebug() << "deleteEntries query:" << query;
 
-        QueryResultIterator result = d->repository->executeQuery( query, ::Soprano::Query::QUERY_LANGUAGE_SPARQL );
+        QueryResultIterator result = d->repository->executeQuery( query, ::Soprano::Query::QueryLanguageSparql );
         if ( result.next() ) {
             Node indexGraph = result.binding( "g" );
             result.close();
 
-            qDebug() << "Found indexGraph to delete:" << indexGraph;
+//            qDebug() << "Found indexGraph to delete:" << indexGraph;
 
             // delete the indexed data
             d->repository->removeContext( indexGraph );
@@ -271,7 +283,7 @@
         data->context = Util::uniqueUri( "http://www.strigi.org/contexts/", d->repository );
     }
 
-    qDebug() << "Starting analysis for" << data->fileUri << "in thread" << QThread::currentThread();
+//    qDebug() << "Starting analysis for" << data->fileUri << "in thread" << QThread::currentThread();
 
     idx->setWriterData( data );
 }
@@ -319,15 +331,10 @@
         }
 
         else {
-            if ( rfd->dataType != QVariant::Invalid ) {
-                d->repository->addStatement( Statement( md->fileUri,
-                                                        rfd->property,
-                                                        d->createLiteralValue( rfd->dataType, ( unsigned char* )value.c_str(), value.length() ),
-                                                        md->context) );
-            }
-            else {
-                qDebug() << "Ignoring field" << rfd->property << "due to unknown type" << field->properties().typeUri().c_str();
-            }
+            d->repository->addStatement( Statement( md->fileUri,
+                                                    rfd->property,
+                                                    d->createLiteralValue( rfd->dataType, ( unsigned char* )value.c_str(), value.length() ),
+                                                    md->context) );
         }
     }
 //    qDebug() << "IndexWriter::addValue done in thread" << QThread::currentThread();
@@ -449,10 +456,16 @@
 
     // Strigi only indexes files and extractors mostly (if at all) store the xesam:DataObject type (i.e. the contents)
     // Thus, here we go the easy way and mark each indexed file as a xesam:File.
-    d->repository->addStatement( Statement( md->fileUri,
-                                            Vocabulary::RDF::type(),
-                                            Vocabulary::Xesam::File(),
-                                            md->context ) );
+    if ( QFileInfo( QFile::decodeName( idx->path().c_str() ) ).isDir() )
+        d->repository->addStatement( Statement( md->fileUri,
+                                                Vocabulary::RDF::type(),
+                                                Vocabulary::Xesam::Folder(),
+                                                md->context ) );
+    else
+        d->repository->addStatement( Statement( md->fileUri,
+                                                Vocabulary::RDF::type(),
+                                                Vocabulary::Xesam::File(),
+                                                md->context ) );
 
 
     // create the provedance data for the data graph
diff -Naur nepomuk/strigibackend/sopranoindexwriter.cpp.liblzma nepomuk/strigibackend/sopranoindexwriter.cpp.liblzma
--- nepomuk/strigibackend/sopranoindexwriter.cpp.liblzma	2008-05-15 20:37:14.000000000 +0200
+++ nepomuk/strigibackend/sopranoindexwriter.cpp.liblzma	1970-01-01 01:00:00.000000000 +0100
@@ -1,507 +0,0 @@
-/*
-   Copyright (C) 2007-2008 Sebastian Trueg <trueg@kde.org>
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU 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 General Public License
-   along with this library; see the file COPYING.  If not, write to
-   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.
- */
-
-#include "sopranoindexwriter.h"
-#include "util.h"
-
-#include <Soprano/Soprano>
-#include <Soprano/Index/IndexFilterModel>
-#include <Soprano/Index/CLuceneIndex>
-#include <Soprano/Vocabulary/RDF>
-#include <Soprano/Vocabulary/Xesam>
-#include <Soprano/LiteralValue>
-
-#include <QtCore/QList>
-#include <QtCore/QHash>
-#include <QtCore/QVariant>
-#include <QtCore/QFileInfo>
-#include <QtCore/QFile>
-#include <QtCore/QUrl>
-#include <QtCore/QDebug>
-#include <QtCore/QThread>
-#include <QtCore/QDateTime>
-
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <map>
-#include <sstream>
-#include <algorithm>
-
-
-// IMPORTANT: strings in Strigi are apparently UTF8! Except for file names. Those are in local encoding.
-
-using namespace Soprano;
-
-
-uint qHash( const std::string& s )
-{
-    return qHash( s.c_str() );
-}
-
-namespace {
-    QString findArchivePath( const QString& path ) {
-        QString p( path );
-        int i = 0;
-        while ( ( i = p.lastIndexOf( '/' ) ) > 0 ) {
-            p.truncate( i );
-            if ( QFileInfo( p ).isFile() ) {
-                return p;
-            }
-        }
-        return QString();
-    }
-
-    QUrl createResourceUri( const Strigi::AnalysisResult* idx ) {
-        // HACK: Strigi includes analysers that recurse into tar or zip archives and index
-        // the files therein. In KDE these files could perfectly be handled through kio slaves
-        // such as tar:/ or zip:/
-        // Here we try to use KDE-compatible URIs for these indexed files the best we can
-        // everything else defaults to file:/
-        QString path = QFile::decodeName( idx->path().c_str() );
-        QUrl url = QUrl::fromLocalFile( QFileInfo( path ).absoluteFilePath() );
-        if ( idx->depth() > 0 ) {
-            QString archivePath = findArchivePath( path );
-            if ( QFile::exists( archivePath ) ) {
-                if ( archivePath.endsWith( QLatin1String( ".tar" ) ) ||
-                     archivePath.endsWith( QLatin1String( ".tar.gz" ) ) ||
-                     archivePath.endsWith( QLatin1String( ".tar.bz2" ) ) ) {
-                    url.setScheme( "tar" );
-                }
-                else if ( archivePath.endsWith( QLatin1String( ".zip" ) ) ) {
-                    url.setScheme( "zip" );
-                }
-            }
-        }
-
-        // fallback for all
-        if ( url.scheme().isEmpty() ) {
-            url.setScheme( "file" );
-        }
-
-        return url;
-    }
-
-    class FileMetaData
-    {
-    public:
-        // caching URIs for little speed improvement
-        QUrl fileUri;
-        QUrl context;
-        std::string content;
-    };
-
-    class RegisteredFieldData
-    {
-    public:
-        RegisteredFieldData( const QUrl& prop, QVariant::Type t )
-            : property( prop ),
-              dataType( t ),
-              isRdfType( prop == Vocabulary::RDF::type() ) {
-        }
-
-        QUrl property;
-        QVariant::Type dataType;
-        bool isRdfType;
-    };
-}
-
-
-class Strigi::Soprano::IndexWriter::Private
-{
-public:
-    Private()
-        : indexTransactionID( 0 ) {
-        literalTypes[FieldRegister::stringType] = QVariant::String;
-        literalTypes[FieldRegister::floatType] = QVariant::Double;
-        literalTypes[FieldRegister::integerType] = QVariant::Int;
-        literalTypes[FieldRegister::binaryType] = QVariant::ByteArray;
-        literalTypes[FieldRegister::datetimeType] = QVariant::DateTime; // Strigi encodes datetime as unsigned integer, i.e. addValue( ..., uint )
-    }
-
-    QVariant::Type literalType( const Strigi::FieldProperties& strigiType ) {
-        // it looks as if the typeUri can contain arbitrary values, URIs or stuff like "string"
-        QHash<std::string, QVariant::Type>::const_iterator it = literalTypes.find( strigiType.typeUri() );
-        if ( it == literalTypes.constEnd() ) {
-            return LiteralValue::typeFromDataTypeUri( QUrl::fromEncoded( strigiType.typeUri().c_str() ) );
-        }
-        else {
-            return *it;
-        }
-    }
-
-    LiteralValue createLiteralValue( QVariant::Type type,
-                                     const unsigned char* data,
-                                     uint32_t size ) {
-        QString value = QString::fromUtf8( ( const char* )data, size );
-        if ( type == QVariant::DateTime ) { // dataTime is stored as integer in strigi!
-            return LiteralValue( QDateTime::fromTime_t( value.toUInt() ) );
-        }
-        else {
-            return LiteralValue::fromString( value, type );
-        }
-    }
-
-//    ::Soprano::Index::IndexFilterModel* repository;
-    ::Soprano::Model* repository;
-    int indexTransactionID;
-
-private:
-    QHash<std::string, QVariant::Type> literalTypes;
-};
-
-
-Strigi::Soprano::IndexWriter::IndexWriter( ::Soprano::Model* model )
-    : Strigi::IndexWriter()
-{
-//    qDebug() << "IndexWriter::IndexWriter in thread" << QThread::currentThread();
-    d = new Private;
-    d->repository = model;
-//    qDebug() << "IndexWriter::IndexWriter done in thread" << QThread::currentThread();
-}
-
-
-Strigi::Soprano::IndexWriter::~IndexWriter()
-{
-    delete d;
-}
-
-
-void Strigi::Soprano::IndexWriter::commit()
-{
-}
-
-
-// delete all indexed data for the files listed in entries
-void Strigi::Soprano::IndexWriter::deleteEntries( const std::vector<std::string>& entries )
-{
-//    qDebug() << "IndexWriter::deleteEntries in thread" << QThread::currentThread();
-
-    QString systemLocationUri = Util::fieldUri( FieldRegister::pathFieldName ).toString();
-    for ( unsigned int i = 0; i < entries.size(); ++i ) {
-        QString path = QString::fromUtf8( entries[i].c_str() );
-        QString query = QString( "select ?g where { ?r <%1> \"%2\"^^<%3> . "
-                                 "?g <http://www.strigi.org/fields#indexGraphFor> ?r . }" )
-                        .arg( systemLocationUri )
-                        .arg( path )
-                        .arg( Vocabulary::XMLSchema::string().toString() );
-
-        qDebug() << "deleteEntries query:" << query;
-
-        QueryResultIterator result = d->repository->executeQuery( query, ::Soprano::Query::QUERY_LANGUAGE_SPARQL );
-        if ( result.next() ) {
-            Node indexGraph = result.binding( "g" );
-            result.close();
-
-            qDebug() << "Found indexGraph to delete:" << indexGraph;
-
-            // delete the indexed data
-            d->repository->removeContext( indexGraph );
-
-            // delete the metadata
-            d->repository->removeAllStatements( Statement( indexGraph, Node(), Node() ) );
-        }
-    }
-}
-
-
-void Strigi::Soprano::IndexWriter::deleteAllEntries()
-{
-//    qDebug() << "IndexWriter::deleteAllEntries in thread" << QThread::currentThread();
-
-    // query all index graphs (FIXME: would a type derived from nrl:Graph be better than only the predicate?)
-    QString query = QString( "select ?g where { ?g <http://www.strigi.org/fields#indexGraphFor> ?r . }" );
-
-    qDebug() << "deleteAllEntries query:" << query;
-
-    QueryResultIterator result = d->repository->executeQuery( query, ::Soprano::Query::QUERY_LANGUAGE_SPARQL );
-    QList<Node> allIndexGraphs = result.iterateBindings( "g" ).allNodes();
-    for ( QList<Node>::const_iterator it = allIndexGraphs.constBegin(); it != allIndexGraphs.constEnd(); ++it ) {
-        Node indexGraph = *it;
-
-        qDebug() << "Found indexGraph to delete:" << indexGraph;
-
-        // delete the indexed data
-        d->repository->removeContext( indexGraph );
-
-        // delete the metadata
-        d->repository->removeAllStatements( Statement( indexGraph, Node(), Node() ) );
-    }
-}
-
-
-// called for each indexed file
-void Strigi::Soprano::IndexWriter::startAnalysis( const AnalysisResult* idx )
-{
-    if ( idx->depth() > 0 ) {
-        return;
-    }
-
-//    qDebug() << "IndexWriter::startAnalysis in thread" << QThread::currentThread();
-    FileMetaData* data = new FileMetaData();
-    data->fileUri = createResourceUri( idx );
-
-    // let's check if we already have data on the file
-    StatementIterator it = d->repository->listStatements( Node(),
-                                                          QUrl::fromEncoded( "http://www.strigi.org/fields#indexGraphFor", QUrl::StrictMode ), // FIXME: put the URI somewhere else
-                                                          data->fileUri );
-    if ( it.next() ) {
-        data->context = it.current().subject().uri();
-    }
-    else {
-        data->context = Util::uniqueUri( "http://www.strigi.org/contexts/", d->repository );
-    }
-
-    qDebug() << "Starting analysis for" << data->fileUri << "in thread" << QThread::currentThread();
-
-    idx->setWriterData( data );
-}
-
-
-void Strigi::Soprano::IndexWriter::addText( const AnalysisResult* idx, const char* text, int32_t length )
-{
-    if ( idx->depth() > 0 ) {
-        return;
-    }
-
-    FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
-    md->content.append( text, length );
-}
-
-
-void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
-                                             const RegisteredField* field,
-                                             const std::string& value )
-{
-    if ( idx->depth() > 0 ) {
-        return;
-    }
-
-//    qDebug() << "IndexWriter::addValue in thread" << QThread::currentThread();
-    if ( value.length() > 0 ) {
-        FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
-        RegisteredFieldData* rfd = reinterpret_cast<RegisteredFieldData*>( field->writerData() );
-
-        if ( rfd->isRdfType ) {
-
-            // Strigi uses rdf:type improperly since it stores the value as a string. We have to
-            // make sure it is a resource. The problem is that this results in the type not being
-            // indexed properly. Thus, it cannot be searched with normal lucene queries.
-            // That is why we need to introduce a stringType property
-
-            d->repository->addStatement( Statement( md->fileUri,
-                                                    ::Soprano::Vocabulary::RDF::type(),
-                                                    QUrl::fromEncoded( value.c_str(), QUrl::StrictMode ), // fromEncoded is faster than the plain constructor and all Xesam URIs work here
-                                                    md->context) );
-            d->repository->addStatement( Statement( md->fileUri,
-                                                    QUrl::fromEncoded( "http://strigi.sourceforge.net/fields#rdf-string-type", QUrl::StrictMode ),
-                                                    LiteralValue( QString::fromUtf8( value.c_str() ) ),
-                                                    md->context) );
-        }
-
-        else {
-            if ( rfd->dataType != QVariant::Invalid ) {
-                d->repository->addStatement( Statement( md->fileUri,
-                                                        rfd->property,
-                                                        d->createLiteralValue( rfd->dataType, ( unsigned char* )value.c_str(), value.length() ),
-                                                        md->context) );
-            }
-            else {
-                qDebug() << "Ignoring field" << rfd->property << "due to unknown type" << field->properties().typeUri().c_str();
-            }
-        }
-    }
-//    qDebug() << "IndexWriter::addValue done in thread" << QThread::currentThread();
-}
-
-
-// the main addValue method
-void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
-                                             const RegisteredField* field,
-                                             const unsigned char* data,
-                                             uint32_t size )
-{
-    addValue( idx, field, std::string( ( const char* )data, size ) );
-}
-
-
-void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult*, const RegisteredField*,
-                                             const std::string&, const std::string& )
-{
-    // we do not support map types
-}
-
-
-void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
-                                             const RegisteredField* field,
-                                             uint32_t value )
-{
-    if ( idx->depth() > 0 ) {
-        return;
-    }
-
-//    qDebug() << "IndexWriter::addValue in thread" << QThread::currentThread();
-    FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
-    RegisteredFieldData* rfd = reinterpret_cast<RegisteredFieldData*>( field->writerData() );
-
-    LiteralValue val( value );
-    if ( field->type() == FieldRegister::datetimeType ) {
-        val = QDateTime::fromTime_t( value );
-    }
-
-    d->repository->addStatement( Statement( md->fileUri,
-                                            rfd->property,
-                                            val,
-                                            md->context) );
-//    qDebug() << "IndexWriter::addValue done in thread" << QThread::currentThread();
-}
-
-
-void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
-                                             const RegisteredField* field,
-                                             int32_t value )
-{
-    if ( idx->depth() > 0 ) {
-        return;
-    }
-
-//    qDebug() << "IndexWriter::addValue in thread" << QThread::currentThread();
-    FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
-    RegisteredFieldData* rfd = reinterpret_cast<RegisteredFieldData*>( field->writerData() );
-
-    d->repository->addStatement( Statement( md->fileUri,
-                                            rfd->property,
-                                            LiteralValue( value ),
-                                            md->context) );
-//    qDebug() << "IndexWriter::addValue done in thread" << QThread::currentThread();
-}
-
-
-void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
-                                             const RegisteredField* field,
-                                             double value )
-{
-    if ( idx->depth() > 0 ) {
-        return;
-    }
-
-//    qDebug() << "IndexWriter::addValue in thread" << QThread::currentThread();
-    FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
-    RegisteredFieldData* rfd = reinterpret_cast<RegisteredFieldData*>( field->writerData() );
-
-    d->repository->addStatement( Statement( md->fileUri,
-                                            rfd->property,
-                                            LiteralValue( value ),
-                                            md->context) );
-//    qDebug() << "IndexWriter::addValue done in thread" << QThread::currentThread();
-}
-
-
-void Strigi::Soprano::IndexWriter::addTriplet( const std::string& subject,
-                                               const std::string& predicate, const std::string& object )
-{
-    // PROBLEM: which named graph (context) should we use here? Create a new one for each triple? Use one until the
-    // next commit()?
-
-    // FIXME: create an NRL metadata graph
-    d->repository->addStatement( Statement( Node( QUrl( QString::fromUtf8( subject.c_str() ) ) ),
-                                            Node( QUrl( QString::fromUtf8( predicate.c_str() ) ) ),
-                                            Node( QUrl( QString::fromUtf8( object.c_str() ) ) ),
-                                            Node() ) );
-}
-
-
-// called after each indexed file
-void Strigi::Soprano::IndexWriter::finishAnalysis( const AnalysisResult* idx )
-{
-    if ( idx->depth() > 0 ) {
-        return;
-    }
-
-//    qDebug() << "IndexWriter::finishAnalysis in thread" << QThread::currentThread();
-    FileMetaData* md = static_cast<FileMetaData*>( idx->writerData() );
-
-    if ( md->content.length() > 0 ) {
-        d->repository->addStatement( Statement( md->fileUri,
-                                                Vocabulary::Xesam::asText(),
-                                                LiteralValue( QString::fromUtf8( md->content.c_str() ) ),
-                                                md->context ) );
-    }
-
-    // Strigi only indexes files and extractors mostly (if at all) store the xesam:DataObject type (i.e. the contents)
-    // Thus, here we go the easy way and mark each indexed file as a xesam:File.
-    d->repository->addStatement( Statement( md->fileUri,
-                                            Vocabulary::RDF::type(),
-                                            Vocabulary::Xesam::File(),
-                                            md->context ) );
-
-
-    // create the provedance data for the data graph
-    // TODO: add more data at some point when it becomes of interest
-    QUrl metaDataContext = Util::uniqueUri( "http://www.strigi.org/graphMetaData/", d->repository );
-    d->repository->addStatement( Statement( md->context,
-                                            Vocabulary::RDF::type(),
-                                            Vocabulary::NRL::InstanceBase(),
-                                            metaDataContext ) );
-    d->repository->addStatement( Statement( md->context,
-                                            Vocabulary::NAO::created(),
-                                            LiteralValue( QDateTime::currentDateTime() ),
-                                            metaDataContext ) );
-    d->repository->addStatement( Statement( md->context,
-                                            QUrl::fromEncoded( "http://www.strigi.org/fields#indexGraphFor", QUrl::StrictMode ), // FIXME: put the URI somewhere else
-                                            md->fileUri,
-                                            metaDataContext ) );
-    d->repository->addStatement( Statement( metaDataContext,
-                                            Vocabulary::RDF::type(),
-                                            Vocabulary::NRL::GraphMetadata(),
-                                            metaDataContext ) );
-
-    // cleanup
-    delete md;
-    idx->setWriterData( 0 );
-
-//    qDebug() << "IndexWriter::finishAnalysis done in thread" << QThread::currentThread();
-}
-
-
-void Strigi::Soprano::IndexWriter::initWriterData( const Strigi::FieldRegister& f )
-{
-    map<string, RegisteredField*>::const_iterator i;
-    map<string, RegisteredField*>::const_iterator end = f.fields().end();
-    for (i = f.fields().begin(); i != end; ++i) {
-        QUrl prop = Util::fieldUri( i->second->key() );
-        i->second->setWriterData( new RegisteredFieldData( prop,
-                                                           prop == Vocabulary::RDF::type()
-                                                           ? QVariant::Invalid
-                                                           : d->literalType( i->second->properties() ) ) );
-    }
-}
-
-
-void Strigi::Soprano::IndexWriter::releaseWriterData( const Strigi::FieldRegister& f )
-{
-    map<string, RegisteredField*>::const_iterator i;
-    map<string, RegisteredField*>::const_iterator end = f.fields().end();
-    for (i = f.fields().begin(); i != end; ++i) {
-        delete static_cast<RegisteredFieldData*>( i->second->writerData() );
-        i->second->setWriterData( 0 );
-    }
-}
diff -Naur nepomuk/strigibackend/sopranoindexwriter.cpp~ nepomuk/strigibackend/sopranoindexwriter.cpp~
--- nepomuk/strigibackend/sopranoindexwriter.cpp~	1970-01-01 01:00:00.000000000 +0100
+++ nepomuk/strigibackend/sopranoindexwriter.cpp~	2008-09-01 14:33:17.000000000 +0200
@@ -0,0 +1,521 @@
+/*
+   Copyright (C) 2007-2008 Sebastian Trueg <trueg@kde.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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 General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+ */
+
+#include "sopranoindexwriter.h"
+#include "util.h"
+
+#include <Soprano/Soprano>
+#include <Soprano/Index/IndexFilterModel>
+#include <Soprano/Index/CLuceneIndex>
+#include <Soprano/Vocabulary/RDF>
+#include <Soprano/Vocabulary/Xesam>
+#include <Soprano/LiteralValue>
+
+#include <QtCore/QList>
+#include <QtCore/QHash>
+#include <QtCore/QVariant>
+#include <QtCore/QFileInfo>
+#include <QtCore/QFile>
+#include <QtCore/QUrl>
+#include <QtCore/QDebug>
+#include <QtCore/QThread>
+#include <QtCore/QDateTime>
+
+#include <KUrl>
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <map>
+#include <sstream>
+#include <algorithm>
+
+
+// IMPORTANT: strings in Strigi are apparently UTF8! Except for file names. Those are in local encoding.
+
+using namespace Soprano;
+
+
+uint qHash( const std::string& s )
+{
+    return qHash( s.c_str() );
+}
+
+namespace {
+    QString findArchivePath( const QString& path ) {
+        QString p( path );
+        int i = 0;
+        while ( ( i = p.lastIndexOf( '/' ) ) > 0 ) {
+            p.truncate( i );
+            if ( QFileInfo( p ).isFile() ) {
+                return p;
+            }
+        }
+        return QString();
+    }
+
+    QUrl createResourceUri( const Strigi::AnalysisResult* idx ) {
+        // HACK: Strigi includes analysers that recurse into tar or zip archives and index
+        // the files therein. In KDE these files could perfectly be handled through kio slaves
+        // such as tar:/ or zip:/
+        // Here we try to use KDE-compatible URIs for these indexed files the best we can
+        // everything else defaults to file:/
+        QUrl uri;
+        QString path = QFile::decodeName( idx->path().c_str() );
+        if ( KUrl::isRelativeUrl( path ) )
+            uri = QUrl::fromLocalFile( QFileInfo( path ).absoluteFilePath() );
+        else
+            uri = KUrl( path ); // try to support http and other URLs
+
+        if ( idx->depth() > 0 ) {
+            QString archivePath = findArchivePath( path );
+            if ( QFile::exists( archivePath ) ) {
+                if ( archivePath.endsWith( QLatin1String( ".tar" ) ) ||
+                     archivePath.endsWith( QLatin1String( ".tar.gz" ) ) ||
+                     archivePath.endsWith( QLatin1String( ".tar.bz2" ) ) ||
+		     archivePath.endsWith( QLatin1String( ".tar.lzma" ) ) ) {
+                    uri.setScheme( "tar" );
+                }
+                else if ( archivePath.endsWith( QLatin1String( ".zip" ) ) ) {
+                    uri.setScheme( "zip" );
+                }
+            }
+        }
+
+        // fallback for all
+        if ( uri.scheme().isEmpty() ) {
+            uri.setScheme( "file" );
+        }
+
+        return uri;
+    }
+
+    class FileMetaData
+    {
+    public:
+        // caching URIs for little speed improvement
+        QUrl fileUri;
+        QUrl context;
+        std::string content;
+    };
+
+    class RegisteredFieldData
+    {
+    public:
+        RegisteredFieldData( const QUrl& prop, QVariant::Type t )
+            : property( prop ),
+              dataType( t ),
+              isRdfType( prop == Vocabulary::RDF::type() ) {
+        }
+
+        QUrl property;
+        QVariant::Type dataType;
+        bool isRdfType;
+    };
+}
+
+
+class Strigi::Soprano::IndexWriter::Private
+{
+public:
+    Private()
+        : indexTransactionID( 0 ) {
+        literalTypes[FieldRegister::stringType] = QVariant::String;
+        literalTypes[FieldRegister::floatType] = QVariant::Double;
+        literalTypes[FieldRegister::integerType] = QVariant::Int;
+        literalTypes[FieldRegister::binaryType] = QVariant::ByteArray;
+        literalTypes[FieldRegister::datetimeType] = QVariant::DateTime; // Strigi encodes datetime as unsigned integer, i.e. addValue( ..., uint )
+    }
+
+    QVariant::Type literalType( const Strigi::FieldProperties& strigiType ) {
+        // it looks as if the typeUri can contain arbitrary values, URIs or stuff like "string"
+        QHash<std::string, QVariant::Type>::const_iterator it = literalTypes.find( strigiType.typeUri() );
+        if ( it == literalTypes.constEnd() ) {
+            return LiteralValue::typeFromDataTypeUri( QUrl::fromEncoded( strigiType.typeUri().c_str() ) );
+        }
+        else {
+            return *it;
+        }
+    }
+
+    LiteralValue createLiteralValue( QVariant::Type type,
+                                     const unsigned char* data,
+                                     uint32_t size ) {
+        QString value = QString::fromUtf8( ( const char* )data, size );
+        if ( type == QVariant::DateTime ) { // dataTime is stored as integer in strigi!
+            return LiteralValue( QDateTime::fromTime_t( value.toUInt() ) );
+        }
+        else if ( type != QVariant::Invalid ) {
+            return LiteralValue::fromString( value, type );
+        }
+        else {
+            // we default to string
+            return LiteralValue( value );
+        }
+    }
+
+//    ::Soprano::Index::IndexFilterModel* repository;
+    ::Soprano::Model* repository;
+    int indexTransactionID;
+
+private:
+    QHash<std::string, QVariant::Type> literalTypes;
+};
+
+
+Strigi::Soprano::IndexWriter::IndexWriter( ::Soprano::Model* model )
+    : Strigi::IndexWriter()
+{
+//    qDebug() << "IndexWriter::IndexWriter in thread" << QThread::currentThread();
+    d = new Private;
+    d->repository = model;
+    Util::storeStrigiMiniOntology( d->repository );
+//    qDebug() << "IndexWriter::IndexWriter done in thread" << QThread::currentThread();
+}
+
+
+Strigi::Soprano::IndexWriter::~IndexWriter()
+{
+    delete d;
+}
+
+
+void Strigi::Soprano::IndexWriter::commit()
+{
+}
+
+
+// delete all indexed data for the files listed in entries
+void Strigi::Soprano::IndexWriter::deleteEntries( const std::vector<std::string>& entries )
+{
+//    qDebug() << "IndexWriter::deleteEntries in thread" << QThread::currentThread();
+
+    QString systemLocationUri = Util::fieldUri( FieldRegister::pathFieldName ).toString();
+    for ( unsigned int i = 0; i < entries.size(); ++i ) {
+        QString path = QString::fromUtf8( entries[i].c_str() );
+        QString query = QString( "select ?g where { ?r <%1> \"%2\"^^<%3> . "
+                                 "?g <http://www.strigi.org/fields#indexGraphFor> ?r . }" )
+                        .arg( systemLocationUri )
+                        .arg( path )
+                        .arg( Vocabulary::XMLSchema::string().toString() );
+
+//        qDebug() << "deleteEntries query:" << query;
+
+        QueryResultIterator result = d->repository->executeQuery( query, ::Soprano::Query::QueryLanguageSparql );
+        if ( result.next() ) {
+            Node indexGraph = result.binding( "g" );
+            result.close();
+
+//            qDebug() << "Found indexGraph to delete:" << indexGraph;
+
+            // delete the indexed data
+            d->repository->removeContext( indexGraph );
+
+            // delete the metadata
+            d->repository->removeAllStatements( Statement( indexGraph, Node(), Node() ) );
+        }
+    }
+}
+
+
+void Strigi::Soprano::IndexWriter::deleteAllEntries()
+{
+//    qDebug() << "IndexWriter::deleteAllEntries in thread" << QThread::currentThread();
+
+    // query all index graphs (FIXME: would a type derived from nrl:Graph be better than only the predicate?)
+    QString query = QString( "select ?g where { ?g <http://www.strigi.org/fields#indexGraphFor> ?r . }" );
+
+    qDebug() << "deleteAllEntries query:" << query;
+
+    QueryResultIterator result = d->repository->executeQuery( query, ::Soprano::Query::QUERY_LANGUAGE_SPARQL );
+    QList<Node> allIndexGraphs = result.iterateBindings( "g" ).allNodes();
+    for ( QList<Node>::const_iterator it = allIndexGraphs.constBegin(); it != allIndexGraphs.constEnd(); ++it ) {
+        Node indexGraph = *it;
+
+        qDebug() << "Found indexGraph to delete:" << indexGraph;
+
+        // delete the indexed data
+        d->repository->removeContext( indexGraph );
+
+        // delete the metadata
+        d->repository->removeAllStatements( Statement( indexGraph, Node(), Node() ) );
+    }
+}
+
+
+// called for each indexed file
+void Strigi::Soprano::IndexWriter::startAnalysis( const AnalysisResult* idx )
+{
+    if ( idx->depth() > 0 ) {
+        return;
+    }
+
+//    qDebug() << "IndexWriter::startAnalysis in thread" << QThread::currentThread();
+    FileMetaData* data = new FileMetaData();
+    data->fileUri = createResourceUri( idx );
+
+    // let's check if we already have data on the file
+    StatementIterator it = d->repository->listStatements( Node(),
+                                                          QUrl::fromEncoded( "http://www.strigi.org/fields#indexGraphFor", QUrl::StrictMode ), // FIXME: put the URI somewhere else
+                                                          data->fileUri );
+    if ( it.next() ) {
+        data->context = it.current().subject().uri();
+    }
+    else {
+        data->context = Util::uniqueUri( "http://www.strigi.org/contexts/", d->repository );
+    }
+
+//    qDebug() << "Starting analysis for" << data->fileUri << "in thread" << QThread::currentThread();
+
+    idx->setWriterData( data );
+}
+
+
+void Strigi::Soprano::IndexWriter::addText( const AnalysisResult* idx, const char* text, int32_t length )
+{
+    if ( idx->depth() > 0 ) {
+        return;
+    }
+
+    FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
+    md->content.append( text, length );
+}
+
+
+void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
+                                             const RegisteredField* field,
+                                             const std::string& value )
+{
+    if ( idx->depth() > 0 ) {
+        return;
+    }
+
+//    qDebug() << "IndexWriter::addValue in thread" << QThread::currentThread();
+    if ( value.length() > 0 ) {
+        FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
+        RegisteredFieldData* rfd = reinterpret_cast<RegisteredFieldData*>( field->writerData() );
+
+        if ( rfd->isRdfType ) {
+
+            // Strigi uses rdf:type improperly since it stores the value as a string. We have to
+            // make sure it is a resource. The problem is that this results in the type not being
+            // indexed properly. Thus, it cannot be searched with normal lucene queries.
+            // That is why we need to introduce a stringType property
+
+            d->repository->addStatement( Statement( md->fileUri,
+                                                    ::Soprano::Vocabulary::RDF::type(),
+                                                    QUrl::fromEncoded( value.c_str(), QUrl::StrictMode ), // fromEncoded is faster than the plain constructor and all Xesam URIs work here
+                                                    md->context) );
+            d->repository->addStatement( Statement( md->fileUri,
+                                                    QUrl::fromEncoded( "http://strigi.sourceforge.net/fields#rdf-string-type", QUrl::StrictMode ),
+                                                    LiteralValue( QString::fromUtf8( value.c_str() ) ),
+                                                    md->context) );
+        }
+
+        else {
+            d->repository->addStatement( Statement( md->fileUri,
+                                                    rfd->property,
+                                                    d->createLiteralValue( rfd->dataType, ( unsigned char* )value.c_str(), value.length() ),
+                                                    md->context) );
+        }
+    }
+//    qDebug() << "IndexWriter::addValue done in thread" << QThread::currentThread();
+}
+
+
+// the main addValue method
+void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
+                                             const RegisteredField* field,
+                                             const unsigned char* data,
+                                             uint32_t size )
+{
+    addValue( idx, field, std::string( ( const char* )data, size ) );
+}
+
+
+void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult*, const RegisteredField*,
+                                             const std::string&, const std::string& )
+{
+    // we do not support map types
+}
+
+
+void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
+                                             const RegisteredField* field,
+                                             uint32_t value )
+{
+    if ( idx->depth() > 0 ) {
+        return;
+    }
+
+//    qDebug() << "IndexWriter::addValue in thread" << QThread::currentThread();
+    FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
+    RegisteredFieldData* rfd = reinterpret_cast<RegisteredFieldData*>( field->writerData() );
+
+    LiteralValue val( value );
+    if ( field->type() == FieldRegister::datetimeType ) {
+        val = QDateTime::fromTime_t( value );
+    }
+
+    d->repository->addStatement( Statement( md->fileUri,
+                                            rfd->property,
+                                            val,
+                                            md->context) );
+//    qDebug() << "IndexWriter::addValue done in thread" << QThread::currentThread();
+}
+
+
+void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
+                                             const RegisteredField* field,
+                                             int32_t value )
+{
+    if ( idx->depth() > 0 ) {
+        return;
+    }
+
+//    qDebug() << "IndexWriter::addValue in thread" << QThread::currentThread();
+    FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
+    RegisteredFieldData* rfd = reinterpret_cast<RegisteredFieldData*>( field->writerData() );
+
+    d->repository->addStatement( Statement( md->fileUri,
+                                            rfd->property,
+                                            LiteralValue( value ),
+                                            md->context) );
+//    qDebug() << "IndexWriter::addValue done in thread" << QThread::currentThread();
+}
+
+
+void Strigi::Soprano::IndexWriter::addValue( const AnalysisResult* idx,
+                                             const RegisteredField* field,
+                                             double value )
+{
+    if ( idx->depth() > 0 ) {
+        return;
+    }
+
+//    qDebug() << "IndexWriter::addValue in thread" << QThread::currentThread();
+    FileMetaData* md = reinterpret_cast<FileMetaData*>( idx->writerData() );
+    RegisteredFieldData* rfd = reinterpret_cast<RegisteredFieldData*>( field->writerData() );
+
+    d->repository->addStatement( Statement( md->fileUri,
+                                            rfd->property,
+                                            LiteralValue( value ),
+                                            md->context) );
+//    qDebug() << "IndexWriter::addValue done in thread" << QThread::currentThread();
+}
+
+
+void Strigi::Soprano::IndexWriter::addTriplet( const std::string& subject,
+                                               const std::string& predicate, const std::string& object )
+{
+    // PROBLEM: which named graph (context) should we use here? Create a new one for each triple? Use one until the
+    // next commit()?
+
+    // FIXME: create an NRL metadata graph
+    d->repository->addStatement( Statement( Node( QUrl( QString::fromUtf8( subject.c_str() ) ) ),
+                                            Node( QUrl( QString::fromUtf8( predicate.c_str() ) ) ),
+                                            Node( QUrl( QString::fromUtf8( object.c_str() ) ) ),
+                                            Node() ) );
+}
+
+
+// called after each indexed file
+void Strigi::Soprano::IndexWriter::finishAnalysis( const AnalysisResult* idx )
+{
+    if ( idx->depth() > 0 ) {
+        return;
+    }
+
+//    qDebug() << "IndexWriter::finishAnalysis in thread" << QThread::currentThread();
+    FileMetaData* md = static_cast<FileMetaData*>( idx->writerData() );
+
+    if ( md->content.length() > 0 ) {
+        d->repository->addStatement( Statement( md->fileUri,
+                                                Vocabulary::Xesam::asText(),
+                                                LiteralValue( QString::fromUtf8( md->content.c_str() ) ),
+                                                md->context ) );
+    }
+
+    // Strigi only indexes files and extractors mostly (if at all) store the xesam:DataObject type (i.e. the contents)
+    // Thus, here we go the easy way and mark each indexed file as a xesam:File.
+    if ( QFileInfo( QFile::decodeName( idx->path().c_str() ) ).isDir() )
+        d->repository->addStatement( Statement( md->fileUri,
+                                                Vocabulary::RDF::type(),
+                                                Vocabulary::Xesam::Folder(),
+                                                md->context ) );
+    else
+        d->repository->addStatement( Statement( md->fileUri,
+                                                Vocabulary::RDF::type(),
+                                                Vocabulary::Xesam::File(),
+                                                md->context ) );
+
+
+    // create the provedance data for the data graph
+    // TODO: add more data at some point when it becomes of interest
+    QUrl metaDataContext = Util::uniqueUri( "http://www.strigi.org/graphMetaData/", d->repository );
+    d->repository->addStatement( Statement( md->context,
+                                            Vocabulary::RDF::type(),
+                                            Vocabulary::NRL::InstanceBase(),
+                                            metaDataContext ) );
+    d->repository->addStatement( Statement( md->context,
+                                            Vocabulary::NAO::created(),
+                                            LiteralValue( QDateTime::currentDateTime() ),
+                                            metaDataContext ) );
+    d->repository->addStatement( Statement( md->context,
+                                            QUrl::fromEncoded( "http://www.strigi.org/fields#indexGraphFor", QUrl::StrictMode ), // FIXME: put the URI somewhere else
+                                            md->fileUri,
+                                            metaDataContext ) );
+    d->repository->addStatement( Statement( metaDataContext,
+                                            Vocabulary::RDF::type(),
+                                            Vocabulary::NRL::GraphMetadata(),
+                                            metaDataContext ) );
+
+    // cleanup
+    delete md;
+    idx->setWriterData( 0 );
+
+//    qDebug() << "IndexWriter::finishAnalysis done in thread" << QThread::currentThread();
+}
+
+
+void Strigi::Soprano::IndexWriter::initWriterData( const Strigi::FieldRegister& f )
+{
+    map<string, RegisteredField*>::const_iterator i;
+    map<string, RegisteredField*>::const_iterator end = f.fields().end();
+    for (i = f.fields().begin(); i != end; ++i) {
+        QUrl prop = Util::fieldUri( i->second->key() );
+        i->second->setWriterData( new RegisteredFieldData( prop,
+                                                           prop == Vocabulary::RDF::type()
+                                                           ? QVariant::Invalid
+                                                           : d->literalType( i->second->properties() ) ) );
+    }
+}
+
+
+void Strigi::Soprano::IndexWriter::releaseWriterData( const Strigi::FieldRegister& f )
+{
+    map<string, RegisteredField*>::const_iterator i;
+    map<string, RegisteredField*>::const_iterator end = f.fields().end();
+    for (i = f.fields().begin(); i != end; ++i) {
+        delete static_cast<RegisteredFieldData*>( i->second->writerData() );
+        i->second->setWriterData( 0 );
+    }
+}
diff -Naur nepomuk/strigibackend/util.cpp nepomuk/strigibackend/util.cpp
--- nepomuk/strigibackend/util.cpp	2008-05-07 11:05:22.000000000 +0200
+++ nepomuk/strigibackend/util.cpp	2008-09-01 14:33:17.000000000 +0200
@@ -31,6 +31,10 @@
 #include <Soprano/Index/CLuceneIndex>
 #include <Soprano/Model>
 #include <Soprano/Vocabulary/RDF>
+#include <Soprano/Vocabulary/RDFS>
+#include <Soprano/Vocabulary/Xesam>
+#include <Soprano/Vocabulary/NRL>
+#include <Soprano/Vocabulary/XMLSchema>
 
 
 #define STRIGI_NS "http://www.strigi.org/data#"
@@ -81,7 +85,7 @@
         return TString::fromUtf8( field.c_str() );
     }
     else if ( QString( field.c_str() ) == ::Soprano::Vocabulary::RDF::type().toString() ) {
-        // see sopranoindexwriter:addValue for details in this conversion
+        // see sopranoindexwriter:addValue for details on this conversion
         static TString strigiType( "http://strigi.sourceforge.net/fields#rdf-string-type" );
         return strigiType;
     }
@@ -124,3 +128,41 @@
         return Strigi::Variant();
     }
 }
+
+
+void Strigi::Soprano::Util::storeStrigiMiniOntology( ::Soprano::Model* model )
+{
+    // we use some nice URI here although we still have the STRIGI_NS for backwards comp
+    // at some point (if parentUrl will not be moved to xesam) we should move to a proper onto
+
+    QUrl graph( "http://nepomuk.kde.org/ontologies/2008/07/24/strigi/metadata" );
+    ::Soprano::Statement parentUrlProp( fieldUri( FieldRegister::parentLocationFieldName ),
+                                        ::Soprano::Vocabulary::RDF::type(),
+                                        ::Soprano::Vocabulary::RDF::Property(),
+                                        graph );
+    ::Soprano::Statement parentUrlRange( parentUrlProp.subject(),
+                                         ::Soprano::Vocabulary::RDFS::range(),
+                                         ::Soprano::Vocabulary::XMLSchema::string(),
+                                         graph );
+    ::Soprano::Statement parentUrlDomain( parentUrlProp.subject(),
+                                          ::Soprano::Vocabulary::RDFS::domain(),
+                                          ::Soprano::Vocabulary::Xesam::File(),
+                                          graph );
+    ::Soprano::Statement metaDataType( graph,
+                                       ::Soprano::Vocabulary::RDF::type(),
+                                       ::Soprano::Vocabulary::NRL::Ontology(),
+                                       graph );
+
+    if ( !model->containsStatement( parentUrlProp ) ) {
+        model->addStatement( parentUrlProp );
+    }
+    if ( !model->containsStatement( parentUrlRange ) ) {
+        model->addStatement( parentUrlRange );
+    }
+    if ( !model->containsStatement( parentUrlDomain ) ) {
+        model->addStatement( parentUrlDomain );
+    }
+    if ( !model->containsStatement( metaDataType ) ) {
+        model->addStatement( metaDataType );
+    }
+}
diff -Naur nepomuk/strigibackend/util.h nepomuk/strigibackend/util.h
--- nepomuk/strigibackend/util.h	2008-05-07 11:05:22.000000000 +0200
+++ nepomuk/strigibackend/util.h	2008-09-01 14:33:17.000000000 +0200
@@ -34,14 +34,20 @@
     class Variant;
 
     namespace Soprano {
-	namespace Util {
-	    QUrl fieldUri( const std::string& s );
-	    QUrl fileUrl( const std::string& filename );
-	    std::string fieldName( const QUrl& uri );
-	    TString convertSearchField( const std::string& field );
-	    QUrl uniqueUri( const QString& ns, ::Soprano::Model* model );
-	    Strigi::Variant nodeToVariant( const ::Soprano::Node& node );
-	}
+        namespace Util {
+            QUrl fieldUri( const std::string& s );
+            QUrl fileUrl( const std::string& filename );
+            std::string fieldName( const QUrl& uri );
+            TString convertSearchField( const std::string& field );
+            QUrl uniqueUri( const QString& ns, ::Soprano::Model* model );
+            Strigi::Variant nodeToVariant( const ::Soprano::Node& node );
+
+            /**
+             * For now only stores the parentUrl property so it can be
+             * searched.
+             */
+            void storeStrigiMiniOntology( ::Soprano::Model* model );
+        }
     }
 }