Index: nepomuk/test/queryserializertest.cpp =================================================================== --- nepomuk/test/queryserializertest.cpp (révision 0) +++ nepomuk/test/queryserializertest.cpp (révision 0) @@ -0,0 +1,261 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "queryserializertest.h" + +#include "filequery.h" +#include "literalterm.h" +#include "resourceterm.h" +#include "andterm.h" +#include "orterm.h" +#include "negationterm.h" +#include "comparisonterm.h" +#include "resourcetypeterm.h" +#include "optionalterm.h" +#include "nie.h" +#include "nfo.h" +#include "nco.h" +#include "pimo.h" +#include "property.h" + +#include <QtTest> + +#include <Soprano/LiteralValue> +#include <Soprano/Node> +#include <Soprano/Vocabulary/NAO> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/XMLSchema> + +#include <kdebug.h> +#include <qtest_kde.h> + +Q_DECLARE_METATYPE( Nepomuk::Query::Query ) + +using namespace Nepomuk::Query; + + +void QuerySerializerTest::testSerialization_data() +{ + QTest::addColumn<Nepomuk::Query::Query>( "query" ); + + QTest::newRow( "simple literal query" ) + << Query( LiteralTerm( "Hello" ) ); + + QTest::newRow( "simple literal query with space" ) + << Query( LiteralTerm( "Hello World" ) ); + QTest::newRow( "simple literal query with space and quotes" ) + << Query( LiteralTerm( "'Hello World'" ) ); + QTest::newRow( "simple literal query with space and quotes" ) + << Query( LiteralTerm( "\"Hello World\"" ) ); + + QTest::newRow( "literal query with depth 2" ) + << Query( AndTerm( LiteralTerm("foo"), ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ComparisonTerm( Soprano::Vocabulary::NAO::prefLabel(), LiteralTerm("bar") ) ) ) ); + + QTest::newRow( "type query" ) + << Query( ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) ); + + QTest::newRow( "negated resource type" ) + << Query( NegationTerm::negateTerm( ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) ) ); + + QDateTime now = QDateTime::currentDateTime(); + QTest::newRow( "nie:lastModified" ) + << Query( ComparisonTerm( Nepomuk::Vocabulary::NIE::lastModified(), LiteralTerm( now ), ComparisonTerm::GreaterOrEqual ) ); + + QTest::newRow( "hastag with literal term" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), LiteralTerm( QLatin1String("nepomuk")) ) ); + + QTest::newRow( "hastag with resource" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) )); + + QTest::newRow( "negated hastag with resource" ) + << Query( NegationTerm::negateTerm(ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) ))); + + QTest::newRow( "comparators <" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ) ); + + QTest::newRow( "comparators <=" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::SmallerOrEqual ) ); + + QTest::newRow( "comparators >" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Greater ) ); + + QTest::newRow( "comparators >=" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::GreaterOrEqual ) ); + + QTest::newRow( "inverted comparisonterm" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) ).inverted() ); + + QTest::newRow( "optional term" ) + << Query(OptionalTerm::optionalizeTerm(ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) ))); + + QTest::newRow( "and term" ) + << Query( AndTerm( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Greater ), + ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm(QUrl("nepomuk:/test")) ) ) ); + + ComparisonTerm setVarNameTerm1( Soprano::Vocabulary::NAO::hasTag(), ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) ); + setVarNameTerm1.setVariableName("myvar"); + QTest::newRow( "set variable name 1" ) + << Query( setVarNameTerm1 ); + + ComparisonTerm setVarNameTerm2( Soprano::Vocabulary::NAO::hasTag(), LiteralTerm( "nepomuk" ) ); + setVarNameTerm2.setVariableName( "myvar" ); + QTest::newRow( "set variable name 2" ) + << Query( setVarNameTerm2 ); + + ComparisonTerm setVarNameTerm3( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ); + setVarNameTerm3.setVariableName("myvar"); + QTest::newRow( "set variable name 3" ) + << Query( setVarNameTerm3 ); + + ComparisonTerm setVarNameTerm4( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ); + setVarNameTerm3.setVariableName("myvar" ); + setVarNameTerm3.setAggregateFunction(ComparisonTerm::Count); + QTest::newRow( "set variable name 4 (with aggregate function count)" ) + << Query( setVarNameTerm3 ); + + ComparisonTerm orderByTerm1( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ); + orderByTerm1.setSortWeight( 1 ); + QTest::newRow( "order by 1" ) + << Query( orderByTerm1 ); + + orderByTerm1.setSortWeight( 1, Qt::DescendingOrder ); + QTest::newRow( "order by 2" ) + << Query( orderByTerm1 ); + + ComparisonTerm orderByTerm2( Soprano::Vocabulary::NAO::prefLabel(), LiteralTerm("hello") ); + orderByTerm2.setSortWeight( 2 ); + + QTest::newRow( "order by 3" ) + << Query( AndTerm( orderByTerm1, orderByTerm2 ) ); + + orderByTerm1.setVariableName("myvar"); + QTest::newRow( "order by 4" ) + << Query( orderByTerm1 ); + + QTest::newRow( "ComparisonTerm with invalid property" ) + << Query( ComparisonTerm( Nepomuk::Types::Property(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) )); + + QTest::newRow( "ComparisonTerm with invalid subterm" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), Term() ) ); + + QTest::newRow( "ComparisonTerm with invalid property and subterm" ) + << Query( ComparisonTerm( Nepomuk::Types::Property(), Term() ) ); + + ComparisonTerm orderByTerm5( Soprano::Vocabulary::NAO::numericRating(), Term() ); + orderByTerm5.setSortWeight( 1 ); + orderByTerm5.setAggregateFunction( ComparisonTerm::Max ); + QTest::newRow( "order by 5 (with aggregate function and invalid subterm)" ) + << Query( orderByTerm5 ); + + orderByTerm5.setVariableName( "myvar" ); + QTest::newRow( "order by 5 (with aggregate function and invalid subterm and varname)" ) + << Query( orderByTerm5 ); + + orderByTerm5.setVariableName( QString() ); + orderByTerm5.setAggregateFunction( ComparisonTerm::DistinctCount ); + QTest::newRow( "order by 5 (with aggregate function and invalid subterm and varname)" ) + << Query( orderByTerm5 ); + + + FileQuery fileQuery( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm(QUrl("nepomuk:/res/foobar")) ) ); + QTest::newRow( "file query" ) + << Query(fileQuery); + + fileQuery.setFileMode(FileQuery::QueryFiles); + QTest::newRow( "file query (only files)" ) + << Query(fileQuery); + + fileQuery.setFileMode(FileQuery::QueryFolders); + QTest::newRow( "file query (only folders)" ) + << Query(fileQuery); + + // + // A more complex example + // + QUrl res("nepomuk:/res/foobar"); + AndTerm mainTerm; + OrTerm typeOr; + typeOr.addSubTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NFO::RasterImage() ) ); + typeOr.addSubTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NFO::Audio() ) ); + mainTerm.addSubTerm( typeOr ); + mainTerm.addSubTerm( NegationTerm::negateTerm( ComparisonTerm( Nepomuk::Types::Property(), ResourceTerm( res ) ).inverted() ) ); + + // an empty comparisonterm results in "?r ?v1 ?v2" + ComparisonTerm ct; + + // change the var name: "?r ?v1 ?cnt" + ct.setVariableName( "cnt" ); + ct.setAggregateFunction( ComparisonTerm::Count ); + + // by default all have 0, Query::toSparqlQuery will add ORDER BY for all ComparisonTerm with sortweight != 0 + ct.setSortWeight( 1, Qt::DescendingOrder ); + + mainTerm.addSubTerm(ct.inverted()); + + QTest::newRow( "a complex one" ) + << Query( mainTerm ); + + + // try to combine it all + Query allQuery( OrTerm( + NegationTerm::negateTerm( ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) ), + OptionalTerm::optionalizeTerm( LiteralTerm("hello 3") ), + AndTerm( + LiteralTerm("hello"), + LiteralTerm("hello 2"), + ResourceTerm( QUrl("nepomuk:/res/foobar") ), + ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ), + ComparisonTerm( Nepomuk::Types::Property(), + ResourceTerm( QUrl("nepomuk:/res/foobar") ) ), + ComparisonTerm( Nepomuk::Types::Property(), + OrTerm( ResourceTerm( QUrl("nepomuk:/res/foobar1") ), + ResourceTerm( QUrl("nepomuk:/res/foobar2") ) ) ) ) ) ); + allQuery.setLimit( 10 ); + allQuery.setOffset( 2 ); + + QTest::newRow( "all" ) + << allQuery; + + FileQuery fileAllQuery( allQuery ); + fileAllQuery.addIncludeFolder( KUrl("/home/trueg/1") ); + fileAllQuery.addIncludeFolder( KUrl("/home/trueg/2") ); + fileAllQuery.addExcludeFolder( KUrl("/home/trueg/3") ); + fileAllQuery.addExcludeFolder( KUrl("/home/trueg/4") ); + QTest::newRow( "fileall" ) + << Query(fileAllQuery); +} + + +void QuerySerializerTest::testSerialization() +{ + QFETCH( Nepomuk::Query::Query, query ); + +// qDebug() << "Before:" << serializeQuery( query ); +// qDebug() << "After: " << serializeQuery( parseQuery( serializeQuery( query ) ) ); + + QCOMPARE( Query::fromString( query.toString() ), query ); + QCOMPARE( Term::fromString( query.term().toString() ), query.term() ); + QCOMPARE( Query::fromString( query.toString() ).toSparqlQuery(), query.toSparqlQuery() ); +} + +QTEST_KDEMAIN_CORE( QuerySerializerTest ) + +#include "queryserializertest.moc" Modification de propriétés sur nepomuk/test/queryserializertest.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/queryserializertest.h =================================================================== --- nepomuk/test/queryserializertest.h (révision 0) +++ nepomuk/test/queryserializertest.h (révision 0) @@ -0,0 +1,38 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _NEPOMUK_QUERY_SERIALIZER_TEST_H_ +#define _NEPOMUK_QUERY_SERIALIZER_TEST_H_ + +#include <QtCore/QObject> + +class QuerySerializerTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void testSerialization_data(); + void testSerialization(); +}; + +#endif + + Modification de propriétés sur nepomuk/test/queryserializertest.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/querytest.cpp =================================================================== --- nepomuk/test/querytest.cpp (révision 0) +++ nepomuk/test/querytest.cpp (révision 0) @@ -0,0 +1,429 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "querytest.h" + +#include "query.h" +#include "filequery.h" +#include "query_p.h" +#include "literalterm.h" +#include "resourceterm.h" +#include "andterm.h" +#include "orterm.h" +#include "negationterm.h" +#include "comparisonterm.h" +#include "resourcetypeterm.h" +#include "optionalterm.h" +#include "nie.h" +#include "nfo.h" +#include "nco.h" +#include "pimo.h" +#include "property.h" + +#include <QtTest> + +#include <Soprano/LiteralValue> +#include <Soprano/Node> +#include <Soprano/Vocabulary/NAO> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/RDF> +#include <Soprano/Vocabulary/XMLSchema> + +#include <kdebug.h> +#include <qtest_kde.h> + +Q_DECLARE_METATYPE( Nepomuk::Query::Query ) + +using namespace Nepomuk::Query; + + +// this is a tricky one as we nee to match the variable names and order of the queries exactly. +void QueryTest::testToSparql_data() +{ + QTest::addColumn<Nepomuk::Query::Query>( "query" ); + QTest::addColumn<QString>( "queryString" ); + + QTest::newRow( "simple literal query" ) + << Query( LiteralTerm( "Hello" ) ) + << QString::fromLatin1( "select distinct ?r (?v5) as ?_n_f_t_m_s_ where { { ?r ?v1 ?v2 . ?v2 bif:contains \"'Hello'\" OPTION (score ?v5) . } " + "UNION { ?r ?v1 ?v3 . ?v3 ?v4 ?v2 . ?v4 %1 %2 . ?v2 bif:contains \"'Hello'\" OPTION (score ?v5) . } . }" ) + .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subPropertyOf()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label()) ); + + QString helloWorldQuery = QString::fromLatin1( "select distinct ?r (?v5) as ?_n_f_t_m_s_ where { { ?r ?v1 ?v2 . ?v2 bif:contains \"'Hello World'\" OPTION (score ?v5) . } " + "UNION " + "{ ?r ?v1 ?v3 . ?v3 ?v4 ?v2 . ?v4 %1 %2 . ?v2 bif:contains \"'Hello World'\" OPTION (score ?v5) . } . }" ) + .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subPropertyOf()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label()) ); + QTest::newRow( "simple literal query with space" ) + << Query( LiteralTerm( "Hello World" ) ) + << helloWorldQuery; + QTest::newRow( "simple literal query with space and quotes" ) + << Query( LiteralTerm( "'Hello World'" ) ) + << helloWorldQuery; + QTest::newRow( "simple literal query with space and quotes" ) + << Query( LiteralTerm( "\"Hello World\"" ) ) + << helloWorldQuery; + + QTest::newRow( "literal query with depth 2" ) + << Query( AndTerm( LiteralTerm("foo"), ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ComparisonTerm( Soprano::Vocabulary::NAO::prefLabel(), LiteralTerm("bar") ) ) ) ) + << QString::fromLatin1("select distinct ?r ((?v8/2)+?v5) as ?_n_f_t_m_s_ where { " + "{ { ?r ?v1 ?v2 . ?v2 bif:contains \"'foo'\" OPTION (score ?v5) . } " + "UNION " + "{ ?r ?v1 ?v3 . ?v3 ?v4 ?v2 . " + "?v4 <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#label> . ?v2 bif:contains \"'foo'\" OPTION (score ?v5) . } . " + "?r <http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag> ?v6 . ?v6 <http://www.semanticdesktop.org/ontologies/2007/08/15/nao#prefLabel> ?v7 . " + "?v7 bif:contains \"'bar'\" OPTION (score ?v8) . } . }"); + + QTest::newRow( "type query" ) + << Query( ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) ) + << QString::fromLatin1("select distinct ?r where { ?r a ?v1 . ?v1 %1 %2 . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subClassOf())) + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::Tag())); + + QTest::newRow( "negated resource type" ) + << Query( NegationTerm::negateTerm( ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) ) ) + << QString::fromLatin1("select distinct ?r where { FILTER(!bif:exists((select (1) where { ?r a ?v1 . ?v1 %1 %2 . }))) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subClassOf())) + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::Tag())); + + QDateTime now = QDateTime::currentDateTime(); + QTest::newRow( "nie:lastModified" ) + << Query( ComparisonTerm( Nepomuk::Vocabulary::NIE::lastModified(), LiteralTerm( now ), ComparisonTerm::GreaterOrEqual ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1>=%2) . }") + .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NIE::lastModified()), + Soprano::Node::literalToN3(now)); + + QTest::newRow( "hastag with literal term" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), LiteralTerm( QLatin1String("nepomuk")) ) ) + << QString::fromLatin1("select distinct ?r (?v4) as ?_n_f_t_m_s_ where { ?r %1 ?v1 . ?v1 ?v2 ?v3 . ?v2 %2 %3 . ?v3 bif:contains \"'nepomuk'\" OPTION (score ?v4) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())) + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subPropertyOf())) + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label())); + + QTest::newRow( "hastag with resource" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) )) + << QString::fromLatin1("select distinct ?r where { ?r %1 <nepomuk:/res/foobar> . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + QTest::newRow( "negated hastag with resource" ) + << Query( NegationTerm::negateTerm(ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) ))) + << QString::fromLatin1("select distinct ?r where { FILTER(!bif:exists((select (1) where { ?r %1 <nepomuk:/res/foobar> . }))) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + QTest::newRow( "comparators <" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "comparators <=" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::SmallerOrEqual ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1<=\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "comparators >" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Greater ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1>\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "comparators >=" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::GreaterOrEqual ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1>=\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "inverted comparisonterm" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) ).inverted() ) + << QString::fromLatin1("select distinct ?r where { <nepomuk:/res/foobar> %1 ?r . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + QTest::newRow( "optional term" ) + << Query(OptionalTerm::optionalizeTerm(ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) ))) + << QString::fromLatin1("select distinct ?r where { OPTIONAL { ?r %1 <nepomuk:/res/foobar> . } }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + QTest::newRow( "and term" ) + << Query( AndTerm( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Greater ), + ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm(QUrl("nepomuk:/test")) ) ) ) + << QString::fromLatin1("select distinct ?r where { { ?r %1 ?v1 . FILTER(?v1>\"4\"^^%2) . ?r %3 <nepomuk:/test> . } . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + ComparisonTerm setVarNameTerm1( Soprano::Vocabulary::NAO::hasTag(), ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) ); + setVarNameTerm1.setVariableName("myvar"); + QTest::newRow( "set variable name 1" ) + << Query( setVarNameTerm1 ) + << QString::fromLatin1("select distinct ?r ?myvar where { ?r %1 ?myvar . ?myvar a ?v1 . ?v1 %2 %3 . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subClassOf()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::Tag())); + + ComparisonTerm setVarNameTerm2( Soprano::Vocabulary::NAO::hasTag(), LiteralTerm( "nepomuk" ) ); + setVarNameTerm2.setVariableName( "myvar" ); + QTest::newRow( "set variable name 2" ) + << Query( setVarNameTerm2 ) + << QString::fromLatin1("select distinct ?r ?myvar (?v3) as ?_n_f_t_m_s_ where { ?r %1 ?myvar . ?myvar ?v1 ?v2 . ?v1 %2 %3 . ?v2 bif:contains \"'nepomuk'\" OPTION (score ?v3) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subPropertyOf()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label())); + + ComparisonTerm setVarNameTerm3( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ); + setVarNameTerm3.setVariableName("myvar"); + QTest::newRow( "set variable name 3" ) + << Query( setVarNameTerm3 ) + << QString::fromLatin1("select distinct ?r ?myvar where { ?r %1 ?myvar . FILTER(?myvar<\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + ComparisonTerm setVarNameTerm4( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ); + setVarNameTerm3.setVariableName("myvar" ); + setVarNameTerm3.setAggregateFunction(ComparisonTerm::Count); + QTest::newRow( "set variable name 4 (with aggregate function count)" ) + << Query( setVarNameTerm3 ) + << QString::fromLatin1("select distinct ?r count(?v1) as ?myvar where { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + ComparisonTerm orderByTerm1( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ); + orderByTerm1.setSortWeight( 1 ); + QTest::newRow( "order by 1" ) + << Query( orderByTerm1 ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . } ORDER BY ASC ( ?v1 )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + orderByTerm1.setSortWeight( 1, Qt::DescendingOrder ); + QTest::newRow( "order by 2" ) + << Query( orderByTerm1 ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . } ORDER BY DESC ( ?v1 )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + ComparisonTerm orderByTerm2( Soprano::Vocabulary::NAO::prefLabel(), LiteralTerm("hello") ); + orderByTerm2.setSortWeight( 2 ); + + QTest::newRow( "order by 3" ) + << Query( AndTerm( orderByTerm1, orderByTerm2 ) ) + << QString::fromLatin1("select distinct ?r (?v3) as ?_n_f_t_m_s_ where { { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . ?r %3 ?v2 . ?v2 bif:contains \"'hello'\" OPTION (score ?v3) . } . } ORDER BY ASC ( ?v2 ) DESC ( ?v1 )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::prefLabel()) ); + + orderByTerm1.setVariableName("myvar"); + QTest::newRow( "order by 4" ) + << Query( orderByTerm1 ) + << QString::fromLatin1("select distinct ?r ?myvar where { ?r %1 ?myvar . FILTER(?myvar<\"4\"^^%2) . } ORDER BY DESC ( ?myvar )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "ComparisonTerm with invalid property" ) + << Query( ComparisonTerm( Nepomuk::Types::Property(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) )) + << QString::fromLatin1("select distinct ?r where { ?r ?v1 <nepomuk:/res/foobar> . }"); + + QTest::newRow( "ComparisonTerm with invalid subterm" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), Term() ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + QTest::newRow( "ComparisonTerm with invalid property and subterm" ) + << Query( ComparisonTerm( Nepomuk::Types::Property(), Term() ) ) + << QString::fromLatin1("select distinct ?r where { ?r ?v1 ?v2 . }"); + + ComparisonTerm orderByTerm5( Soprano::Vocabulary::NAO::numericRating(), Term() ); + orderByTerm5.setSortWeight( 1 ); + orderByTerm5.setAggregateFunction( ComparisonTerm::Max ); + QTest::newRow( "order by 5 (with aggregate function and invalid subterm)" ) + << Query( orderByTerm5 ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . } ORDER BY ASC ( max(?v1) )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()) ); + + orderByTerm5.setVariableName( "myvar" ); + QTest::newRow( "order by 5 (with aggregate function and invalid subterm and varname)" ) + << Query( orderByTerm5 ) + << QString::fromLatin1("select distinct ?r max(?v1) as ?myvar where { ?r %1 ?v1 . } ORDER BY ASC ( ?myvar )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()) ); + + orderByTerm5.setVariableName( QString() ); + orderByTerm5.setAggregateFunction( ComparisonTerm::DistinctCount ); + QTest::newRow( "order by 5 (with aggregate function and invalid subterm and varname)" ) + << Query( orderByTerm5 ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . } ORDER BY ASC ( count(distinct ?v1) )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()) ); + + + FileQuery fileQuery( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm(QUrl("nepomuk:/res/foobar")) ) ); + QTest::newRow( "file query" ) + << Query(fileQuery) + << QString::fromLatin1("select distinct ?r where { { ?r %1 <nepomuk:/res/foobar> . { ?r %2 %3 . } UNION { ?r %2 %4 . } . } . }") + .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDF::type()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::FileDataObject()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::Folder()) ); + + fileQuery.setFileMode(FileQuery::QueryFiles); + QTest::newRow( "file query (only files)" ) + << Query(fileQuery) + << QString::fromLatin1("select distinct ?r where { { ?r %1 <nepomuk:/res/foobar> . ?r %2 %3 . FILTER(!bif:exists((select (1) where { ?r %2 %4 . }))) . } . }") + .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDF::type()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::FileDataObject()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::Folder()) ); + + fileQuery.setFileMode(FileQuery::QueryFolders); + QTest::newRow( "file query (only folders)" ) + << Query(fileQuery) + << QString::fromLatin1("select distinct ?r where { { ?r %1 <nepomuk:/res/foobar> . ?r %2 %3 . FILTER(!bif:exists((select (1) where { ?r %2 %4 . }))) . } . }") + .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDF::type()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::Folder()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::FileDataObject()) ); + + // + // A more complex example + // + QUrl res("nepomuk:/res/foobar"); + AndTerm mainTerm; + OrTerm typeOr; + typeOr.addSubTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NFO::RasterImage() ) ); + typeOr.addSubTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NFO::Audio() ) ); + mainTerm.addSubTerm( typeOr ); + mainTerm.addSubTerm( NegationTerm::negateTerm( ComparisonTerm( Nepomuk::Types::Property(), ResourceTerm( res ) ).inverted() ) ); + + // an empty comparisonterm results in "?r ?v1 ?v2" + ComparisonTerm ct; + + // change the var name: "?r ?v1 ?cnt" + ct.setVariableName( "cnt" ); + ct.setAggregateFunction( ComparisonTerm::Count ); + + // by default all have 0, Query::toSparqlQuery will add ORDER BY for all ComparisonTerm with sortweight != 0 + ct.setSortWeight( 1, Qt::DescendingOrder ); + + mainTerm.addSubTerm(ct.inverted()); + + QString sparql = QString::fromLatin1("select distinct ?r count(?v5) as ?cnt where { { " + "{ ?r a ?v1 . ?v1 %1 %2 . } UNION { ?r a ?v2 . ?v2 %1 %3 . } . " + "FILTER(!bif:exists((select (1) where { <nepomuk:/res/foobar> ?v3 ?r . }))) . " + "?r ?v4 ?v5 . } . } ORDER BY DESC ( ?cnt )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subClassOf()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::RasterImage()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::Audio())); + + QTest::newRow( "a complex one" ) + << Query( mainTerm ) + << sparql; + +#if 0 +// subquery to match grouding occurrences of nepomuk:/TEST + ComparisonTerm goterm( Nepomuk::Vocabulary::PIMO::groundingOccurrence(), + ResourceTerm( Nepomuk::Resource( QUrl("nepomuk:/TEST")) ) ); + goterm.setInverted(true); + +// combine that with only nco:PersonContacts + AndTerm pcgoterm( ResourceTypeTerm( Nepomuk::Vocabulary::NCO::PersonContact() ), + goterm ); + +// now look for im accounts of those grounding occurrences (pcgoterm will become the subject of this comparison, +// thus the comparison will match the im accounts) + ComparisonTerm impcgoterm( Nepomuk::Vocabulary::NCO::hasIMAccount(), + pcgoterm ); + impcgoterm.setInverted(true); + +// now look for all buddies of the accounts + ComparisonTerm buddyTerm( QUrl("http://kde.org/telepathy#isBuddyOf")/*Nepomuk::Vocabulary::Telepathy::isBuddyOf()*/, + impcgoterm ); + +// set the name of the variable (i.e. the buddies) to be able to match it later + buddyTerm.setVariableName("t"); + +// same comparison, other property, but use the same variable name to match them + ComparisonTerm ppterm( QUrl("http://kde.org/telepathy#publishesPresenceTo")/*Nepomuk::Vocabulary::Telepathy::publishesPresenceTo()*/, + ResourceTypeTerm( Nepomuk::Vocabulary::NCO::IMAccount() ) ); + ppterm.setVariableName("t"); + +// combine both to complete the matching of the im account ?account + AndTerm accountTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NCO::IMAccount() ), + buddyTerm, + ppterm ); + +// match the account and select it for the results + ComparisonTerm imaccountTerm( Nepomuk::Vocabulary::NCO::hasIMAccount(), accountTerm ); + imaccountTerm.setVariableName("account"); + +// and finally the exclusion of those person contacts that already have a pimo person attached + ComparisonTerm personTerm( Nepomuk::Vocabulary::PIMO::groundingOccurrence(), + ResourceTypeTerm( Nepomuk::Vocabulary::PIMO::Person() ) ); + personTerm.setInverted(true); + +// and all combined + Query theQuery( AndTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NCO::PersonContact() ), + imaccountTerm, + NegationTerm::negateTerm(personTerm)) ); + + + QTest::newRow( "and term" ) + << theQuery + << QString::fromLatin1(""); +#endif +} + + +void QueryTest::testToSparql() +{ + QFETCH( Nepomuk::Query::Query, query ); + QFETCH( QString, queryString ); + +// kDebug() << query; + QCOMPARE( query.toSparqlQuery().simplified(), queryString ); +} + + +void QueryTest::testOptimization() +{ + LiteralTerm literal("Hello World"); + AndTerm and1; + and1.addSubTerm(literal); + Term optimized = QueryPrivate::optimizeTerm(and1); + QVERIFY(optimized.isLiteralTerm()); + + AndTerm and2; + and2.addSubTerm(and1); + optimized = QueryPrivate::optimizeTerm(and2); + QVERIFY(optimized.isLiteralTerm()); + + Term invalidTerm; + and2.addSubTerm(invalidTerm); + optimized = QueryPrivate::optimizeTerm(and2); + QVERIFY(optimized.isLiteralTerm()); + + and1.setSubTerms(QList<Term>() << invalidTerm); + and2.setSubTerms(QList<Term>() << and1 << literal); + optimized = QueryPrivate::optimizeTerm(and2); + QVERIFY(optimized.isLiteralTerm()); +} + +QTEST_KDEMAIN_CORE( QueryTest ) + +#include "querytest.moc" Modification de propriétés sur nepomuk/test/querytest.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/ratingpaintertestapp.cpp =================================================================== --- nepomuk/test/ratingpaintertestapp.cpp (révision 0) +++ nepomuk/test/ratingpaintertestapp.cpp (révision 0) @@ -0,0 +1,14 @@ +#include "ratingpaintertestwidget.h" + +#include <QApplication> +#include <kcomponentdata.h> + + +int main( int argc, char** argv ) +{ + QApplication app( argc, argv ); + KComponentData data( "NepomukRatingPainterTest" ); + RatingPainterTestWidget ratingW; + ratingW.show(); + return app.exec(); +} Modification de propriétés sur nepomuk/test/ratingpaintertestapp.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/querytest.h =================================================================== --- nepomuk/test/querytest.h (révision 0) +++ nepomuk/test/querytest.h (révision 0) @@ -0,0 +1,39 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _NEPOMUK_QUERY_TEST_H_ +#define _NEPOMUK_QUERY_TEST_H_ + +#include <QtCore/QObject> + +class QueryTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void testToSparql_data(); + void testToSparql(); + void testOptimization(); +}; + +#endif + + Modification de propriétés sur nepomuk/test/querytest.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/testbase.cpp =================================================================== --- nepomuk/test/testbase.cpp (révision 0) +++ nepomuk/test/testbase.cpp (révision 0) @@ -0,0 +1,51 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * + * 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 Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING.LIB" for the exact licensing terms. + */ + +#include "testbase.h" + +#include "resource.h" +#include "resourcemanager.h" + +#include <Soprano/Soprano> + +#include <ktempdir.h> + +void TestBase::initTestCase() +{ + m_tmpDir = new KTempDir(); + const Soprano::Backend* backend = Soprano::PluginManager::instance()->discoverBackendByName("virtuoso"); + m_model = backend->createModel( Soprano::BackendSettings() << Soprano::BackendSetting(Soprano::BackendOptionStorageDir, m_tmpDir->name() )); + Nepomuk::ResourceManager::instance()->setOverrideMainModel( m_model ); +} + + +void TestBase::cleanupTestCase() +{ + Nepomuk::ResourceManager::instance()->setOverrideMainModel( 0 ); + delete m_model; + delete m_tmpDir; +} + + +void TestBase::init() +{ + m_model->removeAllStatements(); +} + + +void TestBase::cleanup() +{ +} + +#include "testbase.moc" Modification de propriétés sur nepomuk/test/testbase.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/ratingpaintertestwidget.cpp =================================================================== --- nepomuk/test/ratingpaintertestwidget.cpp (révision 0) +++ nepomuk/test/ratingpaintertestwidget.cpp (révision 0) @@ -0,0 +1,138 @@ +#include "ratingpaintertestwidget.h" +#include "kratingwidget.h" + +#include <QtGui/QGridLayout> +#include <QtGui/QVBoxLayout> +#include <QtGui/QComboBox> +#include <QtGui/QCheckBox> +#include <QtGui/QLabel> +#include <QtGui/QPushButton> + +#include <kicon.h> +#include <kicondialog.h> +#include <knuminput.h> + + +RatingPainterTestWidget::RatingPainterTestWidget() + : QWidget( 0 ) +{ + QVBoxLayout* layout = new QVBoxLayout( this ); + m_ratingWidget = new KRatingWidget( this ); + m_ratingWidget->setFrameStyle( QFrame::StyledPanel|QFrame::Sunken ); + m_checkHalfSteps = new QCheckBox( "Enable half steps", this ); + m_checkEnalbed = new QCheckBox( "Rating disabled", this ); + m_spinMaxRating = new KIntSpinBox( this ); + m_spinRating = new KIntSpinBox( this ); + m_spinSpacing = new KIntSpinBox( this ); + + m_comboAlignmentH = new QComboBox( this ); + m_comboAlignmentV = new QComboBox( this ); + + m_buttonIcon = new QPushButton( "Change Icon...", this ); + + m_comboAlignmentH->addItem( "Left" ); + m_comboAlignmentH->addItem( "Right" ); + m_comboAlignmentH->addItem( "Center" ); + m_comboAlignmentH->addItem( "Justify" ); + + m_comboAlignmentV->addItem( "Top" ); + m_comboAlignmentV->addItem( "Bottom" ); + m_comboAlignmentV->addItem( "Center" ); + + layout->addWidget( m_ratingWidget, 1 ); + layout->addWidget( new QLabel( "Alignment:" ) ); + layout->addWidget( m_comboAlignmentH ); + layout->addWidget( m_comboAlignmentV ); + layout->addWidget( m_checkHalfSteps ); + layout->addWidget( m_checkEnalbed ); + + QHBoxLayout* ratingLayout = new QHBoxLayout; + ratingLayout->addWidget( new QLabel( "Rating:", this ) ); + ratingLayout->addWidget( m_spinRating ); + layout->addLayout( ratingLayout ); + + QHBoxLayout* maxRatingLayout = new QHBoxLayout; + maxRatingLayout->addWidget( new QLabel( "Max Rating:", this ) ); + maxRatingLayout->addWidget( m_spinMaxRating ); + layout->addLayout( maxRatingLayout ); + + QHBoxLayout* spacingLayout = new QHBoxLayout; + spacingLayout->addWidget( new QLabel( "Spacing:", this ) ); + spacingLayout->addWidget( m_spinSpacing ); + layout->addLayout( spacingLayout ); + + layout->addWidget( m_buttonIcon ); + + connect( m_comboAlignmentH, SIGNAL( activated( int ) ), + this, SLOT( slotAlignmentChanged() ) ); + connect( m_comboAlignmentV, SIGNAL( activated( int ) ), + this, SLOT( slotAlignmentChanged() ) ); + connect( m_spinMaxRating, SIGNAL(valueChanged(int)), + m_ratingWidget, SLOT(setMaxRating(int)) ); + connect( m_spinRating, SIGNAL(valueChanged(int)), + m_ratingWidget, SLOT(setRating(int)) ); + connect( m_spinSpacing, SIGNAL(valueChanged(int)), + m_ratingWidget, SLOT(setSpacing(int)) ); + connect( m_checkHalfSteps, SIGNAL(toggled(bool)), + m_ratingWidget, SLOT(setHalfStepsEnabled(bool)) ); + connect( m_checkEnalbed, SIGNAL(toggled(bool)), + m_ratingWidget, SLOT(setDisabled(bool)) ); + connect( m_ratingWidget, SIGNAL(ratingChanged(int)), + m_spinRating, SLOT(setValue(int)) ); + connect( m_buttonIcon, SIGNAL(clicked()), + this, SLOT(slotChangeIcon()) ); + + m_comboAlignmentH->setCurrentIndex( 2 ); + m_comboAlignmentV->setCurrentIndex( 2 ); + m_spinMaxRating->setValue( m_ratingWidget->maxRating() ); + m_spinRating->setValue( m_ratingWidget->rating() ); + m_spinSpacing->setValue( m_ratingWidget->spacing() ); + m_checkHalfSteps->setChecked( m_ratingWidget->halfStepsEnabled() ); +} + + +RatingPainterTestWidget::~RatingPainterTestWidget() +{ +} + + +void RatingPainterTestWidget::slotAlignmentChanged() +{ + Qt::Alignment align = Qt::AlignLeft; + if ( m_comboAlignmentH->currentText() == "Left" ) { + align = Qt::AlignLeft; + } + else if ( m_comboAlignmentH->currentText() == "Right" ) { + align = Qt::AlignRight; + } + else if ( m_comboAlignmentH->currentText() == "Center" ) { + align = Qt::AlignHCenter; + } + else if ( m_comboAlignmentH->currentText() == "Justify" ) { + align = Qt::AlignJustify; + } + + if ( m_comboAlignmentV->currentText() == "Top" ) { + align |= Qt::AlignTop; + } + else if ( m_comboAlignmentV->currentText() == "Bottom" ) { + align |= Qt::AlignBottom; + } + else if ( m_comboAlignmentV->currentText() == "Center" ) { + align |= Qt::AlignVCenter; + } + + m_ratingWidget->setAlignment( align ); +} + + +void RatingPainterTestWidget::slotChangeIcon() +{ + QString icon = KIconDialog::getIcon(); + if ( !icon.isEmpty() ) { + m_ratingWidget->setIcon( KIcon( icon ) ); + m_buttonIcon->setIcon( KIcon( icon ) ); + } +} + +#include "ratingpaintertestwidget.moc" Modification de propriétés sur nepomuk/test/ratingpaintertestwidget.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/testbase.h =================================================================== --- nepomuk/test/testbase.h (révision 0) +++ nepomuk/test/testbase.h (révision 0) @@ -0,0 +1,40 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * + * 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 Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING.LIB" for the exact licensing terms. + */ + +#ifndef _TEST_BASE_H_ +#define _TEST_BASE_H_ + +#include <QtTest/QtTest> + +class KTempDir; +namespace Soprano { +class Model; +} + +class TestBase : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + virtual void init(); + virtual void cleanup(); + +private: + KTempDir* m_tmpDir; + Soprano::Model* m_model; +}; + +#endif Modification de propriétés sur nepomuk/test/testbase.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/tagwidgettest.cpp =================================================================== --- nepomuk/test/tagwidgettest.cpp (révision 0) +++ nepomuk/test/tagwidgettest.cpp (révision 0) @@ -0,0 +1,95 @@ +#include "tagwidgettest.h" +#include "tagwidget.h" + +#include <QVBoxLayout> +#include <QCheckBox> +#include <kdebug.h> + + +TagWidgetTest::TagWidgetTest() + : QWidget() +{ + m_tagWidget = new Nepomuk::TagWidget(this); + m_tagWidget->setMaxTagsShown(8); + QVBoxLayout* lay = new QVBoxLayout(this); + lay->addWidget(m_tagWidget); + connect(m_tagWidget, SIGNAL(tagClicked(Nepomuk::Tag)), + this, SLOT(slotTagClicked(Nepomuk::Tag))); + connect(m_tagWidget, SIGNAL(selectionChanged(QList<Nepomuk::Tag>)), + this, SLOT(slotSelectionChanged(QList<Nepomuk::Tag>))); + + QCheckBox* box = new QCheckBox( "Minimode", this ); + connect(box, SIGNAL(toggled(bool)), this, SLOT(enableMinimode(bool))); + lay->addWidget(box); + + box = new QCheckBox( "Align Right", this ); + connect(box, SIGNAL(toggled(bool)), this, SLOT(alignRight(bool))); + lay->addWidget(box); + + box = new QCheckBox( "Disable clicking", this ); + connect(box, SIGNAL(toggled(bool)), this, SLOT(disableClicking(bool))); + lay->addWidget(box); + + box = new QCheckBox( "Read only", this ); + connect(box, SIGNAL(toggled(bool)), this, SLOT(setReadOnly(bool))); + lay->addWidget(box); +} + +TagWidgetTest::~TagWidgetTest() +{ +} + + +void TagWidgetTest::slotTagClicked(const Nepomuk::Tag& tag) +{ + kDebug() << "Tag clicked:" << tag.resourceUri() << tag.genericLabel(); +} + + +void TagWidgetTest::slotSelectionChanged( const QList<Nepomuk::Tag>& tags ) +{ + QStringList ts; + foreach(const Nepomuk::Tag& tag, tags) + ts << tag.genericLabel(); + kDebug() << "Selection changed:" << ts; +} + + +void TagWidgetTest::enableMinimode( bool enable ) +{ + Nepomuk::TagWidget::ModeFlags flags = m_tagWidget->modeFlags(); + if( enable ) { + flags |= Nepomuk::TagWidget::MiniMode; + flags &= ~Nepomuk::TagWidget::StandardMode; + } + else { + flags |= Nepomuk::TagWidget::StandardMode; + flags &= ~Nepomuk::TagWidget::MiniMode; + } + m_tagWidget->setModeFlags( flags ); +} + + +void TagWidgetTest::alignRight( bool enable ) +{ + if( enable ) + m_tagWidget->setAlignment( Qt::AlignRight ); + else + m_tagWidget->setAlignment( Qt::AlignLeft ); +} + + +void TagWidgetTest::disableClicking( bool enable ) +{ + Nepomuk::TagWidget::ModeFlags flags = m_tagWidget->modeFlags(); + m_tagWidget->setModeFlags( enable ? flags | Nepomuk::TagWidget::DisableTagClicking : flags & ~Nepomuk::TagWidget::DisableTagClicking ); +} + + +void TagWidgetTest::setReadOnly( bool enable ) +{ + Nepomuk::TagWidget::ModeFlags flags = m_tagWidget->modeFlags(); + m_tagWidget->setModeFlags( enable ? flags | Nepomuk::TagWidget::ReadOnly : flags & ~Nepomuk::TagWidget::ReadOnly ); +} + +#include "tagwidgettest.moc" Modification de propriétés sur nepomuk/test/tagwidgettest.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/ratingpaintertestwidget.h =================================================================== --- nepomuk/test/ratingpaintertestwidget.h (révision 0) +++ nepomuk/test/ratingpaintertestwidget.h (révision 0) @@ -0,0 +1,39 @@ +#ifndef _RATING_PAINTER_TEST_WIDGET_H_ +#define _RATING_PAINTER_TEST_WIDGET_H_ + +#include <QtGui/QWidget> + +class QComboBox; +class QCheckBox; +class KRatingWidget; +class KIntSpinBox; +class QPushButton; + +class RatingPainterTestWidget : public QWidget +{ + Q_OBJECT + +public: + RatingPainterTestWidget(); + ~RatingPainterTestWidget(); + +private Q_SLOTS: + void slotChangeIcon(); + void slotAlignmentChanged(); + +private: + KIntSpinBox* m_spinMaxRating; + KIntSpinBox* m_spinRating; + KIntSpinBox* m_spinSpacing; + + QComboBox* m_comboAlignmentH; + QComboBox* m_comboAlignmentV; + QCheckBox* m_checkHalfSteps; + QCheckBox* m_checkEnalbed; + + QPushButton* m_buttonIcon; + + KRatingWidget* m_ratingWidget; +}; + +#endif Modification de propriétés sur nepomuk/test/ratingpaintertestwidget.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/tagwidgetapp.cpp =================================================================== --- nepomuk/test/tagwidgetapp.cpp (révision 0) +++ nepomuk/test/tagwidgetapp.cpp (révision 0) @@ -0,0 +1,14 @@ +#include "tagwidgettest.h" + +#include <QApplication> +#include <kcomponentdata.h> + + +int main( int argc, char** argv ) +{ + QApplication app( argc, argv ); + KComponentData data( "TagWidgetApp" ); + TagWidgetTest tw; + tw.show(); + return app.exec(); +} Modification de propriétés sur nepomuk/test/tagwidgetapp.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/queryparsertest.cpp =================================================================== --- nepomuk/test/queryparsertest.cpp (révision 0) +++ nepomuk/test/queryparsertest.cpp (révision 0) @@ -0,0 +1,184 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "queryparsertest.h" +#include "queryparser.h" +#include "query.h" +#include "literalterm.h" +#include "resourceterm.h" +#include "andterm.h" +#include "orterm.h" +#include "negationterm.h" +#include "comparisonterm.h" + +#include <QtTest> +#include <qtest_kde.h> + +#include "ktempdir.h" + +#include <Soprano/LiteralValue> +#include <Soprano/Node> +#include <Soprano/StorageModel> +#include <Soprano/Backend> +#include <Soprano/PluginManager> +#include <Soprano/Vocabulary/NAO> +#include <Soprano/Vocabulary/NRL> +#include <Soprano/Vocabulary/RDF> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/XMLSchema> + +#include "property.h" +#include "resourcemanager.h" + +Q_DECLARE_METATYPE( Nepomuk::Query::Query ) + +using namespace Nepomuk::Query; + +void QueryParserTest::initTestCase() +{ + // we need to use a Virtuoso model as tmp model since redland misses important SPARQL features + // that are used by libnepomuk below + const Soprano::Backend* backend = Soprano::PluginManager::instance()->discoverBackendByName( "virtuosobackend" ); + QVERIFY( backend ); + m_storageDir = new KTempDir(); + m_model = backend->createModel( Soprano::BackendSettings() << Soprano::BackendSetting(Soprano::BackendOptionStorageDir, m_storageDir->name()) ); + QVERIFY( m_model ); + + // we create one fake ontology + QUrl graph("graph:/onto"); + m_model->addStatement( graph, Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::NRL::Ontology(), graph ); + + m_model->addStatement( QUrl("onto:/label"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDF::Property(), graph ); + m_model->addStatement( QUrl("onto:/label"), Soprano::Vocabulary::RDFS::label(), Soprano::LiteralValue::createPlainLiteral("label"), graph ); + m_model->addStatement( QUrl("onto:/label"), Soprano::Vocabulary::RDFS::range(), Soprano::Vocabulary::XMLSchema::string(), graph ); + + m_model->addStatement( QUrl("onto:/hasTag"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDF::Property(), graph ); + m_model->addStatement( QUrl("onto:/hasTag"), Soprano::Vocabulary::RDFS::label(), Soprano::LiteralValue::createPlainLiteral("has tag"), graph ); + m_model->addStatement( QUrl("onto:/hasTag"), Soprano::Vocabulary::RDFS::range(), QUrl("onto:/Tag"), graph ); + + m_model->addStatement( QUrl("onto:/tag"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDF::Property(), graph ); + m_model->addStatement( QUrl("onto:/tag"), Soprano::Vocabulary::RDFS::label(), Soprano::LiteralValue::createPlainLiteral("hastag"), graph ); + m_model->addStatement( QUrl("onto:/tag"), Soprano::Vocabulary::RDFS::range(), QUrl("onto:/Tag"), graph ); + + m_model->addStatement( QUrl("onto:/Tag"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDFS::Class(), graph ); + + m_model->addStatement( QUrl("onto:/int"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDF::Property(), graph ); + m_model->addStatement( QUrl("onto:/int"), Soprano::Vocabulary::RDFS::label(), Soprano::LiteralValue::createPlainLiteral("int value"), graph ); + m_model->addStatement( QUrl("onto:/int"), Soprano::Vocabulary::RDFS::range(), Soprano::Vocabulary::XMLSchema::integer(), graph ); + + Nepomuk::ResourceManager::instance()->setOverrideMainModel( m_model ); +} + + +void QueryParserTest::cleanupTestCase() +{ + Nepomuk::ResourceManager::instance()->setOverrideMainModel( 0 ); + delete m_model; + delete m_storageDir; +} + + +void QueryParserTest::testQueryParser_data() +{ + QTest::addColumn<QString>( "queryString" ); + QTest::addColumn<Nepomuk::Query::Query>( "query" ); + + // simple literal queries + QTest::newRow( "simple literal query" ) << QString( "Hello" ) << Query( LiteralTerm( "Hello" ) ); + QTest::newRow( "literal with spaces without quotes" ) << QString( "Hello World" ) << Query( AndTerm( LiteralTerm("Hello"), LiteralTerm("World" ) ) ); + QTest::newRow( "literal with spaces with quotes" ) << QString( "'Hello World'" ) << Query( LiteralTerm( "Hello World" ) ); + + // comparison queries + QTest::newRow( "simple field query" ) << QString( "hastag:nepomuk" ) + << Query( OrTerm( ComparisonTerm( QUrl("onto:/hasTag"), LiteralTerm( "nepomuk" ) ), + ComparisonTerm( QUrl("onto:/tag"), LiteralTerm( "nepomuk" ) ) ) ); + QTest::newRow( "simple property query" ) << QString( "<onto:/hasTag>:nepomuk" ) + << Query( ComparisonTerm( QUrl("onto:/hasTag"), LiteralTerm( "nepomuk" ) ) ); +#ifdef QUERY_PARSER_SUPPORTS_RESOURCE_VALUES + QTest::newRow( "resource field query" ) << QString( "hastag:<nepomuk:/Nepomuk>" ) + << Query( ComparisonTerm( "hastag", ResourceTerm( QUrl( "nepomuk:/Nepomuk" ) ) ) ); +#endif + QTest::newRow( "nested resource query" ) << QString( "hastag:(label:nepomuk)" ) + << Query( OrTerm( ComparisonTerm( QUrl("onto:/hasTag"), ComparisonTerm( QUrl("onto:/label"), LiteralTerm( "nepomuk" ) ) ), + ComparisonTerm( QUrl("onto:/tag"), ComparisonTerm( QUrl("onto:/label"), LiteralTerm( "nepomuk" ) ) ) ) ); + QTest::newRow( "int property query" ) << QString( "'int value':42" ) + << Query( ComparisonTerm( QUrl("onto:/int"), LiteralTerm( 42 ) ) ); + QTest::newRow( "int property query 2" ) << QString( "int:\"42\"" ) + << Query( ComparisonTerm( QUrl("onto:/int"), LiteralTerm( 42 ) ) ); + + + // negation + QTest::newRow( "simple negation" ) << QString( "-Hello" ) << Query( NegationTerm::negateTerm( LiteralTerm( "Hello" ) ) ); + QTest::newRow( "field negation" ) << QString( "-label:nepomuk" ) << Query( NegationTerm::negateTerm( ComparisonTerm( QUrl("onto:/label"), LiteralTerm( "nepomuk" ) ) ) ); + + // and query + QTest::newRow( "and: two literals" ) << QString( "Hello World" ) << Query( AndTerm( LiteralTerm( "Hello" ), LiteralTerm( "World" ) ) ); + QTest::newRow( "and: two literals with AND" ) << QString( "Hello AND World" ) << Query( AndTerm( LiteralTerm( "Hello" ), LiteralTerm( "World" ) ) ); + + // or queries + QTest::newRow( "or: two literals" ) << QString( "Hello OR World" ) << Query( OrTerm( LiteralTerm( "Hello" ), LiteralTerm( "World" ) ) ); +} + + +void QueryParserTest::testQueryParser() +{ + QFETCH( QString, queryString ); + QFETCH( Nepomuk::Query::Query, query ); + + Query q = QueryParser::parseQuery( queryString ); + +// qDebug() << "Wanted query:" << query; +// qDebug() << "Parsed query:" << q; + + QCOMPARE( q, query ); +} + + +void QueryParserTest::testQueryParserWithGlobbing_data() +{ + QTest::addColumn<QString>( "queryString" ); + QTest::addColumn<Nepomuk::Query::Query>( "query" ); + + // simple literal queries + QTest::newRow( "simple literal query" ) << QString( "Hello" ) << Query( LiteralTerm( "Hello*" ) ); + QTest::newRow( "simple literal query" ) << QString( "\"Hello\"" ) << Query( LiteralTerm( "Hello" ) ); + QTest::newRow( "literal with spaces without quotes" ) << QString( "Hello World" ) << Query( AndTerm( LiteralTerm("Hello*"), LiteralTerm("World*" ) ) ); + QTest::newRow( "literal with spaces with quotes" ) << QString( "'Hello World'" ) << Query( LiteralTerm( "Hello World" ) ); +} + + +void QueryParserTest::testQueryParserWithGlobbing() +{ + QFETCH( QString, queryString ); + QFETCH( Nepomuk::Query::Query, query ); + + QueryParser p; + Query q = p.parse( queryString, QueryParser::QueryTermGlobbing ); + +// qDebug() << "Wanted query:" << query; +// qDebug() << "Parsed query:" << q; + + QCOMPARE( q, query ); +} + +QTEST_KDEMAIN_CORE( QueryParserTest ) + +#include "queryparsertest.moc" Modification de propriétés sur nepomuk/test/queryparsertest.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/tagwidgettest.h =================================================================== --- nepomuk/test/tagwidgettest.h (révision 0) +++ nepomuk/test/tagwidgettest.h (révision 0) @@ -0,0 +1,30 @@ +#ifndef TAGWIDGETTEST_H +#define TAGWIDGETTEST_H + +#include <QWidget> +#include "tag.h" +#include "tagwidget.h" + +class TagWidgetTest : public QWidget +{ + Q_OBJECT + +public: + TagWidgetTest(); + ~TagWidgetTest(); + +public slots: + void slotTagClicked(const Nepomuk::Tag&); + void slotSelectionChanged( const QList<Nepomuk::Tag>& tags ); + +private slots: + void enableMinimode( bool enable ); + void alignRight( bool enable ); + void disableClicking( bool enable ); + void setReadOnly( bool enable ); + +private: + Nepomuk::TagWidget* m_tagWidget; +}; + +#endif Modification de propriétés sur nepomuk/test/tagwidgettest.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/queryparsertest.h =================================================================== --- nepomuk/test/queryparsertest.h (révision 0) +++ nepomuk/test/queryparsertest.h (révision 0) @@ -0,0 +1,49 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _NEPOMUK_QUERY_PARSER_TEST_H_ +#define _NEPOMUK_QUERY_PARSER_TEST_H_ + +#include <QtCore/QObject> +#include "ktempdir.h" + +#include <Soprano/Model> + +class QueryParserTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void testQueryParser_data(); + void testQueryParser(); + void testQueryParserWithGlobbing_data(); + void testQueryParserWithGlobbing(); + +private: + KTempDir* m_storageDir; + Soprano::Model* m_model; +}; + +#endif + + Modification de propriétés sur nepomuk/test/queryparsertest.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/resourcetest.cpp =================================================================== --- nepomuk/test/resourcetest.cpp (révision 0) +++ nepomuk/test/resourcetest.cpp (révision 0) @@ -0,0 +1,355 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * + * This file is part of the Nepomuk KDE project. + * Copyright (C) 2006-2009 Sebastian Trueg <trueg@kde.org> + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING.LIB" for the exact licensing terms. + */ + +#include "resourcetest.h" +#include "nie.h" + +#include "resource.h" +#include "variant.h" +#include "resourcemanager.h" + +#include <kdebug.h> +#include <ktemporaryfile.h> +#include <qtest_kde.h> + +#include <Soprano/Soprano> + +#include <QtCore/QTextStream> + +using namespace Soprano; +using namespace Nepomuk; + + +void ResourceTest::testResourceStates() +{ + QUrl someUri = ResourceManager::instance()->generateUniqueUri( QString() ); + + Resource r1( someUri ); + Resource r2( someUri ); + + QCOMPARE( r1, r2 ); + + QVERIFY( r1.isValid() ); + QVERIFY( !r1.exists() ); + + r1.setProperty( QUrl("http://test/something"), 12 ); + + QCOMPARE( r1, r2 ); + QVERIFY( r1.exists() ); +} + + +void ResourceTest::testResourceRemoval() +{ + QString testiId( QLatin1String("testi") ); + + Resource res( testiId ); + res.setProperty( QUrl("http://nepomuk.test.org/foo/bar"), "foobar" ); + + QUrl testiUri = res.resourceUri(); + + QVERIFY( !testiUri.isEmpty() ); + + QVERIFY( ResourceManager::instance()->mainModel()->containsAnyStatement( Statement( testiUri, Node(), Node() ) ) ); + + res.remove(); + + QVERIFY( !res.exists() ); + + QVERIFY( !ResourceManager::instance()->mainModel()->containsAnyStatement( Statement( testiUri, Node(), Node() ) ) ); + + // + // test recursive removal + // + Resource res2( "testi2" ); + + res.setProperty( QUrl("http://nepomuk.test.org/foo/bar2"), res2 ); + + QVERIFY( res.exists() ); + QVERIFY( res2.exists() ); + + QVERIFY( ResourceManager::instance()->mainModel()->containsAnyStatement( Statement( res.resourceUri(), QUrl("http://nepomuk.test.org/foo/bar2"), Node(res2.resourceUri()) ) ) ); + + res2.remove(); + + QVERIFY( res.exists() ); + QVERIFY( !res2.exists() ); + + QVERIFY( !ResourceManager::instance()->mainModel()->containsAnyStatement( Statement( res.resourceUri(), QUrl("http://nepomuk.test.org/foo/bar2"), Node(res2.resourceUri()) ) ) ); + + // + // Now make sure the relation between id and URI has actually be removed + // + Resource res3( testiId ); + QVERIFY( res3.resourceUri() != testiUri ); +} + + +void ResourceTest::testProperties() +{ + QUrl r1Uri, r2Uri; + + { + Resource r1( "testi" ); + Resource r2( "testi2" ); + + r1.setProperty( QUrl("http://nepomuk.test.org/int"), 17 ); + r1.setProperty( QUrl("http://nepomuk.test.org/bool1"), true ); + r1.setProperty( QUrl("http://nepomuk.test.org/bool2"), false ); + r1.setProperty( QUrl("http://nepomuk.test.org/double"), 2.2 ); + r1.setProperty( QUrl("http://nepomuk.test.org/string"), "test" ); + r1.setProperty( QUrl("http://nepomuk.test.org/date"), QDate::currentDate() ); + r1.setProperty( QUrl("http://nepomuk.test.org/Resource"), r2 ); + + r1Uri = r1.resourceUri(); + r2Uri = r2.resourceUri(); + } + + QTextStream s(stdout); + foreach( const Statement& st, ResourceManager::instance()->mainModel()->listStatements().allStatements() ) { + s << st << endl; + } + + { + Resource r1( r1Uri ); + Resource r2( r2Uri ); + + QVERIFY( r1.hasProperty( QUrl("http://nepomuk.test.org/int" ) ) ); + QVERIFY( r1.hasProperty( QUrl("http://nepomuk.test.org/bool1" ) ) ); + QVERIFY( r1.hasProperty( QUrl("http://nepomuk.test.org/bool2" ) ) ); + QVERIFY( r1.hasProperty( QUrl("http://nepomuk.test.org/double" ) ) ); + QVERIFY( r1.hasProperty( QUrl("http://nepomuk.test.org/string" ) ) ); + QVERIFY( r1.hasProperty( QUrl("http://nepomuk.test.org/date" ) ) ); + QVERIFY( r1.hasProperty( QUrl("http://nepomuk.test.org/Resource" ) ) ); + + QCOMPARE( r1.property( QUrl("http://nepomuk.test.org/int" ) ).toInt(), 17 ); + QCOMPARE( r1.property( QUrl("http://nepomuk.test.org/bool1" ) ).toBool(), true ); + QCOMPARE( r1.property( QUrl("http://nepomuk.test.org/bool2" ) ).toBool(), false ); + QCOMPARE( r1.property( QUrl("http://nepomuk.test.org/double" ) ).toDouble(), 2.2 ); + QCOMPARE( r1.property( QUrl("http://nepomuk.test.org/string" ) ).toString(), QString("test") ); + QCOMPARE( r1.property( QUrl("http://nepomuk.test.org/date" ) ).toDate(), QDate::currentDate() ); + QCOMPARE( r1.property( QUrl("http://nepomuk.test.org/Resource" ) ).toResource(), r2 ); + + QHash<QString, Variant> allProps = r1.allProperties(); + QCOMPARE( allProps.count(), 10 ); // properties + type + identifier + modification date + QVERIFY( allProps.keys().contains( "http://nepomuk.test.org/int" ) ); + QVERIFY( allProps.keys().contains( "http://nepomuk.test.org/bool1" ) ); + QVERIFY( allProps.keys().contains( "http://nepomuk.test.org/bool2" ) ); + QVERIFY( allProps.keys().contains( "http://nepomuk.test.org/double" ) ); + QVERIFY( allProps.keys().contains( "http://nepomuk.test.org/string" ) ); + QVERIFY( allProps.keys().contains( "http://nepomuk.test.org/date" ) ); + QVERIFY( allProps.keys().contains( "http://nepomuk.test.org/Resource" ) ); + } +} + + +void ResourceTest::testResourceIdentifiers() +{ + QUrl theUri; + { + Resource r1( "wurst" ); + Resource r2( "wurst" ); + + QVERIFY( r1 == r2 ); + + QVERIFY( r1.resourceUri() != QUrl("wurst") ); + + r1.setProperty( QUrl("http://nepomuk.test.org/foo/bar"), "foobar" ); + + theUri = r1.resourceUri(); + + QList<Statement> sl + = ResourceManager::instance()->mainModel()->listStatements( Statement( r1.resourceUri(), Node(), Node() ) ).allStatements(); + + QCOMPARE( sl.count(), 4 ); + + QVERIFY( ResourceManager::instance()->mainModel()->containsAnyStatement( Statement( r1.resourceUri(), + QUrl( Resource::identifierUri() ), + LiteralValue( "wurst" ) ) ) ); + } + + { + Resource r1( theUri ); + Resource r2( "wurst" ); + + QCOMPARE( r1, r2 ); + } +} + + +void ResourceTest::testResourceManager() +{ + { + Resource r1( "res1", QUrl("http://test/mytype" ) ); + Resource r2( "res2", QUrl("http://test/mytype" ) ); + Resource r3( "res3", QUrl("http://test/myothertype" ) ); + Resource r4( "res4", QUrl("http://test/myothertype" ) ); + Resource r5( "res5", QUrl("http://test/myothertype" ) ); + Resource r6( "res6", QUrl("http://test/mythirdtype" ) ); + + QList<Resource> rl = ResourceManager::instance()->allResourcesOfType( QUrl("http://test/mytype") ); + QCOMPARE( rl.count(), 2 ); + QVERIFY( rl.contains( r1 ) && rl.contains( r2 ) ); + + rl = ResourceManager::instance()->allResourcesOfType( r6.resourceType() ); + QCOMPARE( rl.count(), 1 ); + QCOMPARE( rl.first(), r6 ); + + r1.setProperty( QUrl("http://test/prop1"), 42 ); + r3.setProperty( QUrl("http://test/prop1"), 42 ); + r4.setProperty( QUrl("http://test/prop1"), 41 ); + + r3.setProperty( QUrl("http://test/prop2"), r6 ); + r4.setProperty( QUrl("http://test/prop2"), r6 ); + r5.setProperty( QUrl("http://test/prop2"), r6 ); + r6.setProperty( QUrl("http://test/prop2"), r1 ); + + rl = ResourceManager::instance()->allResourcesWithProperty( QUrl("http://test/prop1"), 42 ); + QCOMPARE( rl.count(), 2 ); + QVERIFY( rl.contains( r1 ) && rl.contains( r3 ) ); + + rl = ResourceManager::instance()->allResourcesWithProperty( QUrl("http://test/prop2"), r6 ); + QCOMPARE( rl.count(), 3 ); + QVERIFY( rl.contains( r3 ) && rl.contains( r4 ) && rl.contains( r5 ) ); + } + + { + Resource r1( "res1", QUrl("http://test/mytype" ) ); + Resource r2( "res2", QUrl("http://test/mytype" ) ); + Resource r3( "res3", QUrl("http://test/myothertype" ) ); + Resource r4( "res4", QUrl("http://test/myothertype" ) ); + Resource r5( "res5", QUrl("http://test/myothertype" ) ); + Resource r6( "res6", QUrl("http://test/mythirdtype" ) ); + + QList<Resource> rl = ResourceManager::instance()->allResourcesOfType( QUrl("http://test/mytype" )); + + QCOMPARE( rl.count(), 2 ); + QVERIFY( rl.contains( r1 ) && rl.contains( r2 ) ); + + rl = ResourceManager::instance()->allResourcesOfType( r6.resourceType() ); + QCOMPARE( rl.count(), 1 ); + QCOMPARE( rl.first(), r6 ); + + rl = ResourceManager::instance()->allResourcesWithProperty( QUrl("http://test/prop1"), 42 ); + QCOMPARE( rl.count(), 2 ); + QVERIFY( rl.contains( r1 ) && rl.contains( r3 ) ); + + rl = ResourceManager::instance()->allResourcesWithProperty( QUrl("http://test/prop2"), r6 ); + QCOMPARE( rl.count(), 3 ); + QVERIFY( rl.contains( r3 ) && rl.contains( r4 ) && rl.contains( r5 ) ); + + QVERIFY( r1.hasProperty( QUrl("http://test/prop1" ) ) ); + QVERIFY( r3.hasProperty( QUrl("http://test/prop1" ) ) ); + QVERIFY( r4.hasProperty( QUrl("http://test/prop1" ) ) ); + + QVERIFY( r3.hasProperty( QUrl("http://test/prop2" ) ) ); + QVERIFY( r4.hasProperty( QUrl("http://test/prop2" ) ) ); + QVERIFY( r5.hasProperty( QUrl("http://test/prop2" ) ) ); + QVERIFY( r6.hasProperty( QUrl("http://test/prop2" ) ) ); + + QCOMPARE( r3.property( QUrl("http://test/prop2" )).toResource(), r6 ); + QCOMPARE( r4.property( QUrl("http://test/prop2" )).toResource(), r6 ); + QCOMPARE( r5.property( QUrl("http://test/prop2" )).toResource(), r6 ); + QCOMPARE( r6.property( QUrl("http://test/prop2" )).toResource(), r1 ); + } +} + + +void ResourceTest::testLocalFileUrls() +{ + // create a testfile + KTemporaryFile tmpFile1; + QVERIFY( tmpFile1.open() ); + + QUrl tmpFile1ResUri; + // create a new file resource. Resource should automatically save the nie:url property + { + Resource fileRes( KUrl(tmpFile1.fileName()) ); + fileRes.setRating( 4 ); + + // make sure the nie:url is saved + QVERIFY( ResourceManager::instance()->mainModel()->containsAnyStatement( fileRes.resourceUri(), Nepomuk::Vocabulary::NIE::url(), KUrl(tmpFile1.fileName()) ) ); + + // make sure a proper nepomuk:/ uri has been created + QVERIFY( fileRes.resourceUri().scheme() == QLatin1String("nepomuk") ); + + // make sure the local resource is reused with the file URL + Resource fileRes2( KUrl(tmpFile1.fileName()) ); + QCOMPARE( fileRes.resourceUri(), fileRes2.resourceUri() ); + + // make sure the local resource is reused with the resource URI + Resource fileRes3( fileRes.resourceUri() ); + QCOMPARE( fileRes.resourceUri(), fileRes3.resourceUri() ); + + tmpFile1ResUri = fileRes.resourceUri(); + + // make sure even the string constructor will find the resource again with + Resource fileRes4( KUrl(tmpFile1ResUri).url() ); + fileRes4.setRating(4); + QCOMPARE( fileRes4.resourceUri(), tmpFile1ResUri ); + + // make sure the resource is reused with the local file path + Resource fileRes5( tmpFile1.fileName() ); + fileRes4.setRating(5); + QCOMPARE( fileRes5.resourceUri(), tmpFile1ResUri ); + } + + // clear cache to be sure we call ResourceData::determineUri + ResourceManager::instance()->clearCache(); + + { + // verify that the resource in question is found again + Resource fileRes1( KUrl(tmpFile1.fileName()) ); + QCOMPARE( tmpFile1ResUri, fileRes1.resourceUri() ); + + // make sure the local resource is reused with the resource URI + Resource fileRes2( tmpFile1ResUri ); + QCOMPARE( tmpFile1ResUri, fileRes2.resourceUri() ); + + // create a second test file + KTemporaryFile tmpFile2; + QVERIFY( tmpFile2.open() ); + + // make sure the file:/ URL is reused as resource URI + ResourceManager::instance()->mainModel()->addStatement( KUrl(tmpFile2.fileName()), Nepomuk::Vocabulary::NIE::url(), KUrl(tmpFile2.fileName()) ); + + Resource fileRes3( KUrl(tmpFile2.fileName()) ); + fileRes3.setRating( 4 ); + QCOMPARE( KUrl(fileRes3.resourceUri()), KUrl(tmpFile2.fileName()) ); + + // create a third test file + KTemporaryFile tmpFile3; + QVERIFY( tmpFile3.open() ); + + // add a random bit of information about it + ResourceManager::instance()->mainModel()->addStatement( KUrl(tmpFile3.fileName()), Soprano::Vocabulary::NAO::rating(), Soprano::LiteralValue(4) ); + + Resource fileRes4( KUrl(tmpFile3.fileName()) ); + QCOMPARE( KUrl(fileRes4.resourceUri()).url(), KUrl(tmpFile3.fileName()).url() ); + + // make sure removing the resource results in us not reusing the URI + QUrl fileRes1Uri = fileRes1.resourceUri(); + fileRes1.remove(); + + Resource fileRes5( KUrl(tmpFile1.fileName()) ); + QVERIFY( fileRes1Uri != fileRes5.resourceUri() ); + } + + // clear cache to be sure we do not reuse the cache + ResourceManager::instance()->clearCache(); +} + +QTEST_KDEMAIN(ResourceTest, NoGUI) + +#include "resourcetest.moc" Modification de propriétés sur nepomuk/test/resourcetest.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/resourcetest.h =================================================================== --- nepomuk/test/resourcetest.h (révision 0) +++ nepomuk/test/resourcetest.h (révision 0) @@ -0,0 +1,33 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * + * This file is part of the Nepomuk KDE project. + * Copyright (C) 2006-2009 Sebastian Trueg <trueg@kde.org> + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING.LIB" for the exact licensing terms. + */ + +#ifndef _RESOURCE_TEST_H_ +#define _RESOURCE_TEST_H_ + +#include "testbase.h" + +class ResourceTest : public TestBase +{ + Q_OBJECT + + private Q_SLOTS: + void testResourceStates(); + void testProperties(); + void testResourceRemoval(); + void testResourceIdentifiers(); + void testResourceManager(); + void testLocalFileUrls(); +}; + +#endif Modification de propriétés sur nepomuk/test/resourcetest.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/test/CMakeLists.txt =================================================================== --- nepomuk/test/CMakeLists.txt (révision 0) +++ nepomuk/test/CMakeLists.txt (révision 0) @@ -0,0 +1,87 @@ +project(nepomuk_tests) + +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) + +add_definitions(-DDISABLE_NEPOMUK_LEGACY=1) + +# Query tests +# -------------------------------------------- +kde4_add_unit_test(queryparsertest NOGUI queryparsertest.cpp) +target_link_libraries(queryparsertest nepomuk nepomukquery + ${QT_QTTEST_LIBRARY} + ${SOPRANO_LIBRARIES} + ${KDE4_KDECORE_LIBS} +) + +set(querytest_SRC querytest.cpp ../query/query_p.cpp) +soprano_add_ontology(querytest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nie.trig" "NIE" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(querytest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nfo.trig" "NFO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(querytest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nco.trig" "NCO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(querytest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/pimo/pimo.trig" "PIMO" "Nepomuk::Vocabulary" "trig") +kde4_add_unit_test(querytest NOGUI ${querytest_SRC}) +target_link_libraries(querytest nepomuk nepomukquery + ${QT_QTTEST_LIBRARY} + ${SOPRANO_LIBRARIES} + ${KDE4_KDECORE_LIBS} +) + +set(queryserializertest_SRC queryserializertest.cpp) +soprano_add_ontology(queryserializertest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nie.trig" "NIE" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(queryserializertest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nfo.trig" "NFO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(queryserializertest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nco.trig" "NCO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(queryserializertest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/pimo/pimo.trig" "PIMO" "Nepomuk::Vocabulary" "trig") +kde4_add_unit_test(queryserializertest NOGUI ${queryserializertest_SRC}) +target_link_libraries(queryserializertest nepomuk nepomukquery + ${QT_QTTEST_LIBRARY} + ${SOPRANO_LIBRARIES} + ${KDE4_KDECORE_LIBS} +) + + + +# Resource tests +# -------------------------------------------- + +# The basis of all the tests handling statements +kde4_add_library(nepomuk_testbase STATIC testbase.cpp) +target_link_libraries(nepomuk_testbase nepomuk ${QT_QTCORE_LIBRARY} ${QT_QTTEST_LIBRARY}) + +set(resourcetest_SRCS resourcetest.cpp) +soprano_add_ontology(resourcetest_SRCS + ${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nie.trig + "NIE" + "Nepomuk::Vocabulary" + "trig") +kde4_add_unit_test(resourcetest ${resourcetest_SRCS}) +target_link_libraries(resourcetest + nepomuk_testbase + ${QT_QTCORE_LIBRARY} + ${QT_QTDBUS_LIBRARY} + ${QT_QTTEST_LIBRARY} + ${QT_QTGUI_LIBRARY} + ${SOPRANO_LIBRARIES} + kdecore) + + + +# Ui tests +# -------------------------------------------- +kde4_add_executable(ratingpaintertestapp TEST ratingpaintertestapp.cpp ratingpaintertestwidget.cpp) +target_link_libraries(ratingpaintertestapp + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + ${KDE4_KDECORE_LIBS} + ${KDE4_KDEUI_LIBS} + ${KDE4_KIO_LIBS} + nepomuk + ) + +kde4_add_executable(tagwidgetapp TEST tagwidgetapp.cpp tagwidgettest.cpp) +target_link_libraries(tagwidgetapp + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + ${KDE4_KDECORE_LIBS} + ${KDE4_KDEUI_LIBS} + ${KDE4_KIO_LIBS} + nepomuk + ) Modification de propriétés sur nepomuk/test/CMakeLists.txt ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/ontology_p.h =================================================================== --- nepomuk/types/ontology_p.h (révision 0) +++ nepomuk/types/ontology_p.h (révision 0) @@ -0,0 +1,76 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ONTOLOGY_PRIVATE_H_ +#define _NEPOMUK_ONTOLOGY_PRIVATE_H_ + +#include "entity_p.h" +#include "class.h" +#include "property.h" + +#include <QtCore/QList> +#include <QtCore/QUrl> +#include <QtCore/QSharedData> + +namespace Nepomuk { + namespace Types { + class Class; + class Property; + + class OntologyPrivate : public EntityPrivate + { + public: + OntologyPrivate( const QUrl& uri = QUrl() ); + + QList<Class> classes; + QList<Property> properties; + + // -1 - unknown + // 0 - no + // 1 - yes + int entitiesAvailable; + + bool addProperty( const QUrl& property, const Soprano::Node& value ); + bool addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ); + + void initEntities(); + bool loadEntities(); + + void reset( bool recursive ); + }; + } +} + + +#include "ontology.h" +namespace Nepomuk { + + class Class; + class Property; + + class Ontology::Private : public QSharedData + { + public: + QUrl uri; + QHash<QUrl, const Class*> classes; + QHash<QUrl, const Property*> properties; + }; +} + +#endif Modification de propriétés sur nepomuk/types/ontology_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/nepomukontologyloader.cpp =================================================================== --- nepomuk/types/nepomukontologyloader.cpp (révision 0) +++ nepomuk/types/nepomukontologyloader.cpp (révision 0) @@ -0,0 +1,74 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "nepomukontologyloader.h" +#include "global.h" + +#include <Soprano/Statement> +#include <Soprano/Model> +#include <Soprano/QueryResultIterator> +#include <Soprano/Client/DBusModel> +#include <Soprano/Client/DBusClient> + +#include <QtCore/QDebug> + + +class Nepomuk::NepomukOntologyLoader::Private +{ +public: + Private() + : client("org.kde.NepomukServer") { + } + Soprano::Client::DBusClient client; +}; + + +Nepomuk::NepomukOntologyLoader::NepomukOntologyLoader() + : OntologyLoader(), + d( new Private() ) +{ +} + + +Nepomuk::NepomukOntologyLoader::~NepomukOntologyLoader() +{ + delete d; +} + + +QList<Soprano::Statement> Nepomuk::NepomukOntologyLoader::loadOntology( const QUrl& uri ) +{ + QList<Soprano::Statement> sl; + + if ( Soprano::Model* model = d->client.createModel( "main" ) ) { + // get the complete named graph describing the ontology + Soprano::QueryResultIterator it = model->executeQuery( QString( "construct {?s ?p ?o} " + "where { GRAPH <%1> { ?s ?p ?o } . }" ) + .arg( uri.toString() ), + Soprano::Query::QUERY_LANGUAGE_SPARQL ); + while ( it.next() ) { + sl.append( it.currentStatement() ); + } + } + else { + qDebug() << "(NepomukOntologyLoader) could not find ontology statements for " << uri; + } + + return sl; +} Modification de propriétés sur nepomuk/types/nepomukontologyloader.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/desktopontologyloader.h =================================================================== --- nepomuk/types/desktopontologyloader.h (révision 0) +++ nepomuk/types/desktopontologyloader.h (révision 0) @@ -0,0 +1,62 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_DESKTOP_ONTOLOGY_LOADER_H_ +#define _NEPOMUK_DESKTOP_ONTOLOGY_LOADER_H_ + +#include "ontologyloader.h" +#include "nepomuk_export.h" + +#include <QtCore/QUrl> +#include <QtCore/QList> + +namespace Nepomuk { + /** + * The DesktopOntologyLoader reads ontologies from the installed + * ontologies on the desktop using KStandardDirs. + * All possible ontology installation folders are searched for + * ontology desktop files. + * + * \deprecated Ontologies should now be handled using the classes + * in the Nepomuk::Types namespace. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT DesktopOntologyLoader : public OntologyLoader + { + public: + DesktopOntologyLoader(); + ~DesktopOntologyLoader(); + + /** + * Get a list of all ontology URIs that could be found + * on the system. + */ + QList<QUrl> allOntologies(); + + /** + * reimplemented from OntologyLoader + */ + QList<Soprano::Statement> loadOntology( const QUrl& url ); + + private: + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/types/desktopontologyloader.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/entity_p.h =================================================================== --- nepomuk/types/entity_p.h (révision 0) +++ nepomuk/types/entity_p.h (révision 0) @@ -0,0 +1,89 @@ +/* This file is part of the Nepomuk-KDE libraries + Copyright (c) 2007-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NEPOMUK_ENTITY_PRIVATE_H_ +#define _NEPOMUK_ENTITY_PRIVATE_H_ + +#include "entity.h" + +#include <QtCore/QHash> +#include <QtCore/QString> +#include <QtCore/QUrl> +#include <QtGui/QIcon> +#include <QtCore/QSharedData> +#include <QtCore/QMutex> + +namespace Nepomuk { + namespace Types { + class EntityPrivate : public QSharedData + { + public: + EntityPrivate( const QUrl& uri = QUrl() ); + virtual ~EntityPrivate() {} + + QMutex mutex; + + QUrl uri; + QString label; + QString comment; + QString l10nLabel; + QString l10nComment; + + QIcon icon; + + // -1 - unknown + // 0 - no + // 1 - yes + int available; + int ancestorsAvailable; + + void init(); + void initAncestors(); + + virtual bool addProperty( const QUrl& property, const Soprano::Node& value ) = 0; + virtual bool addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ) = 0; + + virtual void reset( bool recursive ); + + protected: + virtual bool load(); + virtual bool loadAncestors(); + }; + } +} + + + +class Nepomuk::Entity::Private : public QSharedData +{ +public: + Private() + : ontology( 0 ) { + } + + const Ontology* ontology; + + QUrl uri; + QString label; + QString comment; + QHash<QString, QString> l10nLabels; + QHash<QString, QString> l10nComments; +}; + +#endif Modification de propriétés sur nepomuk/types/entity_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/global.cpp =================================================================== --- nepomuk/types/global.cpp (révision 0) +++ nepomuk/types/global.cpp (révision 0) @@ -0,0 +1,38 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "global.h" + +#include <kdebug.h> +#include <kglobal.h> + + +QUrl Nepomuk::extractNamespace( const QUrl& url ) +{ + QByteArray s = url.toEncoded(); + int pos = s.lastIndexOf( '#' ); + if ( pos == -1 ) { + pos = s.lastIndexOf( '/' ); + } + if ( pos == -1 ) { + kError() << " Failed to extract namespace from " << url << endl; + return QUrl(); + } + return QUrl::fromEncoded( s.left( pos+1 ) ); +} Modification de propriétés sur nepomuk/types/global.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/ontologyloader.cpp =================================================================== --- nepomuk/types/ontologyloader.cpp (révision 0) +++ nepomuk/types/ontologyloader.cpp (révision 0) @@ -0,0 +1,35 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "ontologyloader.h" + +class Nepomuk::OntologyLoader::Private +{ +}; + +Nepomuk::OntologyLoader::OntologyLoader() + :d( new Private() ) +{ +} + + +Nepomuk::OntologyLoader::~OntologyLoader() +{ + delete d; +} Modification de propriétés sur nepomuk/types/ontologyloader.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/fileontologyloader.cpp =================================================================== --- nepomuk/types/fileontologyloader.cpp (révision 0) +++ nepomuk/types/fileontologyloader.cpp (révision 0) @@ -0,0 +1,108 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "fileontologyloader.h" + +#include <soprano/soprano.h> + +#include <QtCore/QDebug> +#include <QtCore/QFile> + + +class Nepomuk::FileOntologyLoader::Private +{ +public: + Private() + : serialization( Soprano::SerializationUnknown ) { + } + + QString filename; + Soprano::RdfSerialization serialization; +}; + + +Nepomuk::FileOntologyLoader::FileOntologyLoader() + : OntologyLoader(), + d( new Private() ) +{ +} + + +Nepomuk::FileOntologyLoader::FileOntologyLoader( const QString& filename, Soprano::RdfSerialization serialization ) + : OntologyLoader(), + d( new Private() ) +{ + setFileName( filename ); + setSerialization( serialization ); +} + + +Nepomuk::FileOntologyLoader::~FileOntologyLoader() +{ + delete d; +} + + +void Nepomuk::FileOntologyLoader::setFileName( const QString& filename ) +{ + d->filename = filename; +} + + +void Nepomuk::FileOntologyLoader::setSerialization( Soprano::RdfSerialization s ) +{ + d->serialization = s; +} + + +QString Nepomuk::FileOntologyLoader::fileName() const +{ + return d->filename; +} + + +QList<Soprano::Statement> Nepomuk::FileOntologyLoader::loadOntology( const QUrl& url ) +{ + QString filename; + + if ( d->filename.isEmpty() ) { + // FIXME: use KIO or is QT sufficient? Actually how about NetAccess and a temp file? + qDebug() << "(FileOntologyLoader) remote support not implemented yet."; + return QList<Soprano::Statement>(); + } + else { + filename = d->filename; + } + + QList<Soprano::Statement> sl; + + QFile f( filename ); + if ( f.open( QIODevice::ReadOnly ) ) { + // TODO: how can we check if the requested onto is really defined in this file? + const Soprano::Parser* rdfParser = Soprano::PluginManager::instance()->discoverParserForSerialization( d->serialization ); + if ( rdfParser ) { + sl = rdfParser->parseFile( d->filename, url, d->serialization ).allStatements(); + } + } + else { + qDebug() << "(FileOntologyLoader) failed to open " << filename; + } + + return sl; +} Modification de propriétés sur nepomuk/types/fileontologyloader.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/literal.h =================================================================== --- nepomuk/types/literal.h (révision 0) +++ nepomuk/types/literal.h (révision 0) @@ -0,0 +1,125 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_LITERAL_H_ +#define _NEPOMUK_LITERAL_H_ + +#include <QtCore/QUrl> +#include <QtCore/QVariant> +#include <QtCore/QSharedData> + +#include "nepomuk_export.h" + +namespace Nepomuk { + namespace Types { + /** + * \class Literal literal.h Nepomuk/Types/Literal + * + * \brief Defines a literal type based on XML Schema. + * + * Each valid Literal represents the literal type + * as XML Schema URI and as QVariant type. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Literal + { + public: + /** + * Default constructor. + * Creates an empty Literal + */ + Literal(); + Literal( const Literal& ); + Literal( const QUrl& dataTypeUri ); + ~Literal(); + + Literal& operator=( const Literal& ); + + /** + * The XML Schema type URI. + */ + QUrl dataTypeUri() const; + + /** + * The type converted to a QVariant::Type. + * \return The QVariant::Type that corresponds to the XML Schema type or + * QVariant::Invalid if it could not be matched. + */ + QVariant::Type dataType() const; + + /** + * Is this a valid Literal, i.e. has it a valid URI. + */ + bool isValid() const; + + private: + class Private; + QExplicitlySharedDataPointer<Private> d; + }; + } +} + + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + /** + * \brief Defines a literal type based on XML Schema. + * + * Each valid Literal represents the literal type + * as XML Schema URI and as QVariant type. + * + * \deprecated in favor of Nepomuk::Types::Literal + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Literal + { + public: + /** + * Default constructor. + * Creates an empty Literal + */ + Literal(); + Literal( const Literal& ); + Literal( const QUrl& dataTypeUri ); + ~Literal(); + + Literal& operator=( const Literal& ); + + /** + * The XML Schema type URI. + */ + const QUrl& dataTypeUri() const; + + /** + * The type converted to a QVariant::Type. + * \return The QVariant::Type that corresponds to the XML Schema type or + * QVariant::Invalid if it could not be matched. + */ + QVariant::Type dataType() const; + + private: + class Private; + QSharedDataPointer<Private> d; + }; +} + +#endif // DISABLE_NEPOMUK_LEGACY + +#endif Modification de propriétés sur nepomuk/types/literal.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/ontologymanager.cpp =================================================================== --- nepomuk/types/ontologymanager.cpp (révision 0) +++ nepomuk/types/ontologymanager.cpp (révision 0) @@ -0,0 +1,343 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "ontologymanager.h" +#include "nepomukontologyloader.h" +#include "desktopontologyloader.h" +#include "ontology.h" +#include "ontology_p.h" +#include "class_p.h" +#include "property_p.h" +#include "entity_p.h" +#include "global.h" + +#include <Soprano/Statement> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/XMLSchema> + +#include <QtCore/QDebug> + + +using namespace Soprano; + +class Nepomuk::OntologyManager::Private +{ +public: + Private( OntologyManager* manager ) + : userOntologyLoader( 0 ), + desktopOntologyLoader( 0 ), + nepomukOntologyLoader( 0 ), + m_manager( manager ) { + } + + OntologyLoader* userOntologyLoader; + DesktopOntologyLoader* desktopOntologyLoader; + NepomukOntologyLoader* nepomukOntologyLoader; + + // cache + QHash<QUrl, Ontology> ontoCache; + QHash<QUrl, Class> classCache; + QHash<QUrl, Property> propertyCache; + + /** + * Find a class in the cache. + * + * \param recurse if true the method will try loading dependancies (i.e. + * other ontologies to fulfill the requirement + */ + Class* findClass( const QUrl& uri, bool recurse = false ) { + QHash<QUrl, Class>::iterator it = classCache.find( uri ); + if ( it != classCache.end() ) { + return &it.value(); + } + else { + if ( recurse ) { + // try loading the ontology containing the class + QUrl parentNs = extractNamespace( uri ); + if ( m_manager->getOntology( parentNs ) ) { + return findClass( uri ); + } + } + return 0; + } + } + + /** + * Find a property in the cache. + * + * \param recurse if true the method will try loading dependancies (i.e. + * other ontologies to fulfill the requirement + */ + Property* findProperty( const QUrl& uri, bool recurse = false ) { + QHash<QUrl, Property>::iterator it = propertyCache.find( uri ); + if ( it != propertyCache.end() ) { + return &it.value(); + } + else { + if ( recurse ) { + // try loading the ontology containing the property + QUrl parentNs = extractNamespace( uri ); + if ( m_manager->getOntology( parentNs ) ) { + return findProperty( uri ); + } + } + return 0; + } + } + +private: + OntologyManager* m_manager; +}; + + +Nepomuk::OntologyManager* Nepomuk::OntologyManager::instance() +{ + static OntologyManager* s_instance = 0; + if ( !s_instance ) { + s_instance = new OntologyManager(); + } + + return s_instance; +} + + +Nepomuk::OntologyManager::OntologyManager() + : d( new Private( this ) ) +{ +} + + +Nepomuk::OntologyManager::~OntologyManager() +{ + delete d->userOntologyLoader; + delete d->desktopOntologyLoader; + delete d->nepomukOntologyLoader; + delete d; +} + + +void Nepomuk::OntologyManager::setOntologyLoader( OntologyLoader* loader ) +{ + if ( d->userOntologyLoader != loader ) { + delete d->userOntologyLoader; + } + d->userOntologyLoader = loader; +} + + +const Nepomuk::Ontology* Nepomuk::OntologyManager::getOntology( const QUrl& uri ) +{ + // if the ontology is already in the cache return it + // + QHash<QUrl, Ontology>::const_iterator it = d->ontoCache.constFind( uri ); + if ( it != d->ontoCache.constEnd() ) { + return &it.value(); + } + + // if not in the cache, try loading it + // + else { + QList<Statement> sl; + if ( !d->userOntologyLoader ) { + if ( !d->desktopOntologyLoader ) { + d->desktopOntologyLoader = new DesktopOntologyLoader(); + } + if ( !d->nepomukOntologyLoader ) { + d->nepomukOntologyLoader = new NepomukOntologyLoader(); + } + + // we prefer the NepomukOntologyLoader since it does not parse + // anything + sl = d->nepomukOntologyLoader->loadOntology( uri ); + if ( sl.isEmpty() ) { + sl = d->desktopOntologyLoader->loadOntology( uri ); + } + } + else { + sl = d->userOntologyLoader->loadOntology( uri ); + } + + if ( !sl.isEmpty() ) { + qDebug() << "(Nepomuk::OntologyManager) Found ontology " << uri << endl; + return constructOntology( uri, sl ); + } + else { + // loading failed, i.e. ontology not stored. + // + qDebug() << "(Nepomuk::OntologyManager) Could not find ontology " << uri << endl; + return 0; + } + } +} + + +Nepomuk::Ontology* Nepomuk::OntologyManager::constructOntology( const QUrl& ontoUri, const QList<Statement>& sl ) +{ + Ontology& ont = d->ontoCache[ ontoUri ]; + ont.d->uri = ontoUri; + + // FIXME: Is it possible to define classes and properties with different namespaces in one file? + // Should we check the namespaces of the resources and if necessary create multiple Ontology + // instances? + + // step 1: collect all classes and properties + for ( QList<Statement>::const_iterator it = sl.constBegin(); it != sl.constEnd(); ++it ) { + const Statement& s = *it; + QUrl subjectUri( s.subject().uri() ); + if( s.predicate().uri().toString().endsWith( "#type" ) ) { + if ( s.object().uri().toString().endsWith( "#Class" ) ) { + d->classCache.insert( subjectUri, Class() ); + Class* c = &d->classCache[ subjectUri ]; + Entity* entity = static_cast<Entity*>( c ); + entity->d->uri = subjectUri; + entity->d->ontology = &ont; + ont.d->classes.insert( subjectUri, c ); + } + else if ( s.object().uri().toString().endsWith( "#Property" ) ) { + d->propertyCache.insert( subjectUri, Property() ); + Property* p = &d->propertyCache[ subjectUri ]; + Entity* entity = static_cast<Entity*>( p ); + entity->d->uri = subjectUri; + entity->d->ontology = &ont; + ont.d->properties.insert( subjectUri, p ); + } + else { + qDebug() << "(OntologyManager) unknown type in ontology: " << s.object().uri(); + } + } + } + + // step 2: construct the classes and properties + for ( QList<Statement>::const_iterator it = sl.constBegin(); it != sl.constEnd(); ++it ) { + const Statement& s = *it; + + // build the objects in the cache. If the ontology references another ontology try loading that one + // BIG PROBLEM: reverse dependancies of ontologies. + // If one ontology depends on another one which in turn depends on the first one. It should work + // since the first step already went through and thus, the class and property bodies have been created. + + const QUrl& subjectUri = s.subject().uri(); + Class* currentClass = d->findClass( subjectUri ); + Property* currentProperty = ( currentClass ? ( Property* )0 : d->findProperty( subjectUri ) ); + Entity* currentEntity = currentClass; + if ( !currentEntity ) { + currentEntity = currentProperty; + } + + if ( !currentClass && !currentProperty ) { + qDebug() << "(OntologyManager) invalid ontology statement: " << s; + d->ontoCache.remove( ontoUri ); + return 0; + } + + if( s.predicate().uri().toString().endsWith( "#subClassOf" ) ) { + Class* parent = d->findClass( s.object().uri(), true ); + if ( !parent ) { + qDebug() << "(OntologyManager) unable to load dependancy for: " << s; + } + else { + currentClass->d->parents.append( parent ); + parent->d->children.append( currentClass ); + } + } + + if( s.predicate().uri().toString().endsWith( "#subPropertyOf" ) ) { + Property* parent = d->findProperty( s.object().uri(), true ); + if ( !parent ) { + qDebug() << "(OntologyManager) unable to load dependancy for: " << s; + } + else { + currentProperty->d->parents.append( parent ); + parent->d->children.append( currentProperty ); + } + } + + else if( s.predicate().toString().endsWith( "#domain" ) ) { + Class* domain = d->findClass( s.object().uri(), true ); + if ( !domain ) { + qDebug() << "(OntologyManager) unable to load dependancy for: " << s; + } + else { + currentProperty->d->domain = domain; + domain->d->domainOf.insert( subjectUri, currentProperty ); + } + } + + else if( s.predicate().toString().endsWith( "#range" ) ) { + if ( s.object().toString().startsWith( Soprano::Vocabulary::XMLSchema::xsdNamespace().toString() ) ) { + currentProperty->d->literalRange = Literal( s.object().literal().toString() ); + } + else { + Class* range = d->findClass( s.object().uri(), true ); + if ( range ) { + currentProperty->d->range = range; + range->d->rangeOf.insert( subjectUri, currentProperty ); + } + else { + qDebug() << "(OntologyManager) unable to load dependancy for: " << s; + } + } + } + + else if( s.predicate().toString().endsWith( "#minCardinality" ) ) { + currentProperty->d->minCardinality = s.object().literal().toInt(); + } + + else if( s.predicate().toString().endsWith( "#maxCardinality" ) ) { + currentProperty->d->maxCardinality = s.object().literal().toInt(); + } + + else if ( s.predicate().toString().endsWith( "#cardinality" ) ) { + currentProperty->d->cardinality = s.object().literal().toInt(); + } + + else if ( s.predicate().toString().endsWith( "#inverseProperty" ) ) { + Property* inverse = d->findProperty( s.object().toString(), true ); + if ( !inverse ) { + qDebug() << "(OntologyManager) failed to load inverse property: " << s; + d->ontoCache.remove( ontoUri ); + return 0; + } + currentProperty->d->inverse = inverse; + inverse->d->inverse = currentProperty; + } + + // load l10n'ed comments + else if( s.predicate() == Soprano::Vocabulary::RDFS::comment() ) { + if ( s.object().language().isEmpty() ) { + currentEntity->d->comment = s.object().toString(); + } + else { + currentEntity->d->l10nComments[s.object().language()] = s.object().toString(); + } + } + + // load l10n'ed labels + else if( s.predicate() == Soprano::Vocabulary::RDFS::label() ) { + if ( s.object().language().isEmpty() ) { + currentEntity->d->label = s.object().toString(); + } + else { + currentEntity->d->l10nLabels[s.object().language()] = s.object().toString(); + } + } + } + + return &ont; +} Modification de propriétés sur nepomuk/types/ontologymanager.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/nepomukontologyloader.h =================================================================== --- nepomuk/types/nepomukontologyloader.h (révision 0) +++ nepomuk/types/nepomukontologyloader.h (révision 0) @@ -0,0 +1,45 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_NEPOMUK_ONTOLOGY_LOADER_H_ +#define _NEPOMUK_NEPOMUK_ONTOLOGY_LOADER_H_ + +#include "ontologyloader.h" +#include "nepomuk_export.h" + +namespace Nepomuk { + /** + * \deprecated Ontologies should now be handled using the classes + * in the Nepomuk::Types namespace. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT NepomukOntologyLoader : public OntologyLoader + { + public: + NepomukOntologyLoader(); + ~NepomukOntologyLoader(); + + QList<Soprano::Statement> loadOntology( const QUrl& url ); + + private: + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/types/nepomukontologyloader.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/class.cpp =================================================================== --- nepomuk/types/class.cpp (révision 0) +++ nepomuk/types/class.cpp (révision 0) @@ -0,0 +1,662 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "class.h" +#include "class_p.h" +#include "ontology.h" +#include "resourcemanager.h" +#include "property.h" +#include "entitymanager.h" + +#include <QtCore/QList> + +#include <kdebug.h> + +#include <Soprano/QueryResultIterator> +#include <Soprano/Model> +#include <Soprano/Vocabulary/NRL> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/RDF> +#include <Soprano/Vocabulary/OWL> + +#undef D +#define D static_cast<Nepomuk::Types::ClassPrivate*>( d.data() ) + +Nepomuk::Types::ClassPrivate::ClassPrivate( const QUrl& uri ) + : EntityPrivate( uri ), + propertiesAvailable( uri.isValid() ? -1 : 0 ) +{ +} + + +bool Nepomuk::Types::ClassPrivate::load() +{ + // + // Nearly all here can be done in a very clean way. There is only + // one special case: rdfs:Resource, the base class of them all + // + if ( EntityPrivate::load() ) { + // undefined super class means that we are derived from rdfs:Resource directly + if ( parents.isEmpty() ) { + if ( uri != Soprano::Vocabulary::RDFS::Resource() ) { + parents += Soprano::Vocabulary::RDFS::Resource(); + } + } + return true; + } + else { + return false; + } +} + + +bool Nepomuk::Types::ClassPrivate::loadAncestors() +{ + // + // Nearly all here can be done in a very clean way. There is only + // one special case: rdfs:Resource, the base class of them all + // + if ( uri == Soprano::Vocabulary::RDFS::Resource() ) { + // + // All classes that do not explicetely state a superclass are + // derived from rdfs:Resource. This query selects those classes + // (might fail on redland though) + // + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select distinct ?s where { " + "{ ?s a <%1> . } UNION { ?s a <%2> . } " + "OPTIONAL { graph ?g { ?s <%3> ?ss . } . " + "{ ?g a <%4> . } UNION { ?g a <%5> . } . } . " + "FILTER(!BOUND(?ss)) . }") + .arg( Soprano::Vocabulary::RDFS::Class().toString() ) + .arg( Soprano::Vocabulary::OWL::Class().toString() ) + .arg( Soprano::Vocabulary::RDFS::subClassOf().toString() ) + .arg( Soprano::Vocabulary::NRL::Ontology().toString() ) + .arg( Soprano::Vocabulary::NRL::KnowledgeBase().toString() ), + Soprano::Query::QueryLanguageSparql ); + while ( it.next() ) { + QUrl resUri = it.binding( "s" ).uri(); + if ( resUri != Soprano::Vocabulary::RDFS::Resource() ) { + children.append( resUri ); + } + } + } + + return EntityPrivate::loadAncestors(); +} + + +bool Nepomuk::Types::ClassPrivate::addProperty( const QUrl& property, const Soprano::Node& value ) +{ + // we avoid subclassing loops (as created for crappy inferencing) by checking for our own uri + if( value.isResource() && value.uri() == uri ) { + return false; + } + + if( property == Soprano::Vocabulary::RDFS::subClassOf() ) { + parents.append( Class( value.uri() ) ); + return true; + } + + return false; +} + + +bool Nepomuk::Types::ClassPrivate::addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ) +{ + // we avoid subclassing loops (as created for crappy inferencing) by checking for our own uri + if ( property == Soprano::Vocabulary::RDFS::subClassOf() && + ancestorResource != uri ) { + children.append( Class( ancestorResource ) ); + return true; + } + + return false; +} + + +void Nepomuk::Types::ClassPrivate::initProperties() +{ + QMutexLocker lock( &mutex ); + + if ( propertiesAvailable < 0 ) { + propertiesAvailable = loadProperties() ? 1 : 0; + } +} + + +bool Nepomuk::Types::ClassPrivate::loadProperties() +{ + // load domains with a hack to get at least a subset of properties that inherit their domain from parents + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select distinct ?p where { " + "{ ?p <%1> <%2> . } " + "UNION " + "{ ?p <%3> ?p1 . " + "OPTIONAL { ?p <%1> ?undefdom . } . " + "?p1 <%1> <%2> . " + "FILTER(!bound(?undefdom)) . } " + "UNION " + "{ ?p <%3> ?p1 . " + "OPTIONAL { ?p <%1> ?undefdom1 . } . " + "?p1 <%3> ?p2 . " + "OPTIONAL { ?p1 <%1> ?undefdom2 . } . " + "?p2 <%1> <%2> . " + "FILTER(!bound(?undefdom1) && !bound(?undefdom2)) . } " + "}") + .arg( Soprano::Vocabulary::RDFS::domain().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ) + .arg( Soprano::Vocabulary::RDFS::subPropertyOf().toString() ), + Soprano::Query::QueryLanguageSparql ); + + // redland cannot handle UNION queries! So fallback to the "old" query + if( it.lastError() ) { + it = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?p where { " + "?p <%1> <%2> . }") + .arg( Soprano::Vocabulary::RDFS::domain().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ), + Soprano::Query::QueryLanguageSparql ); + } + + while ( it.next() ) { + domainOf.append( Property( it.binding( "p" ).uri() ) ); + } + + + // load ranges + it = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?p where { " + "?p <%1> <%2> . }") + .arg( Soprano::Vocabulary::RDFS::range().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ), + Soprano::Query::QueryLanguageSparql ); + while ( it.next() ) { + rangeOf.append( Property( it.binding( "p" ).uri() ) ); + } + + return !it.lastError(); +} + + +void Nepomuk::Types::ClassPrivate::reset( bool recursive ) +{ + kDebug(); + + QMutexLocker lock( &mutex ); + + if ( propertiesAvailable != -1 ) { + if ( recursive ) { + foreach( Property p, domainOf ) { + p.reset( true ); + } + foreach( Property p, rangeOf ) { + p.reset( true ); + } + } + + domainOf.clear(); + rangeOf.clear(); + propertiesAvailable = -1; + } + + if ( available != -1 ) { + if ( recursive ) { + foreach( Class c, parents ) { + c.reset( true ); + } + } + parents.clear(); + available = -1; + } + + if ( ancestorsAvailable != -1 ) { + if ( recursive ) { + foreach( Class c, children ) { + c.reset( true ); + } + } + children.clear(); + ancestorsAvailable = -1; + } + + EntityPrivate::reset( recursive ); +} + + +QSet<Nepomuk::Types::Class> Nepomuk::Types::ClassPrivate::findParentClasses( ClassPrivate* requestingClass ) +{ + QSet<Class> allParents; + + for ( QList<Class>::iterator it = parents.begin(); it != parents.end(); ++it ) { + ClassPrivate* p = static_cast<Nepomuk::Types::ClassPrivate*>( it->d.data() ); + if ( p != requestingClass ) { + p->init(); + allParents += p->findParentClasses( requestingClass ); + allParents += *it; + } + } + + return allParents; +} + + +QSet<Nepomuk::Types::Class> Nepomuk::Types::ClassPrivate::findSubClasses( ClassPrivate* requestingClass ) +{ + QSet<Class> allChildren; + + for ( QList<Class>::iterator it = children.begin(); it != children.end(); ++it ) { + ClassPrivate* p = static_cast<Nepomuk::Types::ClassPrivate*>( it->d.data() ); + if ( p != requestingClass ) { + p->initAncestors(); + allChildren += p->findSubClasses( requestingClass ); + allChildren += *it; + } + } + + return allChildren; +} + + + +Nepomuk::Types::Class::Class() + : Entity() +{ + d = 0; +} + + +Nepomuk::Types::Class::Class( const QUrl& uri ) + : Entity() +{ + d = EntityManager::self()->getClass( uri ); +} + + +Nepomuk::Types::Class::Class( const Class& other ) + : Entity( other ) +{ +} + + +Nepomuk::Types::Class::~Class() +{ +} + + +Nepomuk::Types::Class& Nepomuk::Types::Class::operator=( const Class& other ) +{ + d = other.d; + return *this; +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Class::rangeOf() +{ + if ( d ) { + D->initProperties(); + return D->rangeOf; + } + else { + return QList<Nepomuk::Types::Property>(); + } +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Class::rangeOf() const +{ + return const_cast<Class*>(this)->rangeOf(); +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Class::domainOf() +{ + if ( d ) { + D->initProperties(); + return D->domainOf; + } + else { + return QList<Nepomuk::Types::Property>(); + } +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Class::domainOf() const +{ + return const_cast<Class*>(this)->domainOf(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Class::findPropertyByName( const QString& name ) +{ + if ( d ) { + D->initProperties(); + for ( QList<Property>::const_iterator it = D->domainOf.constBegin(); + it != D->domainOf.constEnd(); ++it ) { + const Property& p = *it; + if ( p.name() == name ) { + return p; + } + } + } + + return Property(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Class::findPropertyByName( const QString& name ) const +{ + return const_cast<Class*>(this)->findPropertyByName(name); +} + + +Nepomuk::Types::Property Nepomuk::Types::Class::findPropertyByLabel( const QString& label, const QString& language ) +{ + if ( d ) { + D->initProperties(); + for ( QList<Property>::iterator it = D->domainOf.begin(); + it != D->domainOf.end(); ++it ) { + Property& p = *it; + if ( p.label( language ) == label ) { + return p; + } + } + } + + return Property(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Class::findPropertyByLabel( const QString& label, const QString& language ) const +{ + return const_cast<Class*>(this)->findPropertyByLabel( label, language ); +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::parentClasses() +{ + if ( d ) { + D->init(); + return D->parents; + } + else { + return QList<Nepomuk::Types::Class>(); + } +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::parentClasses() const +{ + return const_cast<Class*>(this)->parentClasses(); +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::subClasses() +{ + if ( d ) { + D->initAncestors(); + return D->children; + } + else { + return QList<Nepomuk::Types::Class>(); + } +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::subClasses() const +{ + return const_cast<Class*>(this)->subClasses(); +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::allParentClasses() +{ + if ( d ) { + D->init(); + return D->findParentClasses( D ).toList(); + } + else { + return QList<Nepomuk::Types::Class>(); + } +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::allParentClasses() const +{ + return const_cast<Class*>(this)->allParentClasses(); +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::allSubClasses() +{ + if ( d ) { + D->initAncestors(); + return D->findSubClasses( D ).toList(); + } + else { + return QList<Nepomuk::Types::Class>(); + } +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::allSubClasses() const +{ + return const_cast<Class*>(this)->allSubClasses(); +} + + +bool Nepomuk::Types::Class::isParentOf( const Class& other ) +{ + if ( d ) { + D->initAncestors(); + + if ( D->children.contains( other ) ) { + return true; + } + else { + for ( QList<Nepomuk::Types::Class>::iterator it = D->children.begin(); + it != D->children.end(); ++it ) { + if ( ( *it ).isParentOf( other ) ) { + return true; + } + } + } + } + + return false; +} + + +bool Nepomuk::Types::Class::isParentOf( const Class& other ) const +{ + return const_cast<Class*>(this)->isParentOf( other ); +} + + +bool Nepomuk::Types::Class::isSubClassOf( const Class& other ) +{ + if ( d ) { + D->init(); + + if ( D->parents.contains( other ) ) { + return true; + } + else { + for ( QList<Nepomuk::Types::Class>::iterator it = D->parents.begin(); + it != D->parents.end(); ++it ) { + if ( ( *it ).isSubClassOf( other ) ) { + return true; + } + } + } + } + + return false; +} + + +bool Nepomuk::Types::Class::isSubClassOf( const Class& other ) const +{ + return const_cast<Class*>(this)->isSubClassOf( other ); +} + + + + + +// Start of code for deprecated Class +// ---------------------------------- + +#include "global.h" +#include "ontologymanager.h" + +Nepomuk::Class::Class() + : Entity() +{ + d = new Private(); +} + + +Nepomuk::Class::Class( const Class& other ) + : Entity( other ) +{ + d = other.d; +} + + +Nepomuk::Class::~Class() +{ +} + + +Nepomuk::Class& Nepomuk::Class::operator=( const Class& other ) +{ + d = other.d; + return *this; +} + + +QList<const Nepomuk::Property*> Nepomuk::Class::allProperties() const +{ + return d->domainOf.values(); +} + + +const Nepomuk::Property* Nepomuk::Class::findPropertyByName( const QString& name ) const +{ + for ( QHash<QUrl, const Property*>::const_iterator it = d->domainOf.constBegin(); + it != d->domainOf.constEnd(); ++it ) { + const Property* p = it.value(); + if ( p->name() == name ) { + return p; + } + } + + return 0; +} + + +const Nepomuk::Property* Nepomuk::Class::findPropertyByLabel( const QString& label, const QString& language ) const +{ + for ( QHash<QUrl, const Property*>::const_iterator it = d->domainOf.constBegin(); + it != d->domainOf.constEnd(); ++it ) { + const Property* p = it.value(); + if ( p->label( language ) == label ) { + return p; + } + } + + return 0; +} + + +const Nepomuk::Property* Nepomuk::Class::findPropertyByUri( const QUrl& uri ) const +{ + QHash<QUrl, const Property*>::const_iterator it = d->domainOf.find( uri ); + if ( it != d->domainOf.constEnd() ) { + return it.value(); + } + else { + return 0; + } +} + + +QList<const Nepomuk::Class*> Nepomuk::Class::parentClasses() const +{ + return d->parents; +} + + +QList<const Nepomuk::Class*> Nepomuk::Class::subClasses() const +{ + return d->children; +} + + +bool Nepomuk::Class::isParentOf( const Class* other ) const +{ + if ( d->children.contains( other ) ) { + return true; + } + else { + for ( QList<const Nepomuk::Class*>::const_iterator it = d->children.constBegin(); + it != d->children.constEnd(); ++it ) { + if ( ( *it )->isParentOf( other ) ) { + return true; + } + } + return false; + } +} + + +bool Nepomuk::Class::isSubClassOf( const Class* other ) const +{ + if ( d->parents.contains( other ) ) { + return true; + } + else { + for ( QList<const Nepomuk::Class*>::const_iterator it = d->parents.constBegin(); + it != d->parents.constEnd(); ++it ) { + if ( ( *it )->isSubClassOf( other ) ) { + return true; + } + } + return false; + } +} + + +const Nepomuk::Class* Nepomuk::Class::load( const QUrl& uri ) +{ + Q_ASSERT( !uri.isEmpty() ); + + QUrl ns = extractNamespace( uri ); + + // load the ontology in the cache + const Ontology* ont = OntologyManager::instance()->getOntology( ns ); + + // return the requested class or an invalid one if the ontology + // was not found + if ( ont ) { + return ont->findClassByUri( uri ); + } + else { + return 0; + } +} Modification de propriétés sur nepomuk/types/class.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/global.h =================================================================== --- nepomuk/types/global.h (révision 0) +++ nepomuk/types/global.h (révision 0) @@ -0,0 +1,32 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_GLOBAL_H_ +#define _NEPOMUK_GLOBAL_H_ + +#include "nepomuk_export.h" + +#include <QtCore/QString> +#include <QtCore/QUrl> + +namespace Nepomuk { + KDE_DEPRECATED NEPOMUK_EXPORT QUrl extractNamespace( const QUrl& url ); +} + +#endif Modification de propriétés sur nepomuk/types/global.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/ontologyloader.h =================================================================== --- nepomuk/types/ontologyloader.h (révision 0) +++ nepomuk/types/ontologyloader.h (révision 0) @@ -0,0 +1,60 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ONTOLOGY_LOADER_H_ +#define _NEPOMUK_ONTOLOGY_LOADER_H_ + +#include <QtCore/QUrl> + +#include "nepomuk_export.h" + +namespace Soprano { + class Statement; +} + +namespace Nepomuk { + + /** + * An OntologyLoader provides the statements that make up an ontology + * for the OntologyManager to create the ontology classes and properties. + * + * Typical implementations read RDF statements from RDF files or from the + * Nepomuk-KDE RDF store. + * + * \deprecated Ontologies should now be handled using the classes + * in the Nepomuk::Types namespace. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT OntologyLoader + { + public: + virtual ~OntologyLoader(); + + // FIXME: use StatementIterator + virtual QList<Soprano::Statement> loadOntology( const QUrl& url ) = 0; + + protected: + OntologyLoader(); + + private: + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/types/ontologyloader.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/fileontologyloader.h =================================================================== --- nepomuk/types/fileontologyloader.h (révision 0) +++ nepomuk/types/fileontologyloader.h (révision 0) @@ -0,0 +1,89 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_FILE_ONTOLOGY_LOADER_H_ +#define _NEPOMUK_FILE_ONTOLOGY_LOADER_H_ + +#include "ontologyloader.h" +#include "nepomuk_export.h" + +#include <soprano/parser.h> +#include <soprano/sopranotypes.h> + + +namespace Nepomuk { + /** + * \deprecated Ontologies should now be handled using the classes + * in the Nepomuk::Types namespace. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT FileOntologyLoader : public OntologyLoader + { + public: + /** + * Default constructor. + * Creates a FileOntologyLoader that will try to load the + * ontology directly from its URL, i.e. the internet. + */ + FileOntologyLoader(); + + /** + * Creates a FileOntologyLoader that will load the + * ontology from the specified filename. + */ + explicit FileOntologyLoader( const QString& filename, + Soprano::RdfSerialization serialization = Soprano::SerializationUnknown ); + + /** + * Destructor + */ + ~FileOntologyLoader(); + + /** + * Set the filename to be used for reading the ontologies. + * If no filename has been set FileOntologyLoader will try + * load the ontology file from the internet, i.e. directly + * use the ontology URL - NOT IMPLEMENTED YET. + */ + void setFileName( const QString& filename ); + + /** + * The filename that has been set. + * \sa setFileName + * \return The filename set (can be empty) + */ + QString fileName() const; + + /** + * Set the serialization that is used in the file. + * Defaults to Soprano::SerializationUnknown + */ + void setSerialization( Soprano::RdfSerialization ); + + /** + * reimplemented from OntologyLoader + */ + QList<Soprano::Statement> loadOntology( const QUrl& url ); + + private: + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/types/fileontologyloader.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/entitymanager.cpp =================================================================== --- nepomuk/types/entitymanager.cpp (révision 0) +++ nepomuk/types/entitymanager.cpp (révision 0) @@ -0,0 +1,131 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "entitymanager.h" +#include "class_p.h" +#include "property_p.h" +#include "ontology_p.h" + +#include "resourcemanager.h" + +#include <QtCore/QMutexLocker> + +Q_GLOBAL_STATIC( Nepomuk::Types::EntityManager, entityManager ) + +Nepomuk::Types::EntityManager::EntityManager() +{ +} + + +Nepomuk::Types::EntityPrivate* Nepomuk::Types::EntityManager::findEntity( const QUrl& uri ) const +{ + if ( ClassPrivate* cp = findClass( uri ) ) { + return cp; + } + else if ( PropertyPrivate* pp = findProperty( uri ) ) { + return pp; + } + else if ( OntologyPrivate* op = findOntology( uri ) ) { + return op; + } + else { + return 0; + } +} + + +Nepomuk::Types::ClassPrivate* Nepomuk::Types::EntityManager::findClass( const QUrl& uri ) const +{ + QHash<QUrl, QExplicitlySharedDataPointer<ClassPrivate> >::const_iterator it = m_classMap.constFind( uri ); + if ( it != m_classMap.end() ) { + return it.value().data(); + } + return 0; +} + + +Nepomuk::Types::PropertyPrivate* Nepomuk::Types::EntityManager::findProperty( const QUrl& uri ) const +{ + QHash<QUrl, QExplicitlySharedDataPointer<PropertyPrivate> >::const_iterator it = m_propertyMap.constFind( uri ); + if ( it != m_propertyMap.end() ) { + return it.value().data(); + } + return 0; +} + + +Nepomuk::Types::OntologyPrivate* Nepomuk::Types::EntityManager::findOntology( const QUrl& uri ) const +{ + QHash<QUrl, QExplicitlySharedDataPointer<OntologyPrivate> >::const_iterator it = m_ontologyMap.constFind( uri ); + if ( it != m_ontologyMap.end() ) { + return it.value().data(); + } + return 0; +} + + +Nepomuk::Types::ClassPrivate* Nepomuk::Types::EntityManager::getClass( const QUrl& uri ) +{ + QMutexLocker lock( &m_mutex ); + + if ( ClassPrivate* cp = findClass( uri ) ) { + return cp; + } + else { + QExplicitlySharedDataPointer<ClassPrivate> scp( new ClassPrivate( uri ) ); + m_classMap.insert( uri, scp ); + return scp.data(); + } +} + + +Nepomuk::Types::PropertyPrivate* Nepomuk::Types::EntityManager::getProperty( const QUrl& uri ) +{ + QMutexLocker lock( &m_mutex ); + + if ( PropertyPrivate* pp = findProperty( uri ) ) { + return pp; + } + else { + QExplicitlySharedDataPointer<PropertyPrivate> cp( new PropertyPrivate( uri ) ); + m_propertyMap.insert( uri, cp ); + return cp.data(); + } +} + + +Nepomuk::Types::OntologyPrivate* Nepomuk::Types::EntityManager::getOntology( const QUrl& uri ) +{ + QMutexLocker lock( &m_mutex ); + + if ( OntologyPrivate* op = findOntology( uri ) ) { + return op; + } + else { + QExplicitlySharedDataPointer<OntologyPrivate> cp( new OntologyPrivate( uri ) ); + m_ontologyMap.insert( uri, cp ); + return cp.data(); + } +} + + +Nepomuk::Types::EntityManager* Nepomuk::Types::EntityManager::self() +{ + return entityManager(); +} Modification de propriétés sur nepomuk/types/entitymanager.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/property_p.h =================================================================== --- nepomuk/types/property_p.h (révision 0) +++ nepomuk/types/property_p.h (révision 0) @@ -0,0 +1,94 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_PROPERTY_PRIVATE_H_ +#define _NEPOMUK_PROPERTY_PRIVATE_H_ + +#include "entity_p.h" +#include "property.h" +#include "literal.h" +#include "class.h" + +#include <QtCore/QVariant> +#include <QtCore/QSharedData> + +namespace Nepomuk { + namespace Types { + class PropertyPrivate : public EntityPrivate + { + public: + PropertyPrivate( const QUrl& uri = QUrl() ); + + Class range; + Class domain; + + Literal literalRange; + + Property inverse; + + QList<Property> parents; + QList<Property> children; + + int minCardinality; + int maxCardinality; + int cardinality; + + bool addProperty( const QUrl& property, const Soprano::Node& value ); + bool addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ); + + void reset( bool recursive ); + }; + } +} + + + +namespace Nepomuk { + + class Class; + + class Property::Private : public QSharedData + { + public: + Private() + : range( 0 ), + domain( 0 ), + inverse( 0 ), + minCardinality( -1 ), + maxCardinality( -1 ), + cardinality( -1 ) { + } + + const Class* range; + const Class* domain; + + Literal literalRange; + + const Property* inverse; + + QList<const Property*> parents; + QList<const Property*> children; + + int minCardinality; + int maxCardinality; + int cardinality; + }; +} + +#endif Modification de propriétés sur nepomuk/types/property_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/class.h =================================================================== --- nepomuk/types/class.h (révision 0) +++ nepomuk/types/class.h (révision 0) @@ -0,0 +1,400 @@ +/* This file is part of the Nepomuk-KDE libraries + Copyright (c) 2007-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NEPOMUK_CLASS_H_ +#define _NEPOMUK_CLASS_H_ + +#include <QtCore/QList> +#include <QtCore/QUrl> +#include <QtCore/QString> +#include <QtCore/QSharedData> + +#include "entity.h" +#include "nepomuk_export.h" + + +namespace Nepomuk { + namespace Types { + class Property; + + /** + * \class Class class.h Nepomuk/Types/Class + * + * \brief A Class is a resource of type rdf:Class. + * + * Class instances are explicitly shared. Two instances created + * with the same uri reference the same data. + * + * While Resource objects can be changed Class instances are considered + * to be static and never changed during their lifetime. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Class : public Entity + { + friend class ClassPrivate; + + public: + /** + * Default constructor. Creates an empty Class. + */ + Class(); + + /** + * Create the class referred to by \p uri. + * The result is either a valid class which could be loaded from the + * Nepomuk store or a simple class which only contains the uri. + * + * Be aware that the data is only loaded once read. + * + * Subsequent calls result in a simple hash lookup of cached data. + */ + Class( const QUrl& uri ); + + /** + * Default copy constructor + */ + Class( const Class& ); + + /** + * Destructor + */ + ~Class(); + + /** + * Copy operator. + */ + Class& operator=( const Class& ); + + /** + * A Property has a certain range which is a Class or a Literal. + * \return A list of all properties that have this Class as a range. + * \sa Property::range() + */ + QList<Property> rangeOf(); + + /** + * A Property has a certain range which is a Class or a Literal. + * \return A list of all properties that have this Class as a range. + * \sa Property::range() + * + * Const version. + * + * \since 4.4 + */ + QList<Property> rangeOf() const; + + /** + * A Property has a certain domain which is a Class. + * \return A list of all properties that have this Class as a domain. + * \sa Property::domain() + */ + QList<Property> domainOf(); + + /** + * A Property has a certain domain which is a Class. + * \return A list of all properties that have this Class as a domain. + * \sa Property::domain() + * + * Const version. + * + * \since 4.4 + */ + QList<Property> domainOf() const; + + /** + * Search for a property in the class by its name. + * \param name The name of the property. + * \return the Property object identified by name or an invalid property if it could not be found. + */ + Property findPropertyByName( const QString& name ); + + /** + * Search for a property in the class by its name. + * \param name The name of the property. + * \return the Property object identified by name or an invalid property if it could not be found. + * + * Const version. + * + * \since 4.4 + */ + Property findPropertyByName( const QString& name ) const; + + /** + * Search for a property in the class by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or an invalid property if it could not be found. + */ + Property findPropertyByLabel( const QString& label, const QString& language = QString() ); + + /** + * Search for a property in the class by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or an invalid property if it could not be found. + * + * Const version. + * + * \since 4.4 + */ + Property findPropertyByLabel( const QString& label, const QString& language = QString() ) const; + + /** + * Each class can have multiple parent classes. This method + * provides a list of all direct parents. + * \return A list of all parent classes of this class. + * If the list is emppty it means that the class has no direct + * parents, i.e. it is derived from rdf:Resource. + * \sa allParentClasses() + */ + QList<Class> parentClasses(); + + /** + * Each class can have multiple parent classes. This method + * provides a list of all direct parents. + * \return A list of all parent classes of this class. + * If the list is emppty it means that the class has no direct + * parents, i.e. it is derived from rdf:Resource. + * \sa allParentClasses() + * + * Const version. + * + * \since 4.4 + */ + QList<Class> parentClasses() const; + + /** + * \return A list of all classes that have this class as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain classes that are derived + * from this class. + */ + QList<Class> subClasses(); + + /** + * \return A list of all classes that have this class as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain classes that are derived + * from this class. + * + * Const version. + * + * \since 4.4 + */ + QList<Class> subClasses() const; + + /** + * Recursively determines all parent classes of this class, not + * only the direct ones. + * \return A list of parent classes of this class. + * \sa parentClasses() + */ + QList<Class> allParentClasses(); + + /** + * Recursively determines all parent classes of this class, not + * only the direct ones. + * \return A list of parent classes of this class. + * \sa parentClasses() + * + * Const version. + * + * \since 4.4 + */ + QList<Class> allParentClasses() const; + + /** + * Recursively determines all sub classes of this class, not + * only the direct ones. + * \return A list of sub classes of this class. + * \sa subClasses() + */ + QList<Class> allSubClasses(); + + /** + * Recursively determines all sub classes of this class, not + * only the direct ones. + * \return A list of sub classes of this class. + * \sa subClasses() + * + * Const version. + * + * \since 4.4 + */ + QList<Class> allSubClasses() const; + + /** + * Check if a class inherits this class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if other is derived from this class, false otherwise. + */ + bool isParentOf( const Class& other ); + + /** + * Check if a class inherits this class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if other is derived from this class, false otherwise. + * + * Const version. + * + * \since 4.4 + */ + bool isParentOf( const Class& other ) const; + + /** + * Check if this class is derived from another class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if this class is derived from other, false otherwise. + */ + bool isSubClassOf( const Class& other ); + + /** + * Check if this class is derived from another class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if this class is derived from other, false otherwise. + * + * Const version. + * + * \since 4.4 + */ + bool isSubClassOf( const Class& other ) const; + }; + } +} + + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + + class Ontology; + class Property; + + /** + * A Class is a resource of type rdf:Class. + * + * \deprecated in favor of Nepomuk::Types::Class + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Class : public Entity + { + public: + /** + * Default constructor. Creates an empty Class. + */ + Class(); + + /** + * Default copy constructor + */ + Class( const Class& ); + + /** + * Destructor + */ + ~Class(); + + Class& operator=( const Class& ); + + // an alternative would be: QList<Property> rangeOf() and QList<Property> domainOf() + QList<const Property*> allProperties() const; + + /** + * Search for a property in the class by its name. + * \param name The name of the property. + * \return the Property object identified by name or 0 if the property could not be found. + */ + const Property* findPropertyByName( const QString& name ) const; + + /** + * Search for a property in the class by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or 0 if the property could not be found. + */ + const Property* findPropertyByLabel( const QString& label, const QString& language = QString() ) const; + + /** + * Search for a property in the class by its name. + * \param uri the URI of the property + * \return the Property object identified by uri or 0 if the property could not be found. + */ + const Property* findPropertyByUri( const QUrl& uri ) const; + + /** + * Each class can have multiple parent classes. + * \return A list of all parent classes of this class. + * If the list is emppty it means that the class has no direct + * parents, i.e. it is derived from rdf:Resource. + */ + QList<const Class*> parentClasses() const; + + /** + * \return A list of all classes that have this class as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain classes that are derived + * from this class. + */ + QList<const Class*> subClasses() const; + + /** + * Check if a class inherits this class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if other is derived from this class, false otherwise. + */ + bool isParentOf( const Class* other ) const; + + /** + * Check if this class is derived from another class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if this class is derived from other, false otherwise. + */ + bool isSubClassOf( const Class* other ) const; + + /** + * Loads a class actually including the whole ontology + * it is declared in. + * + * Dependancies are resolved automatically if possible. + * + * \return A Class object representing the class identified + * by uri or an invalid Class object if the resource identified + * by uri is either not a class or does not exist. + */ + static const Class* load( const QUrl& uri ); + + private: + class Private; + QSharedDataPointer<Private> d; + + friend class OntologyManager; + }; +} + +#endif +#endif Modification de propriétés sur nepomuk/types/class.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/ontology.cpp =================================================================== --- nepomuk/types/ontology.cpp (révision 0) +++ nepomuk/types/ontology.cpp (révision 0) @@ -0,0 +1,360 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "ontology.h" +#include "ontology_p.h" +#include "class.h" +#include "property.h" +#include "entitymanager.h" +#include "resourcemanager.h" + +#include <Soprano/QueryResultIterator> +#include <Soprano/Model> +#include <Soprano/Vocabulary/NAO> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/RDF> +#include <Soprano/Vocabulary/XMLSchema> + +#undef D +#define D static_cast<Nepomuk::Types::OntologyPrivate*>( d.data() ) + +Nepomuk::Types::OntologyPrivate::OntologyPrivate( const QUrl& uri ) + : EntityPrivate( uri ), + entitiesAvailable( uri.isValid() ? -1 : 0 ) +{ +} + + +void Nepomuk::Types::OntologyPrivate::initEntities() +{ + if ( entitiesAvailable < 0 ) { + entitiesAvailable = loadEntities() ? 1 : 0; + } +} + + +bool Nepomuk::Types::OntologyPrivate::loadEntities() +{ + // load classes + // We use a FILTER(STR(?ns)...) to support both Soprano 2.3 (with plain literals) and earlier (with only typed ones) + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?c where { " + "graph ?g { ?c a <%1> . } . " + "?g <%2> ?ns . " + "FILTER(STR(?ns) = \"%3\") . }" ) + .arg( Soprano::Vocabulary::RDFS::Class().toString() ) + .arg( Soprano::Vocabulary::NAO::hasDefaultNamespace().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ), + Soprano::Query::QueryLanguageSparql ); + while ( it.next() ) { + classes.append( Class( it.binding( "c" ).uri() ) ); + } + + + // load properties + it = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?p where { " + "graph ?g { ?p a <%1> . } . " + "?g <%2> ?ns . " + "FILTER(STR(?ns) = \"%3\") . }" ) + .arg( Soprano::Vocabulary::RDF::Property().toString() ) + .arg( Soprano::Vocabulary::NAO::hasDefaultNamespace().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ), + Soprano::Query::QueryLanguageSparql ); + while ( it.next() ) { + properties.append( Property( it.binding( "p" ).uri() ) ); + } + + return !it.lastError(); +} + + +bool Nepomuk::Types::OntologyPrivate::addProperty( const QUrl&, const Soprano::Node& ) +{ + return false; +} + + +bool Nepomuk::Types::OntologyPrivate::addAncestorProperty( const QUrl&, const QUrl& ) +{ + return false; +} + + +void Nepomuk::Types::OntologyPrivate::reset( bool recursive ) +{ + QMutexLocker lock( &mutex ); + + if ( entitiesAvailable != -1 ) { + if ( recursive ) { + foreach( Class c, classes ) { + c.reset( true ); + } + foreach( Property p, properties ) { + p.reset( true ); + } + } + classes.clear(); + properties.clear(); + + entitiesAvailable = -1; + } + + EntityPrivate::reset( recursive ); +} + + + +Nepomuk::Types::Ontology::Ontology() +{ + d = new OntologyPrivate(); +} + + +Nepomuk::Types::Ontology::Ontology( const QUrl& uri ) +{ + d = EntityManager::self()->getOntology( uri ); +} + + +Nepomuk::Types::Ontology::Ontology( const Ontology& other ) + : Entity( other ) +{ +} + + +Nepomuk::Types::Ontology::~Ontology() +{ +} + + +Nepomuk::Types::Ontology& Nepomuk::Types::Ontology::operator=( const Ontology& other ) +{ + d = other.d; + return *this; +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Ontology::allClasses() +{ + D->initEntities(); + return D->classes; +} + + +Nepomuk::Types::Class Nepomuk::Types::Ontology::findClassByName( const QString& name ) +{ + D->initEntities(); + for ( QList<Class>::const_iterator it = D->classes.constBegin(); + it != D->classes.constEnd(); ++it ) { + const Class& c = *it; + if ( c.name() == name ) { + return c; + } + } + + return Class(); +} + + +Nepomuk::Types::Class Nepomuk::Types::Ontology::findClassByLabel( const QString& label, const QString& language ) +{ + D->initEntities(); + for ( QList<Class>::iterator it = D->classes.begin(); + it != D->classes.end(); ++it ) { + Class& c = *it; + if ( c.label( language ) == label ) { + return c; + } + } + + return Class(); +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Ontology::allProperties() +{ + D->initEntities(); + return D->properties; +} + + +Nepomuk::Types::Property Nepomuk::Types::Ontology::findPropertyByName( const QString& name ) +{ + D->initEntities(); + for ( QList<Property>::const_iterator it = D->properties.constBegin(); + it != D->properties.constEnd(); ++it ) { + const Property& p = *it; + if ( p.name() == name ) { + return p; + } + } + + return Property(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Ontology::findPropertyByLabel( const QString& label, const QString& language ) +{ + D->initEntities(); + for ( QList<Property>::iterator it = D->properties.begin(); + it != D->properties.end(); ++it ) { + Property& p = *it; + if ( p.label( language ) == label ) { + return p; + } + } + + return Property(); +} + + + +// Start of code for deprecated Ontology +// ------------------------------------- +#include "global.h" +#include "ontologymanager.h" + + +Nepomuk::Ontology::Ontology() +{ + d = new Private; +} + + +Nepomuk::Ontology::Ontology( const Ontology& other ) +{ + d = other.d; +} + + +Nepomuk::Ontology::~Ontology() +{ +} + + +Nepomuk::Ontology& Nepomuk::Ontology::operator=( const Ontology& other) +{ + d = other.d; + return *this; +} + + +QUrl Nepomuk::Ontology::uri() const +{ + return d->uri; +} + + +QList<const Nepomuk::Class*> Nepomuk::Ontology::allClasses() const +{ + return d->classes.values(); +} + + +const Nepomuk::Class* Nepomuk::Ontology::findClassByName( const QString& name ) const +{ + for ( QHash<QUrl, const Class*>::const_iterator it = d->classes.constBegin(); + it != d->classes.constEnd(); ++it ) { + const Class* c = it.value(); + if ( c->name() == name ) { + return c; + } + } + + return 0; +} + + +const Nepomuk::Class* Nepomuk::Ontology::findClassByLabel( const QString& label, const QString& language ) const +{ + for ( QHash<QUrl, const Class*>::const_iterator it = d->classes.constBegin(); + it != d->classes.constEnd(); ++it ) { + const Class* c = it.value(); + if ( c->label( language ) == label ) { + return c; + } + } + + return 0; +} + + +const Nepomuk::Class* Nepomuk::Ontology::findClassByUri( const QUrl& uri ) const +{ + QHash<QUrl, const Class*>::const_iterator it = d->classes.find( uri ); + if ( it != d->classes.constEnd() ) { + return it.value(); + } + else { + return 0; + } +} + + +QList<const Nepomuk::Property*> Nepomuk::Ontology::allProperties() const +{ + return d->properties.values(); +} + + +const Nepomuk::Property* Nepomuk::Ontology::findPropertyByName( const QString& name ) const +{ + for ( QHash<QUrl, const Property*>::const_iterator it = d->properties.constBegin(); + it != d->properties.constEnd(); ++it ) { + const Property* p = it.value(); + if ( p->name() == name ) { + return p; + } + } + + return 0; +} + + +const Nepomuk::Property* Nepomuk::Ontology::findPropertyByLabel( const QString& label, const QString& language ) const +{ + for ( QHash<QUrl, const Property*>::const_iterator it = d->properties.constBegin(); + it != d->properties.constEnd(); ++it ) { + const Property* p = it.value(); + if ( p->label( language ) == label ) { + return p; + } + } + + return 0; +} + + +const Nepomuk::Property* Nepomuk::Ontology::findPropertyByUri( const QUrl& uri ) const +{ + QHash<QUrl, const Property*>::const_iterator it = d->properties.find( uri ); + if ( it != d->properties.constEnd() ) { + return it.value(); + } + else { + return 0; + } +} + + +const Nepomuk::Ontology* Nepomuk::Ontology::load( const QUrl& uri ) +{ + // load the ontology in the cache + return OntologyManager::instance()->getOntology( uri ); +} Modification de propriétés sur nepomuk/types/ontology.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/ontologymanager.h =================================================================== --- nepomuk/types/ontologymanager.h (révision 0) +++ nepomuk/types/ontologymanager.h (révision 0) @@ -0,0 +1,99 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ONTOLOGY_MANAGER_H_ +#define _NEPOMUK_ONTOLOGY_MANAGER_H_ + +#include <QtCore/QUrl> + +#include "nepomuk_export.h" + +namespace Soprano { + class Statement; +} + +namespace Nepomuk { + + class OntologyLoader; + class Ontology; + + /** + * The OntologyManager is the central ontology cache handler. + * It is modeled as a singleton and its instance can be accessed + * through OntologyManager::instance. + * + * \deprecated Ontologies should be handled via the classes in + * Nepomuk::Types. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT OntologyManager + { + public: + ~OntologyManager(); + + static OntologyManager* instance(); + + /** + * Set an OntologyLoader to be used to retrieve + * the RDF statements that make up an ontology. + * + * By default Nepomuk uses a combination of the + * NepomukOntologyLoader and DesktopOntologyLoader + * where the NepomukOntologyLoader is the preferred + * one, i.e. only if it is not able to load the + * ontology DesktopOntologyLoader is used as a fallback. + * + * If an OntologyLoader is set no fallback loader will + * be used. Thus, to force one of the default loaders + * (for example the DesktopOntologyLoader) just do: + * + * \code + * OntologyManager::instance()->setOntologyLoader( new DesktopOntologyLoader() ); + * \endcode + * + * OntologyManager will take over ownership of loader. + * + * Overwriting the loader will delete any loader previously + * set via setOntologyLoader. + */ + void setOntologyLoader( OntologyLoader* loader ); + + /** + * Attempt to load the ontology referenced by uri. + * If the manager already has the ontology in the cache + * it is simply returned. Otherwise the manager tries + * to load the ontology from one of the configured + * OntologyLoader instances. + * + * \return The requested ontology or 0 in case it could + * not be found, i.e. none of the OntologyLoader instances + * could provide the RDF statements making up the ontology. + */ + const Ontology* getOntology( const QUrl& uri ); + + private: + OntologyManager(); + + Ontology* constructOntology( const QUrl& uri, const QList<Soprano::Statement>& sl ); + + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/types/ontologymanager.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/entitymanager.h =================================================================== --- nepomuk/types/entitymanager.h (révision 0) +++ nepomuk/types/entitymanager.h (révision 0) @@ -0,0 +1,69 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ENTITY_MANAGER_H_ +#define _NEPOMUK_ENTITY_MANAGER_H_ + +#include <QtCore/QHash> +#include <QtCore/QUrl> +#include <QtCore/QSharedData> +#include <QtCore/QMutex> + + +namespace Soprano { + class Statement; +} + +namespace Nepomuk { + namespace Types { + class EntityPrivate; + class ClassPrivate; + class PropertyPrivate; + class OntologyPrivate; + + /** + * Cache for all loaded entities. + */ + class EntityManager + { + public: + EntityManager(); + + ClassPrivate* getClass( const QUrl& uri ); + PropertyPrivate* getProperty( const QUrl& uri ); + OntologyPrivate* getOntology( const QUrl& uri ); + + static EntityManager* self(); + + private: + EntityPrivate* findEntity( const QUrl& uri ) const; + ClassPrivate* findClass( const QUrl& uri ) const; + PropertyPrivate* findProperty( const QUrl& uri ) const; + OntologyPrivate* findOntology( const QUrl& uri ) const; + + QHash<QUrl, QExplicitlySharedDataPointer<ClassPrivate> > m_classMap; + QHash<QUrl, QExplicitlySharedDataPointer<PropertyPrivate> > m_propertyMap; + QHash<QUrl, QExplicitlySharedDataPointer<OntologyPrivate> > m_ontologyMap; + + QMutex m_mutex; + }; + } +} + +#endif Modification de propriétés sur nepomuk/types/entitymanager.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/entity.cpp =================================================================== --- nepomuk/types/entity.cpp (révision 0) +++ nepomuk/types/entity.cpp (révision 0) @@ -0,0 +1,384 @@ +/* This file is part of the Nepomuk-KDE libraries + Copyright (c) 2007-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "entity.h" +#include "entity_p.h" +#include "resourcemanager.h" + +#include <QtCore/QHash> +#include <QtCore/QMutexLocker> + +#include <Soprano/QueryResultIterator> +#include <Soprano/Model> +#include <Soprano/Vocabulary/NRL> +#include <Soprano/Vocabulary/NAO> +#include <Soprano/Vocabulary/RDFS> + +#include <kicon.h> + + +Nepomuk::Types::EntityPrivate::EntityPrivate( const QUrl& uri_ ) + : mutex(QMutex::Recursive), + uri( uri_ ), + available( uri_.isValid() ? -1 : 0 ), + ancestorsAvailable( uri_.isValid() ? -1 : 0 ) +{ +} + + +void Nepomuk::Types::EntityPrivate::init() +{ + QMutexLocker lock( &mutex ); + + if ( available < 0 ) { + available = load() ? 1 : 0; + } +} + + +void Nepomuk::Types::EntityPrivate::initAncestors() +{ + QMutexLocker lock( &mutex ); + + if ( ancestorsAvailable < 0 ) { + ancestorsAvailable = loadAncestors() ? 1 : 0; + } +} + + +bool Nepomuk::Types::EntityPrivate::load() +{ + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?p ?o where { " + "graph ?g { <%1> ?p ?o . } . " + "{ ?g a <%2> . } UNION { ?g a <%3> . } . }") + .arg( QString::fromAscii( uri.toEncoded() ) ) + .arg( Soprano::Vocabulary::NRL::Ontology().toString() ) + .arg( Soprano::Vocabulary::NRL::KnowledgeBase().toString() ), + Soprano::Query::QueryLanguageSparql ); + while ( it.next() ) { + QUrl property = it.binding( "p" ).uri(); + Soprano::Node value = it.binding( "o" ); + + if ( property == Soprano::Vocabulary::RDFS::label() ) { + if ( value.language().isEmpty() ) { + label = value.toString(); + } + else if( value.language() == KGlobal::locale()->language() ) { + l10nLabel = value.toString(); + } + } + + else if ( property == Soprano::Vocabulary::RDFS::comment() ) { + if ( value.language().isEmpty() ) { + comment = value.toString(); + } + else if( value.language() == KGlobal::locale()->language() ) { + l10nComment = value.toString(); + } + } + + else if ( property == Soprano::Vocabulary::NAO::hasSymbol() ) { + icon = KIcon( value.toString() ); + } + + else { + addProperty( property, value ); + } + } + + return !it.lastError(); +} + + +bool Nepomuk::Types::EntityPrivate::loadAncestors() +{ + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?s ?p where { " + "graph ?g { ?s ?p <%1> . } . " + "{ ?g a <%2> . } UNION { ?g a <%3> . } . }") + .arg( QString::fromAscii( uri.toEncoded() ) ) + .arg( Soprano::Vocabulary::NRL::Ontology().toString() ) + .arg( Soprano::Vocabulary::NRL::KnowledgeBase().toString() ), + Soprano::Query::QueryLanguageSparql ); + while ( it.next() ) { + addAncestorProperty( it.binding( "s" ).uri(), it.binding( "p" ).uri() ); + } + + return !it.lastError(); +} + + + +void Nepomuk::Types::EntityPrivate::reset( bool ) +{ + QMutexLocker lock( &mutex ); + + label.truncate(0); + comment.truncate(0); + l10nLabel.truncate(0); + l10nComment.truncate(0);; + + icon = QIcon(); + + available = -1; + ancestorsAvailable = -1; +} + + +Nepomuk::Types::Entity::Entity() +{ +} + + +Nepomuk::Types::Entity::Entity( const Entity& other ) +{ + d = other.d; +} + + +Nepomuk::Types::Entity::~Entity() +{ +} + + +Nepomuk::Types::Entity& Nepomuk::Types::Entity::operator=( const Entity& other ) +{ + d = other.d; + return *this; +} + + +QUrl Nepomuk::Types::Entity::uri() const +{ + return d ? d->uri : QUrl(); +} + + +QString Nepomuk::Types::Entity::name() const +{ + return d ? (d->uri.fragment().isEmpty() ? d->uri.toString().section('/',-1) : d->uri.fragment() ) : QString(); +} + + +QString Nepomuk::Types::Entity::label( const QString& language ) +{ + if ( d ) { + d->init(); + + if ( language == KGlobal::locale()->language() && + !d->l10nLabel.isEmpty() ) { + return d->l10nLabel; + } + else if( !d->label.isEmpty() ) { + return d->label; + } + else { + return name(); + } + } + else { + return QString(); + } +} + + +QString Nepomuk::Types::Entity::label( const QString& language ) const +{ + return const_cast<Entity*>(this)->label( language ); +} + + +QString Nepomuk::Types::Entity::comment( const QString& language ) +{ + if ( d ) { + d->init(); + + if ( language == KGlobal::locale()->language() && + !d->l10nComment.isEmpty() ) { + return d->l10nComment; + } + else { + return d->comment; + } + } + else { + return QString(); + } +} + + +QString Nepomuk::Types::Entity::comment( const QString& language ) const +{ + return const_cast<Entity*>(this)->comment( language ); +} + + +QIcon Nepomuk::Types::Entity::icon() +{ + if ( d ) { + d->init(); + + return d->icon; + } + else { + return QIcon(); + } +} + + +QIcon Nepomuk::Types::Entity::icon() const +{ + return const_cast<Entity*>(this)->icon(); +} + + +bool Nepomuk::Types::Entity::isValid() const +{ + return d ? d->uri.isValid() : false; +} + + +bool Nepomuk::Types::Entity::isAvailable() +{ + if ( d ) { + d->init(); + return d->available == 1; + } + else { + return false; + } +} + + +bool Nepomuk::Types::Entity::isAvailable() const +{ + return const_cast<Entity*>(this)->isAvailable(); +} + + +void Nepomuk::Types::Entity::reset( bool recursive ) +{ + d->reset( recursive ); +} + + +bool Nepomuk::Types::Entity::operator==( const Entity& other ) const +{ + // since we use one instace cache we can improve comparation operations + // intensly by not comparing URLs but pointers. + return( d.constData() == other.d.constData() ); +} + + +bool Nepomuk::Types::Entity::operator==( const QUrl& other ) const +{ + // since we use one instace cache we can improve comparation operations + // intensly by not comparing URLs but pointers. + return( d.constData()->uri == other ); +} + + +bool Nepomuk::Types::Entity::operator!=( const Entity& other ) const +{ + // since we use one instace cache we can improve comparation operations + // intensly by not comparing URLs but pointers. + return( d.constData() != other.d.constData() ); +} + + +bool Nepomuk::Types::Entity::operator!=( const QUrl& other ) const +{ + // since we use one instace cache we can improve comparation operations + // intensly by not comparing URLs but pointers. + return( d.constData()->uri != other ); +} + + + +#ifndef DISABLE_NEPOMUK_LEGACY + +// Code for old deprecated Entity class +// ------------------------------------------- +Nepomuk::Entity::Entity() +{ + d = new Private(); +} + +Nepomuk::Entity::Entity( const Entity& other ) +{ + d = other.d; +} + + +Nepomuk::Entity::~Entity() +{ +} + + +Nepomuk::Entity& Nepomuk::Entity::operator=( const Entity& other ) +{ + d = other.d; + return *this; +} + + +const Nepomuk::Ontology* Nepomuk::Entity::definingOntology() const +{ + return d->ontology; +} + + +QUrl Nepomuk::Entity::uri() const +{ + return d->uri; +} + + +QString Nepomuk::Entity::name() const +{ + return d->uri.fragment(); +} + + +QString Nepomuk::Entity::label( const QString& language ) const +{ + QHash<QString, QString>::const_iterator it = d->l10nLabels.find( language ); + if ( it != d->l10nLabels.constEnd() ) { + return it.value(); + } + else { + return d->label; + } +} + + +QString Nepomuk::Entity::comment( const QString& language ) const +{ + QHash<QString, QString>::const_iterator it = d->l10nComments.find( language ); + if ( it != d->l10nComments.constEnd() ) { + return it.value(); + } + else { + return d->comment; + } +} + +#endif // DISABLE_NEPOMUK_LEGACY + Modification de propriétés sur nepomuk/types/entity.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/ontology.h =================================================================== --- nepomuk/types/ontology.h (révision 0) +++ nepomuk/types/ontology.h (révision 0) @@ -0,0 +1,238 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ONTOLOGY_H_ +#define _NEPOMUK_ONTOLOGY_H_ + +#include <QtCore/QList> +#include <QtCore/QUrl> +#include <QtCore/QString> +#include <QtCore/QSharedData> + +#include "entity.h" +#include "nepomuk_export.h" + + +namespace Nepomuk { + namespace Types { + + class Class; + class Property; + + /** + * \class Ontology ontology.h Nepomuk/Types/Ontology + * + * \brief Represents one ontology. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Ontology : public Entity + { + public: + /** + * Default constructor. Creates an empty Ontology. + */ + Ontology(); + + /** + * Create the ontology referred to by \p uri. + * The result is either a valid ontology which could be loaded from the + * Nepomuk store or a simple class which only contains the uri. + * + * Be aware that the data is only loaded once read. + * + * Subsequent calls result in a simple hash lookup of cached data. + */ + Ontology( const QUrl& uri ); + + /** + * Default copy constructor + */ + Ontology( const Ontology& ); + + /** + * Destructor + */ + ~Ontology(); + + Ontology& operator=( const Ontology& ); + + /** + * All classes defined in this ontology, i.e. its namespace. + */ + QList<Class> allClasses(); + + /** + * Search for a class in the ontology by its name. + * \param name The name of the class. + * \return the Class object identified by name or an invalid one if the class could not be found. + */ + Class findClassByName( const QString& name ); + + /** + * Search for a class in the ontology by its label. + * \param label The label of the class (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Class object identified by label or an invalid one if the class could not be found. + */ + Class findClassByLabel( const QString& label, const QString& language = QString() ); + + /** + * A list of all properties defined in this ontology. This does not include properties that use + * classes of this ontology but are defined in a different one. + */ + QList<Property> allProperties(); + + /** + * Search for a property in the ontology by its name. + * \param name The name of the property. + * \return the Property object identified by name or an invalid one if the property could not be found. + */ + Property findPropertyByName( const QString& name ); + + /** + * Search for a property in the ontology by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or an invalid one if the property could not be found. + */ + Property findPropertyByLabel( const QString& label, const QString& language = QString() ); + }; + } +} + + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + + class Class; + class Property; + + /** + * Ontology represents one ontology specified using NRL. + * + * \deprecated in favor of Nepomuk::Types::Ontology + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Ontology + { + public: + /** + * Default constructor. Creates an empty Ontology. + */ + Ontology(); + + /** + * Default copy constructor + */ + Ontology( const Ontology& ); + + /** + * Destructor + */ + ~Ontology(); + + Ontology& operator=( const Ontology& ); + + /** + * The URI of the ontology, i.e. its namespace + */ + QUrl uri() const; + + /** + * All classes defined in this ontology, i.e. its namespace. + */ + QList<const Class*> allClasses() const; + + /** + * Search for a class in the ontology by its name. + * \param name The name of the class. + * \return the Class object identified by name or 0 if the class could not be found. + */ + const Class* findClassByName( const QString& name ) const; + + /** + * Search for a class in the ontology by its label. + * \param label The label of the class (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Class object identified by label or 0 if the class could not be found. + */ + const Class* findClassByLabel( const QString& label, const QString& language = QString() ) const; + + /** + * Search for a class in the ontology by its name. + * \param uri the URI of the class + * \return the Class object identified by uri or 0 if the class could not be found. + */ + const Class* findClassByUri( const QUrl& uri ) const; + + /** + * A list of all properties defined in this ontology. This does not include properties that use + * classes of this ontology but are defined in a different one. + */ + QList<const Property*> allProperties() const; + + /** + * Search for a property in the ontology by its name. + * \param name The name of the property. + * \return the Property object identified by name or 0 if the property could not be found. + */ + const Property* findPropertyByName( const QString& name ) const; + + /** + * Search for a property in the ontology by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or 0 if the property could not be found. + */ + const Property* findPropertyByLabel( const QString& label, const QString& language = QString() ) const; + + /** + * Search for a property in the ontology by its name. + * \param uri the URI of the property + * \return the Property object identified by uri or 0 if the property could not be found. + */ + const Property* findPropertyByUri( const QUrl& uri ) const; + + /** + * Loads an ontology. + * + * Dependancies are resolved automatically if possible. + * + * \return An Ontology object representing the ontology identified + * by uri or an invalid Ontology object if the resource identified + * by uri is either not an ontology or does not exist. + */ + static const Ontology* load( const QUrl& uri ); + + private: + class Private; + QSharedDataPointer<Private> d; + + friend class OntologyManager; + }; +} + +#endif // DISABLE_NEPOMUK_LEGACY + +#endif Modification de propriétés sur nepomuk/types/ontology.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/literal_p.h =================================================================== --- nepomuk/types/literal_p.h (révision 0) +++ nepomuk/types/literal_p.h (révision 0) @@ -0,0 +1,52 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_LITERAL_PRIVATE_H_ +#define _NEPOMUK_LITERAL_PRIVATE_H_ + +#include "literal.h" + +#include <QtCore/QUrl> +#include <QtCore/QVariant> +#include <QtCore/QSharedData> + +class Nepomuk::Types::Literal::Private : public QSharedData +{ + public: + Private() + : dataType( QVariant::Invalid ) { + } + + QUrl dataTypeUri; + QVariant::Type dataType; +}; + + +class Nepomuk::Literal::Private : public QSharedData +{ + public: + Private() + : dataType( QVariant::Invalid ) { + } + + QUrl dataTypeUri; + QVariant::Type dataType; +}; + +#endif Modification de propriétés sur nepomuk/types/literal_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/entity.h =================================================================== --- nepomuk/types/entity.h (révision 0) +++ nepomuk/types/entity.h (révision 0) @@ -0,0 +1,297 @@ +/* This file is part of the Nepomuk-KDE libraries + Copyright (c) 2007-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NEPOMUK_ENTITY_H_ +#define _NEPOMUK_ENTITY_H_ + +#include <QtCore/QUrl> +#include <QtCore/QString> +#include <QtCore/QSharedData> +#include <QtCore/QHash> + +#include <Soprano/Node> + +#include <kglobal.h> +#include <klocale.h> + +#include "nepomuk_export.h" + +class QIcon; + + +namespace Nepomuk { + namespace Types { + class EntityPrivate; + + /** + * \brief Abstract base class for Class and Property; + * + * Base class for static ontology entities Class and Property. + * It encapsulates the generic labels and comments that both + * types have. + * + * Due to internal optimizations comparing two Entities is much + * faster than comparing two QUrl objects. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Entity + { + public: + /** + * Default copy constructor. + */ + Entity( const Entity& ); + + /** + * Destructor. + */ + virtual ~Entity(); + + /** + * Copy operator. + */ + Entity& operator=( const Entity& ); + + /** + * The name of the resource. The name equals the fragment of the + * URI. + */ + QString name() const; + + /** + * The URI of the resource + */ + QUrl uri() const; + + /** + * Retrieve the label of the entity (rdfs:label) + * + * \param language The code of the language to use. Defaults to the session + * language configured in KDE. As of KDE 4.3 only the currently + * configured language is loaded to save memory. + * + * \return The label translated into \p language or the default fallback label + * if no translation is available or the name() if no label could be found + * at all. + */ + QString label( const QString& language = KGlobal::locale()->language() ); + + /** + * Retrieve the label of the entity (rdfs:label) + * + * \param language The code of the language to use. Defaults to the session + * language configured in KDE. As of KDE 4.3 only the currently + * configured language is loaded to save memory. + * + * \return The label translated into \p language or the default fallback label + * if no translation is available or the name() if no label could be found + * at all. + * + * Const version + * + * \since 4.4 + */ + QString label( const QString& language = KGlobal::locale()->language() ) const; + + /** + * Retrieve the comment of the entity (rdfs:comment) + * + * \param language The code of the language to use. Defaults to the session + * language configured in KDE. As of KDE 4.3 only the currently + * configured language is loaded to save memory. + * + * \return The comment translated into \p language or the default fallback comment + * if no translation is available or an empty string if no comment could be found + * at all. + */ + QString comment( const QString& language = KGlobal::locale()->language() ); + + /** + * Retrieve the comment of the entity (rdfs:comment) + * + * \param language The code of the language to use. Defaults to the session + * language configured in KDE. As of KDE 4.3 only the currently + * configured language is loaded to save memory. + * + * \return The comment translated into \p language or the default fallback comment + * if no translation is available or an empty string if no comment could be found + * at all. + * + * Const version + * + * \since 4.4 + */ + QString comment( const QString& language = KGlobal::locale()->language() ) const; + + /** + * Retrieve the icon stored for the entity (nao:hasSymbol) + * + * If no symbol is defined for the entity a null icon will be returned. + * + * \since 4.1 + */ + QIcon icon(); + + /** + * Retrieve the icon stored for the entity (nao:hasSymbol) + * + * If no symbol is defined for the entity a null icon will be returned. + * + * Const version. + * + * \since 4.4 + */ + QIcon icon() const; + + /** + * Is this a valid Entity, i.e. has it a valid URI. + * A valid Entity does not necessarily have a label and a comment, it + * does not even have to exist in the Nepomuk store. + * + * \sa isAvailable + */ + bool isValid() const; + + /** + * Is this Entity available locally, i.e. could its properties + * be loaded from the Nepomuk store. + */ + bool isAvailable(); + + /** + * Is this Entity available locally, i.e. could its properties + * be loaded from the Nepomuk store. + * + * Const version. + * + * \since 4.4 + */ + bool isAvailable() const; + + /** + * The Types classes are optimized for performance under the + * aasumption that ontologies never change during the execution + * time of an application. + * + * Since there might be situations where this does not apply + * the internal cache can be reset via this method. + * + * \param recursive If \p true all related entities will be reset + * as well. + * + * \since 4.1 + */ + void reset( bool recursive = false ); + + /** + * An Entity can be used as a QUrl automagically. + */ + operator QUrl() const { return uri(); } + + /** + * Compares two Entity instances by simply comparing their URI. + */ + bool operator==( const Entity& other ) const; + + /** + * Compares the Entity with a URI. + * + * \since 4.5 + */ + bool operator==( const QUrl& other ) const; + + /** + * Compares two Entity instances by simply comparing their URI. + */ + bool operator!=( const Entity& other ) const; + + /** + * Compares the Entity with a URI. + * + * \since 4.5 + */ + bool operator!=( const QUrl& other ) const; + + protected: + /** + * Create an invalid Entity instance. + */ + Entity(); + + QExplicitlySharedDataPointer<EntityPrivate> d; + }; + + inline uint qHash( const Entity& c ) + { + return qHash( c.uri() ); + } + } +} + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + + class Ontology; + + /** + * \deprecated in favor of Nepomuk::Types::Entity + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Entity + { + public: + Entity( const Entity& ); + ~Entity(); + + Entity& operator=( const Entity& ); + + /** + * The ontology in which the resource is defined. + */ + const Ontology* definingOntology() const; + + /** + * The name of the resource. The name equals the fragment of the + * URI. + */ + QString name() const; + + /** + * The URI of the resource + */ + QUrl uri() const; + + QString label( const QString& language = QString() ) const; + QString comment( const QString& language = QString() ) const; + + protected: + Entity(); + + private: + class Private; + QSharedDataPointer<Private> d; + + friend class OntologyManager; + }; +} + +#endif // DISABLE_NEPOMUK_LEGACY + +#endif // _NEPOMUK_ENTITY_H_ Modification de propriétés sur nepomuk/types/entity.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/property.cpp =================================================================== --- nepomuk/types/property.cpp (révision 0) +++ nepomuk/types/property.cpp (révision 0) @@ -0,0 +1,565 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "property.h" +#include "property_p.h" +#include "class.h" +#include "ontology.h" +#include "literal.h" +#include "entitymanager.h" + +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/NRL> +#include <Soprano/Vocabulary/XMLSchema> + +#undef D +#define D static_cast<Nepomuk::Types::PropertyPrivate*>( d.data() ) + +Nepomuk::Types::PropertyPrivate::PropertyPrivate( const QUrl& uri ) + : EntityPrivate( uri ), + minCardinality( -1 ), + maxCardinality( -1 ), + cardinality( -1 ) +{ +} + + +bool Nepomuk::Types::PropertyPrivate::addProperty( const QUrl& property, const Soprano::Node& value ) +{ + // we avoid subclassing loops (as created for crappy inferencing) by checking for our own uri + if( value.isResource() && + value.uri() != uri && + property == Soprano::Vocabulary::RDFS::subPropertyOf() ) { + parents.append( value.uri() ); + return true; + } + + else if( property == Soprano::Vocabulary::RDFS::domain() ) { + domain = value.uri(); + return true; + } + + else if( property == Soprano::Vocabulary::RDFS::range() ) { + if ( value.toString().startsWith( Soprano::Vocabulary::XMLSchema::xsdNamespace().toString() ) ) { + literalRange = Literal( value.uri() ); + } + else if ( value.uri() == Soprano::Vocabulary::RDFS::Literal()) { + literalRange = Literal( value.uri() ); + } + else { + range = value.uri(); + } + return true; + } + + else if( property == Soprano::Vocabulary::NRL::minCardinality() ) { + minCardinality = value.literal().toInt(); + return true; + } + + else if( property == Soprano::Vocabulary::NRL::maxCardinality() ) { + maxCardinality = value.literal().toInt(); + return true; + } + + else if ( property == Soprano::Vocabulary::NRL::cardinality() ) { + cardinality = value.literal().toInt(); + return true; + } + + else if ( property == Soprano::Vocabulary::NRL::inverseProperty() ) { + inverse = value.uri(); + return true; + } + + return false; +} + + +bool Nepomuk::Types::PropertyPrivate::addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ) +{ + // we avoid subclassing loops (as created for crappy inferencing) by checking for our own uri + if( property == Soprano::Vocabulary::RDFS::subPropertyOf() && + ancestorResource != uri ) { + children.append( ancestorResource ); + return true; + } + else if ( property == Soprano::Vocabulary::NRL::inverseProperty() ) { + inverse = ancestorResource; + return true; + } + + return false; +} + + +void Nepomuk::Types::PropertyPrivate::reset( bool recursive ) +{ + QMutexLocker lock( &mutex ); + + if ( available != -1 ) { + if ( recursive ) { + range.reset( true ); + domain.reset( true ); + inverse.reset( true ); + foreach( Property p, parents ) { + p.reset( true ); + } + } + + parents.clear(); + available = -1; + } + + if ( ancestorsAvailable != -1 ) { + if ( recursive ) { + foreach( Property p, children ) { + p.reset( true ); + } + } + + children.clear(); + ancestorsAvailable = -1; + } + + EntityPrivate::reset( recursive ); +} + + + +Nepomuk::Types::Property::Property() + : Entity() +{ + d = 0; +} + + +Nepomuk::Types::Property::Property( const QUrl& uri ) + : Entity() +{ + d = EntityManager::self()->getProperty( uri ); +} + + +Nepomuk::Types::Property::Property( const Property& other ) + : Entity( other ) +{ +} + + +Nepomuk::Types::Property::~Property() +{ +} + + +Nepomuk::Types::Property& Nepomuk::Types::Property::operator=( const Property& other ) +{ + d = other.d; + return *this; +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Property::parentProperties() +{ + if ( d ) { + D->init(); + return D->parents; + } + else { + return QList<Nepomuk::Types::Property>(); + } +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Property::parentProperties() const +{ + return const_cast<Property*>(this)->parentProperties(); +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Property::subProperties() +{ + if ( d ) { + D->initAncestors(); + return D->children; + } + else { + return QList<Nepomuk::Types::Property>(); + } +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Property::subProperties() const +{ + return const_cast<Property*>(this)->subProperties(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Property::inverseProperty() +{ + if ( d ) { + D->init(); + D->initAncestors(); + return D->inverse; + } + else { + return Property(); + } +} + + +Nepomuk::Types::Property Nepomuk::Types::Property::inverseProperty() const +{ + return const_cast<Property*>(this)->inverseProperty(); +} + + +Nepomuk::Types::Class Nepomuk::Types::Property::range() +{ + if ( d ) { + D->init(); + + if( D->range.isValid() ) { + return D->range; + } + else if( !literalRangeType().isValid() ) { + // try getting a domain from one of the parent properties + for( int i = 0; i < D->parents.count(); ++i ) { + Class pr = D->parents[i].range(); + if( pr.isValid() ) { + return pr; + } + } + + // if we have no literal range type, we fall back to rdfs:Resource + return Class( Soprano::Vocabulary::RDFS::Resource() ); + } + else { + // other than domain() we do not use a general fallback since the range + // might be a literalRangeType() + return Class(); + } + } + else { + return Class(); + } +} + + +Nepomuk::Types::Class Nepomuk::Types::Property::range() const +{ + return const_cast<Property*>(this)->range(); +} + + +Nepomuk::Types::Literal Nepomuk::Types::Property::literalRangeType() +{ + if ( d ) { + D->init(); + + if( D->literalRange.isValid() ) { + return D->literalRange; + } + else { + // try getting a domain from one of the parent properties + // We cannot check the resource range here since that would + // result in an endless loop + for( int i = 0; i < D->parents.count(); ++i ) { + Literal pr = D->parents[i].literalRangeType(); + if( pr.isValid() ) { + return pr; + } + } + + // fallback is an invalid range which will then result in + // range() returning a valid one + return Literal(); + } + } + else { + return Literal(); + } +} + + +Nepomuk::Types::Literal Nepomuk::Types::Property::literalRangeType() const +{ + return const_cast<Property*>(this)->literalRangeType(); +} + + +Nepomuk::Types::Class Nepomuk::Types::Property::domain() +{ + if ( d ) { + D->init(); + + if( D->domain.isValid() ) { + return D->domain; + } + else { + // try getting a domain from one of the parent properties + for( int i = 0; i < D->parents.count(); ++i ) { + Class pd = D->parents[i].domain(); + if( pd.isValid() ) { + return pd; + } + } + + // fallback: rdfs:Resource + return Class( Soprano::Vocabulary::RDFS::Resource() ); + } + } + else { + return Class(); + } +} + + +Nepomuk::Types::Class Nepomuk::Types::Property::domain() const +{ + return const_cast<Property*>(this)->domain(); +} + + +int Nepomuk::Types::Property::cardinality() +{ + if ( d ) { + D->init(); + return D->cardinality; + } + else { + return -1; + } +} + + +int Nepomuk::Types::Property::cardinality() const +{ + return const_cast<Property*>(this)->cardinality(); +} + + +int Nepomuk::Types::Property::minCardinality() +{ + if ( d ) { + D->init(); + if ( D->minCardinality > 0 ) { + return D->minCardinality; + } + else { + return D->cardinality; + } + } + else { + return -1; + } +} + + +int Nepomuk::Types::Property::minCardinality() const +{ + return const_cast<Property*>(this)->minCardinality(); +} + + +int Nepomuk::Types::Property::maxCardinality() +{ + if ( d ) { + D->init(); + if ( D->maxCardinality > 0 ) { + return D->maxCardinality; + } + else { + return D->cardinality; + } + } + else { + return -1; + } +} + + +int Nepomuk::Types::Property::maxCardinality() const +{ + return const_cast<Property*>(this)->maxCardinality(); +} + + +bool Nepomuk::Types::Property::isParentOf( const Property& other ) +{ + if ( d ) { + D->initAncestors(); + + if ( D->children.contains( other ) ) { + return true; + } + else { + for ( QList<Nepomuk::Types::Property>::iterator it = D->children.begin(); + it != D->children.end(); ++it ) { + if ( ( *it ).isParentOf( other ) ) { + return true; + } + } + } + } + + return false; +} + + +bool Nepomuk::Types::Property::isParentOf( const Property& other ) const +{ + return const_cast<Property*>(this)->isParentOf( other ); +} + + +bool Nepomuk::Types::Property::isSubPropertyOf( const Property& other ) +{ + if ( d ) { + D->init(); + + if ( D->parents.contains( other ) ) { + return true; + } + else { + for ( QList<Nepomuk::Types::Property>::iterator it = D->parents.begin(); + it != D->parents.end(); ++it ) { + if ( ( *it ).isSubPropertyOf( other ) ) { + return true; + } + } + } + } + + return false; +} + + +bool Nepomuk::Types::Property::isSubPropertyOf( const Property& other ) const +{ + return const_cast<Property*>(this)->isSubPropertyOf( other ); +} + + + +#ifndef DISABLE_NEPOMUK_LEGACY + +// Start of code for deprecated Property +// ------------------------------------- +#include "global.h" +#include "ontologymanager.h" + +Nepomuk::Property::Property() + : Entity() +{ + d = new Private(); +} + + +Nepomuk::Property::Property( const Property& other ) + : Entity( other ) +{ + d = other.d; +} + + +Nepomuk::Property::~Property() +{ +} + + +Nepomuk::Property& Nepomuk::Property::operator=( const Property& other ) +{ + d = other.d; + return *this; +} + + +QList<const Nepomuk::Property*> Nepomuk::Property::parentProperties() const +{ + return d->parents; +} + + +QList<const Nepomuk::Property*> Nepomuk::Property::parentOf() const +{ + return d->children; +} + + +const Nepomuk::Property* Nepomuk::Property::inverseProperty() const +{ + return d->inverse; +} + + +const Nepomuk::Class* Nepomuk::Property::range() const +{ + return d->range; +} + + +Nepomuk::Literal Nepomuk::Property::literalRangeType() const +{ + return d->literalRange; +} + + +const Nepomuk::Class* Nepomuk::Property::domain() const +{ + return d->domain; +} + + +int Nepomuk::Property::cardinality() const +{ + return d->cardinality; +} + + +int Nepomuk::Property::minCardinality() const +{ + return d->minCardinality; +} + + +int Nepomuk::Property::maxCardinality() const +{ + return d->maxCardinality; +} + + +const Nepomuk::Property* Nepomuk::Property::load( const QUrl& uri ) +{ + QUrl ns = extractNamespace( uri ); + + // load the ontology in the cache + const Ontology* ont = OntologyManager::instance()->getOntology( ns ); + + // return the requested class or an invalid one if the ontology + // was not found + if ( ont ) { + return ont->findPropertyByUri( uri ); + } + else { + return 0; + } +} + +#endif // DISABLE_NEPOMUK_LEGACY Modification de propriétés sur nepomuk/types/property.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/class_p.h =================================================================== --- nepomuk/types/class_p.h (révision 0) +++ nepomuk/types/class_p.h (révision 0) @@ -0,0 +1,84 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_CLASS_PRIVATE_H_ +#define _NEPOMUK_CLASS_PRIVATE_H_ + +#include "entity_p.h" +#include "class.h" +#include "property.h" + +#include <QtCore/QHash> +#include <QtCore/QSharedData> + + +namespace Nepomuk { + namespace Types { + class ClassPrivate : public EntityPrivate + { + public: + ClassPrivate( const QUrl& uri = QUrl() ); + + QList<Property> domainOf; + QList<Property> rangeOf; + + QList<Class> parents; + QList<Class> children; + + // -1 - unknown + // 0 - no + // 1 - yes + int propertiesAvailable; + + bool addProperty( const QUrl& property, const Soprano::Node& value ); + bool addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ); + + void initProperties(); + bool loadProperties(); + + void reset( bool recursive ); + + // recursively find all parent or sub classes but stop at requestingClass to avoid endless loops + QSet<Class> findParentClasses( ClassPrivate* requestingClass ); + QSet<Class> findSubClasses( ClassPrivate* requestingClass ); + + protected: + virtual bool load(); + virtual bool loadAncestors(); + }; + } +} + + +namespace Nepomuk { + + class Property; + + class Class::Private : public QSharedData + { + public: + QHash<QUrl, const Property*> domainOf; + QHash<QUrl, const Property*> rangeOf; + + QList<const Nepomuk::Class*> parents; + QList<const Nepomuk::Class*> children; + }; +} + +#endif Modification de propriétés sur nepomuk/types/class_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/property.h =================================================================== --- nepomuk/types/property.h (révision 0) +++ nepomuk/types/property.h (révision 0) @@ -0,0 +1,428 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_PROPERTY_H_ +#define _NEPOMUK_PROPERTY_H_ + +#include <QtCore/QList> +#include <QtCore/QUrl> +#include <QtCore/QString> +#include <QtCore/QVariant> +#include <QtCore/QSharedData> + +#include "entity.h" +#include "nepomuk_export.h" + +namespace Nepomuk { + namespace Types { + + class Class; + class Literal; + + /** + * \class Property property.h Nepomuk/Types/Property + * + * \brief A property is a resource of type rdf:Property which relates a domain + * with a range. The latter one can be a Literal or a Class. + * + * Property instances are explicitly shared. Two instances created + * with the same uri reference the same data. + * + * While Resource objects can be changed Property instances are considered + * to be static and never changed during their lifetime. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Property : public Entity + { + public: + /** + * Default constructor. Creates an empty Property. + */ + Property(); + + /** + * Create the property referred to by \p uri. + * The result is either a valid property which could be loaded from the + * Nepomuk store or a simple property which only contains the uri. + * + * Be aware that the data is only loaded once read. + * + * Subsequent calls result in a simple hash lookup of cached data. + */ + Property( const QUrl& uri ); + + /** + * Default copy constructor + */ + Property( const Property& ); + + /** + * Destructor + */ + ~Property(); + + /** + * Copy operator. + */ + Property& operator=( const Property& ); + + /** + * Each property can have multiple parent properties. + * \return A list of all parent properties of this property. + * If the list is emppty it means that the property has no direct + * parents, i.e. it is derived from rdf:Resource. + */ + QList<Property> parentProperties(); + + /** + * Each property can have multiple parent properties. + * \return A list of all parent properties of this property. + * If the list is emppty it means that the property has no direct + * parents, i.e. it is derived from rdf:Resource. + * + * Const version + * + * \since 4.4 + */ + QList<Property> parentProperties() const; + + /** + * \return A list of all properties that have this property as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain properties that are derived + * from this property. + */ + QList<Property> subProperties(); + + /** + * \return A list of all properties that have this property as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain properties that are derived + * from this property. + * + * Const version + * + * \since 4.4 + */ + QList<Property> subProperties() const; + + /** + * The inverse property (nrl:inverseProperty). + * \return A Property instance representing the inverse property of this one + * or 0 if none was specified in the ontology. + */ + Property inverseProperty(); + + /** + * The inverse property (nrl:inverseProperty). + * \return A Property instance representing the inverse property of this one + * or 0 if none was specified in the ontology. + * + * Const version + * + * \since 4.4 + */ + Property inverseProperty() const; + + /** + * The range of the property. + * \return The range of the property or an invalid Class in case + * the range of this poperty is a literal. + * \sa literalRange + */ + Class range(); + + /** + * The range of the property. + * \return The range of the property or an invalid Class in case + * the range of this poperty is a literal. + * \sa literalRange + * + * Const version + * + * \since 4.4 + */ + Class range() const; + + /** + * If the rage of this property is a literal (i.e. range returns an invalid Class) + * this method provides the literal type. + * + * \returns the literal type of this property or an empty, invalid Literal + * if the range is a Class. + * + * \sa range + */ + Literal literalRangeType(); + + /** + * If the rage of this property is a literal (i.e. range returns an invalid Class) + * this method provides the literal type. + * + * \returns the literal type of this property or an empty, invalid Literal + * if the range is a Class. + * + * \sa range + * + * Const version + * + * \since 4.4 + */ + Literal literalRangeType() const; + + /** + * The domain of the property. + */ + Class domain(); + + /** + * The domain of the property. + * + * Const version + * + * \since 4.4 + */ + Class domain() const; + + /** + * The cardinality of this property as specified by nrl:cardinality. + * + * \return the cardinality of the property or -1 if none was set. + */ + int cardinality(); + + /** + * The cardinality of this property as specified by nrl:cardinality. + * + * \return the cardinality of the property or -1 if none was set. + * + * Const version + * + * \since 4.4 + */ + int cardinality() const; + + /** + * The minimum cardinality of this property as specified by nrl:minCardinality. + * + * \return the minimum cardinality of the property or -1 if none was set. + */ + int minCardinality(); + + /** + * The minimum cardinality of this property as specified by nrl:minCardinality. + * + * \return the minimum cardinality of the property or -1 if none was set. + * + * Const version + * + * \since 4.4 + */ + int minCardinality() const; + + /** + * The maximum cardinality of this property as specified by nrl:maxCardinality. + * + * \return the maximum cardinality of the property or -1 if none was set. + */ + int maxCardinality(); + + /** + * The maximum cardinality of this property as specified by nrl:maxCardinality. + * + * \return the maximum cardinality of the property or -1 if none was set. + * + * Const version + * + * \since 4.4 + */ + int maxCardinality() const; + + /** + * Check if a property inherits this property. This is a recursive method which + * does not only check direct child propertyes. + * + * \return true if other is derived from this property, false otherwise. + */ + bool isParentOf( const Property& other ); + + /** + * Check if a property inherits this property. This is a recursive method which + * does not only check direct child propertyes. + * + * \return true if other is derived from this property, false otherwise. + * + * Const version + * + * \since 4.4 + */ + bool isParentOf( const Property& other ) const; + + /** + * Check if this property is derived from another property. This is a recursive method which + * does not only check direct child propertyes. + * + * \return true if this property is derived from other, false otherwise. + */ + bool isSubPropertyOf( const Property& other ); + + /** + * Check if this property is derived from another property. This is a recursive method which + * does not only check direct child propertyes. + * + * \return true if this property is derived from other, false otherwise. + * + * Const version + * + * \since 4.4 + */ + bool isSubPropertyOf( const Property& other ) const; + }; + } +} + + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + + class Ontology; + class Class; + class Literal; + + /** + * A property is a resource of type rdf:Property which relates a domain + * with a range. The latter one can be a literal in addition to a Class. + * + * \deprecated in favor of Nepomuk::Types::Property + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Property : public Entity + { + public: + /** + * Default constructor. Creates an empty Property. + */ + Property(); + + /** + * Default copy constructor + */ + Property( const Property& ); + + /** + * Destructor + */ + ~Property(); + + Property& operator=( const Property& ); + + /** + * Each property can have multiple parent properties. + * \return A list of all parent properties of this property. + * If the list is emppty it means that the property has no direct + * parents, i.e. it is derived from rdf:Resource. + */ + QList<const Property*> parentProperties() const; + + /** + * \return A list of all properties that have this property as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain properties that are derived + * from this property. + */ + QList<const Property*> parentOf() const; + + /** + * The inverse property (nrl:inverseProperty). + * \return A Property instance representing the inverse property of this one + * or 0 if none was specified in the ontology. + */ + const Property* inverseProperty() const; + + /** + * The range of the property. + * \return The range of the property or an invalid Class in case + * the range of this poperty is a literal. + * \sa literalRange + */ + const Class* range() const; + + /** + * If the rage of this property is a literal (i.e. range returns 0) + * this method provides the literal type. + * + * \returns the literal type of this property or an empty, invalid Literal + * if the range is a Class. + * + * \sa range + */ + Literal literalRangeType() const; + + /** + * The domain of the property. + */ + const Class* domain() const; + + /** + * The cardinality of this property as specified by nrl:cardinality. + * + * \return the cardinality of the property or -1 if none was set. + */ + int cardinality() const; + + /** + * The minimum cardinality of this property as specified by nrl:minCardinality. + * + * \return the minimum cardinality of the property or -1 if none was set. + */ + int minCardinality() const; + + /** + * The maximum cardinality of this property as specified by nrl:maxCardinality. + * + * \return the maximum cardinality of the property or -1 if none was set. + */ + int maxCardinality() const; + + // QString unit() const; + + /** + * Loads a property actually including the whole ontology + * it is declared in. + * + * Dependancies are resolved automatically if possible. + * + * \return A property object representing the property identified + * by uri or an invalid Property object if the resource identified + * by uri is either not a property or does not exist. + */ + static const Property* load( const QUrl& uri ); + + private: + class Private; + QSharedDataPointer<Private> d; + + friend class OntologyManager; + }; +} + +#endif // DISABLE_NEPOMUK_LEGACY + +#endif // _NEPOMUK_PROPERTY_H_ Modification de propriétés sur nepomuk/types/property.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/desktopontologyloader.cpp =================================================================== --- nepomuk/types/desktopontologyloader.cpp (révision 0) +++ nepomuk/types/desktopontologyloader.cpp (révision 0) @@ -0,0 +1,114 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "desktopontologyloader.h" +#include "fileontologyloader.h" + +#include <kstandarddirs.h> +#include <kdesktopfile.h> +#include <kconfiggroup.h> +#include <kdebug.h> +#include <kglobal.h> + +#include <QtCore/QDir> + +#include <soprano/statement.h> + +struct OntoBuffer +{ + QString fileName; + Soprano::RdfSerialization serialization; +}; + + +class Nepomuk::DesktopOntologyLoader::Private +{ +public: + Private() { + } + + void updateOntologyCache() { +// ontoCache.clear(); + + QStringList allOntologies = KGlobal::dirs()->findAllResources( "data", "nepomuk/ontologies/*.desktop" ); + foreach( const QString &ontoDesktopFilePath, allOntologies ) { + KDesktopFile ontoDesktopFile( ontoDesktopFilePath ); + + if ( ontoDesktopFile.hasLinkType() ) { + QUrl uri = ontoDesktopFile.readUrl(); + + if ( !ontoCache.contains( uri ) ) { + QString path = ontoDesktopFile.readPath(); + + // make it an absolute path + if ( path[0] != QDir::separator() ) { + path.prepend( ontoDesktopFilePath.section( QDir::separator(), + 0, -2, + QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep ) ); + } + + OntoBuffer onto; + onto.fileName = path; + onto.serialization = Soprano::mimeTypeToSerialization( ontoDesktopFile.desktopGroup().readEntry( "MimeType", "application/rdf+xml" ) ); + + kDebug() << "(Nepomuk::DesktopOntologyLoader) found ontology " << uri; + ontoCache.insert( uri, onto ); + } + } + } + } + + // contains the filename for each cached ontology + QHash<QUrl, OntoBuffer> ontoCache; +}; + + +Nepomuk::DesktopOntologyLoader::DesktopOntologyLoader() + : OntologyLoader(), + d( new Private() ) +{ +} + + +Nepomuk::DesktopOntologyLoader::~DesktopOntologyLoader() +{ + delete d; +} + + +QList<QUrl> Nepomuk::DesktopOntologyLoader::allOntologies() +{ + d->updateOntologyCache(); + return d->ontoCache.keys(); +} + + +QList<Soprano::Statement> Nepomuk::DesktopOntologyLoader::loadOntology( const QUrl& url ) +{ + d->updateOntologyCache(); + if ( d->ontoCache.contains( url ) ) { + const OntoBuffer& onto = d->ontoCache[url]; + FileOntologyLoader loader( onto.fileName, onto.serialization ); + return loader.loadOntology( url ); + } + else { + kDebug() << "(Nepomuk::DesktopOntologyLoader) could not find ontology " << url; + return QList<Soprano::Statement>(); + } +} Modification de propriétés sur nepomuk/types/desktopontologyloader.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/types/literal.cpp =================================================================== --- nepomuk/types/literal.cpp (révision 0) +++ nepomuk/types/literal.cpp (révision 0) @@ -0,0 +1,181 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "literal.h" +#include "literal_p.h" + +#include <QtCore/QHash> +#include <QtCore/QVariant> + +#include <Soprano/Vocabulary/RDFS> + +#include <kglobal.h> + + +namespace { +typedef QHash<QString, QVariant::Type> XmlSchemaMap; + +K_GLOBAL_STATIC(XmlSchemaMap, s_xmlSchemaTypes) + +void initXmlSchemaTypes() { + if( s_xmlSchemaTypes->isEmpty() ) { + s_xmlSchemaTypes->insert( "int", QVariant::Int ); + s_xmlSchemaTypes->insert( "integer", QVariant::Int ); + s_xmlSchemaTypes->insert( "negativeInteger", QVariant::Int ); + s_xmlSchemaTypes->insert( "decimal", QVariant::Int ); + s_xmlSchemaTypes->insert( "short", QVariant::Int ); + s_xmlSchemaTypes->insert( "long", QVariant::LongLong ); + s_xmlSchemaTypes->insert( "unsignedInt", QVariant::UInt ); + s_xmlSchemaTypes->insert( "unsignedShort", QVariant::UInt ); + s_xmlSchemaTypes->insert( "unsignedLong", QVariant::ULongLong ); + s_xmlSchemaTypes->insert( "boolean", QVariant::Bool ); + s_xmlSchemaTypes->insert( "double", QVariant::Double ); + s_xmlSchemaTypes->insert( "float", QVariant::Double ); + s_xmlSchemaTypes->insert( "string", QVariant::String ); + s_xmlSchemaTypes->insert( "date", QVariant::Date ); + s_xmlSchemaTypes->insert( "time", QVariant::Time ); + s_xmlSchemaTypes->insert( "dateTime", QVariant::DateTime ); + // s_xmlSchemaTypes->insert( "", QVariant::Url ); + } +} + +const XmlSchemaMap& xmlSchemaTypes() +{ + if(s_xmlSchemaTypes->isEmpty()) + initXmlSchemaTypes(); + return *s_xmlSchemaTypes; +} +} + + +Nepomuk::Types::Literal::Literal() +{ + d = new Private(); +} + + +Nepomuk::Types::Literal::Literal( const Literal& other ) +{ + d = other.d; +} + + +Nepomuk::Types::Literal::Literal( const QUrl& dataType ) +{ + d = new Private(); + d->dataTypeUri = dataType; + + // now determine the QVariant type + initXmlSchemaTypes(); + + // check if it is a known type, otherwise leave it as QVariant::Invalid + if ( dataType == Soprano::Vocabulary::RDFS::Literal() ) { + d->dataType = QVariant::String; + } + else { + QHash<QString, QVariant::Type>::const_iterator it = xmlSchemaTypes().constFind( dataType.fragment() ); + if ( it != xmlSchemaTypes().constEnd() ) { + d->dataType = it.value(); + } + } +} + + +Nepomuk::Types::Literal::~Literal() +{ +} + + +Nepomuk::Types::Literal& Nepomuk::Types::Literal::operator=( const Literal& other ) +{ + d = other.d; + return *this; +} + + +QUrl Nepomuk::Types::Literal::dataTypeUri() const +{ + return d->dataTypeUri; +} + + +QVariant::Type Nepomuk::Types::Literal::dataType() const +{ + return d->dataType; +} + + +bool Nepomuk::Types::Literal::isValid() const +{ + return d->dataTypeUri.isValid(); +} + + + + +Nepomuk::Literal::Literal() +{ + d = new Private(); +} + + +Nepomuk::Literal::Literal( const Literal& other ) +{ + d = other.d; +} + + +Nepomuk::Literal::Literal( const QUrl& dataType ) +{ + d = new Private(); + d->dataTypeUri = dataType; + + // now determine the QVariant type + initXmlSchemaTypes(); + + // check if it is a known type, otherwise leave it as QVariant::Invalid + QHash<QString, QVariant::Type>::const_iterator it = xmlSchemaTypes().constFind( dataType.fragment() ); + if ( it != xmlSchemaTypes().constEnd() ) { + d->dataType = it.value(); + } +} + + +Nepomuk::Literal::~Literal() +{ +} + + +Nepomuk::Literal& Nepomuk::Literal::operator=( const Literal& other ) +{ + d = other.d; + return *this; +} + + +const QUrl& Nepomuk::Literal::dataTypeUri() const +{ + return d->dataTypeUri; +} + + +QVariant::Type Nepomuk::Literal::dataType() const +{ + return d->dataType; +} Modification de propriétés sur nepomuk/types/literal.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/query/queryserializer.cpp =================================================================== --- nepomuk/query/queryserializer.cpp (révision 0) +++ nepomuk/query/queryserializer.cpp (révision 0) @@ -0,0 +1,493 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2008-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License 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 "queryserializer.h" + +#include "filequery.h" +#include "term.h" +#include "literalterm.h" +#include "resourceterm.h" +#include "andterm.h" +#include "orterm.h" +#include "negationterm.h" +#include "comparisonterm.h" +#include "resourcetypeterm.h" +#include "optionalterm.h" + +#include "property.h" +#include "class.h" + +#include <Soprano/LiteralValue> + +#include <kurl.h> +#include <kdebug.h> + +#include <QtCore/QXmlStreamWriter> + + +using namespace Nepomuk::Query; + +namespace { + QString comparatorToString( Nepomuk::Query::ComparisonTerm::Comparator c ) + { + switch( c ) { + case Nepomuk::Query::ComparisonTerm::Contains: + return QChar( ':' ); + case Nepomuk::Query::ComparisonTerm::Equal: + return QChar( '=' ); + case Nepomuk::Query::ComparisonTerm::Regexp: + return QLatin1String( "regex" ); + case Nepomuk::Query::ComparisonTerm::Greater: + return QChar( '>' ); + case Nepomuk::Query::ComparisonTerm::Smaller: + return QChar( '<' ); + case Nepomuk::Query::ComparisonTerm::GreaterOrEqual: + return QLatin1String( ">=" ); + case Nepomuk::Query::ComparisonTerm::SmallerOrEqual: + return QLatin1String( "<=" ); + default: + return QString(); + } + } + + + Nepomuk::Query::ComparisonTerm::Comparator stringToComparator( const QStringRef& c ) + { + if( c == QChar( '=' ) ) + return Nepomuk::Query::ComparisonTerm::Equal; + else if( c == QLatin1String( "regex" ) ) + return Nepomuk::Query::ComparisonTerm::Regexp; + else if( c == QChar( '>' ) ) + return Nepomuk::Query::ComparisonTerm::Greater; + else if( c == QChar( '<' ) ) + return Nepomuk::Query::ComparisonTerm::Smaller; + else if( c == QLatin1String( ">=" ) ) + return Nepomuk::Query::ComparisonTerm::GreaterOrEqual; + else if( c == QLatin1String( "<=" ) ) + return Nepomuk::Query::ComparisonTerm::SmallerOrEqual; + else + return Nepomuk::Query::ComparisonTerm::Contains; + } + + + QString aggregateToString( Nepomuk::Query::ComparisonTerm::AggregateFunction f ) + { + switch( f ) { + case Nepomuk::Query::ComparisonTerm::Count: + return QString::fromLatin1("count"); + case Nepomuk::Query::ComparisonTerm::DistinctCount: + return QString::fromLatin1("distinctcount"); + case Nepomuk::Query::ComparisonTerm::Max: + return QString::fromLatin1("max"); + case Nepomuk::Query::ComparisonTerm::Min: + return QString::fromLatin1("min"); + case Nepomuk::Query::ComparisonTerm::Sum: + return QString::fromLatin1("sum"); + case Nepomuk::Query::ComparisonTerm::DistinctSum: + return QString::fromLatin1("distinctsum"); + case Nepomuk::Query::ComparisonTerm::Average: + return QString::fromLatin1("avg"); + case Nepomuk::Query::ComparisonTerm::DistinctAverage: + return QString::fromLatin1("distinctavg"); + default: + return QString(); + } + } + + Nepomuk::Query::ComparisonTerm::AggregateFunction stringToAggregate( const QStringRef& f ) + { + if( f == QString::fromLatin1("count") ) + return Nepomuk::Query::ComparisonTerm::Count; + else if( f == QString::fromLatin1("distinctcount") ) + return Nepomuk::Query::ComparisonTerm::DistinctCount; + else if( f == QString::fromLatin1("max") ) + return Nepomuk::Query::ComparisonTerm::Max; + else if( f == QString::fromLatin1("min") ) + return Nepomuk::Query::ComparisonTerm::Min; + else if( f == QString::fromLatin1("sum") ) + return Nepomuk::Query::ComparisonTerm::Sum; + else if( f == QString::fromLatin1("distinctsum") ) + return Nepomuk::Query::ComparisonTerm::DistinctSum; + else if( f == QString::fromLatin1("avg") ) + return Nepomuk::Query::ComparisonTerm::Average; + else if( f == QString::fromLatin1("distinctavg") ) + return Nepomuk::Query::ComparisonTerm::DistinctAverage; + else + return Nepomuk::Query::ComparisonTerm::NoAggregateFunction; + } + + + bool doSerializeTerm( QXmlStreamWriter& xml, const Nepomuk::Query::Term& term ) + { + switch(term.type()) { + case Term::Literal: { + xml.writeStartElement( QLatin1String("literal") ); + const Soprano::LiteralValue value = term.toLiteralTerm().value(); + if( value.isPlain() ) + xml.writeAttribute( QLatin1String("lang"), value.language().toString() ); + else + xml.writeAttribute( QLatin1String("datatype"), KUrl(value.dataTypeUri()).url() ); + xml.writeCharacters( value.toString() ); + xml.writeEndElement(); + break; + } + + case Term::Resource: + xml.writeStartElement( QLatin1String("resource") ); + xml.writeAttribute( QLatin1String("uri"), KUrl( term.toResourceTerm().resource().resourceUri() ).url() ); + xml.writeEndElement(); + break; + + case Term::And: + xml.writeStartElement( QLatin1String("and") ); + Q_FOREACH( const Term& term, term.toAndTerm().subTerms() ) { + doSerializeTerm( xml, term ); + } + xml.writeEndElement(); + break; + + case Term::Or: + xml.writeStartElement( QLatin1String("or") ); + Q_FOREACH( const Term& term, term.toOrTerm().subTerms() ) { + doSerializeTerm( xml, term ); + } + xml.writeEndElement(); + break; + + case Term::Comparison: { + ComparisonTerm cTerm( term.toComparisonTerm() ); + + xml.writeStartElement( QLatin1String("comparison") ); + + if( cTerm.property().isValid() ) + xml.writeAttribute( QLatin1String("property"), KUrl(cTerm.property().uri()).url() ); + xml.writeAttribute( QLatin1String("comparator"), comparatorToString(cTerm.comparator()) ); + if( !cTerm.variableName().isEmpty() ) + xml.writeAttribute( QLatin1String("varname"), cTerm.variableName() ); + if( cTerm.aggregateFunction() != ComparisonTerm::NoAggregateFunction ) + xml.writeAttribute( QLatin1String("aggregate"), aggregateToString(cTerm.aggregateFunction()) ); + if( cTerm.sortWeight() != 0 ) { + xml.writeAttribute( QLatin1String("sortWeight"), QString::number(cTerm.sortWeight()) ); + xml.writeAttribute( QLatin1String("sortOrder"), cTerm.sortOrder() == Qt::AscendingOrder ? QLatin1String("asc") : QLatin1String("desc") ); + } + xml.writeAttribute( QLatin1String("inverted"), cTerm.isInverted() ? QLatin1String("true") : QLatin1String("false") ); + + doSerializeTerm( xml, cTerm.subTerm() ); + + xml.writeEndElement(); + break; + } + + case Term::ResourceType: + xml.writeStartElement( QLatin1String("type") ); + xml.writeAttribute( QLatin1String("uri"), KUrl( term.toResourceTypeTerm().type().uri() ).url() ); + xml.writeEndElement(); + break; + + case Term::Negation: + xml.writeStartElement( QLatin1String("not") ); + doSerializeTerm( xml, term.toNegationTerm().subTerm() ); + xml.writeEndElement(); + break; + + case Term::Optional: + xml.writeStartElement( QLatin1String("optional") ); + doSerializeTerm( xml, term.toOptionalTerm().subTerm() ); + xml.writeEndElement(); + break; + + default: + return false; + } + + return true; + } + + + Term doParseTerm( QXmlStreamReader& xml, bool* ok = 0 ) + { + Q_ASSERT( xml.isStartElement() ); + + if( xml.name() == QLatin1String("literal") ) { + if( ok ) + *ok = true; + QXmlStreamAttributes attr = xml.attributes(); + LiteralTerm term; + if( attr.hasAttribute( QLatin1String("datatype") ) ) + term = LiteralTerm( Soprano::LiteralValue::fromString( xml.readElementText(), KUrl(attr.value( QLatin1String("datatype") ).toString()) ) ); + else + term = LiteralTerm( Soprano::LiteralValue::createPlainLiteral( xml.readElementText(), attr.value( QLatin1String("lang") ).toString()) ); + // no need to skip to next element due to usage of readElementText? + return term; + } + + else if( xml.name() == QLatin1String("resource") ) { + if( ok ) + *ok = true; + ResourceTerm term( KUrl(xml.attributes().value( QLatin1String("uri") ).toString()) ); + xml.readNextStartElement(); // skip to next element + return term; + } + + else if( xml.name() == QLatin1String("and") ) { + AndTerm term; + while( xml.readNextStartElement() ) { + term.addSubTerm( doParseTerm( xml, ok ) ); + if( ok && !*ok ) + return Term(); + } + return term; + } + + else if( xml.name() == QLatin1String("or") ) { + OrTerm term; + while( xml.readNextStartElement() ) { + term.addSubTerm( doParseTerm( xml, ok ) ); + if( ok && !*ok ) + return Term(); + } + return term; + } + + else if( xml.name() == QLatin1String("not") ) { + if( xml.readNextStartElement() ) { + Term term = doParseTerm( xml, ok ); + if( ok && !*ok ) + return Term(); + xml.readNextStartElement(); // skip to next element + return NegationTerm::negateTerm(term); + } + else { + if( ok ) + *ok = false; + return Term(); + } + } + + else if( xml.name() == QLatin1String("optional") ) { + if( xml.readNextStartElement() ) { + Term term = doParseTerm( xml, ok ); + if( ok && !*ok ) + return Term(); + xml.readNextStartElement(); // skip to next element + return OptionalTerm::optionalizeTerm(term); + } + else { + if( ok ) + *ok = false; + return Term(); + } + } + + else if( xml.name() == QLatin1String("type") ) { + if( ok ) + *ok = true; + ResourceTypeTerm term( KUrl(xml.attributes().value( QLatin1String("uri") ).toString()) ); + xml.readNextStartElement(); // skip to next element + return term; + } + + else if( xml.name() == QLatin1String("comparison") ) { + ComparisonTerm cTerm; + + QXmlStreamAttributes attr = xml.attributes(); + + if( attr.hasAttribute( QLatin1String("property") ) ) + cTerm.setProperty( KUrl(attr.value( QLatin1String("property")).toString()) ); + + if( attr.hasAttribute( QLatin1String("comparator") ) ) + cTerm.setComparator( stringToComparator(attr.value( QLatin1String("comparator"))) ); + + if( attr.hasAttribute( QLatin1String("varname") ) ) + cTerm.setVariableName( attr.value( QLatin1String("varname")).toString() ); + + if( attr.hasAttribute( QLatin1String("aggregate") ) ) + cTerm.setAggregateFunction( stringToAggregate(attr.value( QLatin1String("aggregate"))) ); + + if( attr.hasAttribute( QLatin1String("sortWeight") ) ) + cTerm.setSortWeight( attr.value( QLatin1String("sortWeight")).toString().toInt(), + attr.value( QLatin1String("sortOrder")) == QLatin1String("desc") ? Qt::DescendingOrder : Qt::AscendingOrder ); + + if( attr.hasAttribute( QLatin1String("inverted") ) ) + cTerm.setInverted( attr.value( QLatin1String("inverted")) == QLatin1String("true") ); + + if( xml.readNextStartElement() ) { + Term term = doParseTerm( xml, ok ); + if( ok && !*ok ) + return Term(); + cTerm.setSubTerm(term); + xml.readNextStartElement(); // skip to next element + } + + if( ok ) + *ok = true; + return cTerm; + } + + else { + kDebug() << "Unknown term type" << xml.name(); + if( ok ) + *ok = false; + return Term(); + } + } + + + void readQueryAttributes( const QXmlStreamAttributes& attributes, Query& query ) + { + if( attributes.hasAttribute( QLatin1String("limit") ) ) + query.setLimit( attributes.value( QLatin1String("limit") ).toString().toInt() ); + if( attributes.hasAttribute( QLatin1String("offset") ) ) + query.setOffset( attributes.value( QLatin1String("offset") ).toString().toInt() ); + } +} + + +QString Nepomuk::Query::serializeQuery( const Query& query ) +{ + QString s; + QXmlStreamWriter xml( &s ); + + xml.writeStartDocument(); + + if( query.isFileQuery() ) { + FileQuery fq( query ); + xml.writeStartElement( QLatin1String("filequery") ); + xml.writeAttribute( QLatin1String("queryFiles"), fq.fileMode()&FileQuery::QueryFiles ? QLatin1String("true") : QLatin1String("false") ); + xml.writeAttribute( QLatin1String("queryFolders"), fq.fileMode()&FileQuery::QueryFolders ? QLatin1String("true") : QLatin1String("false") ); + } + else { + xml.writeStartElement( QLatin1String("query") ); + } + + xml.writeAttribute( QLatin1String("limit"), QString::number(query.limit()) ); + xml.writeAttribute( QLatin1String("offset"), QString::number(query.offset()) ); + + Q_FOREACH( const Query::RequestProperty& rp, query.requestProperties() ) { + xml.writeStartElement( QLatin1String("requestProperty") ); + xml.writeAttribute( QLatin1String("uri"), KUrl(rp.property().uri()).url() ); + xml.writeAttribute( QLatin1String("optional"), rp.optional() ? QLatin1String("true") : QLatin1String("false") ); + xml.writeEndElement(); + } + + if( query.isFileQuery() ) { + FileQuery fq( query ); + Q_FOREACH( const KUrl& url, fq.includeFolders() ) { + xml.writeStartElement( QLatin1String("folder") ); + xml.writeAttribute( QLatin1String("url"), url.url() ); + xml.writeAttribute( QLatin1String("include"), QLatin1String("true") ); + xml.writeEndElement(); + } + Q_FOREACH( const KUrl& url, fq.excludeFolders() ) { + xml.writeStartElement( QLatin1String("folder") ); + xml.writeAttribute( QLatin1String("url"), url.url() ); + xml.writeAttribute( QLatin1String("include"), QLatin1String("false") ); + xml.writeEndElement(); + } + } + + doSerializeTerm( xml, query.term() ); + + // close query element + xml.writeEndElement(); + xml.writeEndDocument(); + + return s; +} + + +Query Nepomuk::Query::parseQuery( const QString& s ) +{ + QXmlStreamReader xml( s ); + + Query query; + + while( xml.readNextStartElement() ) { + if( xml.name() == QLatin1String("query") ) { + readQueryAttributes( xml.attributes(), query ); + } + else if( xml.name() == QLatin1String("filequery") ) { + readQueryAttributes( xml.attributes(), query ); + + FileQuery fileQuery(query); + FileQuery::FileMode mode; + if( xml.attributes().value(QLatin1String("queryFiles") ) == QLatin1String("true") ) + mode |= FileQuery::QueryFiles; + if( xml.attributes().value(QLatin1String("queryFolders") ) == QLatin1String("true") ) + mode |= FileQuery::QueryFolders; + fileQuery.setFileMode(mode); + + query = fileQuery; + } + else if( xml.name() == QLatin1String("requestProperty") ) { + query.addRequestProperty( Query::RequestProperty( KUrl(xml.attributes().value( QLatin1String("uri") ).toString()), + xml.attributes().value( QLatin1String("optional") ) == QLatin1String("true") ) ); + xml.readNextStartElement(); // skip to next element + } + else if( xml.name() == QLatin1String("folder") ) { + if( !query.isFileQuery() ) { + kDebug() << "Folder tokens are only allowed in filequerys"; + query = Query(); + break; + } + + FileQuery fileQuery(query); + if( xml.attributes().value( QLatin1String("include") ) == QLatin1String("true") ) + fileQuery.addIncludeFolder( KUrl( xml.attributes().value( QLatin1String("url") ).toString() ) ); + else + fileQuery.addExcludeFolder( KUrl( xml.attributes().value( QLatin1String("url") ).toString() ) ); + query = fileQuery; + xml.readNextStartElement(); // skip to next element + } + else { + bool termOk = false; + query.setTerm( doParseTerm( xml, &termOk ) ); + if( !termOk ) { + break; + } + } + } + + return query; +} + + +QString Nepomuk::Query::serializeTerm( const Term& term ) +{ + QString s; + QXmlStreamWriter xml( &s ); + + // FIXME: should we really add the document details? + xml.writeStartDocument(); + doSerializeTerm( xml, term ); + xml.writeEndDocument(); + + return s; +} + + +Term Nepomuk::Query::parseTerm( const QString& s ) +{ + QXmlStreamReader xml( s ); + if( xml.readNextStartElement() ) + return doParseTerm( xml ); + else + return Term(); + +} Modification de propriétés sur nepomuk/query/queryserializer.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/query/optionalterm_p.h =================================================================== --- nepomuk/query/optionalterm_p.h (révision 0) +++ nepomuk/query/optionalterm_p.h (révision 0) @@ -0,0 +1,43 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _NEPOMUK_QUERY_OPTIONAL_TERM_P_H_ +#define _NEPOMUK_QUERY_OPTIONAL_TERM_P_H_ + +#include "simpleterm_p.h" + +namespace Nepomuk { + namespace Query { + class OptionalTermPrivate : public SimpleTermPrivate + { + public: + OptionalTermPrivate() { + m_type = Term::Optional; + } + + TermPrivate* clone() const { return new OptionalTermPrivate( *this ); } + + QString toSparqlGraphPattern( const QString& resourceVarName, QueryBuilderData* qbd ) const; + }; + } +} + +#endif Modification de propriétés sur nepomuk/query/optionalterm_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/query/comparisonterm.cpp =================================================================== --- nepomuk/query/comparisonterm.cpp (révision 1130118) +++ nepomuk/query/comparisonterm.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -53,6 +53,30 @@ return QString(); } } + + QString varInAggregateFunction( Nepomuk::Query::ComparisonTerm::AggregateFunction f, const QString& varName ) + { + switch( f ) { + case Nepomuk::Query::ComparisonTerm::Count: + return QString::fromLatin1("count(%1)").arg(varName); + case Nepomuk::Query::ComparisonTerm::DistinctCount: + return QString::fromLatin1("count(distinct %1)").arg(varName); + case Nepomuk::Query::ComparisonTerm::Max: + return QString::fromLatin1("max(%1)").arg(varName); + case Nepomuk::Query::ComparisonTerm::Min: + return QString::fromLatin1("min(%1)").arg(varName); + case Nepomuk::Query::ComparisonTerm::Sum: + return QString::fromLatin1("sum(%1)").arg(varName); + case Nepomuk::Query::ComparisonTerm::DistinctSum: + return QString::fromLatin1("sum(distinct %1)").arg(varName); + case Nepomuk::Query::ComparisonTerm::Average: + return QString::fromLatin1("avg(%1)").arg(varName); + case Nepomuk::Query::ComparisonTerm::DistinctAverage: + return QString::fromLatin1("avg(distinct %1)").arg(varName); + default: + return QString(); + } + } } @@ -63,7 +87,7 @@ // 1.1. operator = // use a single pattern like: ?r <prop> "value" // 1.2. operator : - // use two patterns: ?r <prop> ?v . ?v bif:contains "'value*'" + // use two patterns: ?r <prop> ?v . ?v bif:contains "'value'" // 1.3. operator <,>,<=,>= // use two patterns: ?r <prop> ?v . FILTER(?v < value) // fail if subterm is not a literal term @@ -78,7 +102,7 @@ // use one pattern and the subpattern: ?r <prop> ?v . subpattern(?v) // 2.2. operator : // 2.2.1. literal subterm - // use 3 pattern: ?r <prop> ?v . ?v rdfs:label ?l . ?l bif:contains "'value*'" + // use 3 pattern: ?r <prop> ?v . ?v rdfs:label ?l . ?l bif:contains "'value'" // 2.2.2. resource subterm // same as = // 2.2.3. subterm type and, or, comparision @@ -87,36 +111,45 @@ // fail! // - if ( m_property.literalRangeType().isValid() ) { + if ( !m_subTerm.isValid() ) { + QString prop = propertyToString( qbd ); + QString ov = getMainVariableName( qbd ); + return QString::fromLatin1( "%1 %2 %3 . " ) + .arg( resourceVarName, prop, ov ); + } + + else if ( m_property.literalRangeType().isValid() ) { if( !m_subTerm.isLiteralTerm() ) kDebug() << "Incompatible subterm type:" << m_subTerm.type(); if ( m_comparator == ComparisonTerm::Equal ) { - return QString( "%1 %2 %3 . " ) + return QString::fromLatin1( "%1 %2 %3 . " ) .arg( resourceVarName, - Soprano::Node::resourceToN3( m_property.uri() ), + propertyToString( qbd ), Soprano::Node::literalToN3( m_subTerm.toLiteralTerm().value() ) ); } else if ( m_comparator == ComparisonTerm::Contains ) { - QString v = qbd->uniqueVarName(); - return QString( "%1 %2 %3 . %3 bif:contains \"'%4'\" . " ) + QString v = getMainVariableName(qbd); + QString vScore = qbd->createScoringVariable(); + return QString::fromLatin1( "%1 %2 %3 . %3 bif:contains \"%4\" OPTION (score %5) . " ) .arg( resourceVarName, - Soprano::Node::resourceToN3( m_property.uri() ), + propertyToString( qbd ), v, - static_cast<const LiteralTermPrivate*>(m_subTerm.toLiteralTerm().d_ptr.constData())->queryText() ); + static_cast<const LiteralTermPrivate*>(m_subTerm.toLiteralTerm().d_ptr.constData())->queryText(), + vScore ); } else if ( m_comparator == ComparisonTerm::Regexp ) { - QString v = qbd->uniqueVarName(); - return QString( "%1 %2 %3 . FILTER(REGEX(STR(%3), '%4', 'i')) . " ) + QString v = getMainVariableName(qbd); + return QString::fromLatin1( "%1 %2 %3 . FILTER(REGEX(STR(%3), '%4', 'i')) . " ) .arg( resourceVarName, - Soprano::Node::resourceToN3( m_property.uri() ), + propertyToString( qbd ), v, m_subTerm.toLiteralTerm().value().toString() ); } else { - QString v = qbd->uniqueVarName(); - return QString( "%1 %2 %3 . FILTER(%3%4%5) . " ) + QString v = getMainVariableName(qbd); + return QString::fromLatin1( "%1 %2 %3 . FILTER(%3%4%5) . " ) .arg( resourceVarName, - Soprano::Node::resourceToN3( m_property.uri() ), + propertyToString( qbd ), v, comparatorToString( m_comparator ), Soprano::Node::literalToN3(m_subTerm.toLiteralTerm().value()) ); @@ -130,23 +163,33 @@ kDebug() << "Incompatible property range:" << m_property.range().uri(); // - // The core pattern is always the same: we match to resource that have a certain + // The core pattern is always the same: we match to resources that have a certain // property defined. The value of that property is filled in below. // QString corePattern; + QString subject; + QString object; + if( m_inverted && !m_subTerm.isLiteralTerm() ) { + subject = QLatin1String("%1"); // funny way to have a resulting string which takes only one arg + object = resourceVarName; + } + else { + subject = resourceVarName; + object = QLatin1String("%1"); + } if( qbd->flags() & Query::HandleInverseProperties && m_property.inverseProperty().isValid() ) { corePattern = QString::fromLatin1("{ %1 %2 %3 . } UNION { %3 %4 %1 . } . ") - .arg( resourceVarName, - Soprano::Node::resourceToN3( m_property.uri() ), - QLatin1String("%1"), // funny way to have a resulting string which takes only one arg + .arg( subject, + propertyToString( qbd ), + object, Soprano::Node::resourceToN3( m_property.inverseProperty().uri() ) ); } else { corePattern = QString::fromLatin1("%1 %2 %3 . ") - .arg( resourceVarName, - Soprano::Node::resourceToN3( m_property.uri() ), - QLatin1String("%1") ); // funny way to have a resulting string which takes only one arg + .arg( subject, + propertyToString( qbd ), + object ); } if ( m_subTerm.isLiteralTerm() ) { @@ -154,7 +197,7 @@ // the base of the pattern is always the same: match to resources related to X // which has a label that we compare somehow. This label's value will be filled below // - QString v1 = qbd->uniqueVarName(); + QString v1 = getMainVariableName(qbd); QString v2 = qbd->uniqueVarName(); QString pattern = QString::fromLatin1( "%1%2 %3 %4 . %3 %5 %6 . " ) .arg( corePattern.arg(v1), @@ -169,10 +212,12 @@ } else if ( m_comparator == ComparisonTerm::Contains ) { QString v3 = qbd->uniqueVarName(); - return QString::fromLatin1( "%1%2 bif:contains \"'%3'\" . " ) + QString v3Score = qbd->createScoringVariable(); + return QString::fromLatin1( "%1%2 bif:contains \"%3\" OPTION (score %4) . " ) .arg( pattern.arg(v3), v3, - static_cast<const LiteralTermPrivate*>(m_subTerm.toLiteralTerm().d_ptr.constData())->queryText() ); + static_cast<const LiteralTermPrivate*>(m_subTerm.toLiteralTerm().d_ptr.constData())->queryText(), + v3Score ); } else if ( m_comparator == ComparisonTerm::Regexp ) { QString v3 = qbd->uniqueVarName(); @@ -192,8 +237,11 @@ } else { // ?r <prop> ?v1 . ?v1 ... - QString v = qbd->uniqueVarName(); - return corePattern.arg(v) + m_subTerm.d_ptr->toSparqlGraphPattern( v, qbd ); + QString v = getMainVariableName(qbd); + qbd->increaseDepth(); + QString subTermSparql = m_subTerm.d_ptr->toSparqlGraphPattern( v, qbd ); + qbd->decreaseDepth(); + return corePattern.arg(v) + subTermSparql; } } } @@ -216,19 +264,91 @@ bool Nepomuk::Query::ComparisonTermPrivate::isValid() const { - return( SimpleTermPrivate::isValid() && m_property.isValid() ); + // an invalid property will simply match all properties + // and an invalid subterm is a wildcard, too + // Thus, a ComparisonTerm is always valid + return true; } -QString Nepomuk::Query::ComparisonTermPrivate::toString() const +// +// Determines the main variable name, i.e. the variable representing the compared value, i.e. the one +// that can be set vie setVariableName. +// +// Thus, the basic scheme is: if a variable name has been set via setVariableName, return that name, +// otherwise create a random new one. +// +// But this method also handles AggregateFunction and sorting. The latter is a bit hacky. +// +// There a quite a few cases that are handled: +// +// 1. No variable name set +// 1.1 no aggregate function set +// 1.1.1 no sorting weight set +// -> return a new random variable +// 1.1.2 sorting weight set +// -> determine a new random variable, use it as sorting var (via QueryBuilderData::addOrderVariable), +// and return it +// 1.2 an aggregate function has been set +// 1.2.1 sorting weight set (no sorting weight is useless and behaves exactly as if no aggregate function was set) +// -> embed a new random variable in the aggregate expression, add that as sort variable, and +// return the new variable +// 2. A variable name has been set +// 2.1 no aggregate function set +// 2.1.1 no sorting weight set +// -> add the variable name as custom variable via QueryBuilderData::addCustomVariable and return the variable name +// 2.1.2 sorting weight set +// -> add the variable name as sort car via QueryBuilderData::addOrderVariable and return it +// 2.2 an aggregate function has been set +// 2.2.1 no sorting weight set +// -> Create a new random variable, embed it in the aggregate expression with the set variable name, +// use that expression as custom variable (this is the hacky part), and return the random one +// 2.2.2 sorting weight set +// -> Do the same as above only also add the set variable name as sort variable via QueryBuilderData::addOrderVariable +// +QString Nepomuk::Query::ComparisonTermPrivate::getMainVariableName( QueryBuilderData* qbd ) const { - return QString( "[%1 %2 %3]" ) - .arg( Soprano::Node::resourceToN3( m_property.uri() ), - comparatorToString( m_comparator ), - m_subTerm.d_ptr->toString() ); + QString v; + QString sortVar; + if( !m_variableName.isEmpty() ) { + sortVar = QLatin1String("?") + m_variableName; + if( m_aggregateFunction == ComparisonTerm::NoAggregateFunction ) { + v = sortVar; + qbd->addCustomVariable( v ); + } + else { + // this is a bit hacky as far as the method naming in QueryBuilderData is concerned. + // we add a select statement as a variable name. + v = qbd->uniqueVarName(); + QString selectVar = QString::fromLatin1( "%1 as ?%2") + .arg(varInAggregateFunction(m_aggregateFunction, v), + m_variableName ); + qbd->addCustomVariable( selectVar ); + } + } + else { + v = qbd->uniqueVarName(); + if( m_aggregateFunction == ComparisonTerm::NoAggregateFunction ) + sortVar = v; + else + sortVar = varInAggregateFunction(m_aggregateFunction, v); + } + if( m_sortWeight != 0 ) { + qbd->addOrderVariable( sortVar, m_sortWeight, m_sortOrder ); + } + return v; } +QString Nepomuk::Query::ComparisonTermPrivate::propertyToString( QueryBuilderData* qbd ) const +{ + if( m_property.isValid() ) + return Soprano::Node::resourceToN3( m_property.uri() ); + else + return qbd->uniqueVarName(); +} + + Nepomuk::Query::ComparisonTerm::ComparisonTerm() : SimpleTerm( new ComparisonTermPrivate() ) { @@ -289,3 +409,75 @@ N_D( ComparisonTerm ); d->m_property = property; } + + +void Nepomuk::Query::ComparisonTerm::setVariableName( const QString& name ) +{ + N_D( ComparisonTerm ); + d->m_variableName = name; +} + + +QString Nepomuk::Query::ComparisonTerm::variableName() const +{ + N_D_CONST( ComparisonTerm ); + return d->m_variableName; +} + + +void Nepomuk::Query::ComparisonTerm::setAggregateFunction( AggregateFunction function ) +{ + N_D( ComparisonTerm ); + d->m_aggregateFunction = function; +} + + +Nepomuk::Query::ComparisonTerm::AggregateFunction Nepomuk::Query::ComparisonTerm::aggregateFunction() const +{ + N_D_CONST( ComparisonTerm ); + return d->m_aggregateFunction; +} + + +void Nepomuk::Query::ComparisonTerm::setSortWeight( int weight, Qt::SortOrder sortOrder ) +{ + N_D( ComparisonTerm ); + d->m_sortWeight = weight; + d->m_sortOrder = sortOrder; +} + + +int Nepomuk::Query::ComparisonTerm::sortWeight() const +{ + N_D_CONST( ComparisonTerm ); + return d->m_sortWeight; +} + + +Qt::SortOrder Nepomuk::Query::ComparisonTerm::sortOrder() const +{ + N_D_CONST( ComparisonTerm ); + return d->m_sortOrder; +} + + +bool Nepomuk::Query::ComparisonTerm::isInverted() const +{ + N_D_CONST( ComparisonTerm ); + return d->m_inverted; +} + + +void Nepomuk::Query::ComparisonTerm::setInverted( bool invert ) +{ + N_D( ComparisonTerm ); + d->m_inverted = invert; +} + + +Nepomuk::Query::ComparisonTerm Nepomuk::Query::ComparisonTerm::inverted() const +{ + ComparisonTerm ct( *this ); + ct.setInverted( !isInverted() ); + return ct; +} Index: nepomuk/query/resourceterm_p.h =================================================================== --- nepomuk/query/resourceterm_p.h (révision 1130118) +++ nepomuk/query/resourceterm_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -41,7 +41,6 @@ bool equals( const TermPrivate* other ) const; bool isValid() const { return m_resource.isValid(); } QString toSparqlGraphPattern( const QString& resourceVarName, QueryBuilderData* qbd ) const; - QString toString() const; Resource m_resource; }; Index: nepomuk/query/query.cpp =================================================================== --- nepomuk/query/query.cpp (révision 1130118) +++ nepomuk/query/query.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2008-2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2008-2010 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 @@ -31,11 +31,14 @@ #include "negationterm.h" #include "comparisonterm.h" #include "resourcetypeterm.h" +#include "queryserializer.h" +#include "queryparser.h" #include <QtCore/QDebug> #include <QtCore/QDateTime> #include <QtCore/QRegExp> #include <QtCore/QVariant> +#include <QtCore/QTextStream> #include <Soprano/Node> #include <Soprano/Model> @@ -50,10 +53,17 @@ #include <kdebug.h> +/* +## Full Text Score +## Entity Rank +## Surfaced via SPARQL +SELECT ?s ?sc ( <LONG::IRI_RANK> (?s) ) as ?Rank +WHERE { ?s ?p ?o . +?o bif:contains 'NEW AND YOR' option (score ?sc). } +ORDER BY desc (? +*/ -namespace { -} QString Nepomuk::Query::QueryPrivate::createFolderFilter( const QString& resourceVarName, QueryBuilderData* qbd ) const @@ -62,10 +72,10 @@ QString uriVarName = qbd->uniqueVarName(); QString filter = resourceVarName + ' ' + Soprano::Node::resourceToN3( Nepomuk::Vocabulary::NIE::url() ) + ' ' + uriVarName + QLatin1String( " . " ); if ( !m_includeFolders.isEmpty() ) { - filter += QString( " FILTER(REGEX(STR(%1), \"^%2/\")) ." ).arg( uriVarName ).arg( m_includeFolders.toStringList().join( "|" ) ); + filter += QString( " FILTER(REGEX(STR(%1), \"^(%2/)\")) ." ).arg( uriVarName ).arg( m_includeFolders.toStringList().join( "|" ) ); } if ( !m_excludeFolders.isEmpty() ) { - filter += QString( " FILTER(!REGEX(STR(%1), \"^%2/\")) ." ).arg( uriVarName ).arg( m_excludeFolders.toStringList().join( "|" ) ); + filter += QString( " FILTER(!REGEX(STR(%1), \"^(%2/)\")) ." ).arg( uriVarName ).arg( m_excludeFolders.toStringList().join( "|" ) ); } return filter; } @@ -185,12 +195,25 @@ } +Nepomuk::Query::Query& Nepomuk::Query::Query::operator=( const Term& term ) +{ + d->m_term = term; + return *this; +} + + bool Nepomuk::Query::Query::isValid() const { return d->m_term.isValid(); } +bool Nepomuk::Query::Query::isFileQuery() const +{ + return d->m_isFileQuery; +} + + Nepomuk::Query::Term Nepomuk::Query::Query::term() const { return d->m_term; @@ -203,6 +226,12 @@ } +int Nepomuk::Query::Query::offset() const +{ + return d->m_offset; +} + + void Nepomuk::Query::Query::setTerm( const Term& term ) { d->m_term = term; @@ -215,6 +244,12 @@ } +void Nepomuk::Query::Query::setOffset( int offset ) +{ + d->m_offset = offset; +} + + void Nepomuk::Query::Query::addRequestProperty( const RequestProperty& property ) { d->m_requestProperties.append( property ); @@ -254,62 +289,98 @@ bool Nepomuk::Query::Query::operator==( const Query& other ) const { return( d->m_limit == other.d->m_limit && + d->m_offset == other.d->m_offset && d->m_term == other.d->m_term && compareQList( d->m_requestProperties, other.d->m_requestProperties ) && compareQList( d->m_includeFolders, other.d->m_includeFolders ) && - compareQList( d->m_excludeFolders, other.d->m_excludeFolders ) ); + compareQList( d->m_excludeFolders, other.d->m_excludeFolders ) && + d->m_isFileQuery == other.d->m_isFileQuery && + d->m_fileMode == other.d->m_fileMode ); } QString Nepomuk::Query::Query::toSparqlQuery( SparqlFlags flags ) const { - // optimize whatever we can - Term term = QueryPrivate::optimizeTerm( d->m_term ); + Term term = d->m_term; // restrict to files if we are a file query if( d->m_isFileQuery ) { // // we do not use ResourceTypeTerm since we do not want to use crappy inference every time. All files have nfo:FileDataObject type anyway // - term = AndTerm( term, OrTerm( ComparisonTerm( Soprano::Vocabulary::RDF::type(), ResourceTerm(Vocabulary::NFO::FileDataObject()), ComparisonTerm::Equal ), - ComparisonTerm( Soprano::Vocabulary::RDF::type(), ResourceTerm(Vocabulary::NFO::Folder()), ComparisonTerm::Equal ) ) ); + Term fileModeTerm; + ComparisonTerm fileTerm( Soprano::Vocabulary::RDF::type(), ResourceTerm(Vocabulary::NFO::FileDataObject()), ComparisonTerm::Equal ); + ComparisonTerm folderTerm( Soprano::Vocabulary::RDF::type(), ResourceTerm(Vocabulary::NFO::Folder()), ComparisonTerm::Equal ); + if( d->m_fileMode == FileQuery::QueryFiles ) + fileModeTerm = AndTerm( fileTerm, NegationTerm::negateTerm( folderTerm ) ); + else if( d->m_fileMode == FileQuery::QueryFolders ) + fileModeTerm = AndTerm( folderTerm, NegationTerm::negateTerm( fileTerm ) ); + else + fileModeTerm = OrTerm( fileTerm, folderTerm ); + term = AndTerm( term, fileModeTerm ); } + // optimize whatever we can + term = QueryPrivate::optimizeTerm( term ); + // actually build the SPARQL query string QueryBuilderData qbd( flags ); - QString termGraphPattern = term.d_ptr->toSparqlGraphPattern( QLatin1String( "?r" ), &qbd ); - if( !termGraphPattern.isEmpty() ) { - QString query = QString::fromLatin1( "select %1 %2 where { %3 %4 %5 }" ) - .arg( flags & CreateCountQuery ? QLatin1String("count(distinct ?r)") : QLatin1String("distinct ?r"), - d->buildRequestPropertyVariableList(), - termGraphPattern, - d->createFolderFilter( QLatin1String( "?r" ), &qbd ), - d->buildRequestPropertyPatterns() ); - if ( d->m_limit > 0 ) - query += QString::fromLatin1( " LIMIT %1" ).arg( d->m_limit ); - return query; + QString termGraphPattern; + if( term.isValid() ) { + termGraphPattern = term.d_ptr->toSparqlGraphPattern( QLatin1String( "?r" ), &qbd ); + if( termGraphPattern.isEmpty() ) { + kDebug() << "Got no valid SPARQL pattern from" << term; + return QString(); + } } else { - kDebug() << "Got no valid SPARQL pattern from" << term; - return QString(); + // create the "all resources query" + termGraphPattern = QString::fromLatin1("graph ?g { ?r a ?t . } . ?g a ?gt . ?gt rdfs:subClassOf nrl:InstanceBase . "); } + + QString query = QString::fromLatin1( "select %1 %2 %3 %4 where { %5 %6 %7 }" ) + .arg( flags & CreateCountQuery ? QLatin1String("count(distinct ?r)") : QLatin1String("distinct ?r"), + d->buildRequestPropertyVariableList(), + qbd.customVariables().join( QLatin1String(" ") ), + qbd.buildScoringExpression(), + termGraphPattern, + d->createFolderFilter( QLatin1String( "?r" ), &qbd ), + d->buildRequestPropertyPatterns() ); + + query += qbd.buildOrderString(); + + if ( d->m_offset > 0 ) + query += QString::fromLatin1( " OFFSET %1" ).arg( d->m_offset ); + if ( d->m_limit > 0 ) + query += QString::fromLatin1( " LIMIT %1" ).arg( d->m_limit ); + return query.simplified(); } KUrl Nepomuk::Query::Query::toSearchUrl( SparqlFlags flags ) const { - QString sparql = toSparqlQuery( flags & ~CreateCountQuery ); - if( sparql.isEmpty() ) { - return KUrl(); - } - else { - KUrl url( QLatin1String("nepomuksearch:/") ); - url.addQueryItem( QLatin1String("sparql"), sparql ); - return url; - } + return toSearchUrl( QString(), flags ); } +// This is a bit dodgy: if there are sparql flags we encode the SPARQL query into the url +// otherwise the serialized query (which allows for more power in the kio slave). It would +// probably be nicer to somehow put the flags in the URL. But new query items in the URL +// would make the URL handling in the kio slave more complicated.... oh, well. +KUrl Nepomuk::Query::Query::toSearchUrl( const QString& customTitle, SparqlFlags flags ) const +{ + flags &= ~CreateCountQuery; + KUrl url( QLatin1String("nepomuksearch:/") ); + if( flags == NoFlags ) + url.addQueryItem( QLatin1String("encodedquery"), toString() ); + else + url.addQueryItem( QLatin1String("sparql"), toSparqlQuery( flags ) ); + if( !customTitle.isEmpty() ) + url.addQueryItem( QLatin1String("title"), customTitle ); + return url; +} + + Nepomuk::Query::RequestPropertyMap Nepomuk::Query::Query::requestPropertyMap() const { RequestPropertyMap rpm; @@ -319,12 +390,117 @@ return rpm; } +QString Nepomuk::Query::Query::toString() const +{ + return Nepomuk::Query::serializeQuery( *this ); +} + +// static +Nepomuk::Query::Query Nepomuk::Query::Query::fromString( const QString& queryString ) +{ + return Nepomuk::Query::parseQuery( queryString ); +} + + +namespace { + /** + * Returns an empty string for sparql query URLs. + */ + inline QString extractPlainQuery( const KUrl& url ) { + if( url.queryItems().contains( "query" ) ) { + return url.queryItem( "query" ); + } + else if ( !url.queryItems().contains( "sparql" ) && + !url.queryItems().contains( "encodedquery" ) ) { + return url.path().section( '/', 0, 0, QString::SectionSkipEmpty ); + } + else { + return QString(); + } + } +} + +// static +Nepomuk::Query::Query Nepomuk::Query::Query::fromQueryUrl( const KUrl& url ) +{ + if( url.protocol() != QLatin1String("nepomuksearch") ) { + kDebug() << "No nepomuksearch:/ URL:" << url; + return Query(); + } + + if ( url.queryItems().contains( "sparql" ) ) { + kDebug() << "Cannot parse SPARQL query from:" << url; + return Query(); + } + else if( url.queryItems().contains( "encodedquery" ) ) { + return fromString( url.queryItem( "encodedquery") ); + } + else { + Query query = QueryParser::parseQuery( extractPlainQuery(url) ); + query.setRequestProperties( QList<RequestProperty>() << Query::Query::RequestProperty( Nepomuk::Vocabulary::NIE::url(), true ) ); + return query; + } +} + + +// static +QString Nepomuk::Query::Query::sparqlFromQueryUrl( const KUrl& url ) +{ + if( url.protocol() != QLatin1String("nepomuksearch") ) { + kDebug() << "No nepomuksearch:/ URL:" << url; + return QString(); + } + + if( url.queryItems().contains( "sparql" ) ) { + return url.queryItem( "sparql" ); + } + else { + Query query = fromQueryUrl( url ); + if( query.isValid() ) { + query.setRequestProperties( QList<RequestProperty>() << Query::Query::RequestProperty( Nepomuk::Vocabulary::NIE::url(), true ) ); + return query.toSparqlQuery(); + } + else { + return QString(); + } + } +} + + +// static +QString Nepomuk::Query::Query::titleFromQueryUrl( const KUrl& url ) +{ + if( url.protocol() != QLatin1String("nepomuksearch") ) { + kDebug() << "No nepomuksearch:/ URL:" << url; + return QString(); + } + + if ( url.hasQueryItem( QLatin1String( "title" ) ) ) { + return url.queryItem(QLatin1String( "title" ) ); + } + + QString userQuery( url.queryItem(QLatin1String( "userquery" ) ) ); + + if ( userQuery.isEmpty() ) { + userQuery = extractPlainQuery( url ); + } + + if ( !userQuery.isEmpty() ) { + return i18nc( "@title UDS_DISPLAY_NAME for a KIO directory listing. %1 is the query the user entered.", + "Query Results from '%1'", + userQuery ); + } + + // fallback + return i18nc( "@title UDS_DISPLAY_NAME for a KIO directory listing.", + "Query Results"); +} + + QDebug operator<<( QDebug dbg, const Nepomuk::Query::Query& query ) { - dbg << "(Query: " << query.term() << endl - << " Limit: " << query.limit() << ")"; - return dbg; + return dbg << query.toString(); } Index: nepomuk/query/resourcetypeterm_p.h =================================================================== --- nepomuk/query/resourcetypeterm_p.h (révision 1130118) +++ nepomuk/query/resourcetypeterm_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -41,7 +41,6 @@ bool equals( const TermPrivate* other ) const; bool isValid() const { return m_class.isValid(); } QString toSparqlGraphPattern( const QString& resourceVarName, QueryBuilderData* qbd ) const; - QString toString() const; Types::Class m_class; }; Index: nepomuk/query/simpleterm_p.h =================================================================== --- nepomuk/query/simpleterm_p.h (révision 1130118) +++ nepomuk/query/simpleterm_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public Index: nepomuk/query/literalterm_p.h =================================================================== --- nepomuk/query/literalterm_p.h (révision 1130118) +++ nepomuk/query/literalterm_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -38,10 +38,8 @@ bool equals( const TermPrivate* other ) const; bool isValid() const { return m_value.isValid(); } QString toSparqlGraphPattern( const QString& resourceVarName, QueryBuilderData* qbd ) const; - QString toString() const; - /// The text that is to be used in the bif:contains pattern. A '*' wildcard will be - /// added if it does not exist yet. + /// The text that is to be used in the bif:contains pattern. QString queryText() const; Soprano::LiteralValue m_value; Index: nepomuk/query/groupterm_p.h =================================================================== --- nepomuk/query/groupterm_p.h (révision 1130118) +++ nepomuk/query/groupterm_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -31,7 +31,6 @@ public: bool isValid() const; bool equals( const TermPrivate* other ) const; - QString toString() const; QList<Term> m_subTerms; }; Index: nepomuk/query/queryserviceclient_p.h =================================================================== --- nepomuk/query/queryserviceclient_p.h (révision 0) +++ nepomuk/query/queryserviceclient_p.h (révision 0) @@ -0,0 +1,49 @@ +/* + Copyright (c) 2010 Dario Freddi <drf@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _NEPOMUK_QUERY_SERVICE_CLIENT_P_H_ +#define _NEPOMUK_QUERY_SERVICE_CLIENT_P_H_ + +#include "result.h" + +#include <QtCore/QEventLoop> +#include <QtCore/QTimer> + +namespace { + + class NepomukResultListEventLoop : public QEventLoop + { + Q_OBJECT + public: + NepomukResultListEventLoop(Nepomuk::Query::QueryServiceClient *parent); + virtual ~NepomukResultListEventLoop(); + + QList<Nepomuk::Query::Result> result() const; + + public Q_SLOTS: + void addEntries(const QList<Nepomuk::Query::Result> &entries); + + private: + QList<Nepomuk::Query::Result> m_result; + }; + +} + +#endif Modification de propriétés sur nepomuk/query/queryserviceclient_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/query/filequery.h =================================================================== --- nepomuk/query/filequery.h (révision 1130118) +++ nepomuk/query/filequery.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 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 @@ -50,6 +50,13 @@ FileQuery(); /** + * Create a file query with root term \a term. + * + * \since 4.6 + */ + explicit FileQuery( const Term& term ); + + /** * Copy constructor. */ FileQuery( const Query& query ); @@ -123,8 +130,41 @@ * \sa addExcludeFolder, setExcludeFolders, includeFolders */ KUrl::List excludeFolders() const; + + /** + * An enumeration used in setFileMode() to state wether the query + * should return files and folders or only files or only folders. + * + * \since 4.5 + */ + enum FileModeFlags { + QueryFiles = 0x1, + QueryFolders = 0x2, + QueryFilesAndFolders = QueryFiles|QueryFolders + }; + Q_DECLARE_FLAGS( FileMode, FileModeFlags ) + + /** + * Set the file mode, i.e. wether the query should return + * files and folders or only files or only folders. + * By default both files and folders are returned. + * + * \sa fileMode() + * + * \since 4.5 + */ + void setFileMode( FileMode mode ); + + /** + * \return The file mode set in setFileMode() + * + * \since 4.5 + */ + FileMode fileMode() const; }; } } +Q_DECLARE_OPERATORS_FOR_FLAGS( Nepomuk::Query::FileQuery::FileMode ) + #endif Index: nepomuk/query/term.h =================================================================== --- nepomuk/query/term.h (révision 1130118) +++ nepomuk/query/term.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2007-2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2007-2010 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 @@ -38,6 +38,7 @@ class OrTerm; class ComparisonTerm; class ResourceTypeTerm; + class OptionalTerm; class TermPrivate; @@ -116,7 +117,16 @@ * * \sa NegationTerm */ - Negation + Negation, + + /** + * An optional term which marks its sub term as optional. + * + * \sa OptionalTerm + * + * \since 4.5 + */ + Optional }; /** @@ -166,6 +176,13 @@ bool isNegationTerm() const; /** + * \return \p true if this term is a OptionalTerm. + * + * \since 4.5 + */ + bool isOptionalTerm() const; + + /** * \return \p true if this term is an AndTerm. */ bool isAndTerm() const; @@ -210,6 +227,16 @@ NegationTerm toNegationTerm() const; /** + * Interpret this term as a OptionalTerm. + * + * \return A copy of this term if its type + * is Optional, a new OptionalTerm otherwise. + * + * \since 4.5 + */ + OptionalTerm toOptionalTerm() const; + + /** * Interpret this term as a AndTerm. * * \return A copy of this term if its type @@ -269,6 +296,17 @@ NegationTerm& toNegationTerm(); /** + * Convert this term into a OptionalTerm. + * If type is not Optional it will be changed + * and the result is a new OptionalTerm. + * + * \return A reference to this term as a OptionalTerm. + * + * \since 4.5 + */ + OptionalTerm& toOptionalTerm(); + + /** * Convert this term into a AndTerm. * If type is not And it will be changed * and the result is a new AndTerm. @@ -305,6 +343,28 @@ ResourceTypeTerm& toResourceTypeTerm(); /** + * Encode the Term in a string. Be aware that this does NOT create a SPARQL + * query. The returned string can be used to serialize terms that can later + * be read via fromString(). + * + * \sa fromString() + * + * \since 4.5 + */ + QString toString() const; + + /** + * Parse a Term that has been encoded as a string via toString(). + * + * \warning This method can NOT parse SPARQL syntax. + * + * \sa toString() + * + * \since 4.5 + */ + static Term fromString( const QString& s ); + + /** * Comparison operator. * * \return \p true if this term is equal to \p term. @@ -314,7 +374,7 @@ // FIXME: the compiler does not find this operator! QDebug operator<<( QDebug ) const; - /** \cond protected_error_members */ + /** \cond protected_term_members */ protected: Term( TermPrivate* ); @@ -326,6 +386,7 @@ friend class OrTermPrivate; friend class ComparisonTermPrivate; friend class NegationTermPrivate; + friend class OptionalTermPrivate; friend class Query; /** \endcond */ }; Index: nepomuk/query/negationterm_p.h =================================================================== --- nepomuk/query/negationterm_p.h (révision 1130118) +++ nepomuk/query/negationterm_p.h (copie de travail) @@ -36,7 +36,6 @@ TermPrivate* clone() const { return new NegationTermPrivate( *this ); } QString toSparqlGraphPattern( const QString& resourceVarName, QueryBuilderData* qbd ) const; - QString toString() const; }; } } Index: nepomuk/query/optionalterm.h =================================================================== --- nepomuk/query/optionalterm.h (révision 0) +++ nepomuk/query/optionalterm.h (révision 0) @@ -0,0 +1,81 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _NEPOMUK_QUERY_OPTIONAL_TERM_H_ +#define _NEPOMUK_QUERY_OPTIONAL_TERM_H_ + +#include "simpleterm.h" + +#include "nepomukquery_export.h" + +namespace Nepomuk { + namespace Query { + /** + * \class OptionalTerm optionalterm.h Nepomuk/Query/OptionalTerm + * + * \brief Make a term optional. + * + * %OptionalTerm can be used to mark another term as optional. + * This is mostly useful with subterms of type ComparisonTerm + * (or an AndTerm combining ComparisonTerms) which either have + * additional bindings (ComparisonTerm::setVariableName()) or + * a specified sort weight (ComparisonTerm::setSortWeight()). + * + * \author Sebastian Trueg <trueg@kde.org> + * + * \since 4.5 + */ + class NEPOMUKQUERY_EXPORT OptionalTerm : public SimpleTerm + { + public: + /** + * Default constructor: creates an invalid optional term. + */ + OptionalTerm(); + + /** + * Copy constructor. + */ + OptionalTerm( const OptionalTerm& term ); + + /** + * Destructor. + */ + ~OptionalTerm(); + + /** + * Assignment operator. + */ + OptionalTerm& operator=( const OptionalTerm& term ); + + /** + * Mark \p term as optional. This method will encasulate + * \p term in an OptionalTerm except if \p term is already + * of type OptionalTerm. + * + * \return The optional term. + */ + static Term optionalizeTerm( const Term& term ); + }; + } +} + +#endif Modification de propriétés sur nepomuk/query/optionalterm.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/query/result.h =================================================================== --- nepomuk/query/result.h (révision 1130118) +++ nepomuk/query/result.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2008-2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2008-2010 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 @@ -26,12 +26,14 @@ #include <QtCore/QHash> #include <Soprano/Statement> +#include <Soprano/BindingSet> #include "nepomukquery_export.h" namespace Nepomuk { class Resource; + class Variant; namespace Types { class Property; } @@ -45,6 +47,9 @@ * A search via QueryServiceClient returns a set of Result object. A result consists * of a Nepomuk::Resource and an optional score. * + * Additional bindings (variable values) as requested via ComparisonTerm::setVariableName() + * can be retrieved using additionalBinding(). + * * \author Sebastian Trueg <trueg@kde.org> * * \since 4.4 @@ -124,11 +129,54 @@ /** * Retrieve value of request property \p property. * - * \sa requestProperties, addRequestProperty + * \sa additionalBinding, requestProperties, addRequestProperty */ Soprano::Node requestProperty( const Types::Property& property ) const; /** + * Set the additional bindings a query returned besides the result + * itself and the request properties. + * + * Normally there is no need to call this method as the query service + * does set the bindings. + * + * \since 4.5 + */ + void setAdditionalBindings( const Soprano::BindingSet& bindings ); + + /** + * Retrieve the set of additional bindings as set via setAdditionalBindings(). + * Normally one would use additionalBinding() instead. + * + * \since 4.5 + */ + Soprano::BindingSet additionalBindings() const; + + /** + * Retrieve an additional binding as returned by the query. Typically + * these bindings are created via ComparisonTerm::setVariableName(). + * But they could also stem from custom SPARQL queries. A simple + * example would be: + * + * \code + * select ?r ?rating where { ?r nao:numericRating ?rating . } + * \endcode + * + * Here \p ?r would be used as the result's resource while + * \p ?rating could be accessed via + * + * \code + * additionalBinding( QLatin1String("rating") ); + * \endcode + * + * If for some reason one needs the plain binding values one + * could use additionalBinding(). + * + * \since 4.5 + */ + Variant additionalBinding( const QString& name ) const; + + /** * Comparison operator */ bool operator==( const Result& ) const; Index: nepomuk/query/comparisonterm_p.h =================================================================== --- nepomuk/query/comparisonterm_p.h (révision 1130118) +++ nepomuk/query/comparisonterm_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -29,10 +29,17 @@ namespace Nepomuk { namespace Query { + + class QueryBuilderData; + class ComparisonTermPrivate : public SimpleTermPrivate { public: - ComparisonTermPrivate() { + ComparisonTermPrivate() + : m_aggregateFunction(ComparisonTerm::NoAggregateFunction), + m_sortWeight(0), + m_sortOrder(Qt::AscendingOrder), + m_inverted(false) { m_type = Term::Comparison; } @@ -41,10 +48,27 @@ bool equals( const TermPrivate* other ) const; bool isValid() const; QString toSparqlGraphPattern( const QString& resourceVarName, QueryBuilderData* qbd ) const; - QString toString() const; + /** + * return m_variableName and register it with qbd + * or ask the latter to create a new variable. + */ + QString getMainVariableName( QueryBuilderData* qbd ) const; + + /** + * return the N3 form of m_property or a new variable + * in case m_property is invalid. + */ + QString propertyToString( QueryBuilderData* qbd ) const; + Types::Property m_property; ComparisonTerm::Comparator m_comparator; + + QString m_variableName; + ComparisonTerm::AggregateFunction m_aggregateFunction; + int m_sortWeight; + Qt::SortOrder m_sortOrder; + bool m_inverted; }; } } Index: nepomuk/query/queryparser.h =================================================================== --- nepomuk/query/queryparser.h (révision 1130118) +++ nepomuk/query/queryparser.h (copie de travail) @@ -99,6 +99,31 @@ ~QueryParser(); /** + * Flags to change the behaviour of the parser. + * + * \since 4.5 + */ + enum ParserFlag { + /** + * No flags. Default for parse() + */ + NoParserFlags = 0x0, + + /** + * Make each full text term use a '*' wildcard + * to match longer strings ('foobar' is matched + * by 'foob*'). + * + * Be aware that the query engine needs at least + * 4 chars to do globbing though. + * + * This is disabled by default. + */ + QueryTermGlobbing = 0x1 + }; + Q_DECLARE_FLAGS( ParserFlags, ParserFlag ) + + /** * Parse a user query. * * \return The parsed query or an invalid Query object @@ -107,6 +132,19 @@ Query parse( const QString& query ) const; /** + * Parse a user query. + * + * \param query The query string to parse + * \param flags a set of flags influencing the parsing process. + * + * \return The parsed query or an invalid Query object + * in case the parsing failed. + * + * \since 4.5 + */ + Query parse( const QString& query, ParserFlags flags ) const; + + /** * Try to match a field name as used in a query string to actual * properties. * @@ -140,4 +178,6 @@ } } +Q_DECLARE_OPERATORS_FOR_FLAGS( Nepomuk::Query::QueryParser::ParserFlags ) + #endif Index: nepomuk/query/literalterm.h =================================================================== --- nepomuk/query/literalterm.h (révision 1130118) +++ nepomuk/query/literalterm.h (copie de travail) @@ -62,6 +62,23 @@ * The example above will match all resources that have a property with a value containing * the string "nepomuk". * + * \section literalterm_examples Examples + * + * <pre>LiteralTerm("nepomuk")</pre> searches for the term "nepomuk". + * + * <pre>LiteralTerm("'nepomuk*'")</pre> searches for the terms starting with "nepomuk". + * + * <pre>LiteralTerm("'nepomuk kde'")</pre> searches for the term "nepomuk kde". + * + * <pre>LiteralTerm("'nepomuk* kde'")</pre> searches for terms matching "nepomuk* kde". + * + * %LiteralTerm always tries to normalize the query terms as best as possible. This includes + * automatically adding quotes as needed. + * + * \warning Be aware that the examples above apply to using %LiteralTerm as a stand-alone term + * or in a ComparisonTerm::Contains term. When using ComparisonTerm::Regexp the test as specified + * will be used as-is to create the regular expression. + * * \author Sebastian Trueg <trueg@kde.org> * * \since 4.4 Index: nepomuk/query/query_p.h =================================================================== --- nepomuk/query/query_p.h (révision 1130118) +++ nepomuk/query/query_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2008-2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2008-2010 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 @@ -27,6 +27,7 @@ #include "term.h" #include "query.h" +#include "filequery.h" #include "nepomukquery_export.h" @@ -40,7 +41,9 @@ public: QueryPrivate() : m_limit( 0 ), - m_isFileQuery( false ) { + m_offset( 0 ), + m_isFileQuery( false ), + m_fileMode( FileQuery::QueryFilesAndFolders ) { } QString createFolderFilter( const QString& resourceVarName, QueryBuilderData* ) const; @@ -54,12 +57,14 @@ Term m_term; int m_limit; + int m_offset; QList<Query::RequestProperty> m_requestProperties; bool m_isFileQuery; KUrl::List m_includeFolders; KUrl::List m_excludeFolders; + FileQuery::FileMode m_fileMode; }; } } Index: nepomuk/query/queryserviceclient.h =================================================================== --- nepomuk/query/queryserviceclient.h (révision 1130118) +++ nepomuk/query/queryserviceclient.h (copie de travail) @@ -48,6 +48,9 @@ * track. One instance may also be reused for subsequent queries if further updates * of the persistent query are not necessary. * + * For quick queries which do not require any updates one of the static query methods + * can be used: syncQuery(), syncSparqlQuery(), or syncDesktopQuery(). + * * \author Sebastian Trueg <trueg@kde.org> * * \since 4.4 @@ -74,6 +77,62 @@ */ static bool serviceAvailable(); + /** + * Start a query using the Nepomuk query service. + * + * A local event loop will be started to block the method + * call until all results have been listed, and results will be + * returned. You can check if the query was successful through + * the \p ok pointer. + * + * If updates to the query results are required an instance of QueryServiceClient + * should be created and one of the non-static query methods be used. + * + * \param query the query to perform. + * \param ok a valid boolean pointer, which will be set to \p true + * if the query service was found and the query was started, \p false otherwise. + * If you don't want to track errors, you can pass a null pointer instead. + * + * \return a list of \p Result for the given query. + * + * \sa query(const Query&) + * + * \since 4.5 + */ + static QList<Nepomuk::Query::Result> syncQuery( const Query& query, bool *ok = 0 ); + + /** + * \overload + * + * \param query a SPARQL query which binds results to variable \p 'r'. + * \param ok a valid boolean pointer, which will be set to \p true + * if the query service was found and the query was started, \p false otherwise. + * If you don't want to track errors, you can pass a null pointer instead. + * \param requestPropertyMap An optional mapping of variable binding names in \p query + * to their corresponding properties. For details see sparqlQuery. + * + * \sa sparqlQuery(const Query&) + * + * \since 4.5 + */ + static QList<Nepomuk::Query::Result> syncSparqlQuery( const QString& query, + const Nepomuk::Query::RequestPropertyMap& requestPropertyMap = Nepomuk::Query::RequestPropertyMap(), + bool *ok = 0 ); + + /** + * \overload + * + * \param query a desktop query string which can be parsed by QueryParser. + * \param ok a valid boolean pointer, which will be set to \p true + * if the query service was found and the query was started, \p false otherwise. + * If you don't want to track errors, you can pass a null pointer instead. + * + * \sa desktopQuery(const QString&) + * + * \since 4.5 + */ + static QList<Nepomuk::Query::Result> syncDesktopQuery( const QString& query, bool *ok = 0 ); + public Q_SLOTS: /** * Start a query using the Nepomuk query service. Index: nepomuk/query/querybuilderdata_p.h =================================================================== --- nepomuk/query/querybuilderdata_p.h (révision 1130118) +++ nepomuk/query/querybuilderdata_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include <QtCore/QString> #include <QtCore/QLatin1String> +#include <QtCore/QSet> #include "query.h" @@ -34,20 +35,119 @@ public: inline QueryBuilderData( Query::SparqlFlags flags ) : m_varNameCnt( 0 ), - m_flags( flags ) { + m_flags( flags ), + m_depth( 0 ) { } inline Query::SparqlFlags flags() const { return m_flags; } + inline int depth() const { + return m_depth; + } + + inline void increaseDepth() { + ++m_depth; + } + + inline void decreaseDepth() { + --m_depth; + } + + /// used by different implementations of TermPrivate::toSparqlGraphPattern and Query::toSparqlQuery inline QString uniqueVarName() { return QLatin1String( "?v" ) + QString::number( ++m_varNameCnt ); } + /// used by ComparisonTerm to add variable names set via ComparisonTerm::setVariableName + inline void addCustomVariable( const QString& name ) { + m_customVariables << name; + } + + /// used by Query::toSparqlQuery + inline QStringList customVariables() const { + return m_customVariables.toList(); + } + + struct OrderVariable { + OrderVariable(int w, const QString& n, Qt::SortOrder o) + : weight(w), + name(n), + sortOrder(o) { + } + int weight; + QString name; + Qt::SortOrder sortOrder; + }; + + /// used by ComparisonTerm to add sorting variables (names include the '?') + inline void addOrderVariable( const QString& name, int weight, Qt::SortOrder order ) { + int i = 0; + while( i < m_orderVariables.count() && + m_orderVariables[i].weight > weight ) + ++i; + m_orderVariables.insert( i, OrderVariable( weight, name, order ) ); + } + + /// used by Query::toSparqlQuery + inline QString buildOrderString() const { + if( m_orderVariables.isEmpty() ) + return QString(); + QString s = QLatin1String(" ORDER BY "); + for( int i = 0; i < m_orderVariables.count(); ++i ) { + if( m_orderVariables[i].sortOrder == Qt::DescendingOrder ) + s += QLatin1String("DESC "); + else + s += QLatin1String("ASC "); + s += QString::fromLatin1("( %1 )").arg(m_orderVariables[i].name); + s += ' '; + } + return s; + } + + /// create and remember a scoring variable for full text matching + inline QString createScoringVariable() { + QString v = uniqueVarName(); + m_scoreVariables.insert(v, m_depth); + return v; + } + + inline QString buildScoringExpression() const { + QStringList scores; + for( QHash<QString, int>::const_iterator it = m_scoreVariables.constBegin(); + it != m_scoreVariables.constEnd(); ++it ) { + const QString var = it.key(); + int depth = it.value(); + if( depth > 0 ) + scores += QString::fromLatin1("(%1/%2)").arg(var).arg(depth+1); + else + scores += var; + } + if( !scores.isEmpty() ) + return '(' + scores.join(QLatin1String("+")) + QLatin1String(") as ?_n_f_t_m_s_"); + else + return QString(); + } + private: + /// a running counter for unique variable names int m_varNameCnt; - Query::SparqlFlags m_flags; + + /// copy of the flags as set in Query::toSparqlQuery + const Query::SparqlFlags m_flags; + + /// custom variables that have been added via ComparisonTerm::setVariableName + QSet<QString> m_customVariables; + + /// variables that are used for sorting set via ComparisonTerm::setSortWeight + QList<OrderVariable> m_orderVariables; + + /// all full-text matching scoring variables + QHash<QString, int> m_scoreVariables; + + /// The depth of a term in the query. This is only changed by ComparisonTerm + int m_depth; }; } } Index: nepomuk/query/dbusoperators.cpp =================================================================== --- nepomuk/query/dbusoperators.cpp (révision 1130118) +++ nepomuk/query/dbusoperators.cpp (copie de travail) @@ -26,6 +26,7 @@ #include "property.h" #include <Soprano/Node> +#include <Soprano/BindingSet> void Nepomuk::Query::registerDBusTypes() @@ -45,10 +46,12 @@ arg.beginStructure(); + // resource URI and score arg << QString::fromAscii( result.resource().resourceUri().toEncoded() ) << result.score(); arg.beginMap( QVariant::String, qMetaTypeId<Soprano::Node>() ); + // request properties QHash<Nepomuk::Types::Property, Soprano::Node> rp = result.requestProperties(); for ( QHash<Nepomuk::Types::Property, Soprano::Node>::const_iterator it = rp.constBegin(); it != rp.constEnd(); ++it ) { arg.beginMapEntry(); @@ -56,6 +59,15 @@ arg.endMapEntry(); } + // additional bindings (the hacked version to make sure we do not change the signature. It would probably + // not be a big deal to change it but neither is this hack) + const Soprano::BindingSet additionalBindings = result.additionalBindings(); + foreach( const QString& binding, additionalBindings.bindingNames() ) { + arg.beginMapEntry(); + arg << (QLatin1String("|") + binding) << additionalBindings[binding]; // we use some char which is very invalid in URIs + arg.endMapEntry(); + } + arg.endMap(); arg.endStructure(); @@ -73,9 +85,10 @@ arg.beginStructure(); QString uri; double score = 0.0; + Soprano::BindingSet additionalBindings; arg >> uri >> score; - result = Nepomuk::Query::Result( QUrl::fromEncoded( uri.toAscii() ), score ); + result = Nepomuk::Query::Result( Nepomuk::Resource::fromResourceUri( QUrl::fromEncoded( uri.toAscii() ) ), score ); arg.beginMap(); while ( !arg.atEnd() ) { @@ -84,12 +97,17 @@ arg.beginMapEntry(); arg >> rs >> node; arg.endMapEntry(); - result.addRequestProperty( QUrl::fromEncoded( rs.toAscii() ), node ); + if( rs.startsWith(QLatin1String("|")) ) + additionalBindings.insert( rs.mid(1), node ); + else + result.addRequestProperty( QUrl::fromEncoded( rs.toAscii() ), node ); } arg.endMap(); arg.endStructure(); + result.setAdditionalBindings( additionalBindings ); + return arg; } Index: nepomuk/query/CMakeLists.txt =================================================================== --- nepomuk/query/CMakeLists.txt (révision 1130118) +++ nepomuk/query/CMakeLists.txt (copie de travail) @@ -8,10 +8,11 @@ ${NEPOMUK_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../core - ${CMAKE_CURRENT_SOURCE_DIR}/../core/ontology + ${CMAKE_CURRENT_SOURCE_DIR}/../types ) add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) +add_definitions(-DDISABLE_NEPOMUK_LEGACY=1) set(nepomukquery_SRC term.cpp @@ -24,6 +25,7 @@ resourceterm.cpp literalterm.cpp resourcetypeterm.cpp + optionalterm.cpp query.cpp query_p.cpp filequery.cpp @@ -32,6 +34,8 @@ result.cpp queryserviceclient.cpp dbusoperators.cpp + ../core/dbusconnectionpool.cpp + queryserializer.cpp ) soprano_add_ontology(nepomukquery_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nie.trig" "NIE" "Nepomuk::Vocabulary" "trig") @@ -74,6 +78,7 @@ resourceterm.h literalterm.h resourcetypeterm.h + optionalterm.h query.h filequery.h result.h @@ -82,5 +87,3 @@ nepomukquery_export.h DESTINATION ${INCLUDE_INSTALL_DIR}/nepomuk COMPONENT Devel ) - -add_subdirectory(test) Index: nepomuk/query/test/queryparsertest.cpp =================================================================== --- nepomuk/query/test/queryparsertest.cpp (révision 1130118) +++ nepomuk/query/test/queryparsertest.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -30,18 +30,72 @@ #include "comparisonterm.h" #include <QtTest> +#include <qtest_kde.h> +#include "ktempdir.h" + #include <Soprano/LiteralValue> #include <Soprano/Node> +#include <Soprano/StorageModel> +#include <Soprano/Backend> +#include <Soprano/PluginManager> #include <Soprano/Vocabulary/NAO> +#include <Soprano/Vocabulary/NRL> +#include <Soprano/Vocabulary/RDF> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/XMLSchema> #include "property.h" +#include "resourcemanager.h" - Q_DECLARE_METATYPE( Nepomuk::Query::Query ) using namespace Nepomuk::Query; +void QueryParserTest::initTestCase() +{ + // we need to use a Virtuoso model as tmp model since redland misses important SPARQL features + // that are used by libnepomuk below + const Soprano::Backend* backend = Soprano::PluginManager::instance()->discoverBackendByName( "virtuosobackend" ); + QVERIFY( backend ); + m_storageDir = new KTempDir(); + m_model = backend->createModel( Soprano::BackendSettings() << Soprano::BackendSetting(Soprano::BackendOptionStorageDir, m_storageDir->name()) ); + QVERIFY( m_model ); + + // we create one fake ontology + QUrl graph("graph:/onto"); + m_model->addStatement( graph, Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::NRL::Ontology(), graph ); + + m_model->addStatement( QUrl("onto:/label"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDF::Property(), graph ); + m_model->addStatement( QUrl("onto:/label"), Soprano::Vocabulary::RDFS::label(), Soprano::LiteralValue::createPlainLiteral("label"), graph ); + m_model->addStatement( QUrl("onto:/label"), Soprano::Vocabulary::RDFS::range(), Soprano::Vocabulary::XMLSchema::string(), graph ); + + m_model->addStatement( QUrl("onto:/hasTag"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDF::Property(), graph ); + m_model->addStatement( QUrl("onto:/hasTag"), Soprano::Vocabulary::RDFS::label(), Soprano::LiteralValue::createPlainLiteral("has tag"), graph ); + m_model->addStatement( QUrl("onto:/hasTag"), Soprano::Vocabulary::RDFS::range(), QUrl("onto:/Tag"), graph ); + + m_model->addStatement( QUrl("onto:/tag"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDF::Property(), graph ); + m_model->addStatement( QUrl("onto:/tag"), Soprano::Vocabulary::RDFS::label(), Soprano::LiteralValue::createPlainLiteral("hastag"), graph ); + m_model->addStatement( QUrl("onto:/tag"), Soprano::Vocabulary::RDFS::range(), QUrl("onto:/Tag"), graph ); + + m_model->addStatement( QUrl("onto:/Tag"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDFS::Class(), graph ); + + m_model->addStatement( QUrl("onto:/int"), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::RDF::Property(), graph ); + m_model->addStatement( QUrl("onto:/int"), Soprano::Vocabulary::RDFS::label(), Soprano::LiteralValue::createPlainLiteral("int value"), graph ); + m_model->addStatement( QUrl("onto:/int"), Soprano::Vocabulary::RDFS::range(), Soprano::Vocabulary::XMLSchema::integer(), graph ); + + Nepomuk::ResourceManager::instance()->setOverrideMainModel( m_model ); +} + + +void QueryParserTest::cleanupTestCase() +{ + Nepomuk::ResourceManager::instance()->setOverrideMainModel( 0 ); + delete m_model; + delete m_storageDir; +} + + void QueryParserTest::testQueryParser_data() { QTest::addColumn<QString>( "queryString" ); @@ -49,36 +103,38 @@ // simple literal queries QTest::newRow( "simple literal query" ) << QString( "Hello" ) << Query( LiteralTerm( "Hello" ) ); - QTest::newRow( "literal with spaces query" ) << QString( "'Hello World'" ) << Query( LiteralTerm( "Hello World" ) ); + QTest::newRow( "literal with spaces without quotes" ) << QString( "Hello World" ) << Query( AndTerm( LiteralTerm("Hello"), LiteralTerm("World" ) ) ); + QTest::newRow( "literal with spaces with quotes" ) << QString( "'Hello World'" ) << Query( LiteralTerm( "Hello World" ) ); // comparison queries -#ifdef MAKE_OR_QUERIES_WITH_PROPERTIES_IN_THEM QTest::newRow( "simple field query" ) << QString( "hastag:nepomuk" ) - << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), LiteralTerm( "nepomuk" ) ) ); - QTest::newRow( "simple property query" ) << QString( "%1:nepomuk" ).arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::NAO::hasTag() ) ) - << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), LiteralTerm( "nepomuk" ) ) ); + << Query( OrTerm( ComparisonTerm( QUrl("onto:/hasTag"), LiteralTerm( "nepomuk" ) ), + ComparisonTerm( QUrl("onto:/tag"), LiteralTerm( "nepomuk" ) ) ) ); + QTest::newRow( "simple property query" ) << QString( "<onto:/hasTag>:nepomuk" ) + << Query( ComparisonTerm( QUrl("onto:/hasTag"), LiteralTerm( "nepomuk" ) ) ); #ifdef QUERY_PARSER_SUPPORTS_RESOURCE_VALUES QTest::newRow( "resource field query" ) << QString( "hastag:<nepomuk:/Nepomuk>" ) << Query( ComparisonTerm( "hastag", ResourceTerm( QUrl( "nepomuk:/Nepomuk" ) ) ) ); #endif QTest::newRow( "nested resource query" ) << QString( "hastag:(label:nepomuk)" ) - << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), LiteralTerm( "nepomuk" ) ) ); - << Query( ComparisonTerm( "hastag", ComparisonTerm( "label", LiteralTerm( "nepomuk" ) ) ) ); -#endif + << Query( OrTerm( ComparisonTerm( QUrl("onto:/hasTag"), ComparisonTerm( QUrl("onto:/label"), LiteralTerm( "nepomuk" ) ) ), + ComparisonTerm( QUrl("onto:/tag"), ComparisonTerm( QUrl("onto:/label"), LiteralTerm( "nepomuk" ) ) ) ) ); + QTest::newRow( "int property query" ) << QString( "'int value':42" ) + << Query( ComparisonTerm( QUrl("onto:/int"), LiteralTerm( 42 ) ) ); + QTest::newRow( "int property query 2" ) << QString( "int:\"42\"" ) + << Query( ComparisonTerm( QUrl("onto:/int"), LiteralTerm( 42 ) ) ); // negation QTest::newRow( "simple negation" ) << QString( "-Hello" ) << Query( NegationTerm::negateTerm( LiteralTerm( "Hello" ) ) ); -#ifdef MAKE_OR_QUERIES_WITH_PROPERTIES_IN_THEM - QTest::newRow( "field negation" ) << QString( "-hastag:nepomuk" ) << Query( NegationTerm::negateTerm( ComparisonTerm( "hastag", LiteralTerm( "nepomuk" ) ) ) ); -#endif + QTest::newRow( "field negation" ) << QString( "-label:nepomuk" ) << Query( NegationTerm::negateTerm( ComparisonTerm( QUrl("onto:/label"), LiteralTerm( "nepomuk" ) ) ) ); // and query - QTest::newRow( "and: two literals" ) << QString( "Hello World" ) << Query( AndTerm( QList<Term>() << LiteralTerm( "Hello" ) << LiteralTerm( "World" ) ) ); - QTest::newRow( "and: two literals with AND" ) << QString( "Hello AND World" ) << Query( AndTerm( QList<Term>() << LiteralTerm( "Hello" ) << LiteralTerm( "World" ) ) ); + QTest::newRow( "and: two literals" ) << QString( "Hello World" ) << Query( AndTerm( LiteralTerm( "Hello" ), LiteralTerm( "World" ) ) ); + QTest::newRow( "and: two literals with AND" ) << QString( "Hello AND World" ) << Query( AndTerm( LiteralTerm( "Hello" ), LiteralTerm( "World" ) ) ); // or queries - QTest::newRow( "or: two literals" ) << QString( "Hello OR World" ) << Query( OrTerm( QList<Term>() << LiteralTerm( "Hello" ) << LiteralTerm( "World" ) ) ); + QTest::newRow( "or: two literals" ) << QString( "Hello OR World" ) << Query( OrTerm( LiteralTerm( "Hello" ), LiteralTerm( "World" ) ) ); } @@ -87,16 +143,42 @@ QFETCH( QString, queryString ); QFETCH( Nepomuk::Query::Query, query ); - qDebug() << "Wanted query:" << query; - Query q = QueryParser::parseQuery( queryString ); - qDebug() << "Parsed query:" << q; +// qDebug() << "Wanted query:" << query; +// qDebug() << "Parsed query:" << q; QCOMPARE( q, query ); } -QTEST_MAIN( QueryParserTest ) +void QueryParserTest::testQueryParserWithGlobbing_data() +{ + QTest::addColumn<QString>( "queryString" ); + QTest::addColumn<Nepomuk::Query::Query>( "query" ); + // simple literal queries + QTest::newRow( "simple literal query" ) << QString( "Hello" ) << Query( LiteralTerm( "Hello*" ) ); + QTest::newRow( "simple literal query" ) << QString( "\"Hello\"" ) << Query( LiteralTerm( "Hello" ) ); + QTest::newRow( "literal with spaces without quotes" ) << QString( "Hello World" ) << Query( AndTerm( LiteralTerm("Hello*"), LiteralTerm("World*" ) ) ); + QTest::newRow( "literal with spaces with quotes" ) << QString( "'Hello World'" ) << Query( LiteralTerm( "Hello World" ) ); +} + + +void QueryParserTest::testQueryParserWithGlobbing() +{ + QFETCH( QString, queryString ); + QFETCH( Nepomuk::Query::Query, query ); + + QueryParser p; + Query q = p.parse( queryString, QueryParser::QueryTermGlobbing ); + +// qDebug() << "Wanted query:" << query; +// qDebug() << "Parsed query:" << q; + + QCOMPARE( q, query ); +} + +QTEST_KDEMAIN_CORE( QueryParserTest ) + #include "queryparsertest.moc" Index: nepomuk/query/test/querytest.cpp =================================================================== --- nepomuk/query/test/querytest.cpp (révision 1130118) +++ nepomuk/query/test/querytest.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,12 @@ #include "negationterm.h" #include "comparisonterm.h" #include "resourcetypeterm.h" +#include "optionalterm.h" #include "nie.h" +#include "nfo.h" +#include "nco.h" +#include "pimo.h" +#include "property.h" #include <QtTest> @@ -38,8 +43,10 @@ #include <Soprano/Node> #include <Soprano/Vocabulary/NAO> #include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/XMLSchema> #include <kdebug.h> +#include <qtest_kde.h> Q_DECLARE_METATYPE( Nepomuk::Query::Query ) @@ -54,10 +61,25 @@ QTest::newRow( "simple literal query" ) << Query( LiteralTerm( "Hello" ) ) - << QString::fromLatin1( "select distinct ?r where { { ?r ?v1 ?v2 . ?v2 bif:contains \"'Hello*'\" . } UNION { ?r ?v1 ?v3 . ?v3 ?v4 ?v2 . ?v4 %1 %2 . ?v2 bif:contains \"'Hello*'\" . } . }" ) + << QString::fromLatin1( "select distinct ?r where { { ?r ?v1 ?v2 . ?v2 bif:contains \"Hello\" . } UNION { ?r ?v1 ?v3 . ?v3 ?v4 ?v2 . ?v4 %1 %2 . ?v2 bif:contains \"Hello\" . } . }" ) .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subPropertyOf()), Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label()) ); + QString helloWorldQuery = QString::fromLatin1( "select distinct ?r where { { ?r ?v1 ?v2 . ?v2 bif:contains \"'Hello World'\" . } " + "UNION " + "{ ?r ?v1 ?v3 . ?v3 ?v4 ?v2 . ?v4 %1 %2 . ?v2 bif:contains \"'Hello World'\" . } . }" ) + .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subPropertyOf()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label()) ); + QTest::newRow( "simple literal query with space" ) + << Query( LiteralTerm( "Hello World" ) ) + << helloWorldQuery; + QTest::newRow( "simple literal query with space and quotes" ) + << Query( LiteralTerm( "'Hello World'" ) ) + << helloWorldQuery; + QTest::newRow( "simple literal query with space and quotes" ) + << Query( LiteralTerm( "\"Hello World\"" ) ) + << helloWorldQuery; + QTest::newRow( "type query" ) << Query( ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) ) << QString::fromLatin1("select distinct ?r where { ?r a ?v1 . ?v1 %1 %2 . }") @@ -73,7 +95,7 @@ QTest::newRow( "hastag with literal term" ) << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), LiteralTerm( QLatin1String("nepomuk")) ) ) - << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . ?v1 ?v2 ?v3 . ?v2 %2 %3 . ?v3 bif:contains \"'nepomuk*'\" . }") + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . ?v1 ?v2 ?v3 . ?v2 %2 %3 . ?v3 bif:contains \"nepomuk\" . }") .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())) .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subPropertyOf())) .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label())); @@ -87,6 +109,238 @@ << Query( NegationTerm::negateTerm(ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) ))) << QString::fromLatin1("select distinct ?r where { OPTIONAL { ?v1 %1 <nepomuk:/res/foobar> . FILTER(?v1=?r) . } . FILTER(!BOUND(?v1)) . }") .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + QTest::newRow( "comparators <" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "comparators <=" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::SmallerOrEqual ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1<=\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "comparators >" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Greater ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1>\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "comparators >=" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::GreaterOrEqual ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1>=\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "inverted comparisonterm" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) ).inverted() ) + << QString::fromLatin1("select distinct ?r where { <nepomuk:/res/foobar> %1 ?r . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + QTest::newRow( "optional term" ) + << Query(OptionalTerm::optionalizeTerm(ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) ))) + << QString::fromLatin1("select distinct ?r where { OPTIONAL { ?r %1 <nepomuk:/res/foobar> . } }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + QTest::newRow( "and term" ) + << Query( AndTerm( ComparisonTerm( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Greater ), + ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), ResourceTerm(QUrl("nepomuk:/test")) ) ) ) + << QString::fromLatin1("select distinct ?r where { { ?r %1 ?v1 . FILTER(?v1>\"4\"^^%2) . ?r %3 <nepomuk:/test> . } . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + ComparisonTerm setVarNameTerm1( Soprano::Vocabulary::NAO::hasTag(), ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) ); + setVarNameTerm1.setVariableName("myvar"); + QTest::newRow( "set variable name 1" ) + << Query( setVarNameTerm1 ) + << QString::fromLatin1("select distinct ?r ?myvar where { ?r %1 ?myvar . ?myvar a ?v1 . ?v1 %2 %3 . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subClassOf()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::Tag())); + + ComparisonTerm setVarNameTerm2( Soprano::Vocabulary::NAO::hasTag(), LiteralTerm( "nepomuk" ) ); + setVarNameTerm2.setVariableName( "myvar" ); + QTest::newRow( "set variable name 2" ) + << Query( setVarNameTerm2 ) + << QString::fromLatin1("select distinct ?r ?myvar where { ?r %1 ?myvar . ?myvar ?v1 ?v2 . ?v1 %2 %3 . ?v2 bif:contains \"nepomuk\" . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subPropertyOf()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label())); + + ComparisonTerm setVarNameTerm3( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ); + setVarNameTerm3.setVariableName("myvar"); + QTest::newRow( "set variable name 3" ) + << Query( setVarNameTerm3 ) + << QString::fromLatin1("select distinct ?r ?myvar where { ?r %1 ?myvar . FILTER(?myvar<\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + ComparisonTerm setVarNameTerm4( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ); + setVarNameTerm3.setVariableName("myvar" ); + setVarNameTerm3.setAggregateFunction(ComparisonTerm::Count); + QTest::newRow( "set variable name 4 (with aggregate function count)" ) + << Query( setVarNameTerm3 ) + << QString::fromLatin1("select distinct ?r count(?v1) as ?myvar where { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + ComparisonTerm orderByTerm1( Soprano::Vocabulary::NAO::numericRating(), LiteralTerm(4), ComparisonTerm::Smaller ); + orderByTerm1.setSortWeight( 1 ); + QTest::newRow( "order by 1" ) + << Query( orderByTerm1 ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . } ORDER BY ASC ( ?v1 )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + orderByTerm1.setSortWeight( 1, Qt::DescendingOrder ); + QTest::newRow( "order by 2" ) + << Query( orderByTerm1 ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . } ORDER BY DESC ( ?v1 )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + ComparisonTerm orderByTerm2( Soprano::Vocabulary::NAO::prefLabel(), LiteralTerm("hello") ); + orderByTerm2.setSortWeight( 2 ); + + QTest::newRow( "order by 3" ) + << Query( AndTerm( orderByTerm1, orderByTerm2 ) ) + << QString::fromLatin1("select distinct ?r where { { ?r %1 ?v1 . FILTER(?v1<\"4\"^^%2) . ?r %3 ?v2 . ?v2 bif:contains \"hello\" . } . } ORDER BY ASC ( ?v2 ) DESC ( ?v1 )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::prefLabel()) ); + + orderByTerm1.setVariableName("myvar"); + QTest::newRow( "order by 4" ) + << Query( orderByTerm1 ) + << QString::fromLatin1("select distinct ?r ?myvar where { ?r %1 ?myvar . FILTER(?myvar<\"4\"^^%2) . } ORDER BY DESC ( ?myvar )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::XMLSchema::xsdInt()) ); + + QTest::newRow( "ComparisonTerm with invalid property" ) + << Query( ComparisonTerm( Nepomuk::Types::Property(), ResourceTerm( QUrl("nepomuk:/res/foobar") ) )) + << QString::fromLatin1("select distinct ?r where { ?r ?v1 <nepomuk:/res/foobar> . }"); + + QTest::newRow( "ComparisonTerm with invalid subterm" ) + << Query( ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), Term() ) ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . }") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())); + + QTest::newRow( "ComparisonTerm with invalid property and subterm" ) + << Query( ComparisonTerm( Nepomuk::Types::Property(), Term() ) ) + << QString::fromLatin1("select distinct ?r where { ?r ?v1 ?v2 . }"); + + ComparisonTerm orderByTerm5( Soprano::Vocabulary::NAO::numericRating(), Term() ); + orderByTerm5.setSortWeight( 1 ); + orderByTerm5.setAggregateFunction( ComparisonTerm::Max ); + QTest::newRow( "order by 5 (with aggregate function and invalid subterm)" ) + << Query( orderByTerm5 ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . } ORDER BY ASC ( max(?v1) )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()) ); + + orderByTerm5.setVariableName( "myvar" ); + QTest::newRow( "order by 5 (with aggregate function and invalid subterm and varname)" ) + << Query( orderByTerm5 ) + << QString::fromLatin1("select distinct ?r max(?v1) as ?myvar where { ?r %1 ?v1 . } ORDER BY ASC ( ?myvar )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()) ); + + orderByTerm5.setVariableName( QString() ); + orderByTerm5.setAggregateFunction( ComparisonTerm::DistinctCount ); + QTest::newRow( "order by 5 (with aggregate function and invalid subterm and varname)" ) + << Query( orderByTerm5 ) + << QString::fromLatin1("select distinct ?r where { ?r %1 ?v1 . } ORDER BY ASC ( count(distinct ?v1) )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::numericRating()) ); + + + // + // A more complex example + // + QUrl res("nepomuk:/res/foobar"); + AndTerm mainTerm; + OrTerm typeOr; + typeOr.addSubTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NFO::RasterImage() ) ); + typeOr.addSubTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NFO::Audio() ) ); + mainTerm.addSubTerm( typeOr ); + mainTerm.addSubTerm( NegationTerm::negateTerm( ComparisonTerm( Nepomuk::Types::Property(), ResourceTerm( res ) ).inverted() ) ); + + // an empty comparisonterm results in "?r ?v1 ?v2" + ComparisonTerm ct; + + // change the var name: "?r ?v1 ?cnt" + ct.setVariableName( "cnt" ); + ct.setAggregateFunction( ComparisonTerm::Count ); + + // by default all have 0, Query::toSparqlQuery will add ORDER BY for all ComparisonTerm with sortweight != 0 + ct.setSortWeight( 1, Qt::DescendingOrder ); + + mainTerm.addSubTerm(ct.inverted()); + + QString sparql = QString::fromLatin1("select distinct ?r count(?v6) as ?cnt where { { " + "{ ?r a ?v1 . ?v1 %1 %2 . } UNION { ?r a ?v2 . ?v2 %1 %3 . } . " + "OPTIONAL { <nepomuk:/res/foobar> ?v4 ?v3 . FILTER(?v3=?r) . } . FILTER(!BOUND(?v3)) . " + "?r ?v5 ?v6 . } . } ORDER BY DESC ( ?cnt )") + .arg(Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subClassOf()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::RasterImage()), + Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NFO::Audio())); + + QTest::newRow( "a complex one" ) + << Query( mainTerm ) + << sparql; + +#if 0 +// subquery to match grouding occurrences of nepomuk:/TEST + ComparisonTerm goterm( Nepomuk::Vocabulary::PIMO::groundingOccurrence(), + ResourceTerm( Nepomuk::Resource( QUrl("nepomuk:/TEST")) ) ); + goterm.setInverted(true); + +// combine that with only nco:PersonContacts + AndTerm pcgoterm( ResourceTypeTerm( Nepomuk::Vocabulary::NCO::PersonContact() ), + goterm ); + +// now look for im accounts of those grounding occurrences (pcgoterm will become the subject of this comparison, +// thus the comparison will match the im accounts) + ComparisonTerm impcgoterm( Nepomuk::Vocabulary::NCO::hasIMAccount(), + pcgoterm ); + impcgoterm.setInverted(true); + +// now look for all buddies of the accounts + ComparisonTerm buddyTerm( QUrl("http://kde.org/telepathy#isBuddyOf")/*Nepomuk::Vocabulary::Telepathy::isBuddyOf()*/, + impcgoterm ); + +// set the name of the variable (i.e. the buddies) to be able to match it later + buddyTerm.setVariableName("t"); + +// same comparison, other property, but use the same variable name to match them + ComparisonTerm ppterm( QUrl("http://kde.org/telepathy#publishesPresenceTo")/*Nepomuk::Vocabulary::Telepathy::publishesPresenceTo()*/, + ResourceTypeTerm( Nepomuk::Vocabulary::NCO::IMAccount() ) ); + ppterm.setVariableName("t"); + +// combine both to complete the matching of the im account ?account + AndTerm accountTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NCO::IMAccount() ), + buddyTerm, + ppterm ); + +// match the account and select it for the results + ComparisonTerm imaccountTerm( Nepomuk::Vocabulary::NCO::hasIMAccount(), accountTerm ); + imaccountTerm.setVariableName("account"); + +// and finally the exclusion of those person contacts that already have a pimo person attached + ComparisonTerm personTerm( Nepomuk::Vocabulary::PIMO::groundingOccurrence(), + ResourceTypeTerm( Nepomuk::Vocabulary::PIMO::Person() ) ); + personTerm.setInverted(true); + +// and all combined + Query theQuery( AndTerm( ResourceTypeTerm( Nepomuk::Vocabulary::NCO::PersonContact() ), + imaccountTerm, + NegationTerm::negateTerm(personTerm)) ); + + + QTest::newRow( "and term" ) + << theQuery + << QString::fromLatin1(""); +#endif } @@ -95,6 +349,7 @@ QFETCH( Nepomuk::Query::Query, query ); QFETCH( QString, queryString ); +// kDebug() << query.toSparqlQuery(); QCOMPARE( query.toSparqlQuery().simplified(), queryString ); } @@ -123,6 +378,6 @@ QVERIFY(optimized.isLiteralTerm()); } -QTEST_MAIN( QueryTest ) +QTEST_KDEMAIN_CORE( QueryTest ) #include "querytest.moc" Index: nepomuk/query/test/queryparsertest.h =================================================================== --- nepomuk/query/test/queryparsertest.h (révision 1130118) +++ nepomuk/query/test/queryparsertest.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -23,14 +23,25 @@ #define _NEPOMUK_QUERY_PARSER_TEST_H_ #include <QtCore/QObject> +#include "ktempdir.h" +#include <Soprano/Model> + class QueryParserTest : public QObject { Q_OBJECT private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); void testQueryParser_data(); void testQueryParser(); + void testQueryParserWithGlobbing_data(); + void testQueryParserWithGlobbing(); + +private: + KTempDir* m_storageDir; + Soprano::Model* m_model; }; #endif Index: nepomuk/query/test/CMakeLists.txt =================================================================== --- nepomuk/query/test/CMakeLists.txt (révision 1130118) +++ nepomuk/query/test/CMakeLists.txt (copie de travail) @@ -2,8 +2,10 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) +add_definitions(-DDISABLE_NEPOMUK_LEGACY=1) + kde4_add_unit_test(queryparsertest NOGUI queryparsertest.cpp) -target_link_libraries(queryparsertest nepomukquery +target_link_libraries(queryparsertest nepomuk nepomukquery ${QT_QTTEST_LIBRARY} ${SOPRANO_LIBRARIES} ${KDE4_KDECORE_LIBS} @@ -12,6 +14,8 @@ set(querytest_SRC querytest.cpp ../query_p.cpp) soprano_add_ontology(querytest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nie.trig" "NIE" "Nepomuk::Vocabulary" "trig") soprano_add_ontology(querytest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nfo.trig" "NFO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(querytest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nco.trig" "NCO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(querytest_SRC "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/pimo/pimo.trig" "PIMO" "Nepomuk::Vocabulary" "trig") kde4_add_unit_test(querytest NOGUI ${querytest_SRC}) target_link_libraries(querytest nepomuk nepomukquery ${QT_QTTEST_LIBRARY} Index: nepomuk/query/queryserializer.h =================================================================== --- nepomuk/query/queryserializer.h (révision 0) +++ nepomuk/query/queryserializer.h (révision 0) @@ -0,0 +1,39 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2008-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License 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_QUERY_QUERY_SERIALIZER_H_ +#define _NEPOMUK_QUERY_QUERY_SERIALIZER_H_ + +class QString; + +namespace Nepomuk { + namespace Query { + class Query; + class Term; + + QString serializeQuery( const Query& query ); + Query parseQuery( const QString& s ); + + QString serializeTerm( const Term& term ); + Term parseTerm( const QString& s ); + } +} + +#endif + Modification de propriétés sur nepomuk/query/queryserializer.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/query/filequery.cpp =================================================================== --- nepomuk/query/filequery.cpp (révision 1130118) +++ nepomuk/query/filequery.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2008-2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2008-2010 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 @@ -27,6 +27,13 @@ } +Nepomuk::Query::FileQuery::FileQuery( const Term& term ) + : Query( term ) +{ + d->m_isFileQuery = true; +} + + Nepomuk::Query::FileQuery::FileQuery( const Query& query ) : Query( query ) { @@ -81,3 +88,15 @@ { return d->m_excludeFolders; } + + +void Nepomuk::Query::FileQuery::setFileMode( FileMode mode ) +{ + d->m_fileMode = mode; +} + + +Nepomuk::Query::FileQuery::FileMode Nepomuk::Query::FileQuery::fileMode() const +{ + return d->m_fileMode; +} Index: nepomuk/query/term.cpp =================================================================== --- nepomuk/query/term.cpp (révision 1130118) +++ nepomuk/query/term.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2007 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2007-2010 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 @@ -24,6 +24,7 @@ #include "andterm.h" #include "orterm.h" #include "negationterm.h" +#include "optionalterm.h" #include "comparisonterm.h" #include "resourcetypeterm.h" #include "literalterm_p.h" @@ -31,8 +32,10 @@ #include "andterm_p.h" #include "orterm_p.h" #include "negationterm_p.h" +#include "optionalterm_p.h" #include "comparisonterm_p.h" #include "resourcetypeterm_p.h" +#include "queryserializer.h" #include <QtCore/QStringList> #include <QtCore/QList> @@ -101,6 +104,12 @@ } +bool Nepomuk::Query::Term::isOptionalTerm() const +{ + return type() == Optional; +} + + bool Nepomuk::Query::Term::isAndTerm() const { return type() == And; @@ -153,6 +162,15 @@ } +Nepomuk::Query::OptionalTerm Nepomuk::Query::Term::toOptionalTerm() const +{ + if ( isOptionalTerm() ) + return *static_cast<const OptionalTerm*>( this ); + else + return OptionalTerm(); +} + + Nepomuk::Query::AndTerm Nepomuk::Query::Term::toAndTerm() const { if ( isAndTerm() ) @@ -212,6 +230,12 @@ } +Nepomuk::Query::OptionalTerm& Nepomuk::Query::Term::toOptionalTerm() +{ + CONVERT_AND_RETURN( OptionalTerm ); +} + + Nepomuk::Query::AndTerm& Nepomuk::Query::Term::toAndTerm() { CONVERT_AND_RETURN( AndTerm ); @@ -236,6 +260,19 @@ } +QString Nepomuk::Query::Term::toString() const +{ + return Nepomuk::Query::serializeTerm( *this ); +} + + +// static +Nepomuk::Query::Term Nepomuk::Query::Term::fromString( const QString& s ) +{ + return Nepomuk::Query::parseTerm( s ); +} + + bool Nepomuk::Query::Term::operator==( const Term& other ) const { return d_ptr->equals( other.d_ptr ); @@ -244,7 +281,7 @@ QDebug Nepomuk::Query::Term::operator<<( QDebug dbg ) const { - return dbg << d_ptr->toString(); + return dbg << toString(); } @@ -266,8 +303,11 @@ ( uint )term.toComparisonTerm().comparator()<<8 ); case Nepomuk::Query::Term::Negation: - return 1; + return qHash(term.toNegationTerm().subTerm()); + case Nepomuk::Query::Term::Optional: + return qHash(term.toOptionalTerm().subTerm()); + case Nepomuk::Query::Term::Resource: return qHash( term.toResourceTerm().resource().resourceUri() ); Index: nepomuk/query/comparisonterm.h =================================================================== --- nepomuk/query/comparisonterm.h (révision 1130118) +++ nepomuk/query/comparisonterm.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -38,21 +38,31 @@ * \brief A term matching the value of a property. * * The %ComparisonTerm is the most important term in the query API. It can be - * used to match the values of properties. As such it consists of a property(), - * a comparator() and a subTerm(). + * used to match the values of properties. As such its core components are + * a property(), a comparator() (see Comparator for details) and a subTerm(). + * The latter can be any other term including AndTerm, OrTerm, or even an invalid + * term. The matching is done as follows: * - * The latter can be any other term including AndTerm and OrTerm. The matching - * is done in one of two ways: - * * \li A LiteralTerm as subTerm() is directly matched to the value of a literal * property (see also Nepomuk::Types::Property::literalRangeType()) or to the * labels of related resources in case of a property that has a resource range. + * \li An invalid sub term simply matches any resource or value, effectively + * acting as a wildcard. * \li Any other term type will be used as a sort of subquery to match the * related resources. This means that the property() needs to have a resource * range. * - * For more details see the Comparator enumeration. + * In addition to these basic features %ComparisonTerm has a few tricks up its + * sleeve: * + * \li By forcing the variable name via setVariableName() it is possible to + * include a value matched by the term in the resulting SPARQL query (Query::toSparqlQuery()) + * or accessing it via Result::additionalBinding(). + * \li It is possible to set an aggregate function via setAggregateFunction() + * to count or sum up the results instead of returning the actual values. + * \li Using setSortWeight() the sorting of the results in the final query + * can be influenced in a powerful way - especially when combined with setAggregateFunction(). + * * \author Sebastian Trueg <trueg@kde.org> * * \since 4.4 @@ -105,8 +115,77 @@ }; /** - * Default constructor: creates an invalid comparison term. + * Aggregate functions which can be applied to a comparison term to influence + * the value they return. + * + * \sa setAggregateFunction() + * + * \since 4.5 */ + enum AggregateFunction { + /** + * Do not use any aggregate function. + */ + NoAggregateFunction = 0, + + /** + * Count the number of matching results instead + * of returning the results themselves. + * For counting the results of a complete query use + * Query::CreateCountQuery. + */ + Count, + + /** + * The same as Count except that no two similar results + * are counted twice. + */ + DistinctCount, + + /** + * Return the maximum value of all results instead + * of the results themselves. + * Does only make sense for numerical values. + */ + Max, + + /** + * Return the minimum value of all results instead + * of the results themselves. + * Does only make sense for numerical values. + */ + Min, + + /** + * Return the sum of all result values instead + * of the results themselves. + * Does only make sense for numerical values. + */ + Sum, + + /** + * The same as Sum except that no two similar results + * are added twice. + */ + DistinctSum, + + /** + * Return the average value of all results instead + * of the results themselves. + * Does only make sense for numerical values. + */ + Average, + + /** + * The same as Average except that no two similar results + * are counted twice. + */ + DistinctAverage + }; + + /** + * Default constructor: creates a comparison term that matches all properties. + */ ComparisonTerm(); /** @@ -115,9 +194,9 @@ ComparisonTerm( const ComparisonTerm& term ); /** - * Default constructor. + * Convinience constructor which covers most simple use cases. * - * \param property The property that should be matched. + * \param property The property that should be matched. An invalid property will act as a wildcard. * \param term The sub term to match to. * \param comparator The Comparator to use for comparison. Not all Comparators make sense * with all sub term types. @@ -143,6 +222,7 @@ /** * A property used for ComparisonTerm Terms. + * An invalid property will act as a wildcard. * * \sa setProperty */ @@ -155,11 +235,183 @@ /** * Set the property for ComparisonTerm - * Terms. + * Terms. An invalid property will act as a wildcard. * * \sa property */ void setProperty( const Types::Property& ); + + /** + * Set the variable name that is to be used for the + * variable to match to. The variable will then be added + * to the set of variables returned in the results and can + * be read via Result::additionalBinding(). Setting + * the variable name can be seen as a less restricted variant + * of Query::addRequestProperty(). + * + * When manually setting the variable name on more + * than one ComparisonTerm there is no guarantee for the + * uniqueness of variable names anymore which can result + * in unwanted query results. However, this can also be + * used deliberately in case one needs to compare the + * same variable twice: + * + * \code + * ComparisonTerm ct1( prop1, Term() ); + * ComparisonTerm ct1( prop2, Term() ); + * ct1.setVariableName( "myvar" ); + * ct2.setVariableName( "myvar" ); + * \endcode + * + * The above example would result in a SPARQL query + * pattern along the lines of + * + * \code + * ?r <prop1> ?myVar . + * ?r <prop2> ?myVar . + * \endcode + * + * Be aware that the variable name does not apply + * to sub terms of types ResourceTerm or LiteralTerm. + * In those cases the value will be ignored. The only exception + * are LiteralTerm sub terms that are compared other than + * with equals. + * + * \param name The name of the variable to be used when requesting + * the binding via Result::additionalBinding() + * + * \sa Result::additionalBinding(), Query::HandleInverseProperties, \ref examples_query + * + * \since 4.5 + */ + void setVariableName( const QString& name ); + + /** + * The variable name set in setVariableName() or an empty + * string if none has been set. + * + * \sa setVariableName() + * + * \since 4.5 + */ + QString variableName() const; + + /** + * Set an aggregate function which changes the + * result. The typical usage is to count the results instead of actually + * returning them. For counting the results of a complete query use + * Query::CreateCountQuery. + * + * \sa aggregateFunction() + * + * \since 4.5 + */ + void setAggregateFunction( AggregateFunction function ); + + /** + * The aggregate function to be used with the additional binding set in + * setVariableName(). + * + * \sa setAggregateFunction() + * + * \since 4.5 + */ + AggregateFunction aggregateFunction() const; + + /** + * Set the sort weight of this property. By default all ComparisonTerms have + * a weight of 0 which means that they are ignored for sorting. By setting \p + * weight to a value different from 0 (typically higher than 0) the comparison + * subterm will be used for sorting. + * + * Be aware that as with the variableName() sorting does not apply to sub + * terms of types ResourceTerm or LiteralTerm. + * In those cases the value will be ignored. The only exception + * are LiteralTerm sub terms that are compared other than + * with equals. + * + * \param weight The new sort weight. If different from 0 this term will be + * used for sorting in the Query. + * \param sortOrder The sort order to use for this term. + * + * \sa sortWeight() + * + * \since 4.5 + */ + void setSortWeight( int weight, Qt::SortOrder sortOrder = Qt::AscendingOrder ); + + /** + * \return The sort weight as set in setSortWeight() or 0 if + * sorting is disabled for this term. + * + * \since 4.5 + */ + int sortWeight() const; + + /** + * \return The sort order as set in setSortWeight(). + * + * \since 4.5 + */ + Qt::SortOrder sortOrder() const; + + /** + * \return \p true if the comparison is inverted. + * \sa setInverted + * + * \since 4.5 + */ + bool isInverted() const; + + /** + * Invert the comparison, i.e. make the subterm the subject + * of the term and match to objects of the term. + * + * A typical example would be: + * + * \code + * ComparisonTerm term( Soprano::Vocabulary::NAO::hasTag(), + * ResourceTerm( somefile ) ); + * term.setInverted(true); + * \endcode + * + * which would yield a query like the following: + * + * \code + * select ?r where { <somefile> nao:hasTag ?r . } + * \endcode + * + * to get all tags attached to a file. + * + * Be aware that this does only make sense with + * sub terms that match to resources. When using + * LiteralTerm as a sub term \p invert is ignored. + * + * \sa inverted() + * + * \since 4.5 + */ + void setInverted( bool invert ); + + /** + * Create an inverted copy of this %ComparisonTerm. + * This is a convenience method to allow inline creation of + * inverted comparison terms when creating queries in a + * single line of code. + * + * Be aware that calling this method twice wil result in + * a non-inverted comparison term: + * + * \code + * // always true: + * (term.inverted().inverted() == term); + * \endcode + * + * \sa setInverted() + * + * \since 4.5 + */ + ComparisonTerm inverted() const; }; } } Index: nepomuk/query/query.h =================================================================== --- nepomuk/query/query.h (révision 1130118) +++ nepomuk/query/query.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2008-2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2008-2010 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 @@ -31,6 +31,8 @@ #include "nepomukquery_export.h" +class QTextStream; + namespace Nepomuk { namespace Query { @@ -64,7 +66,7 @@ * directly in Soprano::Model::executeQuery() via \p ResourceManager::instance()->mainModel() * or in a custom Model. * - * \sa QueryParser + * \sa QueryParser, FileQuery * * \author Sebastian Trueg <trueg@kde.org> * @@ -79,8 +81,7 @@ Query(); /** - * Create a query of type PlainQuery based on - * \a term. + * Create a query with root term \a term. */ explicit Query( const Term& term ); @@ -100,27 +101,55 @@ Query& operator=( const Query& ); /** + * Assignment operator. Assigns \p term to + * this query without changing any other + * properties. + * + * \since 4.5 + */ + Query& operator=( const Term& term ); + + /** * \return \p true if the query is valid, i.e. * it has a valid term(). */ bool isValid() const; /** + * \return \p true if this is a file query that will + * only return files and folders. + * + * \sa FileQuery + * + * \since 4.5 + */ + bool isFileQuery() const; + + /** * The root term of the query. * This can be any type of term. * - * \sa setTerm + * \sa setTerm() */ Term term() const; /** * The maximum number of results that this query should yield. * - * \sa setLimit + * \sa setLimit() */ int limit() const; /** + * The first result that should be retrieved. + * + * \sa setOffset() + * + * \since 4.5 + */ + int offset() const; + + /** * Set the root term of the query. * * \sa term @@ -136,6 +165,14 @@ void setLimit( int ); /** + * The first result that should be retrieved. This can be combined + * with setLimit() to do paged results. + * + * \since 4.5 + */ + void setOffset( int offset ); + + /** * \class RequestProperty query.h Nepomuk/Query/Query * * \brief A request property can be added to a Query to retrieve @@ -201,7 +238,10 @@ * * \param property The requested property. * - * \sa setRequestProperties, requestProperties + * ComparisonTerm::setVariableName() provides a more flexible (but also + * slightly more complicated) way to select additional results. + * + * \sa setRequestProperties, requestProperties, ComparisonTerm::setVariableName() */ void addRequestProperty( const RequestProperty& property ); @@ -210,7 +250,10 @@ * * \param properties The requested properties. * - * \sa addRequestProperty, requestProperties + * ComparisonTerm::setVariableName() provides a more flexible (but also + * slightly more complicated) way to select additional results. + * + * \sa addRequestProperty, requestProperties, ComparisonTerm::setVariableName() */ void setRequestProperties( const QList<RequestProperty>& properties ); @@ -254,6 +297,9 @@ * The resulting query will bind the results to variable \p 'r'. Request * properties will be bound to variables \p 'reqProp1' through \p 'reqPropN'. * + * If you are looking for a serialization of a Query which can be parsed again + * use toString() instead. + * * \warning The SPARQL queries created by this method contain SPARQL extensions * from Virtuoso and will not work with other RDF storage solutions! * @@ -262,7 +308,7 @@ * \return The SPARQL representation of this query or an empty string * if the query could not be converted (invalid query.) * - * \sa toSearchUrl(), SparqlFlag + * \sa toString(), toSearchUrl(), SparqlFlag */ QString toSparqlQuery( SparqlFlags flags = NoFlags ) const; @@ -271,9 +317,27 @@ * The URL will use the \p nepomuksearch:/ KIO protocol to handle the listing * of search results. * + * \param flags Optional flags to change the query. Query::CreateCountQuery is not + * supported and will silently be dropped from \p flags. + * + * \return A URL which will list a virtual folder containing all search results + * from this query or an invalid URL in case this query is invalid. + * + * \sa toSparqlQuery(), SparqlFlag + */ + KUrl toSearchUrl( SparqlFlags flags = NoFlags ) const; + + /** + * Convert the query into a URL which can be listed using KIO::DirLister. + * The URL will use the \p nepomuksearch:/ KIO protocol to handle the listing + * of search results. + * * This is the perfect method for listing results in file managers or file * dialogs. * + * \param customTitle An optional custom title that will be used for the listing + * of the results. This is achieved by setting the KIO::UDSEntry::UDS_DISPLAY_NAME to + * the customTitle value. * \param flags Optional flags to change the query. Query::CreateCountQuery is not * supported and will silently be dropped from \p flags. * @@ -281,8 +345,10 @@ * from this query or an invalid URL in case this query is invalid. * * \sa toSparqlQuery(), SparqlFlag + * + * \since 4.5 */ - KUrl toSearchUrl( SparqlFlags flags = NoFlags ) const; + KUrl toSearchUrl( const QString& customTitle, SparqlFlags flags = NoFlags ) const; /** * Build a request property map as used in QueryServiceClient::sparqlQuery() @@ -299,8 +365,71 @@ */ bool operator==( const Query& query ) const; + /** + * Encode the Query in a string. Be aware that this does NOT create a SPARQL + * query. The returned string can be used to serialize queries that can later + * be read via fromString(). + * + * \sa fromString(), toSparqlQuery() + * + * \since 4.5 + */ + QString toString() const; + + /** + * Parse a Query that has been encoded as a string via toString(). + * + * \warning This method can NOT parse SPARQL syntax. + * + * \sa toString() + * + * \since 4.5 + */ + static Query fromString( const QString& queryString ); + + /** + * Extract a query from a nepomuksearch:/ query URL. + * + * \return The query that was encoded in \p url or an invalid query if + * either \p url is not a nepomuksearch:/ URL or if it contains a pure SPARQL + * query. In the latter case sparqlFromQueryUrl() can be used to extract that + * query. + * + * \sa sparqlFromQueryUrl() + * + * \since 4.5 + */ + static Query fromQueryUrl( const KUrl& url ); + + /** + * Extract the SPARQL query from a nepomuksearch:/ query URL. All kinds of + * nepomuksearch:/ URLs are supported. + * + * \return The SPARQL query string representing the query encoded + * in \p url. + * + * \sa fromQueryUrl() + * + * \since 4.5 + */ + static QString sparqlFromQueryUrl( const KUrl& url ); + + /** + * Extact the title from a nepomuksearch:/ query URL. The title + * is either a custom title which has been specified in + * toSearchUrl(const QString&, SparqlFlags) or the user query string + * in case of nepomuksearch:/myquery URLs. + * + * \return A title for the query \p url or an empty string + * in case \p url is not a nepomuksearch:/ URL or a useful title + * cannot be extracted. + * + * \since 4.5 + */ + static QString titleFromQueryUrl( const KUrl& url ); + protected: - /** \cond protected_error_members */ + /** \cond protected_query_members */ QSharedDataPointer<QueryPrivate> d; friend class QueryParser; Index: nepomuk/query/optionalterm.cpp =================================================================== --- nepomuk/query/optionalterm.cpp (révision 0) +++ nepomuk/query/optionalterm.cpp (révision 0) @@ -0,0 +1,67 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "optionalterm.h" +#include "optionalterm_p.h" +#include "querybuilderdata_p.h" + +QString Nepomuk::Query::OptionalTermPrivate::toSparqlGraphPattern( const QString& resourceVarName, QueryBuilderData* qbd ) const +{ + return QString( "OPTIONAL { %1} " ) + .arg( m_subTerm.d_ptr->toSparqlGraphPattern( resourceVarName, qbd ) ); +} + + +Nepomuk::Query::OptionalTerm::OptionalTerm() + : SimpleTerm( new OptionalTermPrivate() ) +{ +} + + +Nepomuk::Query::OptionalTerm::OptionalTerm( const OptionalTerm& term ) + : SimpleTerm( term ) +{ +} + + +Nepomuk::Query::OptionalTerm::~OptionalTerm() +{ +} + + +Nepomuk::Query::OptionalTerm& Nepomuk::Query::OptionalTerm::operator=( const OptionalTerm& term ) +{ + d_ptr = term.d_ptr; + return *this; +} + + +Nepomuk::Query::Term Nepomuk::Query::OptionalTerm::optionalizeTerm( const Term& term ) +{ + if ( !term.isOptionalTerm() ) { + OptionalTerm ot; + ot.setSubTerm(term); + return ot; + } + else { + return term; + } +} Modification de propriétés sur nepomuk/query/optionalterm.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/query/andterm_p.h =================================================================== --- nepomuk/query/andterm_p.h (révision 1130118) +++ nepomuk/query/andterm_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public Index: nepomuk/query/result.cpp =================================================================== --- nepomuk/query/result.cpp (révision 1130118) +++ nepomuk/query/result.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2008-2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2008-2010 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 @@ -18,6 +18,7 @@ */ #include "result.h" +#include "variant.h" #include <QtCore/QSharedData> @@ -25,6 +26,7 @@ #include "property.h" #include <Soprano/Node> // for qHash( QUrl() ) +#include <Soprano/BindingSet> class Nepomuk::Query::Result::Private : public QSharedData @@ -33,6 +35,7 @@ Resource resource; double score; QHash<Types::Property, Soprano::Node> requestProperties; + Soprano::BindingSet additionalBindings; }; @@ -116,6 +119,24 @@ } +void Nepomuk::Query::Result::setAdditionalBindings( const Soprano::BindingSet& bindings ) +{ + d->additionalBindings = bindings; +} + + +Soprano::BindingSet Nepomuk::Query::Result::additionalBindings() const +{ + return d->additionalBindings; +} + + +Nepomuk::Variant Nepomuk::Query::Result::additionalBinding( const QString& name ) const +{ + return Variant::fromNode( d->additionalBindings.value(name) ); +} + + bool Nepomuk::Query::Result::operator==( const Result& other ) const { if ( d->resource != other.d->resource || @@ -138,5 +159,5 @@ return false; } } - return true; + return d->additionalBindings == other.d->additionalBindings; } Index: nepomuk/query/resourceterm.cpp =================================================================== --- nepomuk/query/resourceterm.cpp (révision 1130118) +++ nepomuk/query/resourceterm.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -43,12 +43,6 @@ } -QString Nepomuk::Query::ResourceTermPrivate::toString() const -{ - return QString( "[Resource %1]" ).arg( Soprano::Node::resourceToN3( m_resource.resourceUri() ) ); -} - - Nepomuk::Query::ResourceTerm::ResourceTerm( const ResourceTerm& term ) : Term( term ) { Index: nepomuk/query/resourcetypeterm.cpp =================================================================== --- nepomuk/query/resourcetypeterm.cpp (révision 1130118) +++ nepomuk/query/resourcetypeterm.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -51,12 +51,6 @@ } -QString Nepomuk::Query::ResourceTypeTermPrivate::toString() const -{ - return QString( "[Has type %1]" ).arg( Soprano::Node::resourceToN3( m_class.uri() ) ); -} - - Nepomuk::Query::ResourceTypeTerm::ResourceTypeTerm( const ResourceTypeTerm& term ) : Term( term ) { Index: nepomuk/query/simpleterm.cpp =================================================================== --- nepomuk/query/simpleterm.cpp (révision 1130118) +++ nepomuk/query/simpleterm.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public Index: nepomuk/query/queryparser.cpp =================================================================== --- nepomuk/query/queryparser.cpp (révision 1130118) +++ nepomuk/query/queryparser.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2007-2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2007-2010 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 @@ -106,12 +106,16 @@ } } - QString stripQuotes( const QString& s ) { + QString stripQuotes( const QString& s, bool* hadQuotes = 0 ) { if ( s[0] == '\'' || s[0] == '\"' ) { + if( hadQuotes ) + *hadQuotes = true; return s.mid( 1 ).left( s.length()-2 ); } else { + if( hadQuotes ) + *hadQuotes = false; return s; } } @@ -125,7 +129,9 @@ } } - Soprano::LiteralValue createLiteral( const QString& s ) { + Soprano::LiteralValue createLiteral( const QString& s_, bool globbing ) { + bool hadQuotes = false; + QString s = stripQuotes( s_, &hadQuotes ); bool b = false; int i = s.toInt( &b ); if ( b ) @@ -133,10 +139,17 @@ double d = s.toDouble( &b ); if ( b ) return Soprano::LiteralValue( d ); - return s; + + // + // we can only do query term globbing for strings longer than 3 chars + // + if( !hadQuotes && globbing && s.length() > 3 && !s.endsWith('*') && !s.endsWith('?') ) + return s + '*'; + else + return s; } - bool positiveTerm( const QString& s) { + bool positiveTerm( const QString& s ) { if(s.isEmpty()) return true; else if(s == "+") @@ -411,6 +424,12 @@ Nepomuk::Query::Query Nepomuk::Query::QueryParser::parse( const QString& query ) const { + return parse( query, NoParserFlags ); +} + + +Nepomuk::Query::Query Nepomuk::Query::QueryParser::parse( const QString& query, ParserFlags flags ) const +{ // TODO: a "real" parser which can handle all of the Xesam user language // This one for example does not handle nesting at all. @@ -446,7 +465,7 @@ kDebug() << "matched property term at" << pos << s_propertyRx.cap( 0 ); ComparisonTerm ct; ct.setProperty( tryToBeIntelligentAboutParsingUrl( s_propertyRx.cap( 2 ) ) ); - ct.setSubTerm( LiteralTerm( createLiteral( stripQuotes( s_propertyRx.cap( 4 ) ) ) ) ); + ct.setSubTerm( LiteralTerm( createLiteral( s_propertyRx.cap( 4 ), flags&QueryTermGlobbing ) ) ); QString comparator = s_propertyRx.cap( 3 ); ct.setComparator( fieldTypeRelationFromString( comparator ) ); pos += s_propertyRx.matchedLength(); @@ -472,7 +491,7 @@ QString comparator = s_fieldFieldRx.cap( 4 ); ct.setComparator( fieldTypeRelationFromString( comparator ) ); ct.setSubTerm( ComparisonTerm( QUrl(stripQuotes( s_fieldFieldRx.cap( 5 ) )), - LiteralTerm( s_fieldFieldRx.cap( 8 ) ), + LiteralTerm( createLiteral( s_fieldFieldRx.cap( 8 ), flags&QueryTermGlobbing ) ), fieldTypeRelationFromString( s_fieldFieldRx.cap( 7 ) ) ) ); pos += s_fieldFieldRx.matchedLength(); @@ -499,7 +518,7 @@ else { ComparisonTerm ct; ct.setProperty( QUrl( stripQuotes( s_fieldRx.cap( 2 ) ) ) ); - ct.setSubTerm( LiteralTerm( createLiteral( stripQuotes( s_fieldRx.cap( 5 ) ) ) ) ); + ct.setSubTerm( LiteralTerm( createLiteral( s_fieldRx.cap( 5 ), flags&QueryTermGlobbing ) ) ); QString comparator = s_fieldRx.cap( 4 ); ct.setComparator( fieldTypeRelationFromString( comparator ) ); pos += s_fieldRx.matchedLength(); @@ -515,7 +534,7 @@ } else if ( s_plainTermRx.indexIn( query, pos ) == pos ) { - QString value = stripQuotes( s_plainTermRx.cap( 2 ) ); + QString value = s_plainTermRx.cap( 2 ); if ( d->orKeywords.contains( value.toLower() ) ) { inOrBlock = true; } @@ -524,7 +543,7 @@ } else { kDebug() << "matched literal at" << pos << value; - term = LiteralTerm( Soprano::LiteralValue( value ) ); + term = LiteralTerm( createLiteral( value, flags&QueryTermGlobbing ) ); if ( !positiveTerm(s_plainTermRx.cap( 1 ) ) ) { term = NegationTerm::negateTerm( term ); } Index: nepomuk/query/literalterm.cpp =================================================================== --- nepomuk/query/literalterm.cpp (révision 1130118) +++ nepomuk/query/literalterm.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -55,10 +55,11 @@ QString v2 = qbd->uniqueVarName(); QString v3 = qbd->uniqueVarName(); QString v4 = qbd->uniqueVarName(); + QString v2Score = qbd->createScoringVariable(); // { ?r ?v1 ?v2 . ?v2 bif:contains XXX . } UNION { ?r ?v1 ?v3 . ?v3 ?v4 ?v2 . ?v4 rdfs:subPropertyOf rdfs:label . ?v2 bif:contains XXX . } . - return QString::fromLatin1( "{ %1 %2 %3 . %3 bif:contains \"'%4'\" . } " + return QString::fromLatin1( "{ %1 %2 %3 . %3 bif:contains \"%4\" OPTION (score %9) . } " "UNION " - "{ %1 %2 %5 . %5 %6 %3 . %6 %7 %8 . %3 bif:contains \"'%4'\" . } . " ) + "{ %1 %2 %5 . %5 %6 %3 . %6 %7 %8 . %3 bif:contains \"%4\" OPTION (score %9) . } . " ) .arg( resourceVarName, v1, v2, @@ -66,27 +67,43 @@ v3, v4, Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::subPropertyOf()), - Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label()) ); + Soprano::Node::resourceToN3(Soprano::Vocabulary::RDFS::label()), + v2Score ); } -QString Nepomuk::Query::LiteralTermPrivate::toString() const +QString Nepomuk::Query::LiteralTermPrivate::queryText() const { - return QString( "[Literal %1]" ).arg( Soprano::Node::literalToN3( m_value ) ); -} + // + // we try to be a little smart about creating the query text + // by following a few simple rules: + // + // 1. enclose everything in quotes to be safe + // 2. quotes in search terms are not handled. replace them with spaces + // 3. replace double quotes with single quotes + // [4. wildcards can only be used if they are preceeded by at least 4 chars] + // + QString s = m_value.toString().simplified(); + if( s.isEmpty() ) + return s; -QString Nepomuk::Query::LiteralTermPrivate::queryText() const -{ - // Virtuoso 6 has a min of 4 leading chars before a wildcard. - // Thus, we do not use one with less chars. + // strip quotes + if( s[0] == '"' || s[0] == '\'' ) { + s = s.mid(1); + } + if( !s.isEmpty() && + ( s[s.length()-1] == '"' || s[s.length()-1] == '\'' ) ) { + s.truncate(s.length()-1); + } - QString s = m_value.toString(); - if( s.length() > 3 && - !s.endsWith(QLatin1String("*")) && - !s.endsWith(QLatin1String("?")) ) { - s += QLatin1String("*"); - } + // replace quotes with spaces + s.replace( '"', ' ' ); + s.replace( '\'', ' ' ); + + // add quotes + s = '\'' + s + '\''; + return s; } Index: nepomuk/query/groupterm.cpp =================================================================== --- nepomuk/query/groupterm.cpp (révision 1130118) +++ nepomuk/query/groupterm.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -52,15 +52,6 @@ } -QString Nepomuk::Query::GroupTermPrivate::toString() const -{ - QStringList sts; - foreach( const Term& term, m_subTerms ) - sts << term.d_ptr->toString(); - return QString( "[%1]" ).arg( sts.join( ' ' + ( m_type == Term::And ? QLatin1String( "AND" ) : QLatin1String( "OR" ) ) + ' ' ) ); -} - - Nepomuk::Query::GroupTerm::GroupTerm( const Term& term ) : Term( term ) { Index: nepomuk/query/queryserviceclient.cpp =================================================================== --- nepomuk/query/queryserviceclient.cpp (révision 1130118) +++ nepomuk/query/queryserviceclient.cpp (copie de travail) @@ -19,6 +19,7 @@ */ #include "queryserviceclient.h" +#include "queryserviceclient_p.h" #include "dbusoperators_p.h" #include "result.h" #include "query.h" @@ -60,6 +61,28 @@ } return encodedRps; } + + NepomukResultListEventLoop::NepomukResultListEventLoop(Nepomuk::Query::QueryServiceClient* parent) + : QEventLoop(parent) + { + connect(parent, SIGNAL(newEntries(QList<Nepomuk::Query::Result>)), + this, SLOT(addEntries(QList<Nepomuk::Query::Result>))); + } + + NepomukResultListEventLoop::~NepomukResultListEventLoop() + { + } + + void NepomukResultListEventLoop::addEntries(const QList< Nepomuk::Query::Result >& entries) + { + m_result << entries; + } + + QList< Nepomuk::Query::Result > NepomukResultListEventLoop::result() const + { + return m_result; + } + } @@ -211,6 +234,28 @@ } +QList< Nepomuk::Query::Result > Nepomuk::Query::QueryServiceClient::syncQuery(const Query& q, bool* ok) +{ + QueryServiceClient qsc; + if( qsc.query( q ) ) { + NepomukResultListEventLoop loop(&qsc); + qsc.d->loop = &loop; + loop.exec(); + qsc.d->loop = 0; + if (ok) { + *ok = true; + } + return loop.result(); + } + else { + if (ok) { + *ok = false; + } + return QList< Nepomuk::Query::Result >(); + } +} + + bool Nepomuk::Query::QueryServiceClient::blockingSparqlQuery( const QString& q, const QHash<QString, Nepomuk::Types::Property>& requestPropertyMap ) { if( sparqlQuery( q, requestPropertyMap ) ) { @@ -226,6 +271,30 @@ } +QList< Nepomuk::Query::Result > Nepomuk::Query::QueryServiceClient::syncSparqlQuery(const QString& q, + const QHash<QString, Nepomuk::Types::Property>& requestPropertyMap, + bool *ok) +{ + QueryServiceClient qsc; + if( qsc.sparqlQuery( q, requestPropertyMap ) ) { + NepomukResultListEventLoop loop(&qsc); + qsc.d->loop = &loop; + loop.exec(); + qsc.d->loop = 0; + if (ok) { + *ok = true; + } + return loop.result(); + } + else { + if (ok) { + *ok = false; + } + return QList< Nepomuk::Query::Result >(); + } +} + + bool Nepomuk::Query::QueryServiceClient::blockingDesktopQuery( const QString& q ) { if( desktopQuery( q ) ) { @@ -241,6 +310,28 @@ } +QList< Nepomuk::Query::Result > Nepomuk::Query::QueryServiceClient::syncDesktopQuery(const QString& q, bool* ok) +{ + QueryServiceClient qsc; + if( qsc.desktopQuery( q ) ) { + NepomukResultListEventLoop loop(&qsc); + qsc.d->loop = &loop; + loop.exec(); + qsc.d->loop = 0; + if (ok) { + *ok = true; + } + return loop.result(); + } + else { + if (ok) { + *ok = false; + } + return QList< Nepomuk::Query::Result >(); + } +} + + void Nepomuk::Query::QueryServiceClient::close() { if ( d->queryInterface ) { @@ -260,3 +351,4 @@ } #include "queryserviceclient.moc" +#include "queryserviceclient_p.moc" Index: nepomuk/query/term_p.h =================================================================== --- nepomuk/query/term_p.h (révision 1130118) +++ nepomuk/query/term_p.h (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2007-2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2007-2010 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 @@ -45,7 +45,6 @@ virtual bool equals( const TermPrivate* other ) const { return m_type == other->m_type; } - virtual QString toString() const { return QString(); } Term::Type m_type; }; Index: nepomuk/query/negationterm.cpp =================================================================== --- nepomuk/query/negationterm.cpp (révision 1130118) +++ nepomuk/query/negationterm.cpp (copie de travail) @@ -1,6 +1,6 @@ /* This file is part of the Nepomuk KDE project. - Copyright (C) 2009 Sebastian Trueg <trueg@kde.org> + Copyright (C) 2009-2010 Sebastian Trueg <trueg@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -25,20 +25,11 @@ QString Nepomuk::Query::NegationTermPrivate::toSparqlGraphPattern( const QString& resourceVarName, QueryBuilderData* qbd ) const { - QString varName = qbd->uniqueVarName(); - return QString( "OPTIONAL { %1 FILTER(%2=%3) . } . FILTER(!BOUND(%2)) . " ) - .arg( m_subTerm.d_ptr->toSparqlGraphPattern( varName, qbd ), - varName, - resourceVarName ); + return QString( "FILTER(!bif:exists((select (1) where { %1 }))) . " ) + .arg( m_subTerm.d_ptr->toSparqlGraphPattern( resourceVarName, qbd ) ); } -QString Nepomuk::Query::NegationTermPrivate::toString() const -{ - return QString( "[NOT %1]" ).arg( m_subTerm.d_ptr->toString() ); -} - - Nepomuk::Query::NegationTerm::NegationTerm() : SimpleTerm( new NegationTermPrivate() ) { Index: nepomuk/core/tools.cpp =================================================================== --- nepomuk/core/tools.cpp (révision 1130118) +++ nepomuk/core/tools.cpp (copie de travail) @@ -87,7 +87,7 @@ Nepomuk::Variant Nepomuk::RDFLiteralToValue( const Soprano::Node& node ) { - return Variant( node.literal().variant() ); + return Variant::fromNode( node ); } Index: nepomuk/core/nepomukmainmodel.cpp =================================================================== --- nepomuk/core/nepomukmainmodel.cpp (révision 1130118) +++ nepomuk/core/nepomukmainmodel.cpp (copie de travail) @@ -46,8 +46,6 @@ #include <QtDBus/QDBusConnectionInterface> -// FIXME: connect to some NepomukServer signal which emit enabled/disabled information -// when the server shuts down and is started again // FIXME: disconnect localSocketClient after n seconds of idling (but take care of not // disconnecting when iterators are open) @@ -85,6 +83,8 @@ if( forced ) { m_socketConnectFailed = false; + delete dbusModel; + dbusModel = 0; } // TODO: check if the service is also initialized @@ -155,20 +155,7 @@ d( new Private(this) ) { setParent( parent ); - init(); - - if ( s_modelContainer->dbusModel ) { - // we have to use the dbus model for signals in any case - connect( s_modelContainer->dbusModel, SIGNAL( statementsAdded() ), - this, SIGNAL( statementsAdded() ) ); - connect( s_modelContainer->dbusModel, SIGNAL( statementsRemoved() ), - this, SIGNAL( statementsRemoved() ) ); - connect( s_modelContainer->dbusModel, SIGNAL( statementAdded(const Soprano::Statement&) ), - this, SIGNAL( statementAdded(const Soprano::Statement&) ) ); - connect( s_modelContainer->dbusModel, SIGNAL( statementRemoved(const Soprano::Statement&) ), - this, SIGNAL( statementRemoved(const Soprano::Statement&) ) ); - } } @@ -187,6 +174,17 @@ bool Nepomuk::MainModel::init() { s_modelContainer->init( true ); + if ( s_modelContainer->dbusModel ) { + // we have to use the dbus model for signals in any case + connect( s_modelContainer->dbusModel, SIGNAL( statementsAdded() ), + this, SIGNAL( statementsAdded() ) ); + connect( s_modelContainer->dbusModel, SIGNAL( statementsRemoved() ), + this, SIGNAL( statementsRemoved() ) ); + connect( s_modelContainer->dbusModel, SIGNAL( statementAdded(const Soprano::Statement&) ), + this, SIGNAL( statementAdded(const Soprano::Statement&) ) ); + connect( s_modelContainer->dbusModel, SIGNAL( statementRemoved(const Soprano::Statement&) ), + this, SIGNAL( statementRemoved(const Soprano::Statement&) ) ); + } return isValid(); } Index: nepomuk/core/resourcemanager_p.h =================================================================== --- nepomuk/core/resourcemanager_p.h (révision 1130118) +++ nepomuk/core/resourcemanager_p.h (copie de travail) @@ -42,7 +42,6 @@ class ResourceFilterModel; typedef QHash<KUrl, Nepomuk::ResourceData*> ResourceDataHash; - typedef QHash<QString, Nepomuk::ResourceData*> KickoffDataHash; class ResourceManagerPrivate { @@ -66,9 +65,6 @@ /// contains all non-initialized ResourceData objects created in data(QUrl) ResourceDataHash m_uriKickoffData; - /// contains all non-initialized ResourceData objects created in data(QString) - KickoffDataHash m_idKickoffData; - QAtomicInt dataCnt; ResourceManager* m_manager; @@ -90,15 +86,22 @@ * created at all times. This method searches for an existing data object to reuse or creates * a new one if none exists. * - * \param uri The URI of the resource is question. + * \param uri The URI of the resource is question or it's nie:url or even its identified stored in + * a QUrl object. * \type The type of the resource. * * The Resource constructors use this method in combination with ref() */ ResourceData* data( const QUrl& uri, const QUrl& type ); - bool dataCacheFull(); + /** + * In contrast to data(QUrl,QUrl) this method avoids the overhead of determining the resource URI + * via ResourceData::determineUri() and simply uses \p uri as the resource URI. + */ + ResourceData* dataForResourceUri( const QUrl& uri, const QUrl& type ); + bool dataCacheFull() const; + /** * Delete unused ResourceData objects from the cache. * \param num The number of needed slots. The ResourceData constructor @@ -108,21 +111,20 @@ */ void cleanupCache( int num = 1 ); - /** - * Will call determineUri on all ResourceData instances. - * - * Does lock the mutex. - */ - void determineAllUris(); + bool shouldBeDeleted( ResourceData* rd ) const; + void addToKickOffList( ResourceData* rd, const QSet<KUrl>& uris ); + QList<ResourceData*> allResourceData(); QList<ResourceData*> allResourceDataOfType( const QUrl& type ); QList<ResourceData*> allResourceDataWithProperty( const QUrl& _uri, const Variant& v ); void _k_storageServiceInitialized( bool ); - void _k_dbusServiceOwnerChanged( const QString& name, const QString& oldOwner, const QString& newOwner ); + void _k_dbusServiceUnregistered( const QString& serviceName ); private: + ResourceData* findData( const QUrl& uri ); + QUrl m_mainContext; }; } Index: nepomuk/core/variant.h =================================================================== --- nepomuk/core/variant.h (révision 1130118) +++ nepomuk/core/variant.h (copie de travail) @@ -28,6 +28,10 @@ #include <QtCore/QUrl> #include <QtCore/QVariant> +namespace Soprano { + class Node; +} + namespace Nepomuk { class Resource; @@ -35,7 +39,7 @@ /** * \class Variant variant.h Nepomuk/Variant * - * The %Nepomuk Variant extends over QVariant by introducing + * \brief The %Nepomuk Variant extends over QVariant by introducing * direct support for Resource embedding, automatic list conversion * and a restricted set of supported types. * @@ -348,6 +352,13 @@ */ static Variant fromString( const QString& value, int type ); + /** + * Create a Variant object from a Soprano::Node. + * + * \since 4.5 + */ + static Variant fromNode( const Soprano::Node& node ); + private: class Private; Private* const d; Index: nepomuk/core/dbusconnectionpool.h =================================================================== --- nepomuk/core/dbusconnectionpool.h (révision 1130118) +++ nepomuk/core/dbusconnectionpool.h (copie de travail) @@ -23,17 +23,16 @@ #include <QtDBus/QDBusConnection> -#include "nepomuk_export.h" - namespace DBusConnectionPool { /** * The DBusConnectionPool works around the problem * of QDBusConnection not being thread-safe. As soon as that * has been fixed (either directly in libdbus or with a work- - * around in Qt) this method can be dropped. + * around in Qt) this method can be dropped in favor of + * QDBusConnection::sessionBus(). */ -NEPOMUK_EXPORT QDBusConnection threadConnection(); +QDBusConnection threadConnection(); } #endif Index: nepomuk/core/resourcemanager.h =================================================================== --- nepomuk/core/resourcemanager.h (révision 1130118) +++ nepomuk/core/resourcemanager.h (copie de travail) @@ -32,10 +32,6 @@ } namespace Nepomuk { - namespace Middleware { - class Registry; - } - class Resource; class Variant; class ResourceManagerHelper; @@ -44,8 +40,12 @@ /** * \class ResourceManager resourcemanager.h Nepomuk/ResourceManager * - * \brief The ResourceManager is the central \a %KMetaData configuration point. + * \brief The ResourceManager is the central \a %Nepomuk configuration point. * + * Use the initialized() method to check the availabity of the %Nepomuk system. + * Signals nepomukSystemStarted() and nepomukSystemStopped() can be used to + * enable or disable Nepomuk-specific GUI elements. + * * \author Sebastian Trueg <trueg@kde.org> */ class NEPOMUK_EXPORT ResourceManager : public QObject @@ -68,14 +68,14 @@ /** * Initialize the Nepomuk framework. This method will initialize the communication with - * the local Nepomuk-KDE services, ie. the data repository. + * the local Nepomuk-KDE services, ie. the data repository. It will trigger a reconnect + * to the %Nepomuk database. * - * When using multiple threads make sure to call this method in the main thread + * There is normally no reason to call this method manually except when using multiple + * threads. In that case it is highly recommended to call this method in the main thread * before doing anything else. * * \return 0 if all necessary components could be found and -1 otherwise. - * - * FIXME: introduce error codes and human readable translated error messages. */ int init(); @@ -259,7 +259,7 @@ ResourceManagerPrivate* const d; Q_PRIVATE_SLOT( d, void _k_storageServiceInitialized(bool) ) - Q_PRIVATE_SLOT( d, void _k_dbusServiceOwnerChanged(QString, QString, QString) ) + Q_PRIVATE_SLOT( d, void _k_dbusServiceUnregistered(QString) ) }; } Index: nepomuk/core/CMakeLists.txt =================================================================== --- nepomuk/core/CMakeLists.txt (révision 1130118) +++ nepomuk/core/CMakeLists.txt (copie de travail) @@ -6,6 +6,7 @@ ${nepomuk_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/nepomuk/ ${nepomukcore_SOURCE_DIR} + ${nepomukcore_SOURCE_DIR}/types ${kdecore_SOURCE_DIR}/utils ${CMAKE_SOURCE_DIR} ${KDE4_INCLUDES} @@ -26,26 +27,27 @@ ui/ktagcloudwidget.cpp ui/kblocklayout.cpp ui/kmetadatatagcloud.cpp - ui/kmetadatatagwidget.cpp - ui/kautoscrollarea.cpp ui/ktagdisplaywidget.cpp ui/kratingpainter.cpp ui/nepomukmassupdatejob.cpp + ui/tagwidget.cpp + ui/kedittagsdialog.cpp + ui/tagcheckbox.cpp resource.cpp thing.cpp tag.cpp - ontology/entity.cpp - ontology/ontology.cpp - ontology/class.cpp - ontology/property.cpp - ontology/literal.cpp - ontology/ontologyloader.cpp - ontology/ontologymanager.cpp - ontology/nepomukontologyloader.cpp - ontology/fileontologyloader.cpp - ontology/desktopontologyloader.cpp - ontology/global.cpp - ontology/entitymanager.cpp + types/entity.cpp + types/ontology.cpp + types/class.cpp + types/property.cpp + types/literal.cpp + types/ontologyloader.cpp + types/ontologymanager.cpp + types/nepomukontologyloader.cpp + types/fileontologyloader.cpp + types/desktopontologyloader.cpp + types/global.cpp + types/entitymanager.cpp nepomukservice.cpp graphwrapper.cpp ) @@ -54,6 +56,7 @@ soprano_add_ontology(nepomuk_LIB_SRCS "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nfo.trig" "NFO" "Nepomuk::Vocabulary" "trig") soprano_add_ontology(nepomuk_LIB_SRCS "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nco.trig" "NCO" "Nepomuk::Vocabulary" "trig") soprano_add_ontology(nepomuk_LIB_SRCS "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/pimo/pimo.trig" "PIMO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(nepomuk_LIB_SRCS "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nepomuk/nuao.trig" "NUAO" "Nepomuk::Vocabulary" "trig") kde4_add_library(nepomuk SHARED ${nepomuk_LIB_SRCS}) @@ -94,5 +97,5 @@ ) add_subdirectory(ui) -add_subdirectory(ontology) +add_subdirectory(types) add_subdirectory(test) Index: nepomuk/core/resource.h =================================================================== --- nepomuk/core/resource.h (révision 1130118) +++ nepomuk/core/resource.h (copie de travail) @@ -23,8 +23,11 @@ #include <QtCore/QHash> #include <QtCore/QStringList> -#include <QtCore/QUrl> +#include <kurl.h> + +#include "class.h" + #include "nepomuk_export.h" namespace Nepomuk { @@ -34,6 +37,9 @@ class Variant; class Tag; class Thing; + namespace Types { + class Property; + } enum ErrorCode { NoError = 0, @@ -334,6 +340,13 @@ bool hasProperty( const QUrl& uri ) const; /** + * Check if the resource has a property \p p with value \p v. + * + * \since 4.5 + */ + bool hasProperty( const Types::Property& p, const Variant& v ) const; + + /** * \deprecated use hasProperty( const QUrl& ) const */ KDE_DEPRECATED bool hasProperty( const QString& uri ) const; @@ -659,7 +672,7 @@ /** * Get property 'Symbol'. Each resource can have a symbol assigned. - * For now this is a simple string which can either be the patch to + * For now this is a simple string which can either be the path to * an actual pixmap file or just the name of an icon as defined by * the freedesktop.org standard. */ @@ -667,7 +680,7 @@ /** * Set property 'Symbol'. Each resource can have a symbol assigned. - * For now this is a simple string which can either be the patch to + * For now this is a simple string which can either be the path to * an actual pixmap file or just the name of an icon as defined by * the freedesktop.org standard. */ @@ -676,7 +689,7 @@ /** * Add a value to property 'Symbol'. Each resource can have a symbol * assigned. For now this is a simple string which can either be - * the patch to an actual pixmap file or just the name of an icon as + * the path to an actual pixmap file or just the name of an icon as * defined by the freedesktop.org standard. */ void addSymbol( const QString& value ); @@ -709,7 +722,42 @@ */ static QList<Resource> allResources(); + /** + * \return The usage count stored for this resource. + * + * \sa increaseUsageCount() + * + * \since 4.5 + */ + int usageCount() const; + + /** + * Increase the usage count of this resource and also + * update the last used date to the current date and time. + * + * \since 4.5 + */ + void increaseUsageCount(); + + /** + * Allows to quickly load a resource from its resource URI without any + * additional checks. This is mostly used for optimized code within Nepomuk. + * + * In most situations the construtor Resource( QUrl, QUrl ) is better suited. + * + * \since 4.5 + */ + static Resource fromResourceUri( const KUrl& uri, const Nepomuk::Types::Class& type = Nepomuk::Types::Class(), ResourceManager* manager = 0 ); + private: + /** + * Determines the final ResourceData and updates m_data if + * necessary. This will call ResourceData::determineUri() + * and optionally merge with already loaded ResourceData + * instances representing the same resource. + */ + void determineFinalResourceData() const; + ResourceData* m_data; class Private; Index: nepomuk/core/test/resourcetest.cpp =================================================================== --- nepomuk/core/test/resourcetest.cpp (révision 1130118) +++ nepomuk/core/test/resourcetest.cpp (copie de travail) @@ -293,6 +293,11 @@ QCOMPARE( fileRes.resourceUri(), fileRes3.resourceUri() ); tmpFile1ResUri = fileRes.resourceUri(); + + // make sure even the string constructor will find the resource again with + Resource fileRes4( KUrl(tmpFile1ResUri).url() ); + fileRes4.setRating(4); + QCOMPARE( fileRes4.resourceUri(), tmpFile1ResUri ); } // clear cache to be sure we call ResourceData::determineUri @@ -338,8 +343,6 @@ // clear cache to be sure we do not reuse the cache ResourceManager::instance()->clearCache(); - - } QTEST_KDEMAIN(ResourceTest, NoGUI) Index: nepomuk/core/nepomukservice.cpp =================================================================== --- nepomuk/core/nepomukservice.cpp (révision 1130118) +++ nepomuk/core/nepomukservice.cpp (copie de travail) @@ -17,7 +17,7 @@ */ #include "nepomukservice.h" -#include "nepomukmainmodel.h" +#include "resourcemanager.h" #include <QtCore/QTimer> @@ -25,7 +25,6 @@ class Nepomuk::Service::Private { public: - MainModel* model; }; @@ -33,7 +32,6 @@ : QObject( parent ), d( new Private() ) { - d->model = 0; if ( !delayedInitialization ) { setServiceInitialized( true ); } @@ -42,17 +40,13 @@ Nepomuk::Service::~Service() { - delete d->model; delete d; } Soprano::Model* Nepomuk::Service::mainModel() { - if ( !d->model ) { - d->model = new MainModel( this ); - } - return d->model; + return ResourceManager::instance()->mainModel(); } Index: nepomuk/core/tools.h =================================================================== --- nepomuk/core/tools.h (révision 1130118) +++ nepomuk/core/tools.h (copie de travail) @@ -1,4 +1,4 @@ -/* +/* * This file is part of the Nepomuk KDE project. * Copyright (C) 2006-2008 Sebastian Trueg <trueg@kde.org> * @@ -6,12 +6,12 @@ * 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, @@ -33,40 +33,24 @@ namespace Nepomuk { /** - * \deprecated Has no effect anymore. - */ - KDE_DEPRECATED NEPOMUK_EXPORT void setDefaultRepository( const QString& s ); - - /** * Used internally by Resource. - * \return The URI of the RDF graph meta data is stored in. - * - * \deprecated Use Nepomuk::ResourceManager::mainModel() + * Converts a Variant into a literal value to be used in the RDF store. */ - KDE_DEPRECATED NEPOMUK_EXPORT QString defaultGraph(); + NEPOMUK_EXPORT QList<Soprano::Node> valuesToRDFNodes( const Variant& ); /** * Used internally by Resource. - * \return The URI of the predicate used to state the type of a resource. - * - * \deprecated Use Soprano::Vocabulary::RDF::type() + * Converts a non-list Variant into a Soprano::Node. */ - KDE_DEPRECATED NEPOMUK_EXPORT QString typePredicate(); - - /** - * Used internally by Resource. - * Converts a Variant into a literal value to be used in the RDF store. - * Uses the language set in the current KDE session. - */ - NEPOMUK_EXPORT QList<Soprano::Node> valuesToRDFNodes( const Variant& ); NEPOMUK_EXPORT Soprano::Node valueToRDFNode( const Variant& ); /** * Used internally by Resource. - * Converts a literal value from the RDF store into a Variant. + * Convert a list of resources to a list of Ts where T needs to be a subclass + * of Resource. + * + * \return A list containing all resources in \p l represented as a T. */ - NEPOMUK_EXPORT Variant RDFLiteralToValue( const Soprano::Node& node ); - template<typename T> QList<T> convertResourceList( const QList<Resource>& l ) { QList<T> rl; for( QList<Resource>::const_iterator it = l.constBegin(); @@ -75,16 +59,43 @@ return rl; } + /** + * Used internally by Resource. + * Convert a list of Ts to a list of Resources where T needs to be a subclass + * of Resource. + * + * \return A list containing all resources in \p l. + */ template<typename T> QList<Resource> convertResourceList( const QList<T>& l ) { QList<Resource> rl; - Q_FOREACH( T r, l ) -/* for( QList<T>::const_iterator it = l.constBegin(); */ -/* it != l.constEnd(); ++it ) */ - rl.append( Resource( r/*it*/ ) ); + Q_FOREACH( const T& r, l ) + rl.append( Resource( r ) ); return rl; } /** + * \deprecated Use Variant::fromNode() instead. + */ + KDE_DEPRECATED NEPOMUK_EXPORT Variant RDFLiteralToValue( const Soprano::Node& node ); + + /** + * \deprecated Has no effect anymore. + */ + KDE_DEPRECATED NEPOMUK_EXPORT void setDefaultRepository( const QString& s ); + + /** + * \return The name of the default Nepomuk repository ("main"). + * + * \deprecated Use Nepomuk::ResourceManager::mainModel() + */ + KDE_DEPRECATED NEPOMUK_EXPORT QString defaultGraph(); + + /** + * \deprecated Use Soprano::Vocabulary::RDF::type() + */ + KDE_DEPRECATED NEPOMUK_EXPORT QString typePredicate(); + + /** * \deprecated Use Soprano::Vocabulary::RDF::rdfNamepace() */ KDE_DEPRECATED NEPOMUK_EXPORT QString rdfNamepace(); Index: nepomuk/core/resourcemanager.cpp =================================================================== --- nepomuk/core/resourcemanager.cpp (révision 1130118) +++ nepomuk/core/resourcemanager.cpp (copie de travail) @@ -25,10 +25,9 @@ #include "nepomukmainmodel.h" #include "resource.h" #include "resourcefiltermodel.h" +#include "class.h" #include "nie.h" -#include "ontology/class.h" - #include <kglobal.h> #include <kdebug.h> #include <krandom.h> @@ -43,8 +42,10 @@ #include <QtCore/QMutex> #include <QtCore/QMutexLocker> #include <QtCore/QUuid> +#include <QtCore/QMutableHashIterator> #include <QtDBus/QDBusConnection> #include <QtDBus/QDBusConnectionInterface> +#include <QtDBus/QDBusServiceWatcher> using namespace Soprano; @@ -63,61 +64,43 @@ { if ( uri.isEmpty() ) { // return an invalid resource which may be activated by calling setProperty - return new ResourceData( QUrl(), QString(), type, this ); + return new ResourceData( QUrl(), QUrl(), type, this ); } - QUrl url( uri ); - - // default to "file" scheme, i.e. we do not allow an empty scheme - if ( url.scheme().isEmpty() ) { - url.setScheme( "file" ); + if( ResourceData* data = findData( uri ) ) { + return data; } - - QMutexLocker lock( &mutex ); - - // look for the URI in the initialized and in the URI kickoff data - ResourceDataHash::iterator end = m_initializedData.end(); - ResourceDataHash::iterator it = m_initializedData.find( url ); - if( it == end ) { - end = m_uriKickoffData.end(); - it = m_uriKickoffData.find( url ); - } - - if( it == end ) { - ResourceData* d = new ResourceData( url, QString(), type, this ); - m_uriKickoffData.insert( url, d ); -// kDebug() << "--------------------------- Created new ResourceData:" << *d; - return d; - } else { -// kDebug() << "---------------------------- Reusing" << *it.value() << "for" << uri; - return it.value(); + QMutexLocker lock( &mutex ); + return new ResourceData( QUrl(), uri, type, this ); } } Nepomuk::ResourceData* Nepomuk::ResourceManagerPrivate::data( const QString& uriOrId, const QUrl& type ) { - if ( uriOrId.isEmpty() ) { - return new ResourceData( QUrl(), QString(), type, this ); - } - else { + if ( !uriOrId.isEmpty() ) { KUrl url(uriOrId); - if( QFile::exists( url.toLocalFile() ) ) { - return data( url, type ); - } + return data( url, type ); } - QMutexLocker lock( &mutex ); + return new ResourceData( QUrl(), QUrl(), type, this ); +} - KickoffDataHash::iterator it = m_idKickoffData.find( uriOrId ); - if( it == m_idKickoffData.end() ) { - ResourceData* d = new ResourceData( QUrl(), uriOrId, type, this ); - m_idKickoffData.insert( uriOrId, d ); - return d; + +Nepomuk::ResourceData* Nepomuk::ResourceManagerPrivate::dataForResourceUri( const QUrl& uri, const QUrl& type ) +{ + if ( uri.isEmpty() ) { + // return an invalid resource which may be activated by calling setProperty + return new ResourceData( QUrl(), QUrl(), type, this ); } + + if( ResourceData* data = findData( uri ) ) { + return data; + } else { - return it.value(); + QMutexLocker lock( &mutex ); + return new ResourceData( uri, QUrl(), type, this ); } } @@ -129,8 +112,8 @@ QList<ResourceData*> l; if( !type.isEmpty() ) { - QList<ResourceData*> rdl = m_uriKickoffData.values() + m_idKickoffData.values(); - for( QList<ResourceData*>::iterator rdIt = rdl.begin(); + QSet<ResourceData*> rdl = m_uriKickoffData.values().toSet(); + for( QSet<ResourceData*>::iterator rdIt = rdl.begin(); rdIt != rdl.end(); ++rdIt ) { ResourceData* rd = *rdIt; // @@ -155,10 +138,10 @@ QList<ResourceData*> l; // - // We need to cache both m_uriKickoffData and m_idKickoffData since they might be changed + // We need to cache m_uriKickoffData since it might be changed // in the loop by ResourceData::load() // - QList<ResourceData*> rdl = m_uriKickoffData.values() + m_idKickoffData.values(); + QSet<ResourceData*> rdl = m_uriKickoffData.values().toSet(); // // make sure none of the ResourceData objects are deleted by ResourceData::load below @@ -169,7 +152,7 @@ tmp << Resource( rd ); } - for( QList<ResourceData*>::iterator rdIt = rdl.begin(); + for( QSet<ResourceData*>::iterator rdIt = rdl.begin(); rdIt != rdl.end(); ++rdIt ) { ResourceData* rd = *rdIt; if( rd->hasProperty( uri ) && @@ -184,22 +167,11 @@ QList<Nepomuk::ResourceData*> Nepomuk::ResourceManagerPrivate::allResourceData() { - QList<ResourceData*> l; - - for( ResourceDataHash::iterator rdIt = m_uriKickoffData.begin(); - rdIt != m_uriKickoffData.end(); ++rdIt ) { - l.append( rdIt.value() ); - } - for( KickoffDataHash::iterator rdIt = m_idKickoffData.begin(); - rdIt != m_idKickoffData.end(); ++rdIt ) { - l.append( rdIt.value() ); - } - - return l; + return m_uriKickoffData.values().toSet().toList(); } -bool Nepomuk::ResourceManagerPrivate::dataCacheFull() +bool Nepomuk::ResourceManagerPrivate::dataCacheFull() const { return dataCnt >= 1000; } @@ -207,8 +179,10 @@ void Nepomuk::ResourceManagerPrivate::cleanupCache( int num ) { - QList<ResourceData*> rdl = m_uriKickoffData.values() + m_idKickoffData.values(); - for( QList<ResourceData*>::iterator rdIt = rdl.begin(); + QMutexLocker lock( &mutex ); + + QSet<ResourceData*> rdl = m_uriKickoffData.values().toSet(); + for( QSet<ResourceData*>::iterator rdIt = rdl.begin(); rdIt != rdl.end(); ++rdIt ) { ResourceData* data = *rdIt; if ( !data->cnt() ) { @@ -220,37 +194,66 @@ } -void Nepomuk::ResourceManagerPrivate::determineAllUris() +bool Nepomuk::ResourceManagerPrivate::shouldBeDeleted( ResourceData * rd ) const { - QMutexLocker lock( &mutex ); - QList<ResourceData*> rdl = m_uriKickoffData.values() + m_idKickoffData.values(); - for( QList<ResourceData*>::iterator rdIt = rdl.begin(); - rdIt != rdl.end(); ++rdIt ) { - ResourceData* data = *rdIt; - data->determineUri(); - } + // + // We delete data objects in one of two cases: + // 1. They are not valid and as such not in one of the ResourceManagerPrivate kickoff lists + // 2. The cache is already full and we need to clean up + // + return( !rd->cnt() && ( !rd->isValid() || dataCacheFull() )); } +void Nepomuk::ResourceManagerPrivate::addToKickOffList( ResourceData* rd, const QSet<KUrl> & uris ) +{ + Q_FOREACH( const KUrl& uri, uris ) + m_uriKickoffData.insert( uri, rd ); +} + + void Nepomuk::ResourceManagerPrivate::_k_storageServiceInitialized( bool success ) { if( success ) { kDebug() << "Nepomuk Storage service up and initialized."; + m_manager->init(); emit m_manager->nepomukSystemStarted(); } } -void Nepomuk::ResourceManagerPrivate::_k_dbusServiceOwnerChanged( const QString& name, const QString&, const QString& newOwner ) +void Nepomuk::ResourceManagerPrivate::_k_dbusServiceUnregistered( const QString& serviceName ) { - if( name == QLatin1String("org.kde.NepomukStorage") && - newOwner.isEmpty() ) { + if( serviceName == QLatin1String("org.kde.NepomukStorage") ) { kDebug() << "Nepomuk Storage service went down."; emit m_manager->nepomukSystemStopped(); } } + +Nepomuk::ResourceData* Nepomuk::ResourceManagerPrivate::findData( const QUrl& uri ) +{ + if ( !uri.isEmpty() ) { + QMutexLocker lock( &mutex ); + + // look for the URI in the initialized and in the URI kickoff data + ResourceDataHash::iterator end = m_initializedData.end(); + ResourceDataHash::iterator it = m_initializedData.find( uri ); + if( it == end ) { + end = m_uriKickoffData.end(); + it = m_uriKickoffData.find( uri ); + } + + if( it != end ) { + return it.value(); + } + } + + return 0; +} + + Nepomuk::ResourceManager::ResourceManager() : QObject(), d( new ResourceManagerPrivate( this ) ) @@ -270,10 +273,14 @@ this, SLOT(_k_storageServiceInitialized(bool)) ); - // connect to the ownerChanged signal to be able to connect the nepomukSystemStopped + // connect to the serviceUnregistered signal to be able to connect the nepomukSystemStopped // signal once the storage service goes away - connect( QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString, QString, QString)), - this, SLOT(_k_dbusServiceOwnerChanged(QString, QString, QString)) ); + QDBusServiceWatcher *watcher = new QDBusServiceWatcher( QLatin1String("org.kde.NepomukStorage"), + QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForUnregistration, + this ); + connect( watcher, SIGNAL(serviceUnregistered(QString)), + this, SLOT(_k_dbusServiceUnregistered(QString)) ); init(); } @@ -356,7 +363,7 @@ QList<Nepomuk::Resource> Nepomuk::ResourceManager::allResourcesOfType( const QUrl& type ) { - QList<Resource> l; + QSet<Resource> set; if( !type.isEmpty() ) { // check local data @@ -364,8 +371,7 @@ for( QList<ResourceData*>::iterator rdIt = localData.begin(); rdIt != localData.end(); ++rdIt ) { Resource res( *rdIt ); - if( !l.contains( res ) ) - l.append( res ); + set.insert(res); } // kDebug() << " added local resources: " << l.count(); @@ -376,14 +382,13 @@ while( it.next() ) { Statement s = *it; Resource res( s.subject().uri() ); - if( !l.contains( res ) ) - l.append( res ); + set.insert(res); } // kDebug() << " added remote resources: " << l.count(); } - return l; + return set.toList(); } @@ -413,7 +418,7 @@ QList<Nepomuk::Resource> Nepomuk::ResourceManager::allResourcesWithProperty( const QUrl& uri, const Variant& v ) { - QList<Resource> l; + QSet<Resource> set; if( v.isList() ) { kDebug() << "(ResourceManager::allResourcesWithProperty) list values not supported."; @@ -423,7 +428,7 @@ QList<ResourceData*> localData = d->allResourceDataWithProperty( uri, v ); for( QList<ResourceData*>::iterator rdIt = localData.begin(); rdIt != localData.end(); ++rdIt ) { - l.append( Resource( *rdIt ) ); + set.insert( Resource( *rdIt ) ); } // check remote data @@ -441,12 +446,11 @@ while( it.next() ) { Statement s = *it; Resource res( s.subject().uri() ); - if( !l.contains( res ) ) - l.append( res ); + set.insert( res ); } } - return l; + return set.toList(); } @@ -519,12 +523,14 @@ { QMutexLocker lock( &d->mutex ); - d->overrideModel = model; - d->resourceFilterModel->setParentModel( model ? model : d->mainModel ); + if( model != d->resourceFilterModel ) { + d->overrideModel = model; + d->resourceFilterModel->setParentModel( model ? model : d->mainModel ); - // clear cache to make sure we do not mix data - Q_FOREACH( ResourceData* data, d->allResourceData()) { - data->invalidateCache(); + // clear cache to make sure we do not mix data + Q_FOREACH( ResourceData* data, d->allResourceData()) { + data->invalidateCache(); + } } } Index: nepomuk/core/types/ontology_p.h =================================================================== --- nepomuk/core/types/ontology_p.h (révision 0) +++ nepomuk/core/types/ontology_p.h (révision 0) @@ -0,0 +1,76 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ONTOLOGY_PRIVATE_H_ +#define _NEPOMUK_ONTOLOGY_PRIVATE_H_ + +#include "entity_p.h" +#include "class.h" +#include "property.h" + +#include <QtCore/QList> +#include <QtCore/QUrl> +#include <QtCore/QSharedData> + +namespace Nepomuk { + namespace Types { + class Class; + class Property; + + class OntologyPrivate : public EntityPrivate + { + public: + OntologyPrivate( const QUrl& uri = QUrl() ); + + QList<Class> classes; + QList<Property> properties; + + // -1 - unknown + // 0 - no + // 1 - yes + int entitiesAvailable; + + bool addProperty( const QUrl& property, const Soprano::Node& value ); + bool addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ); + + void initEntities(); + bool loadEntities(); + + void reset( bool recursive ); + }; + } +} + + +#include "ontology.h" +namespace Nepomuk { + + class Class; + class Property; + + class Ontology::Private : public QSharedData + { + public: + QUrl uri; + QHash<QUrl, const Class*> classes; + QHash<QUrl, const Property*> properties; + }; +} + +#endif Modification de propriétés sur nepomuk/core/types/ontology_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/nepomukontologyloader.cpp =================================================================== --- nepomuk/core/types/nepomukontologyloader.cpp (révision 0) +++ nepomuk/core/types/nepomukontologyloader.cpp (révision 0) @@ -0,0 +1,74 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "nepomukontologyloader.h" +#include "global.h" + +#include <Soprano/Statement> +#include <Soprano/Model> +#include <Soprano/QueryResultIterator> +#include <Soprano/Client/DBusModel> +#include <Soprano/Client/DBusClient> + +#include <QtCore/QDebug> + + +class Nepomuk::NepomukOntologyLoader::Private +{ +public: + Private() + : client("org.kde.NepomukServer") { + } + Soprano::Client::DBusClient client; +}; + + +Nepomuk::NepomukOntologyLoader::NepomukOntologyLoader() + : OntologyLoader(), + d( new Private() ) +{ +} + + +Nepomuk::NepomukOntologyLoader::~NepomukOntologyLoader() +{ + delete d; +} + + +QList<Soprano::Statement> Nepomuk::NepomukOntologyLoader::loadOntology( const QUrl& uri ) +{ + QList<Soprano::Statement> sl; + + if ( Soprano::Model* model = d->client.createModel( "main" ) ) { + // get the complete named graph describing the ontology + Soprano::QueryResultIterator it = model->executeQuery( QString( "construct {?s ?p ?o} " + "where { GRAPH <%1> { ?s ?p ?o } . }" ) + .arg( uri.toString() ), + Soprano::Query::QUERY_LANGUAGE_SPARQL ); + while ( it.next() ) { + sl.append( it.currentStatement() ); + } + } + else { + qDebug() << "(NepomukOntologyLoader) could not find ontology statements for " << uri; + } + + return sl; +} Modification de propriétés sur nepomuk/core/types/nepomukontologyloader.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/entity_p.h =================================================================== --- nepomuk/core/types/entity_p.h (révision 0) +++ nepomuk/core/types/entity_p.h (révision 0) @@ -0,0 +1,89 @@ +/* This file is part of the Nepomuk-KDE libraries + Copyright (c) 2007-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NEPOMUK_ENTITY_PRIVATE_H_ +#define _NEPOMUK_ENTITY_PRIVATE_H_ + +#include "entity.h" + +#include <QtCore/QHash> +#include <QtCore/QString> +#include <QtCore/QUrl> +#include <QtGui/QIcon> +#include <QtCore/QSharedData> +#include <QtCore/QMutex> + +namespace Nepomuk { + namespace Types { + class EntityPrivate : public QSharedData + { + public: + EntityPrivate( const QUrl& uri = QUrl() ); + virtual ~EntityPrivate() {} + + QMutex mutex; + + QUrl uri; + QString label; + QString comment; + QString l10nLabel; + QString l10nComment; + + QIcon icon; + + // -1 - unknown + // 0 - no + // 1 - yes + int available; + int ancestorsAvailable; + + void init(); + void initAncestors(); + + virtual bool addProperty( const QUrl& property, const Soprano::Node& value ) = 0; + virtual bool addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ) = 0; + + virtual void reset( bool recursive ); + + protected: + virtual bool load(); + virtual bool loadAncestors(); + }; + } +} + + + +class Nepomuk::Entity::Private : public QSharedData +{ +public: + Private() + : ontology( 0 ) { + } + + const Ontology* ontology; + + QUrl uri; + QString label; + QString comment; + QHash<QString, QString> l10nLabels; + QHash<QString, QString> l10nComments; +}; + +#endif Modification de propriétés sur nepomuk/core/types/entity_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/global.cpp =================================================================== --- nepomuk/core/types/global.cpp (révision 0) +++ nepomuk/core/types/global.cpp (révision 0) @@ -0,0 +1,38 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "global.h" + +#include <kdebug.h> +#include <kglobal.h> + + +QUrl Nepomuk::extractNamespace( const QUrl& url ) +{ + QByteArray s = url.toEncoded(); + int pos = s.lastIndexOf( '#' ); + if ( pos == -1 ) { + pos = s.lastIndexOf( '/' ); + } + if ( pos == -1 ) { + kError() << " Failed to extract namespace from " << url << endl; + return QUrl(); + } + return QUrl::fromEncoded( s.left( pos+1 ) ); +} Modification de propriétés sur nepomuk/core/types/global.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/fileontologyloader.cpp =================================================================== --- nepomuk/core/types/fileontologyloader.cpp (révision 0) +++ nepomuk/core/types/fileontologyloader.cpp (révision 0) @@ -0,0 +1,108 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "fileontologyloader.h" + +#include <soprano/soprano.h> + +#include <QtCore/QDebug> +#include <QtCore/QFile> + + +class Nepomuk::FileOntologyLoader::Private +{ +public: + Private() + : serialization( Soprano::SerializationUnknown ) { + } + + QString filename; + Soprano::RdfSerialization serialization; +}; + + +Nepomuk::FileOntologyLoader::FileOntologyLoader() + : OntologyLoader(), + d( new Private() ) +{ +} + + +Nepomuk::FileOntologyLoader::FileOntologyLoader( const QString& filename, Soprano::RdfSerialization serialization ) + : OntologyLoader(), + d( new Private() ) +{ + setFileName( filename ); + setSerialization( serialization ); +} + + +Nepomuk::FileOntologyLoader::~FileOntologyLoader() +{ + delete d; +} + + +void Nepomuk::FileOntologyLoader::setFileName( const QString& filename ) +{ + d->filename = filename; +} + + +void Nepomuk::FileOntologyLoader::setSerialization( Soprano::RdfSerialization s ) +{ + d->serialization = s; +} + + +QString Nepomuk::FileOntologyLoader::fileName() const +{ + return d->filename; +} + + +QList<Soprano::Statement> Nepomuk::FileOntologyLoader::loadOntology( const QUrl& url ) +{ + QString filename; + + if ( d->filename.isEmpty() ) { + // FIXME: use KIO or is QT sufficient? Actually how about NetAccess and a temp file? + qDebug() << "(FileOntologyLoader) remote support not implemented yet."; + return QList<Soprano::Statement>(); + } + else { + filename = d->filename; + } + + QList<Soprano::Statement> sl; + + QFile f( filename ); + if ( f.open( QIODevice::ReadOnly ) ) { + // TODO: how can we check if the requested onto is really defined in this file? + const Soprano::Parser* rdfParser = Soprano::PluginManager::instance()->discoverParserForSerialization( d->serialization ); + if ( rdfParser ) { + sl = rdfParser->parseFile( d->filename, url, d->serialization ).allStatements(); + } + } + else { + qDebug() << "(FileOntologyLoader) failed to open " << filename; + } + + return sl; +} Modification de propriétés sur nepomuk/core/types/fileontologyloader.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/ontologymanager.cpp =================================================================== --- nepomuk/core/types/ontologymanager.cpp (révision 0) +++ nepomuk/core/types/ontologymanager.cpp (révision 0) @@ -0,0 +1,343 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "ontologymanager.h" +#include "nepomukontologyloader.h" +#include "desktopontologyloader.h" +#include "ontology.h" +#include "ontology_p.h" +#include "class_p.h" +#include "property_p.h" +#include "entity_p.h" +#include "global.h" + +#include <Soprano/Statement> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/XMLSchema> + +#include <QtCore/QDebug> + + +using namespace Soprano; + +class Nepomuk::OntologyManager::Private +{ +public: + Private( OntologyManager* manager ) + : userOntologyLoader( 0 ), + desktopOntologyLoader( 0 ), + nepomukOntologyLoader( 0 ), + m_manager( manager ) { + } + + OntologyLoader* userOntologyLoader; + DesktopOntologyLoader* desktopOntologyLoader; + NepomukOntologyLoader* nepomukOntologyLoader; + + // cache + QHash<QUrl, Ontology> ontoCache; + QHash<QUrl, Class> classCache; + QHash<QUrl, Property> propertyCache; + + /** + * Find a class in the cache. + * + * \param recurse if true the method will try loading dependancies (i.e. + * other ontologies to fulfill the requirement + */ + Class* findClass( const QUrl& uri, bool recurse = false ) { + QHash<QUrl, Class>::iterator it = classCache.find( uri ); + if ( it != classCache.end() ) { + return &it.value(); + } + else { + if ( recurse ) { + // try loading the ontology containing the class + QUrl parentNs = extractNamespace( uri ); + if ( m_manager->getOntology( parentNs ) ) { + return findClass( uri ); + } + } + return 0; + } + } + + /** + * Find a property in the cache. + * + * \param recurse if true the method will try loading dependancies (i.e. + * other ontologies to fulfill the requirement + */ + Property* findProperty( const QUrl& uri, bool recurse = false ) { + QHash<QUrl, Property>::iterator it = propertyCache.find( uri ); + if ( it != propertyCache.end() ) { + return &it.value(); + } + else { + if ( recurse ) { + // try loading the ontology containing the property + QUrl parentNs = extractNamespace( uri ); + if ( m_manager->getOntology( parentNs ) ) { + return findProperty( uri ); + } + } + return 0; + } + } + +private: + OntologyManager* m_manager; +}; + + +Nepomuk::OntologyManager* Nepomuk::OntologyManager::instance() +{ + static OntologyManager* s_instance = 0; + if ( !s_instance ) { + s_instance = new OntologyManager(); + } + + return s_instance; +} + + +Nepomuk::OntologyManager::OntologyManager() + : d( new Private( this ) ) +{ +} + + +Nepomuk::OntologyManager::~OntologyManager() +{ + delete d->userOntologyLoader; + delete d->desktopOntologyLoader; + delete d->nepomukOntologyLoader; + delete d; +} + + +void Nepomuk::OntologyManager::setOntologyLoader( OntologyLoader* loader ) +{ + if ( d->userOntologyLoader != loader ) { + delete d->userOntologyLoader; + } + d->userOntologyLoader = loader; +} + + +const Nepomuk::Ontology* Nepomuk::OntologyManager::getOntology( const QUrl& uri ) +{ + // if the ontology is already in the cache return it + // + QHash<QUrl, Ontology>::const_iterator it = d->ontoCache.constFind( uri ); + if ( it != d->ontoCache.constEnd() ) { + return &it.value(); + } + + // if not in the cache, try loading it + // + else { + QList<Statement> sl; + if ( !d->userOntologyLoader ) { + if ( !d->desktopOntologyLoader ) { + d->desktopOntologyLoader = new DesktopOntologyLoader(); + } + if ( !d->nepomukOntologyLoader ) { + d->nepomukOntologyLoader = new NepomukOntologyLoader(); + } + + // we prefer the NepomukOntologyLoader since it does not parse + // anything + sl = d->nepomukOntologyLoader->loadOntology( uri ); + if ( sl.isEmpty() ) { + sl = d->desktopOntologyLoader->loadOntology( uri ); + } + } + else { + sl = d->userOntologyLoader->loadOntology( uri ); + } + + if ( !sl.isEmpty() ) { + qDebug() << "(Nepomuk::OntologyManager) Found ontology " << uri << endl; + return constructOntology( uri, sl ); + } + else { + // loading failed, i.e. ontology not stored. + // + qDebug() << "(Nepomuk::OntologyManager) Could not find ontology " << uri << endl; + return 0; + } + } +} + + +Nepomuk::Ontology* Nepomuk::OntologyManager::constructOntology( const QUrl& ontoUri, const QList<Statement>& sl ) +{ + Ontology& ont = d->ontoCache[ ontoUri ]; + ont.d->uri = ontoUri; + + // FIXME: Is it possible to define classes and properties with different namespaces in one file? + // Should we check the namespaces of the resources and if necessary create multiple Ontology + // instances? + + // step 1: collect all classes and properties + for ( QList<Statement>::const_iterator it = sl.constBegin(); it != sl.constEnd(); ++it ) { + const Statement& s = *it; + QUrl subjectUri( s.subject().uri() ); + if( s.predicate().uri().toString().endsWith( "#type" ) ) { + if ( s.object().uri().toString().endsWith( "#Class" ) ) { + d->classCache.insert( subjectUri, Class() ); + Class* c = &d->classCache[ subjectUri ]; + Entity* entity = static_cast<Entity*>( c ); + entity->d->uri = subjectUri; + entity->d->ontology = &ont; + ont.d->classes.insert( subjectUri, c ); + } + else if ( s.object().uri().toString().endsWith( "#Property" ) ) { + d->propertyCache.insert( subjectUri, Property() ); + Property* p = &d->propertyCache[ subjectUri ]; + Entity* entity = static_cast<Entity*>( p ); + entity->d->uri = subjectUri; + entity->d->ontology = &ont; + ont.d->properties.insert( subjectUri, p ); + } + else { + qDebug() << "(OntologyManager) unknown type in ontology: " << s.object().uri(); + } + } + } + + // step 2: construct the classes and properties + for ( QList<Statement>::const_iterator it = sl.constBegin(); it != sl.constEnd(); ++it ) { + const Statement& s = *it; + + // build the objects in the cache. If the ontology references another ontology try loading that one + // BIG PROBLEM: reverse dependancies of ontologies. + // If one ontology depends on another one which in turn depends on the first one. It should work + // since the first step already went through and thus, the class and property bodies have been created. + + const QUrl& subjectUri = s.subject().uri(); + Class* currentClass = d->findClass( subjectUri ); + Property* currentProperty = ( currentClass ? ( Property* )0 : d->findProperty( subjectUri ) ); + Entity* currentEntity = currentClass; + if ( !currentEntity ) { + currentEntity = currentProperty; + } + + if ( !currentClass && !currentProperty ) { + qDebug() << "(OntologyManager) invalid ontology statement: " << s; + d->ontoCache.remove( ontoUri ); + return 0; + } + + if( s.predicate().uri().toString().endsWith( "#subClassOf" ) ) { + Class* parent = d->findClass( s.object().uri(), true ); + if ( !parent ) { + qDebug() << "(OntologyManager) unable to load dependancy for: " << s; + } + else { + currentClass->d->parents.append( parent ); + parent->d->children.append( currentClass ); + } + } + + if( s.predicate().uri().toString().endsWith( "#subPropertyOf" ) ) { + Property* parent = d->findProperty( s.object().uri(), true ); + if ( !parent ) { + qDebug() << "(OntologyManager) unable to load dependancy for: " << s; + } + else { + currentProperty->d->parents.append( parent ); + parent->d->children.append( currentProperty ); + } + } + + else if( s.predicate().toString().endsWith( "#domain" ) ) { + Class* domain = d->findClass( s.object().uri(), true ); + if ( !domain ) { + qDebug() << "(OntologyManager) unable to load dependancy for: " << s; + } + else { + currentProperty->d->domain = domain; + domain->d->domainOf.insert( subjectUri, currentProperty ); + } + } + + else if( s.predicate().toString().endsWith( "#range" ) ) { + if ( s.object().toString().startsWith( Soprano::Vocabulary::XMLSchema::xsdNamespace().toString() ) ) { + currentProperty->d->literalRange = Literal( s.object().literal().toString() ); + } + else { + Class* range = d->findClass( s.object().uri(), true ); + if ( range ) { + currentProperty->d->range = range; + range->d->rangeOf.insert( subjectUri, currentProperty ); + } + else { + qDebug() << "(OntologyManager) unable to load dependancy for: " << s; + } + } + } + + else if( s.predicate().toString().endsWith( "#minCardinality" ) ) { + currentProperty->d->minCardinality = s.object().literal().toInt(); + } + + else if( s.predicate().toString().endsWith( "#maxCardinality" ) ) { + currentProperty->d->maxCardinality = s.object().literal().toInt(); + } + + else if ( s.predicate().toString().endsWith( "#cardinality" ) ) { + currentProperty->d->cardinality = s.object().literal().toInt(); + } + + else if ( s.predicate().toString().endsWith( "#inverseProperty" ) ) { + Property* inverse = d->findProperty( s.object().toString(), true ); + if ( !inverse ) { + qDebug() << "(OntologyManager) failed to load inverse property: " << s; + d->ontoCache.remove( ontoUri ); + return 0; + } + currentProperty->d->inverse = inverse; + inverse->d->inverse = currentProperty; + } + + // load l10n'ed comments + else if( s.predicate() == Soprano::Vocabulary::RDFS::comment() ) { + if ( s.object().language().isEmpty() ) { + currentEntity->d->comment = s.object().toString(); + } + else { + currentEntity->d->l10nComments[s.object().language()] = s.object().toString(); + } + } + + // load l10n'ed labels + else if( s.predicate() == Soprano::Vocabulary::RDFS::label() ) { + if ( s.object().language().isEmpty() ) { + currentEntity->d->label = s.object().toString(); + } + else { + currentEntity->d->l10nLabels[s.object().language()] = s.object().toString(); + } + } + } + + return &ont; +} Modification de propriétés sur nepomuk/core/types/ontologymanager.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/ontologyloader.h =================================================================== --- nepomuk/core/types/ontologyloader.h (révision 0) +++ nepomuk/core/types/ontologyloader.h (révision 0) @@ -0,0 +1,60 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ONTOLOGY_LOADER_H_ +#define _NEPOMUK_ONTOLOGY_LOADER_H_ + +#include <QtCore/QUrl> + +#include "nepomuk_export.h" + +namespace Soprano { + class Statement; +} + +namespace Nepomuk { + + /** + * An OntologyLoader provides the statements that make up an ontology + * for the OntologyManager to create the ontology classes and properties. + * + * Typical implementations read RDF statements from RDF files or from the + * Nepomuk-KDE RDF store. + * + * \deprecated Ontologies should now be handled using the classes + * in the Nepomuk::Types namespace. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT OntologyLoader + { + public: + virtual ~OntologyLoader(); + + // FIXME: use StatementIterator + virtual QList<Soprano::Statement> loadOntology( const QUrl& url ) = 0; + + protected: + OntologyLoader(); + + private: + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/core/types/ontologyloader.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/entitymanager.cpp =================================================================== --- nepomuk/core/types/entitymanager.cpp (révision 0) +++ nepomuk/core/types/entitymanager.cpp (révision 0) @@ -0,0 +1,131 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "entitymanager.h" +#include "class_p.h" +#include "property_p.h" +#include "ontology_p.h" + +#include "../resourcemanager.h" + +#include <QtCore/QMutexLocker> + +Q_GLOBAL_STATIC( Nepomuk::Types::EntityManager, entityManager ) + +Nepomuk::Types::EntityManager::EntityManager() +{ +} + + +Nepomuk::Types::EntityPrivate* Nepomuk::Types::EntityManager::findEntity( const QUrl& uri ) const +{ + if ( ClassPrivate* cp = findClass( uri ) ) { + return cp; + } + else if ( PropertyPrivate* pp = findProperty( uri ) ) { + return pp; + } + else if ( OntologyPrivate* op = findOntology( uri ) ) { + return op; + } + else { + return 0; + } +} + + +Nepomuk::Types::ClassPrivate* Nepomuk::Types::EntityManager::findClass( const QUrl& uri ) const +{ + QHash<QUrl, QExplicitlySharedDataPointer<ClassPrivate> >::const_iterator it = m_classMap.constFind( uri ); + if ( it != m_classMap.end() ) { + return it.value().data(); + } + return 0; +} + + +Nepomuk::Types::PropertyPrivate* Nepomuk::Types::EntityManager::findProperty( const QUrl& uri ) const +{ + QHash<QUrl, QExplicitlySharedDataPointer<PropertyPrivate> >::const_iterator it = m_propertyMap.constFind( uri ); + if ( it != m_propertyMap.end() ) { + return it.value().data(); + } + return 0; +} + + +Nepomuk::Types::OntologyPrivate* Nepomuk::Types::EntityManager::findOntology( const QUrl& uri ) const +{ + QHash<QUrl, QExplicitlySharedDataPointer<OntologyPrivate> >::const_iterator it = m_ontologyMap.constFind( uri ); + if ( it != m_ontologyMap.end() ) { + return it.value().data(); + } + return 0; +} + + +Nepomuk::Types::ClassPrivate* Nepomuk::Types::EntityManager::getClass( const QUrl& uri ) +{ + QMutexLocker lock( &m_mutex ); + + if ( ClassPrivate* cp = findClass( uri ) ) { + return cp; + } + else { + QExplicitlySharedDataPointer<ClassPrivate> scp( new ClassPrivate( uri ) ); + m_classMap.insert( uri, scp ); + return scp.data(); + } +} + + +Nepomuk::Types::PropertyPrivate* Nepomuk::Types::EntityManager::getProperty( const QUrl& uri ) +{ + QMutexLocker lock( &m_mutex ); + + if ( PropertyPrivate* pp = findProperty( uri ) ) { + return pp; + } + else { + QExplicitlySharedDataPointer<PropertyPrivate> cp( new PropertyPrivate( uri ) ); + m_propertyMap.insert( uri, cp ); + return cp.data(); + } +} + + +Nepomuk::Types::OntologyPrivate* Nepomuk::Types::EntityManager::getOntology( const QUrl& uri ) +{ + QMutexLocker lock( &m_mutex ); + + if ( OntologyPrivate* op = findOntology( uri ) ) { + return op; + } + else { + QExplicitlySharedDataPointer<OntologyPrivate> cp( new OntologyPrivate( uri ) ); + m_ontologyMap.insert( uri, cp ); + return cp.data(); + } +} + + +Nepomuk::Types::EntityManager* Nepomuk::Types::EntityManager::self() +{ + return entityManager(); +} Modification de propriétés sur nepomuk/core/types/entitymanager.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/property_p.h =================================================================== --- nepomuk/core/types/property_p.h (révision 0) +++ nepomuk/core/types/property_p.h (révision 0) @@ -0,0 +1,94 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_PROPERTY_PRIVATE_H_ +#define _NEPOMUK_PROPERTY_PRIVATE_H_ + +#include "entity_p.h" +#include "property.h" +#include "literal.h" +#include "class.h" + +#include <QtCore/QVariant> +#include <QtCore/QSharedData> + +namespace Nepomuk { + namespace Types { + class PropertyPrivate : public EntityPrivate + { + public: + PropertyPrivate( const QUrl& uri = QUrl() ); + + Class range; + Class domain; + + Literal literalRange; + + Property inverse; + + QList<Property> parents; + QList<Property> children; + + int minCardinality; + int maxCardinality; + int cardinality; + + bool addProperty( const QUrl& property, const Soprano::Node& value ); + bool addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ); + + void reset( bool recursive ); + }; + } +} + + + +namespace Nepomuk { + + class Class; + + class Property::Private : public QSharedData + { + public: + Private() + : range( 0 ), + domain( 0 ), + inverse( 0 ), + minCardinality( -1 ), + maxCardinality( -1 ), + cardinality( -1 ) { + } + + const Class* range; + const Class* domain; + + Literal literalRange; + + const Property* inverse; + + QList<const Property*> parents; + QList<const Property*> children; + + int minCardinality; + int maxCardinality; + int cardinality; + }; +} + +#endif Modification de propriétés sur nepomuk/core/types/property_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/class.h =================================================================== --- nepomuk/core/types/class.h (révision 0) +++ nepomuk/core/types/class.h (révision 0) @@ -0,0 +1,400 @@ +/* This file is part of the Nepomuk-KDE libraries + Copyright (c) 2007-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NEPOMUK_CLASS_H_ +#define _NEPOMUK_CLASS_H_ + +#include <QtCore/QList> +#include <QtCore/QUrl> +#include <QtCore/QString> +#include <QtCore/QSharedData> + +#include "entity.h" +#include "nepomuk_export.h" + + +namespace Nepomuk { + namespace Types { + class Property; + + /** + * \class Class class.h Nepomuk/Types/Class + * + * \brief A Class is a resource of type rdf:Class. + * + * Class instances are explicitly shared. Two instances created + * with the same uri reference the same data. + * + * While Resource objects can be changed Class instances are considered + * to be static and never changed during their lifetime. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Class : public Entity + { + friend class ClassPrivate; + + public: + /** + * Default constructor. Creates an empty Class. + */ + Class(); + + /** + * Create the class referred to by \p uri. + * The result is either a valid class which could be loaded from the + * Nepomuk store or a simple class which only contains the uri. + * + * Be aware that the data is only loaded once read. + * + * Subsequent calls result in a simple hash lookup of cached data. + */ + Class( const QUrl& uri ); + + /** + * Default copy constructor + */ + Class( const Class& ); + + /** + * Destructor + */ + ~Class(); + + /** + * Copy operator. + */ + Class& operator=( const Class& ); + + /** + * A Property has a certain range which is a Class or a Literal. + * \return A list of all properties that have this Class as a range. + * \sa Property::range() + */ + QList<Property> rangeOf(); + + /** + * A Property has a certain range which is a Class or a Literal. + * \return A list of all properties that have this Class as a range. + * \sa Property::range() + * + * Const version. + * + * \since 4.4 + */ + QList<Property> rangeOf() const; + + /** + * A Property has a certain domain which is a Class. + * \return A list of all properties that have this Class as a domain. + * \sa Property::domain() + */ + QList<Property> domainOf(); + + /** + * A Property has a certain domain which is a Class. + * \return A list of all properties that have this Class as a domain. + * \sa Property::domain() + * + * Const version. + * + * \since 4.4 + */ + QList<Property> domainOf() const; + + /** + * Search for a property in the class by its name. + * \param name The name of the property. + * \return the Property object identified by name or an invalid property if it could not be found. + */ + Property findPropertyByName( const QString& name ); + + /** + * Search for a property in the class by its name. + * \param name The name of the property. + * \return the Property object identified by name or an invalid property if it could not be found. + * + * Const version. + * + * \since 4.4 + */ + Property findPropertyByName( const QString& name ) const; + + /** + * Search for a property in the class by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or an invalid property if it could not be found. + */ + Property findPropertyByLabel( const QString& label, const QString& language = QString() ); + + /** + * Search for a property in the class by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or an invalid property if it could not be found. + * + * Const version. + * + * \since 4.4 + */ + Property findPropertyByLabel( const QString& label, const QString& language = QString() ) const; + + /** + * Each class can have multiple parent classes. This method + * provides a list of all direct parents. + * \return A list of all parent classes of this class. + * If the list is emppty it means that the class has no direct + * parents, i.e. it is derived from rdf:Resource. + * \sa allParentClasses() + */ + QList<Class> parentClasses(); + + /** + * Each class can have multiple parent classes. This method + * provides a list of all direct parents. + * \return A list of all parent classes of this class. + * If the list is emppty it means that the class has no direct + * parents, i.e. it is derived from rdf:Resource. + * \sa allParentClasses() + * + * Const version. + * + * \since 4.4 + */ + QList<Class> parentClasses() const; + + /** + * \return A list of all classes that have this class as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain classes that are derived + * from this class. + */ + QList<Class> subClasses(); + + /** + * \return A list of all classes that have this class as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain classes that are derived + * from this class. + * + * Const version. + * + * \since 4.4 + */ + QList<Class> subClasses() const; + + /** + * Recursively determines all parent classes of this class, not + * only the direct ones. + * \return A list of parent classes of this class. + * \sa parentClasses() + */ + QList<Class> allParentClasses(); + + /** + * Recursively determines all parent classes of this class, not + * only the direct ones. + * \return A list of parent classes of this class. + * \sa parentClasses() + * + * Const version. + * + * \since 4.4 + */ + QList<Class> allParentClasses() const; + + /** + * Recursively determines all sub classes of this class, not + * only the direct ones. + * \return A list of sub classes of this class. + * \sa subClasses() + */ + QList<Class> allSubClasses(); + + /** + * Recursively determines all sub classes of this class, not + * only the direct ones. + * \return A list of sub classes of this class. + * \sa subClasses() + * + * Const version. + * + * \since 4.4 + */ + QList<Class> allSubClasses() const; + + /** + * Check if a class inherits this class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if other is derived from this class, false otherwise. + */ + bool isParentOf( const Class& other ); + + /** + * Check if a class inherits this class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if other is derived from this class, false otherwise. + * + * Const version. + * + * \since 4.4 + */ + bool isParentOf( const Class& other ) const; + + /** + * Check if this class is derived from another class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if this class is derived from other, false otherwise. + */ + bool isSubClassOf( const Class& other ); + + /** + * Check if this class is derived from another class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if this class is derived from other, false otherwise. + * + * Const version. + * + * \since 4.4 + */ + bool isSubClassOf( const Class& other ) const; + }; + } +} + + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + + class Ontology; + class Property; + + /** + * A Class is a resource of type rdf:Class. + * + * \deprecated in favor of Nepomuk::Types::Class + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Class : public Entity + { + public: + /** + * Default constructor. Creates an empty Class. + */ + Class(); + + /** + * Default copy constructor + */ + Class( const Class& ); + + /** + * Destructor + */ + ~Class(); + + Class& operator=( const Class& ); + + // an alternative would be: QList<Property> rangeOf() and QList<Property> domainOf() + QList<const Property*> allProperties() const; + + /** + * Search for a property in the class by its name. + * \param name The name of the property. + * \return the Property object identified by name or 0 if the property could not be found. + */ + const Property* findPropertyByName( const QString& name ) const; + + /** + * Search for a property in the class by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or 0 if the property could not be found. + */ + const Property* findPropertyByLabel( const QString& label, const QString& language = QString() ) const; + + /** + * Search for a property in the class by its name. + * \param uri the URI of the property + * \return the Property object identified by uri or 0 if the property could not be found. + */ + const Property* findPropertyByUri( const QUrl& uri ) const; + + /** + * Each class can have multiple parent classes. + * \return A list of all parent classes of this class. + * If the list is emppty it means that the class has no direct + * parents, i.e. it is derived from rdf:Resource. + */ + QList<const Class*> parentClasses() const; + + /** + * \return A list of all classes that have this class as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain classes that are derived + * from this class. + */ + QList<const Class*> subClasses() const; + + /** + * Check if a class inherits this class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if other is derived from this class, false otherwise. + */ + bool isParentOf( const Class* other ) const; + + /** + * Check if this class is derived from another class. This is a recursive method which + * does not only check direct child classes. + * + * \return true if this class is derived from other, false otherwise. + */ + bool isSubClassOf( const Class* other ) const; + + /** + * Loads a class actually including the whole ontology + * it is declared in. + * + * Dependancies are resolved automatically if possible. + * + * \return A Class object representing the class identified + * by uri or an invalid Class object if the resource identified + * by uri is either not a class or does not exist. + */ + static const Class* load( const QUrl& uri ); + + private: + class Private; + QSharedDataPointer<Private> d; + + friend class OntologyManager; + }; +} + +#endif +#endif Modification de propriétés sur nepomuk/core/types/class.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/ontology.h =================================================================== --- nepomuk/core/types/ontology.h (révision 0) +++ nepomuk/core/types/ontology.h (révision 0) @@ -0,0 +1,238 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ONTOLOGY_H_ +#define _NEPOMUK_ONTOLOGY_H_ + +#include <QtCore/QList> +#include <QtCore/QUrl> +#include <QtCore/QString> +#include <QtCore/QSharedData> + +#include "entity.h" +#include "nepomuk_export.h" + + +namespace Nepomuk { + namespace Types { + + class Class; + class Property; + + /** + * \class Ontology ontology.h Nepomuk/Types/Ontology + * + * \brief Represents one ontology. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Ontology : public Entity + { + public: + /** + * Default constructor. Creates an empty Ontology. + */ + Ontology(); + + /** + * Create the ontology referred to by \p uri. + * The result is either a valid ontology which could be loaded from the + * Nepomuk store or a simple class which only contains the uri. + * + * Be aware that the data is only loaded once read. + * + * Subsequent calls result in a simple hash lookup of cached data. + */ + Ontology( const QUrl& uri ); + + /** + * Default copy constructor + */ + Ontology( const Ontology& ); + + /** + * Destructor + */ + ~Ontology(); + + Ontology& operator=( const Ontology& ); + + /** + * All classes defined in this ontology, i.e. its namespace. + */ + QList<Class> allClasses(); + + /** + * Search for a class in the ontology by its name. + * \param name The name of the class. + * \return the Class object identified by name or an invalid one if the class could not be found. + */ + Class findClassByName( const QString& name ); + + /** + * Search for a class in the ontology by its label. + * \param label The label of the class (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Class object identified by label or an invalid one if the class could not be found. + */ + Class findClassByLabel( const QString& label, const QString& language = QString() ); + + /** + * A list of all properties defined in this ontology. This does not include properties that use + * classes of this ontology but are defined in a different one. + */ + QList<Property> allProperties(); + + /** + * Search for a property in the ontology by its name. + * \param name The name of the property. + * \return the Property object identified by name or an invalid one if the property could not be found. + */ + Property findPropertyByName( const QString& name ); + + /** + * Search for a property in the ontology by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or an invalid one if the property could not be found. + */ + Property findPropertyByLabel( const QString& label, const QString& language = QString() ); + }; + } +} + + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + + class Class; + class Property; + + /** + * Ontology represents one ontology specified using NRL. + * + * \deprecated in favor of Nepomuk::Types::Ontology + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Ontology + { + public: + /** + * Default constructor. Creates an empty Ontology. + */ + Ontology(); + + /** + * Default copy constructor + */ + Ontology( const Ontology& ); + + /** + * Destructor + */ + ~Ontology(); + + Ontology& operator=( const Ontology& ); + + /** + * The URI of the ontology, i.e. its namespace + */ + QUrl uri() const; + + /** + * All classes defined in this ontology, i.e. its namespace. + */ + QList<const Class*> allClasses() const; + + /** + * Search for a class in the ontology by its name. + * \param name The name of the class. + * \return the Class object identified by name or 0 if the class could not be found. + */ + const Class* findClassByName( const QString& name ) const; + + /** + * Search for a class in the ontology by its label. + * \param label The label of the class (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Class object identified by label or 0 if the class could not be found. + */ + const Class* findClassByLabel( const QString& label, const QString& language = QString() ) const; + + /** + * Search for a class in the ontology by its name. + * \param uri the URI of the class + * \return the Class object identified by uri or 0 if the class could not be found. + */ + const Class* findClassByUri( const QUrl& uri ) const; + + /** + * A list of all properties defined in this ontology. This does not include properties that use + * classes of this ontology but are defined in a different one. + */ + QList<const Property*> allProperties() const; + + /** + * Search for a property in the ontology by its name. + * \param name The name of the property. + * \return the Property object identified by name or 0 if the property could not be found. + */ + const Property* findPropertyByName( const QString& name ) const; + + /** + * Search for a property in the ontology by its label. + * \param label The label of the property (i.e. rdfs:label) + * \param language The language in which the label was specified. If empty the default rdfs:label + * is returned. + * \return the Property object identified by label or 0 if the property could not be found. + */ + const Property* findPropertyByLabel( const QString& label, const QString& language = QString() ) const; + + /** + * Search for a property in the ontology by its name. + * \param uri the URI of the property + * \return the Property object identified by uri or 0 if the property could not be found. + */ + const Property* findPropertyByUri( const QUrl& uri ) const; + + /** + * Loads an ontology. + * + * Dependancies are resolved automatically if possible. + * + * \return An Ontology object representing the ontology identified + * by uri or an invalid Ontology object if the resource identified + * by uri is either not an ontology or does not exist. + */ + static const Ontology* load( const QUrl& uri ); + + private: + class Private; + QSharedDataPointer<Private> d; + + friend class OntologyManager; + }; +} + +#endif // DISABLE_NEPOMUK_LEGACY + +#endif Modification de propriétés sur nepomuk/core/types/ontology.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/literal_p.h =================================================================== --- nepomuk/core/types/literal_p.h (révision 0) +++ nepomuk/core/types/literal_p.h (révision 0) @@ -0,0 +1,52 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_LITERAL_PRIVATE_H_ +#define _NEPOMUK_LITERAL_PRIVATE_H_ + +#include "literal.h" + +#include <QtCore/QUrl> +#include <QtCore/QVariant> +#include <QtCore/QSharedData> + +class Nepomuk::Types::Literal::Private : public QSharedData +{ + public: + Private() + : dataType( QVariant::Invalid ) { + } + + QUrl dataTypeUri; + QVariant::Type dataType; +}; + + +class Nepomuk::Literal::Private : public QSharedData +{ + public: + Private() + : dataType( QVariant::Invalid ) { + } + + QUrl dataTypeUri; + QVariant::Type dataType; +}; + +#endif Modification de propriétés sur nepomuk/core/types/literal_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/entity.h =================================================================== --- nepomuk/core/types/entity.h (révision 0) +++ nepomuk/core/types/entity.h (révision 0) @@ -0,0 +1,297 @@ +/* This file is part of the Nepomuk-KDE libraries + Copyright (c) 2007-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NEPOMUK_ENTITY_H_ +#define _NEPOMUK_ENTITY_H_ + +#include <QtCore/QUrl> +#include <QtCore/QString> +#include <QtCore/QSharedData> +#include <QtCore/QHash> + +#include <Soprano/Node> + +#include <kglobal.h> +#include <klocale.h> + +#include "nepomuk_export.h" + +class QIcon; + + +namespace Nepomuk { + namespace Types { + class EntityPrivate; + + /** + * \brief Abstract base class for Class and Property; + * + * Base class for static ontology entities Class and Property. + * It encapsulates the generic labels and comments that both + * types have. + * + * Due to internal optimizations comparing two Entities is much + * faster than comparing two QUrl objects. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Entity + { + public: + /** + * Default copy constructor. + */ + Entity( const Entity& ); + + /** + * Destructor. + */ + virtual ~Entity(); + + /** + * Copy operator. + */ + Entity& operator=( const Entity& ); + + /** + * The name of the resource. The name equals the fragment of the + * URI. + */ + QString name() const; + + /** + * The URI of the resource + */ + QUrl uri() const; + + /** + * Retrieve the label of the entity (rdfs:label) + * + * \param language The code of the language to use. Defaults to the session + * language configured in KDE. As of KDE 4.3 only the currently + * configured language is loaded to save memory. + * + * \return The label translated into \p language or the default fallback label + * if no translation is available or the name() if no label could be found + * at all. + */ + QString label( const QString& language = KGlobal::locale()->language() ); + + /** + * Retrieve the label of the entity (rdfs:label) + * + * \param language The code of the language to use. Defaults to the session + * language configured in KDE. As of KDE 4.3 only the currently + * configured language is loaded to save memory. + * + * \return The label translated into \p language or the default fallback label + * if no translation is available or the name() if no label could be found + * at all. + * + * Const version + * + * \since 4.4 + */ + QString label( const QString& language = KGlobal::locale()->language() ) const; + + /** + * Retrieve the comment of the entity (rdfs:comment) + * + * \param language The code of the language to use. Defaults to the session + * language configured in KDE. As of KDE 4.3 only the currently + * configured language is loaded to save memory. + * + * \return The comment translated into \p language or the default fallback comment + * if no translation is available or an empty string if no comment could be found + * at all. + */ + QString comment( const QString& language = KGlobal::locale()->language() ); + + /** + * Retrieve the comment of the entity (rdfs:comment) + * + * \param language The code of the language to use. Defaults to the session + * language configured in KDE. As of KDE 4.3 only the currently + * configured language is loaded to save memory. + * + * \return The comment translated into \p language or the default fallback comment + * if no translation is available or an empty string if no comment could be found + * at all. + * + * Const version + * + * \since 4.4 + */ + QString comment( const QString& language = KGlobal::locale()->language() ) const; + + /** + * Retrieve the icon stored for the entity (nao:hasSymbol) + * + * If no symbol is defined for the entity a null icon will be returned. + * + * \since 4.1 + */ + QIcon icon(); + + /** + * Retrieve the icon stored for the entity (nao:hasSymbol) + * + * If no symbol is defined for the entity a null icon will be returned. + * + * Const version. + * + * \since 4.4 + */ + QIcon icon() const; + + /** + * Is this a valid Entity, i.e. has it a valid URI. + * A valid Entity does not necessarily have a label and a comment, it + * does not even have to exist in the Nepomuk store. + * + * \sa isAvailable + */ + bool isValid() const; + + /** + * Is this Entity available locally, i.e. could its properties + * be loaded from the Nepomuk store. + */ + bool isAvailable(); + + /** + * Is this Entity available locally, i.e. could its properties + * be loaded from the Nepomuk store. + * + * Const version. + * + * \since 4.4 + */ + bool isAvailable() const; + + /** + * The Types classes are optimized for performance under the + * aasumption that ontologies never change during the execution + * time of an application. + * + * Since there might be situations where this does not apply + * the internal cache can be reset via this method. + * + * \param recursive If \p true all related entities will be reset + * as well. + * + * \since 4.1 + */ + void reset( bool recursive = false ); + + /** + * An Entity can be used as a QUrl automagically. + */ + operator QUrl() const { return uri(); } + + /** + * Compares two Entity instances by simply comparing their URI. + */ + bool operator==( const Entity& other ) const; + + /** + * Compares the Entity with a URI. + * + * \since 4.5 + */ + bool operator==( const QUrl& other ) const; + + /** + * Compares two Entity instances by simply comparing their URI. + */ + bool operator!=( const Entity& other ) const; + + /** + * Compares the Entity with a URI. + * + * \since 4.5 + */ + bool operator!=( const QUrl& other ) const; + + protected: + /** + * Create an invalid Entity instance. + */ + Entity(); + + QExplicitlySharedDataPointer<EntityPrivate> d; + }; + + inline uint qHash( const Entity& c ) + { + return qHash( c.uri() ); + } + } +} + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + + class Ontology; + + /** + * \deprecated in favor of Nepomuk::Types::Entity + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Entity + { + public: + Entity( const Entity& ); + ~Entity(); + + Entity& operator=( const Entity& ); + + /** + * The ontology in which the resource is defined. + */ + const Ontology* definingOntology() const; + + /** + * The name of the resource. The name equals the fragment of the + * URI. + */ + QString name() const; + + /** + * The URI of the resource + */ + QUrl uri() const; + + QString label( const QString& language = QString() ) const; + QString comment( const QString& language = QString() ) const; + + protected: + Entity(); + + private: + class Private; + QSharedDataPointer<Private> d; + + friend class OntologyManager; + }; +} + +#endif // DISABLE_NEPOMUK_LEGACY + +#endif // _NEPOMUK_ENTITY_H_ Modification de propriétés sur nepomuk/core/types/entity.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/property.h =================================================================== --- nepomuk/core/types/property.h (révision 0) +++ nepomuk/core/types/property.h (révision 0) @@ -0,0 +1,428 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_PROPERTY_H_ +#define _NEPOMUK_PROPERTY_H_ + +#include <QtCore/QList> +#include <QtCore/QUrl> +#include <QtCore/QString> +#include <QtCore/QVariant> +#include <QtCore/QSharedData> + +#include "entity.h" +#include "nepomuk_export.h" + +namespace Nepomuk { + namespace Types { + + class Class; + class Literal; + + /** + * \class Property property.h Nepomuk/Types/Property + * + * \brief A property is a resource of type rdf:Property which relates a domain + * with a range. The latter one can be a Literal or a Class. + * + * Property instances are explicitly shared. Two instances created + * with the same uri reference the same data. + * + * While Resource objects can be changed Property instances are considered + * to be static and never changed during their lifetime. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Property : public Entity + { + public: + /** + * Default constructor. Creates an empty Property. + */ + Property(); + + /** + * Create the property referred to by \p uri. + * The result is either a valid property which could be loaded from the + * Nepomuk store or a simple property which only contains the uri. + * + * Be aware that the data is only loaded once read. + * + * Subsequent calls result in a simple hash lookup of cached data. + */ + Property( const QUrl& uri ); + + /** + * Default copy constructor + */ + Property( const Property& ); + + /** + * Destructor + */ + ~Property(); + + /** + * Copy operator. + */ + Property& operator=( const Property& ); + + /** + * Each property can have multiple parent properties. + * \return A list of all parent properties of this property. + * If the list is emppty it means that the property has no direct + * parents, i.e. it is derived from rdf:Resource. + */ + QList<Property> parentProperties(); + + /** + * Each property can have multiple parent properties. + * \return A list of all parent properties of this property. + * If the list is emppty it means that the property has no direct + * parents, i.e. it is derived from rdf:Resource. + * + * Const version + * + * \since 4.4 + */ + QList<Property> parentProperties() const; + + /** + * \return A list of all properties that have this property as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain properties that are derived + * from this property. + */ + QList<Property> subProperties(); + + /** + * \return A list of all properties that have this property as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain properties that are derived + * from this property. + * + * Const version + * + * \since 4.4 + */ + QList<Property> subProperties() const; + + /** + * The inverse property (nrl:inverseProperty). + * \return A Property instance representing the inverse property of this one + * or 0 if none was specified in the ontology. + */ + Property inverseProperty(); + + /** + * The inverse property (nrl:inverseProperty). + * \return A Property instance representing the inverse property of this one + * or 0 if none was specified in the ontology. + * + * Const version + * + * \since 4.4 + */ + Property inverseProperty() const; + + /** + * The range of the property. + * \return The range of the property or an invalid Class in case + * the range of this poperty is a literal. + * \sa literalRange + */ + Class range(); + + /** + * The range of the property. + * \return The range of the property or an invalid Class in case + * the range of this poperty is a literal. + * \sa literalRange + * + * Const version + * + * \since 4.4 + */ + Class range() const; + + /** + * If the rage of this property is a literal (i.e. range returns an invalid Class) + * this method provides the literal type. + * + * \returns the literal type of this property or an empty, invalid Literal + * if the range is a Class. + * + * \sa range + */ + Literal literalRangeType(); + + /** + * If the rage of this property is a literal (i.e. range returns an invalid Class) + * this method provides the literal type. + * + * \returns the literal type of this property or an empty, invalid Literal + * if the range is a Class. + * + * \sa range + * + * Const version + * + * \since 4.4 + */ + Literal literalRangeType() const; + + /** + * The domain of the property. + */ + Class domain(); + + /** + * The domain of the property. + * + * Const version + * + * \since 4.4 + */ + Class domain() const; + + /** + * The cardinality of this property as specified by nrl:cardinality. + * + * \return the cardinality of the property or -1 if none was set. + */ + int cardinality(); + + /** + * The cardinality of this property as specified by nrl:cardinality. + * + * \return the cardinality of the property or -1 if none was set. + * + * Const version + * + * \since 4.4 + */ + int cardinality() const; + + /** + * The minimum cardinality of this property as specified by nrl:minCardinality. + * + * \return the minimum cardinality of the property or -1 if none was set. + */ + int minCardinality(); + + /** + * The minimum cardinality of this property as specified by nrl:minCardinality. + * + * \return the minimum cardinality of the property or -1 if none was set. + * + * Const version + * + * \since 4.4 + */ + int minCardinality() const; + + /** + * The maximum cardinality of this property as specified by nrl:maxCardinality. + * + * \return the maximum cardinality of the property or -1 if none was set. + */ + int maxCardinality(); + + /** + * The maximum cardinality of this property as specified by nrl:maxCardinality. + * + * \return the maximum cardinality of the property or -1 if none was set. + * + * Const version + * + * \since 4.4 + */ + int maxCardinality() const; + + /** + * Check if a property inherits this property. This is a recursive method which + * does not only check direct child propertyes. + * + * \return true if other is derived from this property, false otherwise. + */ + bool isParentOf( const Property& other ); + + /** + * Check if a property inherits this property. This is a recursive method which + * does not only check direct child propertyes. + * + * \return true if other is derived from this property, false otherwise. + * + * Const version + * + * \since 4.4 + */ + bool isParentOf( const Property& other ) const; + + /** + * Check if this property is derived from another property. This is a recursive method which + * does not only check direct child propertyes. + * + * \return true if this property is derived from other, false otherwise. + */ + bool isSubPropertyOf( const Property& other ); + + /** + * Check if this property is derived from another property. This is a recursive method which + * does not only check direct child propertyes. + * + * \return true if this property is derived from other, false otherwise. + * + * Const version + * + * \since 4.4 + */ + bool isSubPropertyOf( const Property& other ) const; + }; + } +} + + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + + class Ontology; + class Class; + class Literal; + + /** + * A property is a resource of type rdf:Property which relates a domain + * with a range. The latter one can be a literal in addition to a Class. + * + * \deprecated in favor of Nepomuk::Types::Property + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Property : public Entity + { + public: + /** + * Default constructor. Creates an empty Property. + */ + Property(); + + /** + * Default copy constructor + */ + Property( const Property& ); + + /** + * Destructor + */ + ~Property(); + + Property& operator=( const Property& ); + + /** + * Each property can have multiple parent properties. + * \return A list of all parent properties of this property. + * If the list is emppty it means that the property has no direct + * parents, i.e. it is derived from rdf:Resource. + */ + QList<const Property*> parentProperties() const; + + /** + * \return A list of all properties that have this property as a parent. + * Be aware that this list can never be final since other ontologies + * that have not been loaded yet may contain properties that are derived + * from this property. + */ + QList<const Property*> parentOf() const; + + /** + * The inverse property (nrl:inverseProperty). + * \return A Property instance representing the inverse property of this one + * or 0 if none was specified in the ontology. + */ + const Property* inverseProperty() const; + + /** + * The range of the property. + * \return The range of the property or an invalid Class in case + * the range of this poperty is a literal. + * \sa literalRange + */ + const Class* range() const; + + /** + * If the rage of this property is a literal (i.e. range returns 0) + * this method provides the literal type. + * + * \returns the literal type of this property or an empty, invalid Literal + * if the range is a Class. + * + * \sa range + */ + Literal literalRangeType() const; + + /** + * The domain of the property. + */ + const Class* domain() const; + + /** + * The cardinality of this property as specified by nrl:cardinality. + * + * \return the cardinality of the property or -1 if none was set. + */ + int cardinality() const; + + /** + * The minimum cardinality of this property as specified by nrl:minCardinality. + * + * \return the minimum cardinality of the property or -1 if none was set. + */ + int minCardinality() const; + + /** + * The maximum cardinality of this property as specified by nrl:maxCardinality. + * + * \return the maximum cardinality of the property or -1 if none was set. + */ + int maxCardinality() const; + + // QString unit() const; + + /** + * Loads a property actually including the whole ontology + * it is declared in. + * + * Dependancies are resolved automatically if possible. + * + * \return A property object representing the property identified + * by uri or an invalid Property object if the resource identified + * by uri is either not a property or does not exist. + */ + static const Property* load( const QUrl& uri ); + + private: + class Private; + QSharedDataPointer<Private> d; + + friend class OntologyManager; + }; +} + +#endif // DISABLE_NEPOMUK_LEGACY + +#endif // _NEPOMUK_PROPERTY_H_ Modification de propriétés sur nepomuk/core/types/property.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/CMakeLists.txt =================================================================== --- nepomuk/core/types/CMakeLists.txt (révision 0) +++ nepomuk/core/types/CMakeLists.txt (révision 0) @@ -0,0 +1,18 @@ +project(nepomukcore_onto) + +install(FILES + entity.h + class.h + property.h + ontology.h + literal.h + ontologymanager.h + ontologyloader.h + nepomukontologyloader.h + fileontologyloader.h + desktopontologyloader.h + global.h + DESTINATION ${INCLUDE_INSTALL_DIR}/nepomuk COMPONENT Devel +) + +#add_subdirectory(test) Modification de propriétés sur nepomuk/core/types/CMakeLists.txt ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/test/kontotest.h =================================================================== --- nepomuk/core/types/test/kontotest.h (révision 0) +++ nepomuk/core/types/test/kontotest.h (révision 0) @@ -0,0 +1,36 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 _KONTO_TEST_H_ +#define _KONTO_TEST_H_ + +#include <QtCore/QObject> + +class KontoTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void testOntology(); + void testClass(); + void testProperty(); +}; + +#endif Modification de propriétés sur nepomuk/core/types/test/kontotest.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/test/desktopontologyloadertest.h =================================================================== --- nepomuk/core/types/test/desktopontologyloadertest.h (révision 0) +++ nepomuk/core/types/test/desktopontologyloadertest.h (révision 0) @@ -0,0 +1,35 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 _KONTO_DESKTOP_ONTOLOGY_LOADER_TEST_H_ +#define _KONTO_DESKTOP_ONTOLOGY_LOADER_TEST_H_ + +#include <QtCore/QObject> + +class DesktopOntologyLoaderTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void testLoading(); + void cleanupTestCase(); +}; + +#endif Modification de propriétés sur nepomuk/core/types/test/desktopontologyloadertest.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/test/entitytest.h =================================================================== --- nepomuk/core/types/test/entitytest.h (révision 0) +++ nepomuk/core/types/test/entitytest.h (révision 0) @@ -0,0 +1,35 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 _ENTITY_TEST_H_ +#define _ENTITY_TEST_H_ + +#include <QtCore/QObject> + +class EntityTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void testClass(); + void testProperty(); +}; + +#endif Modification de propriétés sur nepomuk/core/types/test/entitytest.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/test/kontotest.cpp =================================================================== --- nepomuk/core/types/test/kontotest.cpp (révision 0) +++ nepomuk/core/types/test/kontotest.cpp (révision 0) @@ -0,0 +1,180 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "kontotest.h" +#include "../ontologyloader.h" +#include "../ontologymanager.h" +#include "../ontology.h" +#include "../class.h" +#include "../global.h" +#include "../property.h" + +#include <Soprano/Statement> +#include <Soprano/Vocabulary/RDF> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/NRL> + +#include <QtTest/QTest> +#include <QtCore/QCoreApplication> + + +using namespace Nepomuk; +using namespace Soprano; + +class DummyOntologyLoader : public OntologyLoader +{ +public: + QList<Statement> loadOntology( const QUrl& uri ) + { + // create some dummy onto stuff + QList<Statement> sl; + + QString ns = uri.toString(); + if ( !ns.endsWith( "#" ) ) { + ns += '#'; + } + + // one dummy class + sl.append( Statement( Node( QUrl( ns + "DummyClass" ) ), + Node( Soprano::Vocabulary::RDF::type() ), + Node( Soprano::Vocabulary::RDFS::Class() ) ) ); + sl.append( Statement( Node( QUrl( ns + "DummyClass" ) ), + Node( Soprano::Vocabulary::RDFS::label() ), + Node( LiteralValue( "A dummy class" ) ) ) ); + + sl.append( Statement( Node( QUrl( ns + "DummySubClass" ) ), + Node( Soprano::Vocabulary::RDF::type() ), + Node( Soprano::Vocabulary::RDFS::Class() ) ) ); + sl.append( Statement( Node( QUrl( ns + "DummySubClass" ) ), + Node( Soprano::Vocabulary::RDFS::subClassOf() ), + Node( QUrl( ns + "DummyClass" ) ) ) ); + + sl.append( Statement( Node( QUrl( ns + "DummySubSubClass" ) ), + Node( Soprano::Vocabulary::RDF::type() ), + Node( Soprano::Vocabulary::RDFS::Class() ) ) ); + sl.append( Statement( Node( QUrl( ns + "DummySubSubClass" ) ), + Node( Soprano::Vocabulary::RDFS::subClassOf() ), + Node( QUrl( ns + "DummySubClass" ) ) ) ); + + // one dummy property + sl.append( Statement( Node( QUrl( ns + "hasBrother" ) ), + Node( Soprano::Vocabulary::RDF::type() ), + Node( Soprano::Vocabulary::RDF::Property() ) ) ); + sl.append( Statement( Node( QUrl( ns + "hasBrother" ) ), + Node( Soprano::Vocabulary::RDFS::domain() ), + Node( QUrl( ns + "DummyClass" ) ) ) ); + sl.append( Statement( Node( QUrl( ns + "hasBrother" ) ), + Node( Soprano::Vocabulary::RDFS::range() ), + Node( QUrl( ns + "DummyClass" ) ) ) ); + sl.append( Statement( Node( QUrl( ns + "hasBrother" ) ), + Node( Soprano::Vocabulary::NRL::inverseProperty() ), + Node( QUrl( ns + "isBrotherOf" ) ) ) ); + + // and its reverse property + sl.append( Statement( Node( QUrl( ns + "isBrotherOf" ) ), + Node( Soprano::Vocabulary::RDF::type() ), + Node( Soprano::Vocabulary::RDF::Property() ) )); + sl.append( Statement( Node( QUrl( ns + "isBrotherOf" ) ), + Node( Soprano::Vocabulary::RDFS::domain() ), + Node( QUrl( ns + "DummyClass" ) ) ) ); + sl.append( Statement( Node( QUrl( ns + "isBrotherOf" ) ), + Node( Soprano::Vocabulary::RDFS::range() ), + Node( QUrl( ns + "DummyClass" ) ) ) ); + sl.append( Statement( Node( QUrl( ns + "isBrotherOf" ) ), + Node( Soprano::Vocabulary::NRL::inverseProperty() ), + Node( QUrl( ns + "hasBrother" ) ) ) ); + + return sl; + } +}; + + +void KontoTest::initTestCase() +{ + OntologyManager::instance()->setOntologyLoader( new DummyOntologyLoader() ); +} + + +void KontoTest::testOntology() +{ + const Ontology* onto = Ontology::load( QUrl( "test" ) ); + QVERIFY( onto != 0 ); + QCOMPARE( onto->uri(), QUrl( "test" ) ); +} + + +void KontoTest::testClass() +{ + const Ontology* onto = Ontology::load( QUrl( "test" ) ); + + QCOMPARE( onto->allClasses().count(), 3 ); + QVERIFY( onto->findClassByName( "DummyClass" ) != 0 ); + QVERIFY( onto->findClassByUri( QUrl( "test#DummyClass" ) ) != 0 ); + + const Class* dummyClass = Class::load( QUrl( "test#DummyClass" ) ); + QVERIFY( dummyClass != 0 ); + + QCOMPARE( dummyClass->name(), QString( "DummyClass" ) ); + QCOMPARE( dummyClass->label(), QString( "A dummy class" ) ); + + const Class* dummySubClass = onto->findClassByName( "DummySubClass" ); + const Class* dummySubSubClass = onto->findClassByName( "DummySubSubClass" ); + + QVERIFY( dummySubClass != 0 ); + QVERIFY( dummySubSubClass != 0 ); + QVERIFY( dummyClass->subClasses().contains( dummySubClass ) ); + QVERIFY( dummySubClass->subClasses().contains( dummySubSubClass ) ); + QVERIFY( dummySubClass->parentClasses().contains( dummyClass ) ); + QVERIFY( dummySubSubClass->parentClasses().contains( dummySubClass ) ); + + QVERIFY( dummyClass->isParentOf( dummySubClass ) ); + QVERIFY( dummyClass->isParentOf( dummySubSubClass ) ); + QVERIFY( dummySubClass->isParentOf( dummySubSubClass ) ); + QVERIFY( !dummySubClass->isParentOf( dummyClass ) ); + + QVERIFY( dummySubSubClass->isSubClassOf( dummyClass ) ); + QVERIFY( dummySubSubClass->isSubClassOf( dummySubClass ) ); + QVERIFY( dummySubClass->isSubClassOf( dummyClass ) ); + QVERIFY( !dummySubClass->isSubClassOf( dummySubSubClass ) ); +} + + +void KontoTest::testProperty() +{ + const Property* hasBrother = Property::load( QUrl( "test#hasBrother" ) ); + const Property* isBrotherOf = Property::load( QUrl( "test#isBrotherOf" ) ); + + QVERIFY( hasBrother != 0 ); + QVERIFY( isBrotherOf != 0 ); + + QCOMPARE( hasBrother->inverseProperty(), isBrotherOf ); + QCOMPARE( isBrotherOf->inverseProperty(), hasBrother ); + + const Class* dummyClass = Class::load( QUrl( "test#DummyClass" ) ); + QCOMPARE( hasBrother->range(), dummyClass ); + QCOMPARE( hasBrother->domain(), dummyClass ); + + QCOMPARE( isBrotherOf->range(), dummyClass ); + QCOMPARE( isBrotherOf->domain(), dummyClass ); +} + + +QTEST_MAIN( KontoTest ) + +#include "kontotest.moc" Modification de propriétés sur nepomuk/core/types/test/kontotest.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/test/desktopontologyloadertest.cpp =================================================================== --- nepomuk/core/types/test/desktopontologyloadertest.cpp (révision 0) +++ nepomuk/core/types/test/desktopontologyloadertest.cpp (révision 0) @@ -0,0 +1,103 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "desktopontologyloadertest.h" +#include "desktopontologyloader.h" + +#include <QtTest/QTest> +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QTextStream> +#include <QtCore/QList> + +#include <kstandarddirs.h> +#include <kconfiggroup.h> +#include <kdesktopfile.h> +#include <kurl.h> +#include <kio/global.h> +#include <kio/deletejob.h> +#include <qtest_kde.h> + +#include <Soprano/Statement> + + +void DesktopOntologyLoaderTest::initTestCase() +{ + // create our test folder + QDir tmpDir( "/tmp" ); + tmpDir.mkpath( "konto_desktopontologyloader_test/knepomuk/ontologies" ); + KGlobal::dirs()->addResourceDir( "data", "/tmp/konto_desktopontologyloader_test" ); + + // create our little test ontology + QFile ontoFile( "/tmp/konto_desktopontologyloader_test/knepomuk/ontologies/test.nrl" ); + ontoFile.open( QIODevice::WriteOnly ); + QTextStream ontoStream( &ontoFile ); + + // the header + ontoStream << "<?xml version='1.0' encoding='UTF-8'?>" << endl + << "<!DOCTYPE rdf:RDF [" << endl + << "<!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>" << endl + << "<!ENTITY nrl 'http://semanticdesktop.org/ontologies/2006/11/24/nrl#'>" << endl + << "<!ENTITY nao 'http://semanticdesktop.org/ontologies/2007/03/31/nao#'>" << endl + << "<!ENTITY xsd 'http://www.w3.org/2001/XMLSchema#'>" << endl + << "<!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>" << endl + << "<!ENTITY test 'http://test.org/test#'>" << endl + << "]>" << endl + << "<rdf:RDF xmlns:rdf=\"&rdf;\" xmlns:rdfs=\"&rdfs;\" xmlns:nrl=\"&nrl;\" xmlns:nao=\"&nao;\" xmlns:xsd=\"&xsd;\">" << endl; + + // one class + ontoStream << "<rdf:Description rdf:about=\"&test;Test\">" << endl + << "<rdfs:label>test</rdfs:label>" << endl + << "<rdf:type rdf:resource=\"&rdfs;Class\"/>" << endl + << "</rdf:Description>" << endl; + + // the footer + ontoStream << "</rdf:RDF>" << endl; + + KDesktopFile desktopFile( "/tmp/konto_desktopontologyloader_test/knepomuk/ontologies/test.desktop" ); + KConfigGroup desktopGroup( desktopFile.desktopGroup() ); + desktopGroup.writeEntry( "Type", "Link" ); + desktopGroup.writeEntry( "Name", "Test Ontology" ); + desktopGroup.writeEntry( "MimeType", "text/rdf" ); + desktopGroup.writeEntry( "Path", "test.nrl" ); + desktopGroup.writeEntry( "URL", "http://test.org/test" ); +} + + +void DesktopOntologyLoaderTest::testLoading() +{ + Nepomuk::DesktopOntologyLoader loader; + QList<Soprano::Statement> sl = loader.loadOntology( QUrl( "http://test.org/test" ) ); + QVERIFY( !sl.isEmpty() ); + QCOMPARE( sl.count(), 2 ); +} + + +void DesktopOntologyLoaderTest::cleanupTestCase() +{ + QFile::remove( "/tmp/konto_desktopontologyloader_test/knepomuk/ontologies/test.desktop" ); + QFile::remove( "/tmp/konto_desktopontologyloader_test/knepomuk/ontologies/test.nrl" ); + QDir( "/tmp/konto_desktopontologyloader_test/knepomuk/" ).rmdir( "ontologies" ); + QDir( "/tmp/konto_desktopontologyloader_test" ).rmdir( "knepomuk" ); + QDir( "/tmp/" ).rmdir( "konto_desktopontologyloader_test" ); +} + +QTEST_KDEMAIN( DesktopOntologyLoaderTest, NoGUI ) + +#include "desktopontologyloadertest.moc" Modification de propriétés sur nepomuk/core/types/test/desktopontologyloadertest.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/test/CMakeLists.txt =================================================================== --- nepomuk/core/types/test/CMakeLists.txt (révision 0) +++ nepomuk/core/types/test/CMakeLists.txt (révision 0) @@ -0,0 +1,16 @@ +project(konto_test) + +include_directories( + ${nepomukcore_SOURCE_DIR}/ontology +) + +include_directories( ${KDE4_KIO_INCLUDES} ${CMAKE_SOURCE_DIR}/konto ) +include_directories( ${QT_INCLUDES} ${SOPRANO_INCLUDE_DIR} ) +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) + +# tests +# TODO: fix, and turn into kde4_add_unit_test again +kde4_add_executable(entitytest entitytest.cpp) +target_link_libraries(entitytest nepomuk ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} + ${KDE4_KDECORE_LIBS} ${QT_QTTEST_LIBRARY} + ${SOPRANO_LIBRARIES}) Modification de propriétés sur nepomuk/core/types/test/CMakeLists.txt ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/test/entitytest.cpp =================================================================== --- nepomuk/core/types/test/entitytest.cpp (révision 0) +++ nepomuk/core/types/test/entitytest.cpp (révision 0) @@ -0,0 +1,92 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "entitytest.h" +#include "../class.h" +#include "../property.h" + +#include <kdebug.h> +#include <kstandarddirs.h> +#include <qtest_kde.h> +#include <QtDBus/QtDBus> +#include <unistd.h> + +#include <Soprano/Vocabulary/RDFS> + +using namespace Nepomuk::Types; + +static QByteArray origKdeHome; + +// Getting the real KDEHOME has to be done before main() overwrites $KDEHOME +int kInitSocket() +{ + origKdeHome = getenv("KDEHOME"); + return 1; +} +Q_CONSTRUCTOR_FUNCTION(kInitSocket) + +// Make symlink from ~/.kde-unit-test/share/apps/nepomuk/socket to the real socket for the running server +void EntityTest::initTestCase() +{ + QString realSocket = !origKdeHome.isEmpty() ? QFile::encodeName(origKdeHome) : QDir::homePath() + QLatin1String("/.kde"); + realSocket += QLatin1String("/share/apps/nepomuk/socket"); + //kDebug() << realSocket; + if (QFile::exists(realSocket)) { + const QString socketLink = KGlobal::dirs()->locateLocal( "data", "nepomuk/socket" ); + //kDebug() << socketLink << realSocket; + if (!QFile::exists(socketLink)) { + ::symlink(QFile::encodeName(realSocket), QFile::encodeName(socketLink)); + } + } +} + +void EntityTest::testClass() +{ + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.nepomuk.services.nepomukstorage")) { + QSKIP("nepomuk not running", SkipAll); + } + + Class c1( Soprano::Vocabulary::RDFS::Resource() ); + Class c2( Soprano::Vocabulary::RDFS::Resource() ); + + QVERIFY( c1.isValid() ); + QVERIFY( c2.isValid() ); + + QVERIFY( c1.isAvailable() ); + QVERIFY( c2.isAvailable() ); + + QCOMPARE( c1.uri(), c2.uri() ); + QCOMPARE( c1.name(), c2.name() ); + QCOMPARE( c1.label(), c2.label() ); + QCOMPARE( c1.comment(), c2.comment() ); + + QVERIFY( !c1.label().isEmpty() ); + + qDebug() << c1.label() << c1.comment(); +} + + +void EntityTest::testProperty() +{ +} + + +QTEST_KDEMAIN(EntityTest, NoGUI) + +#include "entitytest.moc" Modification de propriétés sur nepomuk/core/types/test/entitytest.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/desktopontologyloader.h =================================================================== --- nepomuk/core/types/desktopontologyloader.h (révision 0) +++ nepomuk/core/types/desktopontologyloader.h (révision 0) @@ -0,0 +1,62 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_DESKTOP_ONTOLOGY_LOADER_H_ +#define _NEPOMUK_DESKTOP_ONTOLOGY_LOADER_H_ + +#include "ontologyloader.h" +#include "nepomuk_export.h" + +#include <QtCore/QUrl> +#include <QtCore/QList> + +namespace Nepomuk { + /** + * The DesktopOntologyLoader reads ontologies from the installed + * ontologies on the desktop using KStandardDirs. + * All possible ontology installation folders are searched for + * ontology desktop files. + * + * \deprecated Ontologies should now be handled using the classes + * in the Nepomuk::Types namespace. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT DesktopOntologyLoader : public OntologyLoader + { + public: + DesktopOntologyLoader(); + ~DesktopOntologyLoader(); + + /** + * Get a list of all ontology URIs that could be found + * on the system. + */ + QList<QUrl> allOntologies(); + + /** + * reimplemented from OntologyLoader + */ + QList<Soprano::Statement> loadOntology( const QUrl& url ); + + private: + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/core/types/desktopontologyloader.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/literal.h =================================================================== --- nepomuk/core/types/literal.h (révision 0) +++ nepomuk/core/types/literal.h (révision 0) @@ -0,0 +1,125 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_LITERAL_H_ +#define _NEPOMUK_LITERAL_H_ + +#include <QtCore/QUrl> +#include <QtCore/QVariant> +#include <QtCore/QSharedData> + +#include "nepomuk_export.h" + +namespace Nepomuk { + namespace Types { + /** + * \class Literal literal.h Nepomuk/Types/Literal + * + * \brief Defines a literal type based on XML Schema. + * + * Each valid Literal represents the literal type + * as XML Schema URI and as QVariant type. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT Literal + { + public: + /** + * Default constructor. + * Creates an empty Literal + */ + Literal(); + Literal( const Literal& ); + Literal( const QUrl& dataTypeUri ); + ~Literal(); + + Literal& operator=( const Literal& ); + + /** + * The XML Schema type URI. + */ + QUrl dataTypeUri() const; + + /** + * The type converted to a QVariant::Type. + * \return The QVariant::Type that corresponds to the XML Schema type or + * QVariant::Invalid if it could not be matched. + */ + QVariant::Type dataType() const; + + /** + * Is this a valid Literal, i.e. has it a valid URI. + */ + bool isValid() const; + + private: + class Private; + QExplicitlySharedDataPointer<Private> d; + }; + } +} + + +#ifndef DISABLE_NEPOMUK_LEGACY + +namespace Nepomuk { + /** + * \brief Defines a literal type based on XML Schema. + * + * Each valid Literal represents the literal type + * as XML Schema URI and as QVariant type. + * + * \deprecated in favor of Nepomuk::Types::Literal + */ + class KDE_DEPRECATED NEPOMUK_EXPORT Literal + { + public: + /** + * Default constructor. + * Creates an empty Literal + */ + Literal(); + Literal( const Literal& ); + Literal( const QUrl& dataTypeUri ); + ~Literal(); + + Literal& operator=( const Literal& ); + + /** + * The XML Schema type URI. + */ + const QUrl& dataTypeUri() const; + + /** + * The type converted to a QVariant::Type. + * \return The QVariant::Type that corresponds to the XML Schema type or + * QVariant::Invalid if it could not be matched. + */ + QVariant::Type dataType() const; + + private: + class Private; + QSharedDataPointer<Private> d; + }; +} + +#endif // DISABLE_NEPOMUK_LEGACY + +#endif Modification de propriétés sur nepomuk/core/types/literal.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/ontologyloader.cpp =================================================================== --- nepomuk/core/types/ontologyloader.cpp (révision 0) +++ nepomuk/core/types/ontologyloader.cpp (révision 0) @@ -0,0 +1,35 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "ontologyloader.h" + +class Nepomuk::OntologyLoader::Private +{ +}; + +Nepomuk::OntologyLoader::OntologyLoader() + :d( new Private() ) +{ +} + + +Nepomuk::OntologyLoader::~OntologyLoader() +{ + delete d; +} Modification de propriétés sur nepomuk/core/types/ontologyloader.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/global.h =================================================================== --- nepomuk/core/types/global.h (révision 0) +++ nepomuk/core/types/global.h (révision 0) @@ -0,0 +1,32 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_GLOBAL_H_ +#define _NEPOMUK_GLOBAL_H_ + +#include "nepomuk_export.h" + +#include <QtCore/QString> +#include <QtCore/QUrl> + +namespace Nepomuk { + KDE_DEPRECATED NEPOMUK_EXPORT QUrl extractNamespace( const QUrl& url ); +} + +#endif Modification de propriétés sur nepomuk/core/types/global.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/class.cpp =================================================================== --- nepomuk/core/types/class.cpp (révision 0) +++ nepomuk/core/types/class.cpp (révision 0) @@ -0,0 +1,658 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "class.h" +#include "class_p.h" +#include "ontology.h" +#include "resourcemanager.h" +#include "property.h" +#include "entitymanager.h" + +#include <QtCore/QList> + +#include <kdebug.h> + +#include <Soprano/QueryResultIterator> +#include <Soprano/Model> +#include <Soprano/Vocabulary/NRL> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/RDF> +#include <Soprano/Vocabulary/OWL> + +#undef D +#define D static_cast<Nepomuk::Types::ClassPrivate*>( d.data() ) + +Nepomuk::Types::ClassPrivate::ClassPrivate( const QUrl& uri ) + : EntityPrivate( uri ), + propertiesAvailable( uri.isValid() ? -1 : 0 ) +{ +} + + +bool Nepomuk::Types::ClassPrivate::load() +{ + // + // Nearly all here can be done in a very clean way. There is only + // one special case: rdfs:Resource, the base class of them all + // + if ( EntityPrivate::load() ) { + // undefined super class means that we are derived from rdfs:Resource directly + if ( parents.isEmpty() ) { + if ( uri != Soprano::Vocabulary::RDFS::Resource() ) { + parents += Soprano::Vocabulary::RDFS::Resource(); + } + } + return true; + } + else { + return false; + } +} + + +bool Nepomuk::Types::ClassPrivate::loadAncestors() +{ + // + // Nearly all here can be done in a very clean way. There is only + // one special case: rdfs:Resource, the base class of them all + // + if ( uri == Soprano::Vocabulary::RDFS::Resource() ) { + // + // All classes that do not explicetely state a superclass are + // derived from rdfs:Resource. This query selects those classes + // (might fail on redland though) + // + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select distinct ?s where { " + "{ ?s a <%1> . } UNION { ?s a <%2> . } " + "OPTIONAL { graph ?g { ?s <%3> ?ss . } . " + "{ ?g a <%4> . } UNION { ?g a <%5> . } . } . " + "FILTER(!BOUND(?ss)) . }") + .arg( Soprano::Vocabulary::RDFS::Class().toString() ) + .arg( Soprano::Vocabulary::OWL::Class().toString() ) + .arg( Soprano::Vocabulary::RDFS::subClassOf().toString() ) + .arg( Soprano::Vocabulary::NRL::Ontology().toString() ) + .arg( Soprano::Vocabulary::NRL::KnowledgeBase().toString() ), + Soprano::Query::QueryLanguageSparql ); + bool success = false; + while ( it.next() ) { + success = true; + QUrl resUri = it.binding( "s" ).uri(); + if ( resUri != Soprano::Vocabulary::RDFS::Resource() ) { + children.append( resUri ); + } + } + } + + return EntityPrivate::loadAncestors(); +} + + +bool Nepomuk::Types::ClassPrivate::addProperty( const QUrl& property, const Soprano::Node& value ) +{ + if( property == Soprano::Vocabulary::RDFS::subClassOf() ) { + parents.append( Class( value.uri() ) ); + return true; + } + + return false; +} + + +bool Nepomuk::Types::ClassPrivate::addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ) +{ + if ( property == Soprano::Vocabulary::RDFS::subClassOf() ) { + children.append( Class( ancestorResource ) ); + return true; + } + + return false; +} + + +void Nepomuk::Types::ClassPrivate::initProperties() +{ + QMutexLocker lock( &mutex ); + + if ( propertiesAvailable < 0 ) { + propertiesAvailable = loadProperties() ? 1 : 0; + } +} + + +bool Nepomuk::Types::ClassPrivate::loadProperties() +{ + // load domains with a hack to get at least a subset of properties that inherit their domain from parents + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select distinct ?p where { " + "{ ?p <%1> <%2> . } " + "UNION " + "{ ?p <%3> ?p1 . " + "OPTIONAL { ?p <%1> ?undefdom . } . " + "?p1 <%1> <%2> . " + "FILTER(!bound(?undefdom)) . } " + "UNION " + "{ ?p <%3> ?p1 . " + "OPTIONAL { ?p <%1> ?undefdom1 . } . " + "?p1 <%3> ?p2 . " + "OPTIONAL { ?p1 <%1> ?undefdom2 . } . " + "?p2 <%1> <%2> . " + "FILTER(!bound(?undefdom1) && !bound(?undefdom2)) . } " + "}") + .arg( Soprano::Vocabulary::RDFS::domain().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ) + .arg( Soprano::Vocabulary::RDFS::subPropertyOf().toString() ), + Soprano::Query::QueryLanguageSparql ); + + // redland cannot handle UNION queries! So fallback to the "old" query + if( it.lastError() ) { + it = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?p where { " + "?p <%1> <%2> . }") + .arg( Soprano::Vocabulary::RDFS::domain().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ), + Soprano::Query::QueryLanguageSparql ); + } + + bool success = false; + while ( it.next() ) { + success = true; + domainOf.append( Property( it.binding( "p" ).uri() ) ); + } + + + // load ranges + it = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?p where { " + "?p <%1> <%2> . }") + .arg( Soprano::Vocabulary::RDFS::range().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ), + Soprano::Query::QueryLanguageSparql ); + while ( it.next() ) { + success = true; + rangeOf.append( Property( it.binding( "p" ).uri() ) ); + } + + return success; +} + + +void Nepomuk::Types::ClassPrivate::reset( bool recursive ) +{ + EntityPrivate::reset( recursive ); + + QMutexLocker lock( &mutex ); + + if ( propertiesAvailable != -1 ) { + if ( recursive ) { + foreach( Property p, domainOf ) { + p.reset( true ); + } + foreach( Property p, rangeOf ) { + p.reset( true ); + } + } + + domainOf.clear(); + rangeOf.clear(); + propertiesAvailable = -1; + } + + if ( available != -1 ) { + if ( recursive ) { + foreach( Class c, parents ) { + c.reset( true ); + } + } + parents.clear(); + available = -1; + } + + if ( ancestorsAvailable != -1 ) { + if ( recursive ) { + foreach( Class c, children ) { + c.reset( true ); + } + } + children.clear(); + ancestorsAvailable = -1; + } +} + + +QSet<Nepomuk::Types::Class> Nepomuk::Types::ClassPrivate::findParentClasses( ClassPrivate* requestingClass ) +{ + QSet<Class> allParents; + + for ( QList<Class>::iterator it = parents.begin(); it != parents.end(); ++it ) { + ClassPrivate* p = static_cast<Nepomuk::Types::ClassPrivate*>( it->d.data() ); + if ( p != requestingClass ) { + p->init(); + allParents += p->findParentClasses( requestingClass ); + allParents += *it; + } + } + + return allParents; +} + + +QSet<Nepomuk::Types::Class> Nepomuk::Types::ClassPrivate::findSubClasses( ClassPrivate* requestingClass ) +{ + QSet<Class> allChildren; + + for ( QList<Class>::iterator it = children.begin(); it != children.end(); ++it ) { + ClassPrivate* p = static_cast<Nepomuk::Types::ClassPrivate*>( it->d.data() ); + if ( p != requestingClass ) { + p->initAncestors(); + allChildren += p->findSubClasses( requestingClass ); + allChildren += *it; + } + } + + return allChildren; +} + + + +Nepomuk::Types::Class::Class() + : Entity() +{ + d = 0; +} + + +Nepomuk::Types::Class::Class( const QUrl& uri ) + : Entity() +{ + d = EntityManager::self()->getClass( uri ); +} + + +Nepomuk::Types::Class::Class( const Class& other ) + : Entity( other ) +{ +} + + +Nepomuk::Types::Class::~Class() +{ +} + + +Nepomuk::Types::Class& Nepomuk::Types::Class::operator=( const Class& other ) +{ + d = other.d; + return *this; +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Class::rangeOf() +{ + if ( d ) { + D->initProperties(); + return D->rangeOf; + } + else { + return QList<Nepomuk::Types::Property>(); + } +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Class::rangeOf() const +{ + return const_cast<Class*>(this)->rangeOf(); +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Class::domainOf() +{ + if ( d ) { + D->initProperties(); + return D->domainOf; + } + else { + return QList<Nepomuk::Types::Property>(); + } +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Class::domainOf() const +{ + return const_cast<Class*>(this)->domainOf(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Class::findPropertyByName( const QString& name ) +{ + if ( d ) { + D->initProperties(); + for ( QList<Property>::const_iterator it = D->domainOf.constBegin(); + it != D->domainOf.constEnd(); ++it ) { + const Property& p = *it; + if ( p.name() == name ) { + return p; + } + } + } + + return Property(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Class::findPropertyByName( const QString& name ) const +{ + return const_cast<Class*>(this)->findPropertyByName(name); +} + + +Nepomuk::Types::Property Nepomuk::Types::Class::findPropertyByLabel( const QString& label, const QString& language ) +{ + if ( d ) { + D->initProperties(); + for ( QList<Property>::iterator it = D->domainOf.begin(); + it != D->domainOf.end(); ++it ) { + Property& p = *it; + if ( p.label( language ) == label ) { + return p; + } + } + } + + return Property(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Class::findPropertyByLabel( const QString& label, const QString& language ) const +{ + return const_cast<Class*>(this)->findPropertyByLabel( label, language ); +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::parentClasses() +{ + if ( d ) { + D->init(); + return D->parents; + } + else { + return QList<Nepomuk::Types::Class>(); + } +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::parentClasses() const +{ + return const_cast<Class*>(this)->parentClasses(); +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::subClasses() +{ + if ( d ) { + D->initAncestors(); + return D->children; + } + else { + return QList<Nepomuk::Types::Class>(); + } +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::subClasses() const +{ + return const_cast<Class*>(this)->subClasses(); +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::allParentClasses() +{ + if ( d ) { + D->init(); + return D->findParentClasses( D ).toList(); + } + else { + return QList<Nepomuk::Types::Class>(); + } +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::allParentClasses() const +{ + return const_cast<Class*>(this)->allParentClasses(); +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::allSubClasses() +{ + if ( d ) { + D->initAncestors(); + return D->findSubClasses( D ).toList(); + } + else { + return QList<Nepomuk::Types::Class>(); + } +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Class::allSubClasses() const +{ + return const_cast<Class*>(this)->allSubClasses(); +} + + +bool Nepomuk::Types::Class::isParentOf( const Class& other ) +{ + if ( d ) { + D->initAncestors(); + + if ( D->children.contains( other ) ) { + return true; + } + else { + for ( QList<Nepomuk::Types::Class>::iterator it = D->children.begin(); + it != D->children.end(); ++it ) { + if ( ( *it ).isParentOf( other ) ) { + return true; + } + } + } + } + + return false; +} + + +bool Nepomuk::Types::Class::isParentOf( const Class& other ) const +{ + return const_cast<Class*>(this)->isParentOf( other ); +} + + +bool Nepomuk::Types::Class::isSubClassOf( const Class& other ) +{ + if ( d ) { + D->init(); + + if ( D->parents.contains( other ) ) { + return true; + } + else { + for ( QList<Nepomuk::Types::Class>::iterator it = D->parents.begin(); + it != D->parents.end(); ++it ) { + if ( ( *it ).isSubClassOf( other ) ) { + return true; + } + } + } + } + + return false; +} + + +bool Nepomuk::Types::Class::isSubClassOf( const Class& other ) const +{ + return const_cast<Class*>(this)->isSubClassOf( other ); +} + + + + + +// Start of code for deprecated Class +// ---------------------------------- + +#include "global.h" +#include "ontologymanager.h" + +Nepomuk::Class::Class() + : Entity() +{ + d = new Private(); +} + + +Nepomuk::Class::Class( const Class& other ) + : Entity( other ) +{ + d = other.d; +} + + +Nepomuk::Class::~Class() +{ +} + + +Nepomuk::Class& Nepomuk::Class::operator=( const Class& other ) +{ + d = other.d; + return *this; +} + + +QList<const Nepomuk::Property*> Nepomuk::Class::allProperties() const +{ + return d->domainOf.values(); +} + + +const Nepomuk::Property* Nepomuk::Class::findPropertyByName( const QString& name ) const +{ + for ( QHash<QUrl, const Property*>::const_iterator it = d->domainOf.constBegin(); + it != d->domainOf.constEnd(); ++it ) { + const Property* p = it.value(); + if ( p->name() == name ) { + return p; + } + } + + return 0; +} + + +const Nepomuk::Property* Nepomuk::Class::findPropertyByLabel( const QString& label, const QString& language ) const +{ + for ( QHash<QUrl, const Property*>::const_iterator it = d->domainOf.constBegin(); + it != d->domainOf.constEnd(); ++it ) { + const Property* p = it.value(); + if ( p->label( language ) == label ) { + return p; + } + } + + return 0; +} + + +const Nepomuk::Property* Nepomuk::Class::findPropertyByUri( const QUrl& uri ) const +{ + QHash<QUrl, const Property*>::const_iterator it = d->domainOf.find( uri ); + if ( it != d->domainOf.constEnd() ) { + return it.value(); + } + else { + return 0; + } +} + + +QList<const Nepomuk::Class*> Nepomuk::Class::parentClasses() const +{ + return d->parents; +} + + +QList<const Nepomuk::Class*> Nepomuk::Class::subClasses() const +{ + return d->children; +} + + +bool Nepomuk::Class::isParentOf( const Class* other ) const +{ + if ( d->children.contains( other ) ) { + return true; + } + else { + for ( QList<const Nepomuk::Class*>::const_iterator it = d->children.constBegin(); + it != d->children.constEnd(); ++it ) { + if ( ( *it )->isParentOf( other ) ) { + return true; + } + } + return false; + } +} + + +bool Nepomuk::Class::isSubClassOf( const Class* other ) const +{ + if ( d->parents.contains( other ) ) { + return true; + } + else { + for ( QList<const Nepomuk::Class*>::const_iterator it = d->parents.constBegin(); + it != d->parents.constEnd(); ++it ) { + if ( ( *it )->isSubClassOf( other ) ) { + return true; + } + } + return false; + } +} + + +const Nepomuk::Class* Nepomuk::Class::load( const QUrl& uri ) +{ + Q_ASSERT( !uri.isEmpty() ); + + QUrl ns = extractNamespace( uri ); + + // load the ontology in the cache + const Ontology* ont = OntologyManager::instance()->getOntology( ns ); + + // return the requested class or an invalid one if the ontology + // was not found + if ( ont ) { + return ont->findClassByUri( uri ); + } + else { + return 0; + } +} Modification de propriétés sur nepomuk/core/types/class.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/nepomukontologyloader.h =================================================================== --- nepomuk/core/types/nepomukontologyloader.h (révision 0) +++ nepomuk/core/types/nepomukontologyloader.h (révision 0) @@ -0,0 +1,45 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_NEPOMUK_ONTOLOGY_LOADER_H_ +#define _NEPOMUK_NEPOMUK_ONTOLOGY_LOADER_H_ + +#include "ontologyloader.h" +#include "nepomuk_export.h" + +namespace Nepomuk { + /** + * \deprecated Ontologies should now be handled using the classes + * in the Nepomuk::Types namespace. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT NepomukOntologyLoader : public OntologyLoader + { + public: + NepomukOntologyLoader(); + ~NepomukOntologyLoader(); + + QList<Soprano::Statement> loadOntology( const QUrl& url ); + + private: + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/core/types/nepomukontologyloader.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/fileontologyloader.h =================================================================== --- nepomuk/core/types/fileontologyloader.h (révision 0) +++ nepomuk/core/types/fileontologyloader.h (révision 0) @@ -0,0 +1,89 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_FILE_ONTOLOGY_LOADER_H_ +#define _NEPOMUK_FILE_ONTOLOGY_LOADER_H_ + +#include "ontologyloader.h" +#include "nepomuk_export.h" + +#include <soprano/parser.h> +#include <soprano/sopranotypes.h> + + +namespace Nepomuk { + /** + * \deprecated Ontologies should now be handled using the classes + * in the Nepomuk::Types namespace. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT FileOntologyLoader : public OntologyLoader + { + public: + /** + * Default constructor. + * Creates a FileOntologyLoader that will try to load the + * ontology directly from its URL, i.e. the internet. + */ + FileOntologyLoader(); + + /** + * Creates a FileOntologyLoader that will load the + * ontology from the specified filename. + */ + explicit FileOntologyLoader( const QString& filename, + Soprano::RdfSerialization serialization = Soprano::SerializationUnknown ); + + /** + * Destructor + */ + ~FileOntologyLoader(); + + /** + * Set the filename to be used for reading the ontologies. + * If no filename has been set FileOntologyLoader will try + * load the ontology file from the internet, i.e. directly + * use the ontology URL - NOT IMPLEMENTED YET. + */ + void setFileName( const QString& filename ); + + /** + * The filename that has been set. + * \sa setFileName + * \return The filename set (can be empty) + */ + QString fileName() const; + + /** + * Set the serialization that is used in the file. + * Defaults to Soprano::SerializationUnknown + */ + void setSerialization( Soprano::RdfSerialization ); + + /** + * reimplemented from OntologyLoader + */ + QList<Soprano::Statement> loadOntology( const QUrl& url ); + + private: + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/core/types/fileontologyloader.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/ontology.cpp =================================================================== --- nepomuk/core/types/ontology.cpp (révision 0) +++ nepomuk/core/types/ontology.cpp (révision 0) @@ -0,0 +1,361 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "ontology.h" +#include "ontology_p.h" +#include "class.h" +#include "property.h" +#include "entitymanager.h" +#include "resourcemanager.h" + +#include <Soprano/QueryResultIterator> +#include <Soprano/Model> +#include <Soprano/Vocabulary/NAO> +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/RDF> +#include <Soprano/Vocabulary/XMLSchema> + +#undef D +#define D static_cast<Nepomuk::Types::OntologyPrivate*>( d.data() ) + +Nepomuk::Types::OntologyPrivate::OntologyPrivate( const QUrl& uri ) + : EntityPrivate( uri ), + entitiesAvailable( uri.isValid() ? -1 : 0 ) +{ +} + + +void Nepomuk::Types::OntologyPrivate::initEntities() +{ + if ( entitiesAvailable < 0 ) { + entitiesAvailable = loadEntities() ? 1 : 0; + } +} + + +bool Nepomuk::Types::OntologyPrivate::loadEntities() +{ + // load classes + // We use a FILTER(STR(?ns)...) to support both Soprano 2.3 (with plain literals) and earlier (with only typed ones) + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?c where { " + "graph ?g { ?c a <%1> . } . " + "?g <%2> ?ns . " + "FILTER(STR(?ns) = \"%3\") . }" ) + .arg( Soprano::Vocabulary::RDFS::Class().toString() ) + .arg( Soprano::Vocabulary::NAO::hasDefaultNamespace().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ), + Soprano::Query::QueryLanguageSparql ); + bool success = false; + while ( it.next() ) { + success = true; + classes.append( Class( it.binding( "c" ).uri() ) ); + } + + + // load properties + it = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?p where { " + "graph ?g { ?p a <%1> . } . " + "?g <%2> ?ns . " + "FILTER(STR(?ns) = \"%3\") . }" ) + .arg( Soprano::Vocabulary::RDF::Property().toString() ) + .arg( Soprano::Vocabulary::NAO::hasDefaultNamespace().toString() ) + .arg( QString::fromAscii( uri.toEncoded() ) ), + Soprano::Query::QueryLanguageSparql ); + while ( it.next() ) { + success = true; + properties.append( Property( it.binding( "p" ).uri() ) ); + } + + return success; +} + + +bool Nepomuk::Types::OntologyPrivate::addProperty( const QUrl&, const Soprano::Node& ) +{ + return false; +} + + +bool Nepomuk::Types::OntologyPrivate::addAncestorProperty( const QUrl&, const QUrl& ) +{ + return false; +} + + +void Nepomuk::Types::OntologyPrivate::reset( bool recursive ) +{ + EntityPrivate::reset( recursive ); + + if ( entitiesAvailable != -1 ) { + if ( recursive ) { + foreach( Class c, classes ) { + c.reset( true ); + } + foreach( Property p, properties ) { + p.reset( true ); + } + } + classes.clear(); + properties.clear(); + + entitiesAvailable = -1; + } +} + + + +Nepomuk::Types::Ontology::Ontology() +{ + d = new OntologyPrivate(); +} + + +Nepomuk::Types::Ontology::Ontology( const QUrl& uri ) +{ + d = EntityManager::self()->getOntology( uri ); +} + + +Nepomuk::Types::Ontology::Ontology( const Ontology& other ) + : Entity( other ) +{ +} + + +Nepomuk::Types::Ontology::~Ontology() +{ +} + + +Nepomuk::Types::Ontology& Nepomuk::Types::Ontology::operator=( const Ontology& other ) +{ + d = other.d; + return *this; +} + + +QList<Nepomuk::Types::Class> Nepomuk::Types::Ontology::allClasses() +{ + D->initEntities(); + return D->classes; +} + + +Nepomuk::Types::Class Nepomuk::Types::Ontology::findClassByName( const QString& name ) +{ + D->initEntities(); + for ( QList<Class>::const_iterator it = D->classes.constBegin(); + it != D->classes.constEnd(); ++it ) { + const Class& c = *it; + if ( c.name() == name ) { + return c; + } + } + + return Class(); +} + + +Nepomuk::Types::Class Nepomuk::Types::Ontology::findClassByLabel( const QString& label, const QString& language ) +{ + D->initEntities(); + for ( QList<Class>::iterator it = D->classes.begin(); + it != D->classes.end(); ++it ) { + Class& c = *it; + if ( c.label( language ) == label ) { + return c; + } + } + + return Class(); +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Ontology::allProperties() +{ + D->initEntities(); + return D->properties; +} + + +Nepomuk::Types::Property Nepomuk::Types::Ontology::findPropertyByName( const QString& name ) +{ + D->initEntities(); + for ( QList<Property>::const_iterator it = D->properties.constBegin(); + it != D->properties.constEnd(); ++it ) { + const Property& p = *it; + if ( p.name() == name ) { + return p; + } + } + + return Property(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Ontology::findPropertyByLabel( const QString& label, const QString& language ) +{ + D->initEntities(); + for ( QList<Property>::iterator it = D->properties.begin(); + it != D->properties.end(); ++it ) { + Property& p = *it; + if ( p.label( language ) == label ) { + return p; + } + } + + return Property(); +} + + + +// Start of code for deprecated Ontology +// ------------------------------------- +#include "global.h" +#include "ontologymanager.h" + + +Nepomuk::Ontology::Ontology() +{ + d = new Private; +} + + +Nepomuk::Ontology::Ontology( const Ontology& other ) +{ + d = other.d; +} + + +Nepomuk::Ontology::~Ontology() +{ +} + + +Nepomuk::Ontology& Nepomuk::Ontology::operator=( const Ontology& other) +{ + d = other.d; + return *this; +} + + +QUrl Nepomuk::Ontology::uri() const +{ + return d->uri; +} + + +QList<const Nepomuk::Class*> Nepomuk::Ontology::allClasses() const +{ + return d->classes.values(); +} + + +const Nepomuk::Class* Nepomuk::Ontology::findClassByName( const QString& name ) const +{ + for ( QHash<QUrl, const Class*>::const_iterator it = d->classes.constBegin(); + it != d->classes.constEnd(); ++it ) { + const Class* c = it.value(); + if ( c->name() == name ) { + return c; + } + } + + return 0; +} + + +const Nepomuk::Class* Nepomuk::Ontology::findClassByLabel( const QString& label, const QString& language ) const +{ + for ( QHash<QUrl, const Class*>::const_iterator it = d->classes.constBegin(); + it != d->classes.constEnd(); ++it ) { + const Class* c = it.value(); + if ( c->label( language ) == label ) { + return c; + } + } + + return 0; +} + + +const Nepomuk::Class* Nepomuk::Ontology::findClassByUri( const QUrl& uri ) const +{ + QHash<QUrl, const Class*>::const_iterator it = d->classes.find( uri ); + if ( it != d->classes.constEnd() ) { + return it.value(); + } + else { + return 0; + } +} + + +QList<const Nepomuk::Property*> Nepomuk::Ontology::allProperties() const +{ + return d->properties.values(); +} + + +const Nepomuk::Property* Nepomuk::Ontology::findPropertyByName( const QString& name ) const +{ + for ( QHash<QUrl, const Property*>::const_iterator it = d->properties.constBegin(); + it != d->properties.constEnd(); ++it ) { + const Property* p = it.value(); + if ( p->name() == name ) { + return p; + } + } + + return 0; +} + + +const Nepomuk::Property* Nepomuk::Ontology::findPropertyByLabel( const QString& label, const QString& language ) const +{ + for ( QHash<QUrl, const Property*>::const_iterator it = d->properties.constBegin(); + it != d->properties.constEnd(); ++it ) { + const Property* p = it.value(); + if ( p->label( language ) == label ) { + return p; + } + } + + return 0; +} + + +const Nepomuk::Property* Nepomuk::Ontology::findPropertyByUri( const QUrl& uri ) const +{ + QHash<QUrl, const Property*>::const_iterator it = d->properties.find( uri ); + if ( it != d->properties.constEnd() ) { + return it.value(); + } + else { + return 0; + } +} + + +const Nepomuk::Ontology* Nepomuk::Ontology::load( const QUrl& uri ) +{ + // load the ontology in the cache + return OntologyManager::instance()->getOntology( uri ); +} Modification de propriétés sur nepomuk/core/types/ontology.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/ontologymanager.h =================================================================== --- nepomuk/core/types/ontologymanager.h (révision 0) +++ nepomuk/core/types/ontologymanager.h (révision 0) @@ -0,0 +1,99 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ONTOLOGY_MANAGER_H_ +#define _NEPOMUK_ONTOLOGY_MANAGER_H_ + +#include <QtCore/QUrl> + +#include "nepomuk_export.h" + +namespace Soprano { + class Statement; +} + +namespace Nepomuk { + + class OntologyLoader; + class Ontology; + + /** + * The OntologyManager is the central ontology cache handler. + * It is modeled as a singleton and its instance can be accessed + * through OntologyManager::instance. + * + * \deprecated Ontologies should be handled via the classes in + * Nepomuk::Types. + */ + class KDE_DEPRECATED NEPOMUK_EXPORT OntologyManager + { + public: + ~OntologyManager(); + + static OntologyManager* instance(); + + /** + * Set an OntologyLoader to be used to retrieve + * the RDF statements that make up an ontology. + * + * By default Nepomuk uses a combination of the + * NepomukOntologyLoader and DesktopOntologyLoader + * where the NepomukOntologyLoader is the preferred + * one, i.e. only if it is not able to load the + * ontology DesktopOntologyLoader is used as a fallback. + * + * If an OntologyLoader is set no fallback loader will + * be used. Thus, to force one of the default loaders + * (for example the DesktopOntologyLoader) just do: + * + * \code + * OntologyManager::instance()->setOntologyLoader( new DesktopOntologyLoader() ); + * \endcode + * + * OntologyManager will take over ownership of loader. + * + * Overwriting the loader will delete any loader previously + * set via setOntologyLoader. + */ + void setOntologyLoader( OntologyLoader* loader ); + + /** + * Attempt to load the ontology referenced by uri. + * If the manager already has the ontology in the cache + * it is simply returned. Otherwise the manager tries + * to load the ontology from one of the configured + * OntologyLoader instances. + * + * \return The requested ontology or 0 in case it could + * not be found, i.e. none of the OntologyLoader instances + * could provide the RDF statements making up the ontology. + */ + const Ontology* getOntology( const QUrl& uri ); + + private: + OntologyManager(); + + Ontology* constructOntology( const QUrl& uri, const QList<Soprano::Statement>& sl ); + + class Private; + Private* const d; + }; +} + +#endif Modification de propriétés sur nepomuk/core/types/ontologymanager.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/entitymanager.h =================================================================== --- nepomuk/core/types/entitymanager.h (révision 0) +++ nepomuk/core/types/entitymanager.h (révision 0) @@ -0,0 +1,69 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_ENTITY_MANAGER_H_ +#define _NEPOMUK_ENTITY_MANAGER_H_ + +#include <QtCore/QHash> +#include <QtCore/QUrl> +#include <QtCore/QSharedData> +#include <QtCore/QMutex> + + +namespace Soprano { + class Statement; +} + +namespace Nepomuk { + namespace Types { + class EntityPrivate; + class ClassPrivate; + class PropertyPrivate; + class OntologyPrivate; + + /** + * Cache for all loaded entities. + */ + class EntityManager + { + public: + EntityManager(); + + ClassPrivate* getClass( const QUrl& uri ); + PropertyPrivate* getProperty( const QUrl& uri ); + OntologyPrivate* getOntology( const QUrl& uri ); + + static EntityManager* self(); + + private: + EntityPrivate* findEntity( const QUrl& uri ) const; + ClassPrivate* findClass( const QUrl& uri ) const; + PropertyPrivate* findProperty( const QUrl& uri ) const; + OntologyPrivate* findOntology( const QUrl& uri ) const; + + QHash<QUrl, QExplicitlySharedDataPointer<ClassPrivate> > m_classMap; + QHash<QUrl, QExplicitlySharedDataPointer<PropertyPrivate> > m_propertyMap; + QHash<QUrl, QExplicitlySharedDataPointer<OntologyPrivate> > m_ontologyMap; + + QMutex m_mutex; + }; + } +} + +#endif Modification de propriétés sur nepomuk/core/types/entitymanager.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/entity.cpp =================================================================== --- nepomuk/core/types/entity.cpp (révision 0) +++ nepomuk/core/types/entity.cpp (révision 0) @@ -0,0 +1,387 @@ +/* This file is part of the Nepomuk-KDE libraries + Copyright (c) 2007-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "entity.h" +#include "entity_p.h" +#include "resourcemanager.h" + +#include <QtCore/QHash> +#include <QtCore/QMutexLocker> + +#include <Soprano/QueryResultIterator> +#include <Soprano/Model> +#include <Soprano/Vocabulary/NRL> +#include <Soprano/Vocabulary/NAO> +#include <Soprano/Vocabulary/RDFS> + +#include <kicon.h> + + +Nepomuk::Types::EntityPrivate::EntityPrivate( const QUrl& uri_ ) + : uri( uri_ ), + available( uri_.isValid() ? -1 : 0 ), + ancestorsAvailable( uri_.isValid() ? -1 : 0 ) +{ +} + + +void Nepomuk::Types::EntityPrivate::init() +{ + QMutexLocker lock( &mutex ); + + if ( available < 0 ) { + available = load() ? 1 : 0; + } +} + + +void Nepomuk::Types::EntityPrivate::initAncestors() +{ + QMutexLocker lock( &mutex ); + + if ( ancestorsAvailable < 0 ) { + ancestorsAvailable = loadAncestors() ? 1 : 0; + } +} + + +bool Nepomuk::Types::EntityPrivate::load() +{ + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?p ?o where { " + "graph ?g { <%1> ?p ?o . } . " + "{ ?g a <%2> . } UNION { ?g a <%3> . } . }") + .arg( QString::fromAscii( uri.toEncoded() ) ) + .arg( Soprano::Vocabulary::NRL::Ontology().toString() ) + .arg( Soprano::Vocabulary::NRL::KnowledgeBase().toString() ), + Soprano::Query::QueryLanguageSparql ); + bool success = false; + while ( it.next() ) { + success = true; + QUrl property = it.binding( "p" ).uri(); + Soprano::Node value = it.binding( "o" ); + + if ( property == Soprano::Vocabulary::RDFS::label() ) { + if ( value.language().isEmpty() ) { + label = value.toString(); + } + else if( value.language() == KGlobal::locale()->language() ) { + l10nLabel = value.toString(); + } + } + + else if ( property == Soprano::Vocabulary::RDFS::comment() ) { + if ( value.language().isEmpty() ) { + comment = value.toString(); + } + else if( value.language() == KGlobal::locale()->language() ) { + l10nComment = value.toString(); + } + } + + else if ( property == Soprano::Vocabulary::NAO::hasSymbol() ) { + icon = KIcon( value.toString() ); + } + + else { + addProperty( property, value ); + } + } + + return success; +} + + +bool Nepomuk::Types::EntityPrivate::loadAncestors() +{ + Soprano::QueryResultIterator it + = ResourceManager::instance()->mainModel()->executeQuery( QString("select ?s ?p where { " + "graph ?g { ?s ?p <%1> . } . " + "{ ?g a <%2> . } UNION { ?g a <%3> . } . }") + .arg( QString::fromAscii( uri.toEncoded() ) ) + .arg( Soprano::Vocabulary::NRL::Ontology().toString() ) + .arg( Soprano::Vocabulary::NRL::KnowledgeBase().toString() ), + Soprano::Query::QueryLanguageSparql ); + bool success = false; + while ( it.next() ) { + success = true; + addAncestorProperty( it.binding( "s" ).uri(), it.binding( "p" ).uri() ); + } + + return success; +} + + + +void Nepomuk::Types::EntityPrivate::reset( bool ) +{ + QMutexLocker lock( &mutex ); + + label.truncate(0); + comment.truncate(0); + l10nLabel.truncate(0); + l10nComment.truncate(0);; + + icon = QIcon(); + + available = -1; + ancestorsAvailable = -1; +} + + +Nepomuk::Types::Entity::Entity() +{ +} + + +Nepomuk::Types::Entity::Entity( const Entity& other ) +{ + d = other.d; +} + + +Nepomuk::Types::Entity::~Entity() +{ +} + + +Nepomuk::Types::Entity& Nepomuk::Types::Entity::operator=( const Entity& other ) +{ + d = other.d; + return *this; +} + + +QUrl Nepomuk::Types::Entity::uri() const +{ + return d ? d->uri : QUrl(); +} + + +QString Nepomuk::Types::Entity::name() const +{ + return d ? (d->uri.fragment().isEmpty() ? d->uri.toString().section('/',-1) : d->uri.fragment() ) : QString(); +} + + +QString Nepomuk::Types::Entity::label( const QString& language ) +{ + if ( d ) { + d->init(); + + if ( language == KGlobal::locale()->language() && + !d->l10nLabel.isEmpty() ) { + return d->l10nLabel; + } + else if( !d->label.isEmpty() ) { + return d->label; + } + else { + return name(); + } + } + else { + return QString(); + } +} + + +QString Nepomuk::Types::Entity::label( const QString& language ) const +{ + return const_cast<Entity*>(this)->label( language ); +} + + +QString Nepomuk::Types::Entity::comment( const QString& language ) +{ + if ( d ) { + d->init(); + + if ( language == KGlobal::locale()->language() && + !d->l10nComment.isEmpty() ) { + return d->l10nComment; + } + else { + return d->comment; + } + } + else { + return QString(); + } +} + + +QString Nepomuk::Types::Entity::comment( const QString& language ) const +{ + return const_cast<Entity*>(this)->comment( language ); +} + + +QIcon Nepomuk::Types::Entity::icon() +{ + if ( d ) { + d->init(); + + return d->icon; + } + else { + return QIcon(); + } +} + + +QIcon Nepomuk::Types::Entity::icon() const +{ + return const_cast<Entity*>(this)->icon(); +} + + +bool Nepomuk::Types::Entity::isValid() const +{ + return d ? d->uri.isValid() : false; +} + + +bool Nepomuk::Types::Entity::isAvailable() +{ + if ( d ) { + d->init(); + return d->available == 1; + } + else { + return false; + } +} + + +bool Nepomuk::Types::Entity::isAvailable() const +{ + return const_cast<Entity*>(this)->isAvailable(); +} + + +void Nepomuk::Types::Entity::reset( bool recursive ) +{ + d->reset( recursive ); +} + + +bool Nepomuk::Types::Entity::operator==( const Entity& other ) const +{ + // since we use one instace cache we can improve comparation operations + // intensly by not comparing URLs but pointers. + return( d.constData() == other.d.constData() ); +} + + +bool Nepomuk::Types::Entity::operator==( const QUrl& other ) const +{ + // since we use one instace cache we can improve comparation operations + // intensly by not comparing URLs but pointers. + return( d.constData()->uri == other ); +} + + +bool Nepomuk::Types::Entity::operator!=( const Entity& other ) const +{ + // since we use one instace cache we can improve comparation operations + // intensly by not comparing URLs but pointers. + return( d.constData() != other.d.constData() ); +} + + +bool Nepomuk::Types::Entity::operator!=( const QUrl& other ) const +{ + // since we use one instace cache we can improve comparation operations + // intensly by not comparing URLs but pointers. + return( d.constData()->uri != other ); +} + + + +#ifndef DISABLE_NEPOMUK_LEGACY + +// Code for old deprecated Entity class +// ------------------------------------------- +Nepomuk::Entity::Entity() +{ + d = new Private(); +} + +Nepomuk::Entity::Entity( const Entity& other ) +{ + d = other.d; +} + + +Nepomuk::Entity::~Entity() +{ +} + + +Nepomuk::Entity& Nepomuk::Entity::operator=( const Entity& other ) +{ + d = other.d; + return *this; +} + + +const Nepomuk::Ontology* Nepomuk::Entity::definingOntology() const +{ + return d->ontology; +} + + +QUrl Nepomuk::Entity::uri() const +{ + return d->uri; +} + + +QString Nepomuk::Entity::name() const +{ + return d->uri.fragment(); +} + + +QString Nepomuk::Entity::label( const QString& language ) const +{ + QHash<QString, QString>::const_iterator it = d->l10nLabels.find( language ); + if ( it != d->l10nLabels.constEnd() ) { + return it.value(); + } + else { + return d->label; + } +} + + +QString Nepomuk::Entity::comment( const QString& language ) const +{ + QHash<QString, QString>::const_iterator it = d->l10nComments.find( language ); + if ( it != d->l10nComments.constEnd() ) { + return it.value(); + } + else { + return d->comment; + } +} + +#endif // DISABLE_NEPOMUK_LEGACY + Modification de propriétés sur nepomuk/core/types/entity.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/README =================================================================== --- nepomuk/core/types/README (révision 0) +++ nepomuk/core/types/README (révision 0) @@ -0,0 +1,9 @@ +Konto provides a slightly simplified view on ontologies defined using the NRL +ontology description language. + +Konto provides three classes: Konto::Ontology, Konto::Class, and Konto::Property +whiche can be used to explore an ontology including internationalized names and +comments if available. + +The ontologies are read from the Nepomuk RDF data store or the default ontology +installation folder (see OntologyLoader subclasses). Index: nepomuk/core/types/property.cpp =================================================================== --- nepomuk/core/types/property.cpp (révision 0) +++ nepomuk/core/types/property.cpp (révision 0) @@ -0,0 +1,560 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "property.h" +#include "property_p.h" +#include "class.h" +#include "ontology.h" +#include "literal.h" +#include "entitymanager.h" + +#include <Soprano/Vocabulary/RDFS> +#include <Soprano/Vocabulary/NRL> +#include <Soprano/Vocabulary/XMLSchema> + +#undef D +#define D static_cast<Nepomuk::Types::PropertyPrivate*>( d.data() ) + +Nepomuk::Types::PropertyPrivate::PropertyPrivate( const QUrl& uri ) + : EntityPrivate( uri ), + minCardinality( -1 ), + maxCardinality( -1 ), + cardinality( -1 ) +{ +} + + +bool Nepomuk::Types::PropertyPrivate::addProperty( const QUrl& property, const Soprano::Node& value ) +{ + if( property == Soprano::Vocabulary::RDFS::subPropertyOf() ) { + parents.append( value.uri() ); + return true; + } + + else if( property == Soprano::Vocabulary::RDFS::domain() ) { + domain = value.uri(); + return true; + } + + else if( property == Soprano::Vocabulary::RDFS::range() ) { + if ( value.toString().startsWith( Soprano::Vocabulary::XMLSchema::xsdNamespace().toString() ) ) { + literalRange = Literal( value.uri() ); + } + else if ( value.uri() == Soprano::Vocabulary::RDFS::Literal()) { + literalRange = Literal( value.uri() ); + } + else { + range = value.uri(); + } + return true; + } + + else if( property == Soprano::Vocabulary::NRL::minCardinality() ) { + minCardinality = value.literal().toInt(); + return true; + } + + else if( property == Soprano::Vocabulary::NRL::maxCardinality() ) { + maxCardinality = value.literal().toInt(); + return true; + } + + else if ( property == Soprano::Vocabulary::NRL::cardinality() ) { + cardinality = value.literal().toInt(); + return true; + } + + else if ( property == Soprano::Vocabulary::NRL::inverseProperty() ) { + inverse = value.uri(); + return true; + } + + return false; +} + + +bool Nepomuk::Types::PropertyPrivate::addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ) +{ + if( property == Soprano::Vocabulary::RDFS::subPropertyOf() ) { + children.append( ancestorResource ); + return true; + } + else if ( property == Soprano::Vocabulary::NRL::inverseProperty() ) { + inverse = ancestorResource; + return true; + } + + return false; +} + + +void Nepomuk::Types::PropertyPrivate::reset( bool recursive ) +{ + EntityPrivate::reset( recursive ); + + QMutexLocker lock( &mutex ); + + if ( available != -1 ) { + if ( recursive ) { + range.reset( true ); + domain.reset( true ); + inverse.reset( true ); + foreach( Property p, parents ) { + p.reset( true ); + } + } + + parents.clear(); + available = -1; + } + + if ( ancestorsAvailable != -1 ) { + if ( recursive ) { + foreach( Property p, children ) { + p.reset( true ); + } + } + + children.clear(); + ancestorsAvailable = -1; + } +} + + + +Nepomuk::Types::Property::Property() + : Entity() +{ + d = 0; +} + + +Nepomuk::Types::Property::Property( const QUrl& uri ) + : Entity() +{ + d = EntityManager::self()->getProperty( uri ); +} + + +Nepomuk::Types::Property::Property( const Property& other ) + : Entity( other ) +{ +} + + +Nepomuk::Types::Property::~Property() +{ +} + + +Nepomuk::Types::Property& Nepomuk::Types::Property::operator=( const Property& other ) +{ + d = other.d; + return *this; +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Property::parentProperties() +{ + if ( d ) { + D->init(); + return D->parents; + } + else { + return QList<Nepomuk::Types::Property>(); + } +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Property::parentProperties() const +{ + return const_cast<Property*>(this)->parentProperties(); +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Property::subProperties() +{ + if ( d ) { + D->initAncestors(); + return D->children; + } + else { + return QList<Nepomuk::Types::Property>(); + } +} + + +QList<Nepomuk::Types::Property> Nepomuk::Types::Property::subProperties() const +{ + return const_cast<Property*>(this)->subProperties(); +} + + +Nepomuk::Types::Property Nepomuk::Types::Property::inverseProperty() +{ + if ( d ) { + D->init(); + D->initAncestors(); + return D->inverse; + } + else { + return Property(); + } +} + + +Nepomuk::Types::Property Nepomuk::Types::Property::inverseProperty() const +{ + return const_cast<Property*>(this)->inverseProperty(); +} + + +Nepomuk::Types::Class Nepomuk::Types::Property::range() +{ + if ( d ) { + D->init(); + + if( D->range.isValid() ) { + return D->range; + } + else if( !literalRangeType().isValid() ) { + // try getting a domain from one of the parent properties + for( int i = 0; i < D->parents.count(); ++i ) { + Class pr = D->parents[i].range(); + if( pr.isValid() ) { + return pr; + } + } + + // if we have no literal range type, we fall back to rdfs:Resource + return Class( Soprano::Vocabulary::RDFS::Resource() ); + } + else { + // other than domain() we do not use a general fallback since the range + // might be a literalRangeType() + return Class(); + } + } + else { + return Class(); + } +} + + +Nepomuk::Types::Class Nepomuk::Types::Property::range() const +{ + return const_cast<Property*>(this)->range(); +} + + +Nepomuk::Types::Literal Nepomuk::Types::Property::literalRangeType() +{ + if ( d ) { + D->init(); + + if( D->literalRange.isValid() ) { + return D->literalRange; + } + else { + // try getting a domain from one of the parent properties + // We cannot check the resource range here since that would + // result in an endless loop + for( int i = 0; i < D->parents.count(); ++i ) { + Literal pr = D->parents[i].literalRangeType(); + if( pr.isValid() ) { + return pr; + } + } + + // fallback is an invalid range which will then result in + // range() returning a valid one + return Literal(); + } + } + else { + return Literal(); + } +} + + +Nepomuk::Types::Literal Nepomuk::Types::Property::literalRangeType() const +{ + return const_cast<Property*>(this)->literalRangeType(); +} + + +Nepomuk::Types::Class Nepomuk::Types::Property::domain() +{ + if ( d ) { + D->init(); + + if( D->domain.isValid() ) { + return D->domain; + } + else { + // try getting a domain from one of the parent properties + for( int i = 0; i < D->parents.count(); ++i ) { + Class pd = D->parents[i].domain(); + if( pd.isValid() ) { + return pd; + } + } + + // fallback: rdfs:Resource + return Class( Soprano::Vocabulary::RDFS::Resource() ); + } + } + else { + return Class(); + } +} + + +Nepomuk::Types::Class Nepomuk::Types::Property::domain() const +{ + return const_cast<Property*>(this)->domain(); +} + + +int Nepomuk::Types::Property::cardinality() +{ + if ( d ) { + D->init(); + return D->cardinality; + } + else { + return -1; + } +} + + +int Nepomuk::Types::Property::cardinality() const +{ + return const_cast<Property*>(this)->cardinality(); +} + + +int Nepomuk::Types::Property::minCardinality() +{ + if ( d ) { + D->init(); + if ( D->minCardinality > 0 ) { + return D->minCardinality; + } + else { + return D->cardinality; + } + } + else { + return -1; + } +} + + +int Nepomuk::Types::Property::minCardinality() const +{ + return const_cast<Property*>(this)->minCardinality(); +} + + +int Nepomuk::Types::Property::maxCardinality() +{ + if ( d ) { + D->init(); + if ( D->maxCardinality > 0 ) { + return D->maxCardinality; + } + else { + return D->cardinality; + } + } + else { + return -1; + } +} + + +int Nepomuk::Types::Property::maxCardinality() const +{ + return const_cast<Property*>(this)->maxCardinality(); +} + + +bool Nepomuk::Types::Property::isParentOf( const Property& other ) +{ + if ( d ) { + D->initAncestors(); + + if ( D->children.contains( other ) ) { + return true; + } + else { + for ( QList<Nepomuk::Types::Property>::iterator it = D->children.begin(); + it != D->children.end(); ++it ) { + if ( ( *it ).isParentOf( other ) ) { + return true; + } + } + } + } + + return false; +} + + +bool Nepomuk::Types::Property::isParentOf( const Property& other ) const +{ + return const_cast<Property*>(this)->isParentOf( other ); +} + + +bool Nepomuk::Types::Property::isSubPropertyOf( const Property& other ) +{ + if ( d ) { + D->init(); + + if ( D->parents.contains( other ) ) { + return true; + } + else { + for ( QList<Nepomuk::Types::Property>::iterator it = D->parents.begin(); + it != D->parents.end(); ++it ) { + if ( ( *it ).isSubPropertyOf( other ) ) { + return true; + } + } + } + } + + return false; +} + + +bool Nepomuk::Types::Property::isSubPropertyOf( const Property& other ) const +{ + return const_cast<Property*>(this)->isSubPropertyOf( other ); +} + + + +#ifndef DISABLE_NEPOMUK_LEGACY + +// Start of code for deprecated Property +// ------------------------------------- +#include "global.h" +#include "ontologymanager.h" + +Nepomuk::Property::Property() + : Entity() +{ + d = new Private(); +} + + +Nepomuk::Property::Property( const Property& other ) + : Entity( other ) +{ + d = other.d; +} + + +Nepomuk::Property::~Property() +{ +} + + +Nepomuk::Property& Nepomuk::Property::operator=( const Property& other ) +{ + d = other.d; + return *this; +} + + +QList<const Nepomuk::Property*> Nepomuk::Property::parentProperties() const +{ + return d->parents; +} + + +QList<const Nepomuk::Property*> Nepomuk::Property::parentOf() const +{ + return d->children; +} + + +const Nepomuk::Property* Nepomuk::Property::inverseProperty() const +{ + return d->inverse; +} + + +const Nepomuk::Class* Nepomuk::Property::range() const +{ + return d->range; +} + + +Nepomuk::Literal Nepomuk::Property::literalRangeType() const +{ + return d->literalRange; +} + + +const Nepomuk::Class* Nepomuk::Property::domain() const +{ + return d->domain; +} + + +int Nepomuk::Property::cardinality() const +{ + return d->cardinality; +} + + +int Nepomuk::Property::minCardinality() const +{ + return d->minCardinality; +} + + +int Nepomuk::Property::maxCardinality() const +{ + return d->maxCardinality; +} + + +const Nepomuk::Property* Nepomuk::Property::load( const QUrl& uri ) +{ + QUrl ns = extractNamespace( uri ); + + // load the ontology in the cache + const Ontology* ont = OntologyManager::instance()->getOntology( ns ); + + // return the requested class or an invalid one if the ontology + // was not found + if ( ont ) { + return ont->findPropertyByUri( uri ); + } + else { + return 0; + } +} + +#endif // DISABLE_NEPOMUK_LEGACY Modification de propriétés sur nepomuk/core/types/property.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/class_p.h =================================================================== --- nepomuk/core/types/class_p.h (révision 0) +++ nepomuk/core/types/class_p.h (révision 0) @@ -0,0 +1,84 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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_CLASS_PRIVATE_H_ +#define _NEPOMUK_CLASS_PRIVATE_H_ + +#include "entity_p.h" +#include "class.h" +#include "property.h" + +#include <QtCore/QHash> +#include <QtCore/QSharedData> + + +namespace Nepomuk { + namespace Types { + class ClassPrivate : public EntityPrivate + { + public: + ClassPrivate( const QUrl& uri = QUrl() ); + + QList<Property> domainOf; + QList<Property> rangeOf; + + QList<Class> parents; + QList<Class> children; + + // -1 - unknown + // 0 - no + // 1 - yes + int propertiesAvailable; + + bool addProperty( const QUrl& property, const Soprano::Node& value ); + bool addAncestorProperty( const QUrl& ancestorResource, const QUrl& property ); + + void initProperties(); + bool loadProperties(); + + void reset( bool recursive ); + + // recursively find all parent or sub classes but stop at requestingClass to avoid endless loops + QSet<Class> findParentClasses( ClassPrivate* requestingClass ); + QSet<Class> findSubClasses( ClassPrivate* requestingClass ); + + protected: + virtual bool load(); + virtual bool loadAncestors(); + }; + } +} + + +namespace Nepomuk { + + class Property; + + class Class::Private : public QSharedData + { + public: + QHash<QUrl, const Property*> domainOf; + QHash<QUrl, const Property*> rangeOf; + + QList<const Nepomuk::Class*> parents; + QList<const Nepomuk::Class*> children; + }; +} + +#endif Modification de propriétés sur nepomuk/core/types/class_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/desktopontologyloader.cpp =================================================================== --- nepomuk/core/types/desktopontologyloader.cpp (révision 0) +++ nepomuk/core/types/desktopontologyloader.cpp (révision 0) @@ -0,0 +1,114 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "desktopontologyloader.h" +#include "fileontologyloader.h" + +#include <kstandarddirs.h> +#include <kdesktopfile.h> +#include <kconfiggroup.h> +#include <kdebug.h> +#include <kglobal.h> + +#include <QtCore/QDir> + +#include <soprano/statement.h> + +struct OntoBuffer +{ + QString fileName; + Soprano::RdfSerialization serialization; +}; + + +class Nepomuk::DesktopOntologyLoader::Private +{ +public: + Private() { + } + + void updateOntologyCache() { +// ontoCache.clear(); + + QStringList allOntologies = KGlobal::dirs()->findAllResources( "data", "nepomuk/ontologies/*.desktop" ); + foreach( const QString &ontoDesktopFilePath, allOntologies ) { + KDesktopFile ontoDesktopFile( ontoDesktopFilePath ); + + if ( ontoDesktopFile.hasLinkType() ) { + QUrl uri = ontoDesktopFile.readUrl(); + + if ( !ontoCache.contains( uri ) ) { + QString path = ontoDesktopFile.readPath(); + + // make it an absolute path + if ( path[0] != QDir::separator() ) { + path.prepend( ontoDesktopFilePath.section( QDir::separator(), + 0, -2, + QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep ) ); + } + + OntoBuffer onto; + onto.fileName = path; + onto.serialization = Soprano::mimeTypeToSerialization( ontoDesktopFile.desktopGroup().readEntry( "MimeType", "application/rdf+xml" ) ); + + kDebug() << "(Nepomuk::DesktopOntologyLoader) found ontology " << uri; + ontoCache.insert( uri, onto ); + } + } + } + } + + // contains the filename for each cached ontology + QHash<QUrl, OntoBuffer> ontoCache; +}; + + +Nepomuk::DesktopOntologyLoader::DesktopOntologyLoader() + : OntologyLoader(), + d( new Private() ) +{ +} + + +Nepomuk::DesktopOntologyLoader::~DesktopOntologyLoader() +{ + delete d; +} + + +QList<QUrl> Nepomuk::DesktopOntologyLoader::allOntologies() +{ + d->updateOntologyCache(); + return d->ontoCache.keys(); +} + + +QList<Soprano::Statement> Nepomuk::DesktopOntologyLoader::loadOntology( const QUrl& url ) +{ + d->updateOntologyCache(); + if ( d->ontoCache.contains( url ) ) { + const OntoBuffer& onto = d->ontoCache[url]; + FileOntologyLoader loader( onto.fileName, onto.serialization ); + return loader.loadOntology( url ); + } + else { + kDebug() << "(Nepomuk::DesktopOntologyLoader) could not find ontology " << url; + return QList<Soprano::Statement>(); + } +} Modification de propriétés sur nepomuk/core/types/desktopontologyloader.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/types/literal.cpp =================================================================== --- nepomuk/core/types/literal.cpp (révision 0) +++ nepomuk/core/types/literal.cpp (révision 0) @@ -0,0 +1,181 @@ +/* This file is part of the Nepomuk-KDE libraries + 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 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 "literal.h" +#include "literal_p.h" + +#include <QtCore/QHash> +#include <QtCore/QVariant> + +#include <Soprano/Vocabulary/RDFS> + +#include <kglobal.h> + + +namespace { +typedef QHash<QString, QVariant::Type> XmlSchemaMap; + +K_GLOBAL_STATIC(XmlSchemaMap, s_xmlSchemaTypes) + +void initXmlSchemaTypes() { + if( s_xmlSchemaTypes->isEmpty() ) { + s_xmlSchemaTypes->insert( "int", QVariant::Int ); + s_xmlSchemaTypes->insert( "integer", QVariant::Int ); + s_xmlSchemaTypes->insert( "negativeInteger", QVariant::Int ); + s_xmlSchemaTypes->insert( "decimal", QVariant::Int ); + s_xmlSchemaTypes->insert( "short", QVariant::Int ); + s_xmlSchemaTypes->insert( "long", QVariant::LongLong ); + s_xmlSchemaTypes->insert( "unsignedInt", QVariant::UInt ); + s_xmlSchemaTypes->insert( "unsignedShort", QVariant::UInt ); + s_xmlSchemaTypes->insert( "unsignedLong", QVariant::ULongLong ); + s_xmlSchemaTypes->insert( "boolean", QVariant::Bool ); + s_xmlSchemaTypes->insert( "double", QVariant::Double ); + s_xmlSchemaTypes->insert( "float", QVariant::Double ); + s_xmlSchemaTypes->insert( "string", QVariant::String ); + s_xmlSchemaTypes->insert( "date", QVariant::Date ); + s_xmlSchemaTypes->insert( "time", QVariant::Time ); + s_xmlSchemaTypes->insert( "dateTime", QVariant::DateTime ); + // s_xmlSchemaTypes->insert( "", QVariant::Url ); + } +} + +const XmlSchemaMap& xmlSchemaTypes() +{ + if(s_xmlSchemaTypes->isEmpty()) + initXmlSchemaTypes(); + return *s_xmlSchemaTypes; +} +} + + +Nepomuk::Types::Literal::Literal() +{ + d = new Private(); +} + + +Nepomuk::Types::Literal::Literal( const Literal& other ) +{ + d = other.d; +} + + +Nepomuk::Types::Literal::Literal( const QUrl& dataType ) +{ + d = new Private(); + d->dataTypeUri = dataType; + + // now determine the QVariant type + initXmlSchemaTypes(); + + // check if it is a known type, otherwise leave it as QVariant::Invalid + if ( dataType == Soprano::Vocabulary::RDFS::Literal() ) { + d->dataType = QVariant::String; + } + else { + QHash<QString, QVariant::Type>::const_iterator it = xmlSchemaTypes().constFind( dataType.fragment() ); + if ( it != xmlSchemaTypes().constEnd() ) { + d->dataType = it.value(); + } + } +} + + +Nepomuk::Types::Literal::~Literal() +{ +} + + +Nepomuk::Types::Literal& Nepomuk::Types::Literal::operator=( const Literal& other ) +{ + d = other.d; + return *this; +} + + +QUrl Nepomuk::Types::Literal::dataTypeUri() const +{ + return d->dataTypeUri; +} + + +QVariant::Type Nepomuk::Types::Literal::dataType() const +{ + return d->dataType; +} + + +bool Nepomuk::Types::Literal::isValid() const +{ + return d->dataTypeUri.isValid(); +} + + + + +Nepomuk::Literal::Literal() +{ + d = new Private(); +} + + +Nepomuk::Literal::Literal( const Literal& other ) +{ + d = other.d; +} + + +Nepomuk::Literal::Literal( const QUrl& dataType ) +{ + d = new Private(); + d->dataTypeUri = dataType; + + // now determine the QVariant type + initXmlSchemaTypes(); + + // check if it is a known type, otherwise leave it as QVariant::Invalid + QHash<QString, QVariant::Type>::const_iterator it = xmlSchemaTypes().constFind( dataType.fragment() ); + if ( it != xmlSchemaTypes().constEnd() ) { + d->dataType = it.value(); + } +} + + +Nepomuk::Literal::~Literal() +{ +} + + +Nepomuk::Literal& Nepomuk::Literal::operator=( const Literal& other ) +{ + d = other.d; + return *this; +} + + +const QUrl& Nepomuk::Literal::dataTypeUri() const +{ + return d->dataTypeUri; +} + + +QVariant::Type Nepomuk::Literal::dataType() const +{ + return d->dataType; +} Modification de propriétés sur nepomuk/core/types/literal.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/resourcedata.h =================================================================== --- nepomuk/core/resourcedata.h (révision 1130118) +++ nepomuk/core/resourcedata.h (copie de travail) @@ -26,6 +26,7 @@ #include <QtCore/QHash> #include <QtCore/QMutex> #include <QtCore/QAtomicInt> +#include <QtCore/QSet> #include "variant.h" #include "thing.h" @@ -37,19 +38,25 @@ namespace Nepomuk { + class Resource; class ResourceManagerPrivate; class ResourceData { public: - explicit ResourceData( const QUrl& uri, const QString& kickoffId_, const QUrl& type_, ResourceManagerPrivate* rm ); + explicit ResourceData( const QUrl& uri, const QUrl& kickOffUri, const QUrl& type_, ResourceManagerPrivate* rm ); ~ResourceData(); - inline bool ref() { + inline bool ref(Nepomuk::Resource* res) { + QMutexLocker lock(&m_resourcesMutex); + m_resources.push_back( res ); return m_ref.ref(); } - inline bool deref() { + + inline bool deref(Nepomuk::Resource* res) { + QMutexLocker lock(&m_resourcesMutex); + m_resources.removeAll( res ); return m_ref.deref(); } @@ -64,7 +71,6 @@ /** * The URI of the resource. This might be empty if the resource was not synced yet. - * \sa kickoffUriOrId */ QUrl uri() const; @@ -82,6 +88,8 @@ bool hasProperty( const QUrl& uri ); + bool hasProperty( const QUrl& p, const Variant& v ); + /** * Does also check for subClass relations. */ @@ -136,9 +144,17 @@ /** * Searches for the resource in the Nepomuk store using m_kickoffId and m_kickoffUri. * - * \returns true if the resource was found and m_uri is set, false otherwise. + * This will either get the actual resource URI from the database + * and add m_data into ResourceManagerPrivate::m_initializedData + * or it will find another ResourceData instance in m_initializedData + * which represents the same resource. The ResourceData that should be + * used is returned. + * + * \returns The initialized ResourceData object representing the actual resource. + * + * m_determineUriMutex needs to be locked before calling this method */ - bool determineUri(); + ResourceData* determineUri(); void invalidateCache(); @@ -153,8 +169,18 @@ ResourceManagerPrivate* rm() const { return m_rm; } - ResourceData* proxy() const { return m_proxyData; } + /// Contains a list of resources which use this ResourceData + QList<Resource*> m_resources; + /// the URI that was used to construct the resource. Will be used by determineUri + /// to find the actual resource URI which is either m_kickoffUri itself or + /// a resource URI which relates to m_kickoffUri by nie:url + /// This is a set since Resource::determineFinalResourceData may add additional uris + QSet<KUrl> m_kickoffUris; + + /// Needs to be locked before calling determineUri() + QMutex m_determineUriMutex; + private: void loadType( const QUrl& type ); @@ -162,36 +188,23 @@ /// Used by remove() and deleteData() void resetAll( bool isDelete = false ); - /// identifier that was used to construct the resource. Will be used by determineUri - /// to check for nao:identifiers or even nie:urls. - QString m_kickoffId; + /// Updates both m_kickoffUris and ResourceMangerPrivate's list + void updateKickOffLists( const QUrl & prop, const QUrl & newUri ); - /// the URI that was used to construct the resource. Will be used by determineUri - /// to find the actual resource URI which is either m_kickoffUri itself or - /// a resource URI which relates to m_kickoffUri by nie:url - KUrl m_kickoffUri; - /// final resource URI created by determineUri KUrl m_uri; /// the URL of file resources - KUrl m_fileUrl; + KUrl m_nieUrl; QUrl m_mainType; QList<QUrl> m_types; QAtomicInt m_ref; - QMutex m_determineUriMutex; mutable QMutex m_modificationMutex; - /** - * Used to virtually merge two data objects representing the same - * resource. This happens if the resource was once created using its - * actual URI and once via its ID. To prevent early loading we allow - * this scenario. - */ - ResourceData* m_proxyData; + QMutex m_resourcesMutex; QHash<QUrl, Variant> m_cache; bool m_cacheDirty; Index: nepomuk/core/resource.cpp =================================================================== --- nepomuk/core/resource.cpp (révision 1130118) +++ nepomuk/core/resource.cpp (copie de travail) @@ -26,9 +26,11 @@ #include "tag.h" #include "pimo.h" #include "thing.h" +#include "property.h" #include "nfo.h" #include "nie.h" #include "nco.h" +#include "nuao.h" #include <klocale.h> #include <kdebug.h> @@ -36,6 +38,8 @@ #include <Soprano/Vocabulary/NAO> #include <Soprano/Vocabulary/Xesam> #include <Soprano/Vocabulary/RDFS> +#include <Soprano/Model> +#include <Soprano/QueryResultIterator> #include <kmimetype.h> @@ -43,14 +47,16 @@ Nepomuk::Resource::Resource() { m_data = ResourceManager::instance()->d->data( QUrl(), QUrl() ); - m_data->ref(); + if ( m_data ) + m_data->ref( this ); } Nepomuk::Resource::Resource( ResourceManager* manager ) { m_data = manager->d->data( QUrl(), QUrl() ); - m_data->ref(); + if ( m_data ) + m_data->ref( this ); } @@ -58,7 +64,7 @@ { m_data = res.m_data; if ( m_data ) - m_data->ref(); + m_data->ref( this ); } @@ -66,7 +72,7 @@ { m_data = ResourceManager::instance()->d->data( uri, type ); if ( m_data ) - m_data->ref(); + m_data->ref( this ); } @@ -74,7 +80,7 @@ { m_data = manager->d->data( uri, type ); if ( m_data ) - m_data->ref(); + m_data->ref( this ); } @@ -82,7 +88,7 @@ { m_data = ResourceManager::instance()->d->data( uri, type ); if ( m_data ) - m_data->ref(); + m_data->ref( this ); } @@ -90,7 +96,7 @@ { m_data = ResourceManager::instance()->d->data( uri, type ); if ( m_data ) - m_data->ref(); + m_data->ref( this ); } @@ -98,7 +104,7 @@ { m_data = manager->d->data( uri, type ); if ( m_data ) - m_data->ref(); + m_data->ref( this ); } @@ -106,26 +112,16 @@ { m_data = data; if ( m_data ) - data->ref(); + m_data->ref( this ); } Nepomuk::Resource::~Resource() { if ( m_data ) { - if ( !m_data->deref() ) { - // - // We delete data objects in one of three cases: - // 1. They are not valid and as such not in one of the ResourceManagerPrivate kickoff lists - // 2. They have a proxy which is the actual thing to reuse later on - // 3. The cache is already full and we need to clean up - // - if ( !m_data->isValid() || - m_data->proxy() || - m_data->rm()->dataCacheFull() ) { - delete m_data; - } - } + m_data->deref( this ); + if ( m_data->rm()->shouldBeDeleted( m_data ) ) + delete m_data; } } @@ -133,12 +129,12 @@ Nepomuk::Resource& Nepomuk::Resource::operator=( const Resource& res ) { if( m_data != res.m_data ) { - if ( m_data && !m_data->deref() && !m_data->isValid() ) { + if ( m_data && !m_data->deref( this ) && m_data->rm()->shouldBeDeleted( m_data ) ) { delete m_data; } m_data = res.m_data; if ( m_data ) - m_data->ref(); + m_data->ref( this ); } return *this; @@ -166,7 +162,7 @@ QUrl Nepomuk::Resource::resourceUri() const { if ( m_data ) { - m_data->determineUri(); + determineFinalResourceData(); return m_data->uri(); } else { @@ -183,46 +179,37 @@ QUrl Nepomuk::Resource::resourceType() const { - if ( m_data ) { - return m_data->type(); - } - else { - return QUrl(); - } + determineFinalResourceData(); + return m_data->type(); } QList<QUrl> Nepomuk::Resource::types() const { - if ( m_data ) { - return m_data->allTypes(); - } - else { - return QList<QUrl>(); - } + determineFinalResourceData(); + return m_data->allTypes(); } void Nepomuk::Resource::setTypes( const QList<QUrl>& types ) { - if ( m_data ) - m_data->setTypes( types ); + determineFinalResourceData(); + m_data->setTypes( types ); } void Nepomuk::Resource::addType( const QUrl& type ) { - if ( m_data ) { - QList<QUrl> tl = types(); - if( !tl.contains( type ) ) - setTypes( tl << type ); - } + QList<QUrl> tl = types(); + if( !tl.contains( type ) ) + setTypes( tl << type ); } bool Nepomuk::Resource::hasType( const QUrl& typeUri ) const { - return m_data ? m_data->hasType( typeUri ) : false; + determineFinalResourceData(); + return m_data->hasType( typeUri ); } @@ -234,12 +221,8 @@ QHash<QUrl, Nepomuk::Variant> Nepomuk::Resource::properties() const { - if ( m_data ) { - return m_data->allProperties(); - } - else { - return QHash<QUrl, Nepomuk::Variant>(); - } + determineFinalResourceData(); + return m_data->allProperties(); } @@ -258,10 +241,18 @@ bool Nepomuk::Resource::hasProperty( const QUrl& uri ) const { - return m_data ? m_data->hasProperty( uri ) : false; + determineFinalResourceData(); + return m_data->hasProperty( uri ); } +bool Nepomuk::Resource::hasProperty( const Types::Property& p, const Variant& v ) const +{ + determineFinalResourceData(); + return m_data->hasProperty( p.uri(), v ); +} + + bool Nepomuk::Resource::hasProperty( const QString& uri ) const { return hasProperty( QUrl( uri ) ); @@ -276,12 +267,8 @@ Nepomuk::Variant Nepomuk::Resource::property( const QUrl& uri ) const { - if ( m_data ) { - return m_data->property( uri ); - } - else { - return Variant(); - } + determineFinalResourceData(); + return m_data->property( uri ); } @@ -301,9 +288,8 @@ void Nepomuk::Resource::setProperty( const QUrl& uri, const Nepomuk::Variant& value ) { - if ( m_data ) { - m_data->setProperty( uri, value ); - } + determineFinalResourceData(); + m_data->setProperty( uri, value ); } @@ -315,35 +301,37 @@ void Nepomuk::Resource::removeProperty( const QUrl& uri ) { - if ( m_data ) { - m_data->removeProperty( uri ); - } + determineFinalResourceData(); + m_data->removeProperty( uri ); } void Nepomuk::Resource::removeProperty( const QUrl& uri, const Variant& value ) { - if ( m_data ) { - QList<Variant> vl = property( uri ).toVariantList(); - foreach( const Variant& v, value.toVariantList() ) { - vl.removeAll( v ); - } - setProperty( uri, Variant( vl ) ); + QList<Variant> vl = property( uri ).toVariantList(); + foreach( const Variant& v, value.toVariantList() ) { + vl.removeAll( v ); } + setProperty( uri, Variant( vl ) ); } void Nepomuk::Resource::remove() { - if ( m_data ) { - m_data->remove(); - } + determineFinalResourceData(); + m_data->remove(); } bool Nepomuk::Resource::exists() const { - return m_data ? m_data->exists() : false; + determineFinalResourceData(); + if ( m_data ) { + return m_data->exists(); + } + else { + return false; + } } @@ -353,6 +341,7 @@ } +// KDE 4.5: cache this one in ResourceData QString Nepomuk::Resource::genericLabel() const { QString label = this->label(); @@ -372,23 +361,27 @@ label = property( Soprano::Vocabulary::Xesam::name() ).toString(); if ( label.isEmpty() ) { - label = property( Nepomuk::Vocabulary::NFO::fileName() ).toString(); + label = m_data->pimoThing().label(); if ( label.isEmpty() ) { - label = KUrl(property( Nepomuk::Vocabulary::NIE::url() ).toUrl()).fileName(); + label = property( Nepomuk::Vocabulary::NFO::fileName() ).toString(); if ( label.isEmpty() ) { - QList<Resource> go = property( Vocabulary::PIMO::groundingOccurrence() ).toResourceList(); - if( !go.isEmpty() ) { - label = go.first().genericLabel(); - if( label == go.first().resourceUri().toString() ) { - label.clear(); + label = KUrl(property( Nepomuk::Vocabulary::NIE::url() ).toUrl()).fileName(); + + if ( label.isEmpty() ) { + QList<Resource> go = property( Vocabulary::PIMO::groundingOccurrence() ).toResourceList(); + if( !go.isEmpty() ) { + label = go.first().genericLabel(); + if( label == go.first().resourceUri().toString() ) { + label.clear(); + } } - } - if ( label.isEmpty() ) { - // ugly fallback - label = resourceUri().toString(); + if ( label.isEmpty() ) { + // ugly fallback + label = resourceUri().toString(); + } } } } @@ -463,12 +456,8 @@ Nepomuk::Thing Nepomuk::Resource::pimoThing() { - if( m_data ) { - return m_data->pimoThing(); - } - else { - return Thing(); - } + determineFinalResourceData(); + return m_data->pimoThing(); } @@ -486,8 +475,8 @@ // get the resource URIs since two different ResourceData instances // can still represent the same Resource - m_data->determineUri(); - other.m_data->determineUri(); + determineFinalResourceData(); + other.determineFinalResourceData(); if( m_data->uri().isEmpty() ) return *m_data == *other.m_data; @@ -858,6 +847,63 @@ } +int Nepomuk::Resource::usageCount() const +{ + return property( Vocabulary::NUAO::usageCount() ).toInt(); +} + + +void Nepomuk::Resource::increaseUsageCount() +{ + int cnt = 0; + if( hasProperty( Vocabulary::NUAO::usageCount() ) ) + cnt = property( Vocabulary::NUAO::usageCount() ).toInt(); + ++cnt; + setProperty( Vocabulary::NUAO::usageCount(), cnt ); + setProperty( Vocabulary::NUAO::lastUsage(), QDateTime::currentDateTime() ); +} + + +// static +Nepomuk::Resource Nepomuk::Resource::fromResourceUri( const KUrl& uri, const Nepomuk::Types::Class& type, ResourceManager* manager ) +{ + if( !manager ) + manager = ResourceManager::instance(); + return Resource( manager->d->dataForResourceUri( uri, type.uri() ) ); +} + + +void Nepomuk::Resource::determineFinalResourceData() const +{ + m_data->m_determineUriMutex.lock(); + + // Get an initialized ResourceData instance + ResourceData* oldData = m_data; + ResourceData* newData = m_data->determineUri(); + + Q_ASSERT(oldData); + Q_ASSERT(newData); + + // in case we get an already existing one we update all instances + // using the old ResourceData to avoid the overhead of calling + // determineUri over and over + if( newData != oldData ) { + Q_FOREACH( Resource* res, m_data->m_resources) { + res->m_data = newData; + oldData->deref( res ); + newData->ref( res ); + } + } + + // we need to unlock before assigning ourselves to make sure we do not + // delete m_data before unlocking + oldData->m_determineUriMutex.unlock(); + + if ( !oldData->cnt() ) + delete oldData; +} + + uint Nepomuk::qHash( const Resource& res ) { return qHash(res.resourceUri()); Index: nepomuk/core/ui/test/tagwidgettest.cpp =================================================================== --- nepomuk/core/ui/test/tagwidgettest.cpp (révision 0) +++ nepomuk/core/ui/test/tagwidgettest.cpp (révision 0) @@ -0,0 +1,95 @@ +#include "tagwidgettest.h" +#include "../tagwidget.h" + +#include <QVBoxLayout> +#include <QCheckBox> +#include <kdebug.h> + + +TagWidgetTest::TagWidgetTest() + : QWidget() +{ + m_tagWidget = new Nepomuk::TagWidget(this); + m_tagWidget->setMaxTagsShown(8); + QVBoxLayout* lay = new QVBoxLayout(this); + lay->addWidget(m_tagWidget); + connect(m_tagWidget, SIGNAL(tagClicked(Nepomuk::Tag)), + this, SLOT(slotTagClicked(Nepomuk::Tag))); + connect(m_tagWidget, SIGNAL(selectionChanged(QList<Nepomuk::Tag>)), + this, SLOT(slotSelectionChanged(QList<Nepomuk::Tag>))); + + QCheckBox* box = new QCheckBox( "Minimode", this ); + connect(box, SIGNAL(toggled(bool)), this, SLOT(enableMinimode(bool))); + lay->addWidget(box); + + box = new QCheckBox( "Align Right", this ); + connect(box, SIGNAL(toggled(bool)), this, SLOT(alignRight(bool))); + lay->addWidget(box); + + box = new QCheckBox( "Disable clicking", this ); + connect(box, SIGNAL(toggled(bool)), this, SLOT(disableClicking(bool))); + lay->addWidget(box); + + box = new QCheckBox( "Read only", this ); + connect(box, SIGNAL(toggled(bool)), this, SLOT(setReadOnly(bool))); + lay->addWidget(box); +} + +TagWidgetTest::~TagWidgetTest() +{ +} + + +void TagWidgetTest::slotTagClicked(const Nepomuk::Tag& tag) +{ + kDebug() << "Tag clicked:" << tag.resourceUri() << tag.genericLabel(); +} + + +void TagWidgetTest::slotSelectionChanged( const QList<Nepomuk::Tag>& tags ) +{ + QStringList ts; + foreach(const Nepomuk::Tag& tag, tags) + ts << tag.genericLabel(); + kDebug() << "Selection changed:" << ts; +} + + +void TagWidgetTest::enableMinimode( bool enable ) +{ + Nepomuk::TagWidget::ModeFlags flags = m_tagWidget->modeFlags(); + if( enable ) { + flags |= Nepomuk::TagWidget::MiniMode; + flags &= ~Nepomuk::TagWidget::StandardMode; + } + else { + flags |= Nepomuk::TagWidget::StandardMode; + flags &= ~Nepomuk::TagWidget::MiniMode; + } + m_tagWidget->setModeFlags( flags ); +} + + +void TagWidgetTest::alignRight( bool enable ) +{ + if( enable ) + m_tagWidget->setAlignment( Qt::AlignRight ); + else + m_tagWidget->setAlignment( Qt::AlignLeft ); +} + + +void TagWidgetTest::disableClicking( bool enable ) +{ + Nepomuk::TagWidget::ModeFlags flags = m_tagWidget->modeFlags(); + m_tagWidget->setModeFlags( enable ? flags | Nepomuk::TagWidget::DisableTagClicking : flags & ~Nepomuk::TagWidget::DisableTagClicking ); +} + + +void TagWidgetTest::setReadOnly( bool enable ) +{ + Nepomuk::TagWidget::ModeFlags flags = m_tagWidget->modeFlags(); + m_tagWidget->setModeFlags( enable ? flags | Nepomuk::TagWidget::ReadOnly : flags & ~Nepomuk::TagWidget::ReadOnly ); +} + +#include "tagwidgettest.moc" Modification de propriétés sur nepomuk/core/ui/test/tagwidgettest.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/test/tagwidgetapp.cpp =================================================================== --- nepomuk/core/ui/test/tagwidgetapp.cpp (révision 0) +++ nepomuk/core/ui/test/tagwidgetapp.cpp (révision 0) @@ -0,0 +1,14 @@ +#include "tagwidgettest.h" + +#include <QApplication> +#include <kcomponentdata.h> + + +int main( int argc, char** argv ) +{ + QApplication app( argc, argv ); + KComponentData data( "TagWidgetApp" ); + TagWidgetTest tw; + tw.show(); + return app.exec(); +} Modification de propriétés sur nepomuk/core/ui/test/tagwidgetapp.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/test/tagwidgettest.h =================================================================== --- nepomuk/core/ui/test/tagwidgettest.h (révision 0) +++ nepomuk/core/ui/test/tagwidgettest.h (révision 0) @@ -0,0 +1,30 @@ +#ifndef TAGWIDGETTEST_H +#define TAGWIDGETTEST_H + +#include <QWidget> +#include "../../tag.h" +#include "../tagwidget.h" + +class TagWidgetTest : public QWidget +{ + Q_OBJECT + +public: + TagWidgetTest(); + ~TagWidgetTest(); + +public slots: + void slotTagClicked(const Nepomuk::Tag&); + void slotSelectionChanged( const QList<Nepomuk::Tag>& tags ); + +private slots: + void enableMinimode( bool enable ); + void alignRight( bool enable ); + void disableClicking( bool enable ); + void setReadOnly( bool enable ); + +private: + Nepomuk::TagWidget* m_tagWidget; +}; + +#endif Modification de propriétés sur nepomuk/core/ui/test/tagwidgettest.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/test/CMakeLists.txt =================================================================== --- nepomuk/core/ui/test/CMakeLists.txt (révision 1130118) +++ nepomuk/core/ui/test/CMakeLists.txt (copie de travail) @@ -15,3 +15,13 @@ ${KDE4_KIO_LIBS} nepomuk ) + +kde4_add_executable(tagwidgetapp TEST tagwidgetapp.cpp tagwidgettest.cpp) +target_link_libraries(tagwidgetapp + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + ${KDE4_KDECORE_LIBS} + ${KDE4_KDEUI_LIBS} + ${KDE4_KIO_LIBS} + nepomuk + ) Index: nepomuk/core/ui/kedittagsdialog.cpp =================================================================== --- nepomuk/core/ui/kedittagsdialog.cpp (révision 0) +++ nepomuk/core/ui/kedittagsdialog.cpp (révision 0) @@ -0,0 +1,259 @@ +/***************************************************************************** + * Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> * + * * + * 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 "kedittagsdialog_p.h" + +#include <kicon.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include <QEvent> +#include <QHBoxLayout> +#include <QLabel> +#include <QListWidget> +#include <QPushButton> +#include <QTimer> +#include <QVBoxLayout> +#include <QWidget> + +KEditTagsDialog::KEditTagsDialog(const QList<Nepomuk::Tag>& tags, + QWidget* parent, + Qt::WFlags flags) : + KDialog(parent, flags), + m_tags(tags), + m_tagsList(0), + m_newTagItem(0), + m_deleteCandidate(0), + m_newTagEdit(0), + m_deleteButtonTimer(0) +{ + + const QString caption = (tags.count() > 0) ? + i18nc("@title:window", "Change Tags") : + i18nc("@title:window", "Add Tags"); + setCaption(caption); + setButtons(KDialog::Ok | KDialog::Cancel); + setDefaultButton(KDialog::Ok); + + QWidget* mainWidget = new QWidget(this); + QVBoxLayout* topLayout = new QVBoxLayout(mainWidget); + + QLabel* label = new QLabel(i18nc("@label:textbox", + "Configure which tags should " + "be applied."), this); + + m_tagsList = new QListWidget(mainWidget); + m_tagsList->setMouseTracking(true); + m_tagsList->setSortingEnabled(true); + m_tagsList->setSelectionMode(QAbstractItemView::NoSelection); + m_tagsList->installEventFilter(this); + connect(m_tagsList, SIGNAL(itemEntered(QListWidgetItem*)), + this, SLOT(slotItemEntered(QListWidgetItem*))); + connect(m_tagsList, SIGNAL(itemEntered(QListWidgetItem*)), + this, SLOT(slotItemEntered(QListWidgetItem*))); + + QLabel* newTagLabel = new QLabel(i18nc("@label", "Create new tag:")); + m_newTagEdit = new KLineEdit(this); + m_newTagEdit->setClearButtonShown(true); + connect(m_newTagEdit, SIGNAL(textEdited(const QString&)), + this, SLOT(slotTextEdited(const QString&))); + + QHBoxLayout* newTagLayout = new QHBoxLayout(); + newTagLayout->addWidget(newTagLabel); + newTagLayout->addWidget(m_newTagEdit, 1); + + topLayout->addWidget(label); + topLayout->addWidget(m_tagsList); + topLayout->addLayout(newTagLayout); + + setMainWidget(mainWidget); + + loadTags(); + + // create the delete button, which is shown when + // hovering the items + m_deleteButton = new QPushButton(m_tagsList->viewport()); + m_deleteButton->setIcon(KIcon("edit-delete")); + m_deleteButton->setToolTip(i18nc("@info", "Delete tag")); + m_deleteButton->hide(); + connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(deleteTag())); + + m_deleteButtonTimer = new QTimer(this); + m_deleteButtonTimer->setSingleShot(true); + m_deleteButtonTimer->setInterval(500); + connect(m_deleteButtonTimer, SIGNAL(timeout()), this, SLOT(showDeleteButton())); +} + +KEditTagsDialog::~KEditTagsDialog() +{ +} + +QList<Nepomuk::Tag> KEditTagsDialog::tags() const +{ + return m_tags; +} + +bool KEditTagsDialog::eventFilter(QObject* watched, QEvent* event) +{ + if ((watched == m_tagsList) && (event->type() == QEvent::Leave)) { + m_deleteButtonTimer->stop(); + m_deleteButton->hide(); + } + return KDialog::eventFilter(watched, event); +} + +void KEditTagsDialog::slotButtonClicked(int button) +{ + if (button == KDialog::Ok) { + // update m_tags with the checked values, so + // that the caller of the KEditTagsDialog can + // receive the tags by KEditTagsDialog::tags() + m_tags.clear(); + + const int count = m_tagsList->count(); + for (int i = 0; i < count; ++i) { + QListWidgetItem* item = m_tagsList->item(i); + if (item->checkState() == Qt::Checked) { + const QString label = item->data(Qt::UserRole).toString(); + Nepomuk::Tag tag(label); + tag.setLabel(label); + m_tags.append(tag); + } + } + + accept(); + } else { + KDialog::slotButtonClicked(button); + } +} + +void KEditTagsDialog::slotTextEdited(const QString& text) +{ + // Remove unnecessary spaces from a new tag is + // mandatory, as the user cannot see the difference + // between a tag "Test" and "Test ". + const QString tagText = text.simplified(); + if (tagText.isEmpty()) { + removeNewTagItem(); + return; + } + + // Check whether the new tag already exists. If this + // is the case, remove the new tag item. + const int count = m_tagsList->count(); + for (int i = 0; i < count; ++i) { + const QListWidgetItem* item = m_tagsList->item(i); + const bool remove = (item->text() == tagText) && + ((m_newTagItem == 0) || (m_newTagItem != item)); + if (remove) { + m_tagsList->scrollToItem(item); + removeNewTagItem(); + return; + } + } + + // There is no tag in the list with the the passed text. + if (m_newTagItem == 0) { + m_newTagItem = new QListWidgetItem(tagText, m_tagsList); + } else { + m_newTagItem->setText(tagText); + } + m_newTagItem->setData(Qt::UserRole, tagText); + m_newTagItem->setCheckState(Qt::Checked); + m_tagsList->scrollToItem(m_newTagItem); +} + +void KEditTagsDialog::slotItemEntered(QListWidgetItem* item) +{ + // align the delete-button to stay on the right border + // of the item + const QRect rect = m_tagsList->visualItemRect(item); + const int size = rect.height(); + const int x = rect.right() - size; + const int y = rect.top(); + m_deleteButton->setGeometry(x, y, size, size); + + m_deleteCandidate = item; + m_deleteButtonTimer->start(); +} + +void KEditTagsDialog::showDeleteButton() +{ + m_deleteButton->show(); +} + +void KEditTagsDialog::deleteTag() +{ + Q_ASSERT(m_deleteCandidate != 0); + const QString text = i18nc("@info", + "Should the tag <resource>%1</resource> really be deleted for all files?", + m_deleteCandidate->text()); + const QString caption = i18nc("@title", "Delete tag"); + const KGuiItem deleteItem(i18nc("@action:button", "Delete"), KIcon("edit-delete")); + const KGuiItem cancelItem(i18nc("@action:button", "Cancel"), KIcon("dialog-cancel")); + if (KMessageBox::warningYesNo(this, text, caption, deleteItem, cancelItem) == KMessageBox::Yes) { + const QString label = m_deleteCandidate->data(Qt::UserRole).toString(); + Nepomuk::Tag tag(label); + tag.remove(); + + delete m_deleteCandidate; + m_deleteCandidate = 0; + } +} + +static bool tagLabelLessThan( const Nepomuk::Tag& t1, const Nepomuk::Tag& t2 ) +{ + return t1.genericLabel() < t2.genericLabel(); +} + +void KEditTagsDialog::loadTags() +{ + // load all available tags and mark those tags as checked + // that have been passed to the KEditTagsDialog + QList<Nepomuk::Tag> tags = Nepomuk::Tag::allTags(); + qSort( tags.begin(), tags.end(), tagLabelLessThan ); + + foreach (const Nepomuk::Tag& tag, tags) { + const QString label = tag.genericLabel(); + + QListWidgetItem* item = new QListWidgetItem(label, m_tagsList); + item->setData(Qt::UserRole, label); + + bool check = false; + foreach (const Nepomuk::Tag& selectedTag, m_tags) { + if (selectedTag == tag) { + check = true; + break; + } + } + item->setCheckState(check ? Qt::Checked : Qt::Unchecked); + } +} + +void KEditTagsDialog::removeNewTagItem() +{ + if (m_newTagItem != 0) { + const int row = m_tagsList->row(m_newTagItem); + m_tagsList->takeItem(row); + delete m_newTagItem; + m_newTagItem = 0; + } +} + +#include "kedittagsdialog_p.moc" Modification de propriétés sur nepomuk/core/ui/kedittagsdialog.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/kmetadatatagwidget.h =================================================================== --- nepomuk/core/ui/kmetadatatagwidget.h (révision 1130118) +++ nepomuk/core/ui/kmetadatatagwidget.h (copie de travail) @@ -1,100 +1,2 @@ -/* - * 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 _KMETADATA_TAG_WIDGET_H_ -#define _KMETADATA_TAG_WIDGET_H_ - -#include "nepomuk_export.h" - -#include <QtGui/QWidget> - -namespace Nepomuk { - class Resource; - class Tag; - - /** - * TagWidget provides a simple GUI interface to assign tags. - * It consists of a single text line displaying the assigned - * tags and a menu to change the tags. - */ - class NEPOMUK_EXPORT TagWidget : public QWidget - { - Q_OBJECT - - public: - /** - * Creates a new TagWidget for resource. The assigned tags are loaded - * instantly. - */ - explicit TagWidget( const Resource& resource, QWidget* parent = 0 ); - TagWidget( QWidget* parent = 0 ); - ~TagWidget(); - - /** - * \return The resources that are supposed to be tagged or an empty - * list if none have been set. - */ - QList<Resource> taggedResources() const; - - /** - * \return The list of all tags that are assigned to the currently set - * resource or an empty list if no resource has been set. - * - * \sa setTaggedResource, taggedResource, Resource::getTags - */ - QList<Tag> assignedTags() const; - - Q_SIGNALS: - /** - * This signal is emitted whenever a tag is clicked. - */ - void tagClicked( Tag ); - - public Q_SLOTS: - /** - * Set the Resource to be tagged. The assigned tags will be loaded - * instantly. - */ - void setTaggedResource( const Resource& resource ); - - void setTaggedResources( const QList<Resource>& resources ); - - /** - * Set the list of tags to be assigned to the configured resource. - * If no resource has been set this method does nothing. - * - * \sa setTaggedResource - */ - void setAssignedTags( const QList<Tag>& tags ); - - private Q_SLOTS: - void fillTagMenu(); - void createTag(); - void updateAssignedTagsFromMenu(); - void slotTagUpdateDone(); - void slotTagClicked( const QString& text ); - - private: - class Private; - Private* const d; - }; -} - -#endif +// backwards compatibility +#include "tagwidget.h" Index: nepomuk/core/ui/nepomukmassupdatejob.cpp =================================================================== --- nepomuk/core/ui/nepomukmassupdatejob.cpp (révision 1130118) +++ nepomuk/core/ui/nepomukmassupdatejob.cpp (copie de travail) @@ -153,4 +153,12 @@ return job; } +Nepomuk::MassUpdateJob* Nepomuk::MassUpdateJob::commentResources( const QList<Nepomuk::Resource>& rl, const QString& comment ) +{ + Nepomuk::MassUpdateJob* job = new Nepomuk::MassUpdateJob(); + job->setResources( rl ); + job->setProperties( QList<QPair<QUrl,Nepomuk::Variant> >() << qMakePair( QUrl( Nepomuk::Resource::descriptionUri() ), Nepomuk::Variant( comment ) ) ); + return job; +} + #include "nepomukmassupdatejob.moc" Index: nepomuk/core/ui/tagwidget_p.h =================================================================== --- nepomuk/core/ui/tagwidget_p.h (révision 0) +++ nepomuk/core/ui/tagwidget_p.h (révision 0) @@ -0,0 +1,70 @@ +/* + * This file is part of the Nepomuk KDE project. + * Copyright (C) 2006-2010 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_TAG_WIDGET_P_H_ +#define _NEPOMUK_TAG_WIDGET_P_H_ + +#include "tagwidget.h" +#include "../tag.h" + +#include <QtCore/QList> +#include <QtCore/QMap> + +class QPushButton; +class QLabel; +class KBlockLayout; + +namespace Nepomuk { + +class TagCheckBox; + +class TagWidgetPrivate +{ +public: + void init( TagWidget* parent ); + void rebuild(); + void buildTagHash( const QList<Tag>& tags ); + QList<Tag> loadTags( int max ); + QList<Tag> intersectResourceTags(); + + /// lookup (and if necessary create) checkbox for tag + TagCheckBox* getTagCheckBox( const Tag& tag ); + + /// check the corresponding checkboxes and even + /// add missing checkboxes + void selectTags( const QList<Tag>& tags ); + + /// start a massupdate job to set the selected tags on the resources + void updateResources(); + + QList<Resource> m_resources; + int m_maxTags; + TagWidget::ModeFlags m_flags; + bool m_blockSelectionChangedSignal; + + QMap<Tag, TagCheckBox*> m_checkBoxHash; + QPushButton* m_showAllButton; + QLabel* m_showAllLinkLabel; + KBlockLayout* m_flowLayout; + TagWidget* q; +}; +} + +#endif Modification de propriétés sur nepomuk/core/ui/tagwidget_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/kratingwidget.cpp =================================================================== --- nepomuk/core/ui/kratingwidget.cpp (révision 1130118) +++ nepomuk/core/ui/kratingwidget.cpp (copie de travail) @@ -162,9 +162,13 @@ void KRatingWidget::setRating( int rating ) { - d->rating = rating; - d->hoverRating = rating; - update(); + if ( rating != d->rating ) { + d->rating = rating; + d->hoverRating = rating; + emit ratingChanged( rating ); + emit ratingChanged( (unsigned int)rating ); + update(); + } } @@ -197,10 +201,8 @@ void KRatingWidget::mousePressEvent( QMouseEvent* e ) { if ( e->button() == Qt::LeftButton ) { - d->hoverRating = d->rating = d->ratingPainter.ratingFromPosition( contentsRect(), e->pos() ); - update(); - emit ratingChanged( d->rating ); - emit ratingChanged( (unsigned int)d->rating ); + d->hoverRating = d->ratingPainter.ratingFromPosition( contentsRect(), e->pos() ); + setRating( d->hoverRating ); } } @@ -208,13 +210,14 @@ void KRatingWidget::mouseMoveEvent( QMouseEvent* e ) { // when moving the mouse we show the user what the result of clicking will be + const int prevHoverRating = d->hoverRating; d->hoverRating = d->ratingPainter.ratingFromPosition( contentsRect(), e->pos() ); + if ( d->hoverRating != prevHoverRating ) { + update(); + } if ( d->hoverRating >= 0 && e->buttons() & Qt::LeftButton ) { - d->rating = d->hoverRating; - emit ratingChanged( d->rating ); - emit ratingChanged( (unsigned int)d->rating ); + setRating( d->hoverRating ); } - update(); } Index: nepomuk/core/ui/kblocklayout.cpp =================================================================== --- nepomuk/core/ui/kblocklayout.cpp (révision 1130118) +++ nepomuk/core/ui/kblocklayout.cpp (copie de travail) @@ -21,13 +21,17 @@ /* KBlockLayout is based on the FlowLayout example from QT4. Copyright (C) 2004-2006 Trolltech ASA. All rights reserved. + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + All rights reserved. + Contact: Nokia Corporation (qt-info@nokia.com) */ #include "kblocklayout.h" #include <QtCore/QList> +#include <QtGui/QStyle> +#include <QtGui/QWidget> - class KBlockLayout::Private { public: @@ -35,24 +39,45 @@ : alignment(Qt::AlignLeft|Qt::AlignTop) { } + int smartSpacing(QStyle::PixelMetric pm) const + { + QObject *parent = q->parent(); + if (!parent) { + return -1; + } else if (parent->isWidgetType()) { + QWidget *pw = static_cast<QWidget *>(parent); + return pw->style()->pixelMetric(pm, 0, pw); + } else { + return static_cast<QLayout *>(parent)->spacing(); + } + } + QList<QLayoutItem*> itemList; + int m_hSpace; + int m_vSpace; + Qt::Alignment alignment; + + KBlockLayout* q; }; -KBlockLayout::KBlockLayout( QWidget* parent, int margin, int spacing ) +KBlockLayout::KBlockLayout( QWidget* parent, int margin, int hSpacing, int vSpacing ) : QLayout(parent), d( new Private() ) { + d->q = this; setMargin(margin); - setSpacing(spacing); + setSpacing(hSpacing, vSpacing); } -KBlockLayout::KBlockLayout( int spacing ) +KBlockLayout::KBlockLayout( int margin, int hSpacing, int vSpacing ) : d( new Private() ) { - setSpacing(spacing); + d->q = this; + setMargin(margin); + setSpacing(hSpacing, vSpacing); } KBlockLayout::~KBlockLayout() @@ -73,6 +98,31 @@ return d->alignment; } +int KBlockLayout::horizontalSpacing() const +{ + if (d->m_hSpace >= 0) { + return d->m_hSpace; + } else { + return d->smartSpacing(QStyle::PM_LayoutHorizontalSpacing); + } +} + +int KBlockLayout::verticalSpacing() const +{ + if (d->m_vSpace >= 0) { + return d->m_vSpace; + } else { + return d->smartSpacing(QStyle::PM_LayoutVerticalSpacing); + } +} + +void KBlockLayout::setSpacing( int h, int v ) +{ + d->m_hSpace = h; + d->m_vSpace = v; + QLayout::setSpacing( h ); +} + void KBlockLayout::addItem( QLayoutItem* item ) { d->itemList.append(item); @@ -153,15 +203,16 @@ // 1. calculate lines QList<Row> rows; QList<QLayoutItem*> rowItems; - foreach( QLayoutItem* item, d->itemList ) { - int nextX = x + item->sizeHint().width() + spacing(); - if (nextX - spacing() > rect.right() && lineHeight > 0) { - rows.append( Row( rowItems, lineHeight, x - spacing() ) ); + for( int i = 0; i < d->itemList.count(); ++i ) { + QLayoutItem* item = d->itemList[i]; + int nextX = x + item->sizeHint().width() + horizontalSpacing(); + if (nextX - horizontalSpacing() > rect.right() && lineHeight > 0) { + rows.append( Row( rowItems, lineHeight, x - horizontalSpacing() ) ); rowItems.clear(); x = rect.x(); - y = y + lineHeight + spacing(); - nextX = x + item->sizeHint().width() + spacing(); + y = y + lineHeight + verticalSpacing(); + nextX = x + item->sizeHint().width() + horizontalSpacing(); lineHeight = 0; } @@ -171,7 +222,7 @@ lineHeight = qMax(lineHeight, item->sizeHint().height()); } // append the last row - rows.append( Row( rowItems, lineHeight, x ) ); + rows.append( Row( rowItems, lineHeight, x-horizontalSpacing() ) ); int finalHeight = y + lineHeight - rect.y(); if( testOnly ) @@ -194,13 +245,13 @@ yy += (row.height - item->sizeHint().height())/2; item->setGeometry(QRect(QPoint(x, yy), item->sizeHint())); - x += item->sizeHint().width() + spacing(); + x += item->sizeHint().width() + horizontalSpacing(); if( alignment() & Qt::AlignJustify ) x += (rect.width() - row.width)/qMax(row.items.count()-1,1); } - y = y + row.height + spacing(); + y = y + row.height + verticalSpacing(); } return finalHeight; Index: nepomuk/core/ui/nepomukmassupdatejob.h =================================================================== --- nepomuk/core/ui/nepomukmassupdatejob.h (révision 1130118) +++ nepomuk/core/ui/nepomukmassupdatejob.h (copie de travail) @@ -34,12 +34,28 @@ namespace Nepomuk { - class MassUpdateJob : public KJob + /** + * \class MassUpdateJob nepomukmassupdatejob.h Nepomuk/MassUpdateJob + * + * \brief A KJob to set Nepomuk properties on a set of resources at once. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT MassUpdateJob : public KJob { Q_OBJECT public: + /** + * Default constructor. Normally there is no need to use this. + * Use tagResources(), rateResources(), or commentResources() + * instead. + */ MassUpdateJob( QObject* parent = 0 ); + + /** + * Destructor + */ ~MassUpdateJob(); /** @@ -57,7 +73,7 @@ /** * Set the properties to change in the mass update. */ - void setProperties( const QList<QPair<QUrl,Nepomuk::Variant> >& props ); + void setProperties( const QList<QPair<QUrl, Nepomuk::Variant> >& props ); /** * Actually start the job. @@ -66,6 +82,7 @@ static MassUpdateJob* tagResources( const QList<Nepomuk::Resource>&, const QList<Nepomuk::Tag>& tags ); static MassUpdateJob* rateResources( const QList<Nepomuk::Resource>&, int rating ); + static MassUpdateJob* commentResources( const QList<Nepomuk::Resource>&, const QString& comment); protected: bool doKill(); Index: nepomuk/core/ui/kratingwidget.h =================================================================== --- nepomuk/core/ui/kratingwidget.h (révision 1130118) +++ nepomuk/core/ui/kratingwidget.h (copie de travail) @@ -26,6 +26,8 @@ #include "nepomuk_export.h" /** + * \class KRatingWidget kratingwidget.h Nepomuk/KRatingWidget + * * \brief Displays a rating value as a row of pixmaps. * * The KRatingWidget displays a range of stars or other arbitrary @@ -69,7 +71,7 @@ /** * The layout direction. If RTL the stars - * representing the rating value will be drawn from the + * representing the rating value will be drawn from the * right. * * \sa setLayoutDirection @@ -104,21 +106,20 @@ Q_SIGNALS: /** - * Emitted if the rating is changed by user interaction (ie. mouse click). - * A call to setRating does not trigger this signal. + * This signal is emitted when the rating is changed. */ void ratingChanged( unsigned int rating ); void ratingChanged( int rating ); public Q_SLOTS: /** - * Set the current rating. Calling this method will NOT trigger the - * ratingChanged signal. + * Set the current rating. Calling this method will trigger the + * ratingChanged signal if @p rating is different from the previous rating. */ void setRating( int rating ); /** - * \deprecated use setRating( int max ) + * \deprecated use setRating( int rating ) */ KDE_DEPRECATED void setRating( unsigned int rating ); Index: nepomuk/core/ui/kblocklayout.h =================================================================== --- nepomuk/core/ui/kblocklayout.h (révision 1130118) +++ nepomuk/core/ui/kblocklayout.h (copie de travail) @@ -36,8 +36,8 @@ class KBlockLayout : public QLayout { public: - explicit KBlockLayout( QWidget *parent, int margin = 0, int spacing = -1 ); - KBlockLayout( int spacing = -1 ); + explicit KBlockLayout( QWidget *parent, int margin = 0, int hSpacing = -1, int vSpacing = -1 ); + KBlockLayout( int margin = 0, int hSpacing = -1, int vSpacing = -1 ); ~KBlockLayout(); /** @@ -50,6 +50,11 @@ void setAlignment( Qt::Alignment ); Qt::Alignment alignment() const; + int horizontalSpacing() const; + int verticalSpacing() const; + + void setSpacing( int h, int v ); + void addItem( QLayoutItem* item ); Qt::Orientations expandingDirections() const; bool hasHeightForWidth() const; Index: nepomuk/core/ui/tagwidget.cpp =================================================================== --- nepomuk/core/ui/tagwidget.cpp (révision 0) +++ nepomuk/core/ui/tagwidget.cpp (révision 0) @@ -0,0 +1,387 @@ +/* + * This file is part of the Nepomuk KDE project. + * Copyright (C) 2006-2010 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 "tagwidget.h" +#include "tagwidget_p.h" +#include "kblocklayout.h" +#include "nepomukmassupdatejob.h" +#include "kedittagsdialog_p.h" +#include "tagcheckbox.h" + +#include "../tools.h" +#include "../tag.h" +#include "../resourcemanager.h" + +#include <karrowbutton.h> +#include <kinputdialog.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kglobalsettings.h> +#include <kdebug.h> + +#include <QtGui/QPushButton> +#include <QtGui/QBoxLayout> +#include <QtGui/QLabel> +#include <QtCore/QSet> + +#include <Soprano/QueryResultIterator> +#include <Soprano/Node> +#include <Soprano/Model> +#include <Soprano/Vocabulary/NAO> + + +void Nepomuk::TagWidgetPrivate::init( TagWidget* parent ) +{ + q = parent; + m_maxTags = 10; + m_flags = TagWidget::StandardMode; + m_blockSelectionChangedSignal = false; + m_showAllLinkLabel = 0; + + QGridLayout* mainLayout = new QGridLayout( q ); + mainLayout->setMargin(0); + m_flowLayout = new KBlockLayout( 0, KDialog::spacingHint()*3 ); + m_showAllButton = new QPushButton( i18nc("@label", "Show all tags..."), q ); + q->connect( m_showAllButton, SIGNAL(clicked()), SLOT(slotShowAll()) ); + mainLayout->addLayout( m_flowLayout, 0, 0, 1, 2 ); + mainLayout->addWidget( m_showAllButton, 1, 1, 1, 1 ); + mainLayout->setColumnStretch( 0, 1 ); + + rebuild(); +} + + +void Nepomuk::TagWidgetPrivate::rebuild() +{ + if( m_flags & TagWidget::MiniMode ) { + buildTagHash( q->selectedTags() ); + } + else { + QList<Tag> tags = q->selectedTags(); + buildTagHash( loadTags( m_maxTags ) ); + selectTags( tags ); + } +} + + +void Nepomuk::TagWidgetPrivate::buildTagHash( const QList<Tag>& tags ) +{ + qDeleteAll(m_checkBoxHash); + m_checkBoxHash.clear(); + + foreach( const Nepomuk::Tag& tag, tags ) { + getTagCheckBox( tag ); + } + + delete m_showAllLinkLabel; + m_showAllLinkLabel = 0; + + if( m_flags & TagWidget::MiniMode ) { + if( !(m_flags&TagWidget::ReadOnly) ) { + m_showAllLinkLabel = new QLabel( q ); + m_flowLayout->addWidget( m_showAllLinkLabel ); + QFont f(q->font()); + f.setUnderline(true); + m_showAllLinkLabel->setFont(f); + m_showAllLinkLabel->setText( QLatin1String("<a href=\"add_tags\">") + + ( m_checkBoxHash.isEmpty() ? i18nc("@label", "Add Tags...") : i18nc("@label", "Change...") ) + + QLatin1String("</a>") ); + q->connect( m_showAllLinkLabel, SIGNAL(linkActivated(QString)), SLOT(slotShowAll()) ); + m_showAllButton->hide(); + } + } + else { + m_showAllButton->setShown( !(m_flags&TagWidget::ReadOnly) ); + } +} + + +QList<Nepomuk::Tag> Nepomuk::TagWidgetPrivate::loadTags( int max ) +{ + // get the "max" first tags with the most resources + QString query = QString::fromLatin1("select ?r count(distinct ?f) as ?c where { " + "?r a %1 . " + "?f %2 ?r . " + "} ORDER BY DESC(?c) LIMIT %3") + .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::Tag()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())) + .arg( max ); + QList<Nepomuk::Tag> tags; + Soprano::QueryResultIterator it = ResourceManager::instance()->mainModel()->executeQuery( query, Soprano::Query::QueryLanguageSparql ); + while( it.next() ) { + // workaround for bug in Virtuoso where resources are returned as strings if a count() is in the select clause + tags << Tag( KUrl(it["r"].toString()) ); + } + return tags; +} + + +QList<Nepomuk::Tag> Nepomuk::TagWidgetPrivate::intersectResourceTags() +{ + if ( m_resources.count() == 1 ) { + return m_resources.first().tags(); + } + else if ( !m_resources.isEmpty() ) { + // determine the tags used for all resources + QSet<Tag> tags = QSet<Tag>::fromList( m_resources.first().tags() ); + QList<Resource>::const_iterator it = m_resources.constBegin(); + for ( ++it; it != m_resources.constEnd(); ++it ) { + tags.intersect( QSet<Tag>::fromList( (*it).tags() ) ); + } + return tags.values(); + } + else { + return QList<Tag>(); + } +} + + +Nepomuk::TagCheckBox* Nepomuk::TagWidgetPrivate::getTagCheckBox( const Tag& tag ) +{ + QMap<Tag, TagCheckBox*>::iterator it = m_checkBoxHash.find(tag); + if( it == m_checkBoxHash.end() ) { + kDebug() << "Creating checkbox for" << tag.genericLabel(); + TagCheckBox* checkBox = new TagCheckBox( tag, this, q ); + q->connect( checkBox, SIGNAL(tagClicked(Nepomuk::Tag)), SIGNAL(tagClicked(Nepomuk::Tag)) ); + q->connect( checkBox, SIGNAL(tagStateChanged(Nepomuk::Tag, int)), SLOT(slotTagStateChanged(Nepomuk::Tag, int)) ); + m_checkBoxHash.insert( tag, checkBox ); + m_flowLayout->addWidget( checkBox ); + return checkBox; + } + else { + return it.value(); + } +} + +namespace Nepomuk { +/// operator necessary for QMap::erase +bool operator<(const Tag& t1, const Tag& t2) { + return t1.resourceUri() < t2.resourceUri(); +} +} + +void Nepomuk::TagWidgetPrivate::selectTags( const QList<Tag>& tags ) +{ + m_blockSelectionChangedSignal = true; + + if( m_flags & TagWidget::MiniMode ) { + buildTagHash( tags ); + } + else { + foreach( TagCheckBox* checkBox, m_checkBoxHash ) { + checkBox->setChecked( false ); + } + + foreach( const Tag& tag, tags ) { + getTagCheckBox(tag)->setChecked( true ); + } + + // remove the previously added check boxes which are not amongst + // the top 10 or remove as many check boxes as possible to get down to + // m_maxTags + if( !m_checkBoxHash.isEmpty() ) { + int r = qMax( m_checkBoxHash.count() - m_maxTags, 0 ); + QMap<Tag, TagCheckBox*>::iterator it = m_checkBoxHash.end(); + --it; + while( r > 0 ) { + + // stop the loop when we reach the beginning of the hash + bool end = ( it == m_checkBoxHash.begin() ); + + // remove unused checkboxes + if( !it.value()->isChecked() ) { + delete it.value(); + it = m_checkBoxHash.erase(it); + --r; + } + + if( end ) { + break; + } + else { + --it; + } + } + } + } + + m_blockSelectionChangedSignal = false; +} + + +void Nepomuk::TagWidgetPrivate::updateResources() +{ + if ( !m_resources.isEmpty() ) { + Nepomuk::MassUpdateJob* job = Nepomuk::MassUpdateJob::tagResources( m_resources, q->selectedTags() ); + q->connect( job, SIGNAL( result( KJob* ) ), + SLOT( slotTagUpdateDone() ) ); + q->setEnabled( false ); // no updates during execution + job->start(); + } +} + + +Nepomuk::TagWidget::TagWidget( const Resource& resource, QWidget* parent ) + : QWidget( parent ), + d( new TagWidgetPrivate() ) +{ + d->init( this ); + setTaggedResource( resource ); +} + + +Nepomuk::TagWidget::TagWidget( QWidget* parent ) + : QWidget( parent ), + d( new TagWidgetPrivate() ) +{ + d->init( this ); +} + + +Nepomuk::TagWidget::~TagWidget() +{ + delete d; +} + + +QList<Nepomuk::Resource> Nepomuk::TagWidget::taggedResources() const +{ + return d->m_resources; +} + + +QList<Nepomuk::Tag> Nepomuk::TagWidget::assignedTags() const +{ + return selectedTags(); +} + + +QList<Nepomuk::Tag> Nepomuk::TagWidget::selectedTags() const +{ + QList<Nepomuk::Tag> tags; + QMapIterator<Tag, TagCheckBox*> it( d->m_checkBoxHash ); + while( it.hasNext() ) { + it.next(); + if( it.value()->isChecked() ) + tags << it.key(); + } + return tags; +} + + +int Nepomuk::TagWidget::maxTagsShown() const +{ + return d->m_maxTags; +} + + +Qt::Alignment Nepomuk::TagWidget::alignment() const +{ + return d->m_flowLayout->alignment(); +} + + +Nepomuk::TagWidget::ModeFlags Nepomuk::TagWidget::modeFlags() const +{ + return d->m_flags; +} + + +void Nepomuk::TagWidget::setTaggedResource( const Resource& resource ) +{ + QList<Resource> l; + l.append( resource ); + setTaggedResources( l ); +} + + +void Nepomuk::TagWidget::setTaggedResources( const QList<Resource>& resources ) +{ + // reset selection to a sensible default + d->buildTagHash( d->loadTags( d->m_maxTags ) ); + + d->m_resources = resources; + if ( !resources.isEmpty() ) { + d->selectTags( d->intersectResourceTags() ); + } + else { + d->selectTags( QList<Tag>() ); + } +} + + +void Nepomuk::TagWidget::setAssignedTags( const QList<Tag>& tags ) +{ + setSelectedTags( tags ); +} + + +void Nepomuk::TagWidget::setSelectedTags( const QList<Nepomuk::Tag>& tags ) +{ + d->selectTags( tags ); + d->updateResources(); +} + + +void Nepomuk::TagWidget::setMaxTagsShown( int max ) +{ + d->m_maxTags = max; + setTaggedResources( d->m_resources ); +} + + +void Nepomuk::TagWidget::setAlignment( Qt::Alignment alignment ) +{ + d->m_flowLayout->setAlignment( alignment ); +} + + +void Nepomuk::TagWidget::setModeFlags( ModeFlags flags ) +{ + d->m_flags = flags; + d->rebuild(); +} + + +void Nepomuk::TagWidget::slotTagUpdateDone() +{ + setEnabled( true ); +} + + +void Nepomuk::TagWidget::slotShowAll() +{ + KEditTagsDialog dlg( selectedTags(), this ); + if( dlg.exec() ) { + setSelectedTags( dlg.tags() ); + emit selectionChanged( selectedTags() ); + } +} + + +void Nepomuk::TagWidget::slotTagStateChanged( const Nepomuk::Tag&, int ) +{ + if( !d->m_blockSelectionChangedSignal ) { + d->updateResources(); + emit selectionChanged( selectedTags() ); + } +} + +#include "tagwidget.moc" Modification de propriétés sur nepomuk/core/ui/tagwidget.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/tagcheckbox.cpp =================================================================== --- nepomuk/core/ui/tagcheckbox.cpp (révision 0) +++ nepomuk/core/ui/tagcheckbox.cpp (révision 0) @@ -0,0 +1,169 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "tagcheckbox.h" +#include "tagwidget.h" +#include "tagwidget_p.h" + +#include <kcursor.h> +#include <kcolorscheme.h> +#include <kglobalsettings.h> + +#include <QtGui/QMouseEvent> +#include <QtGui/QStyleOptionButton> +#include <QtGui/QHBoxLayout> +#include <QtGui/QCheckBox> +#include <QtGui/QLabel> + + +class Nepomuk::TagCheckBox::CheckBoxWithPublicInitStyleOption : public QCheckBox +{ +public: + CheckBoxWithPublicInitStyleOption( const QString& text, QWidget* parent ) + : QCheckBox( text, parent ) { + } + + void initStyleOption( QStyleOptionButton* so ) { + QCheckBox::initStyleOption( so ); + } +}; + + +Nepomuk::TagCheckBox::TagCheckBox( const Tag& tag, TagWidgetPrivate* tagWidget, QWidget* parent ) + : QWidget( parent ), + m_label(0), + m_checkBox(0), + m_tag(tag), + m_urlHover(false), + m_tagWidget(tagWidget) +{ + QHBoxLayout* layout = new QHBoxLayout(this); + layout->setMargin(0); + if( tagWidget->m_flags & TagWidget::MiniMode ) { + setFont(KGlobalSettings::smallestReadableFont()); + m_label = new QLabel( tag.genericLabel(), this ); + m_label->setMouseTracking(true); + m_child = m_label; + } + else { + m_checkBox = new CheckBoxWithPublicInitStyleOption( tag.genericLabel(), this ); + m_child = m_checkBox; + connect(m_checkBox, SIGNAL(stateChanged(int)), this, SLOT(slotStateChanged(int))); + } + m_child->installEventFilter( this ); + m_child->setMouseTracking(true); + layout->addWidget( m_child ); + m_font = font(); +} + + +Nepomuk::TagCheckBox::~TagCheckBox() +{ +} + + +bool Nepomuk::TagCheckBox::isChecked() const +{ + if( m_checkBox ) + return m_checkBox->isChecked(); + else + return true; +} + + +void Nepomuk::TagCheckBox::setChecked( bool checked ) +{ + if( m_checkBox ) + m_checkBox->setChecked( checked ); +} + + +void Nepomuk::TagCheckBox::leaveEvent( QEvent* event ) +{ + QWidget::leaveEvent( event ); + enableUrlHover( false ); +} + + +bool Nepomuk::TagCheckBox::eventFilter( QObject* watched, QEvent* event ) +{ + if( watched == m_child ) { + switch( event->type() ) { + case QEvent::MouseMove: { + QMouseEvent* me = static_cast<QMouseEvent*>(event); + if( !(m_tagWidget->m_flags & TagWidget::DisableTagClicking) ) + enableUrlHover( tagRect().contains(me->pos()) ); + } + + case QEvent::MouseButtonRelease: { + QMouseEvent* me = static_cast<QMouseEvent*>(event); + if( !(m_tagWidget->m_flags & TagWidget::DisableTagClicking) && + me->button() == Qt::LeftButton && + tagRect().contains(me->pos()) ) { + emit tagClicked( m_tag ); + return true; + } + } + + default: + // do nothing + break; + } + } + + return QWidget::eventFilter( watched, event ); +} + + +void Nepomuk::TagCheckBox::slotStateChanged( int state ) +{ + emit tagStateChanged( m_tag, state ); +} + + +QRect Nepomuk::TagCheckBox::tagRect() const +{ + if( m_checkBox ) { + QStyleOptionButton opt; + m_checkBox->initStyleOption(&opt); + return style()->subElementRect(QStyle::SE_CheckBoxContents, + &opt, + m_checkBox); + } + else { + return QRect(QPoint(0, 0), m_label->size()); + } +} + + +void Nepomuk::TagCheckBox::enableUrlHover( bool enable ) +{ + if( m_urlHover != enable ) { + m_urlHover = enable; + QFont f(m_font); + if(enable) + f.setUnderline(true); + m_child->setFont(f); + m_child->setCursor( enable ? Qt::PointingHandCursor : Qt::ArrowCursor ); + } +} + +#include "tagcheckbox.moc" Modification de propriétés sur nepomuk/core/ui/tagcheckbox.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/kedittagsdialog_p.h =================================================================== --- nepomuk/core/ui/kedittagsdialog_p.h (révision 0) +++ nepomuk/core/ui/kedittagsdialog_p.h (révision 0) @@ -0,0 +1,78 @@ +/***************************************************************************** + * Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> * + * * + * 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 KEDIT_TAGS_DIALOG_H +#define KEDIT_TAGS_DIALOG_H + +#include <kdialog.h> +#include <tag.h> + +class KLineEdit; +class QListWidget; +class QListWidgetItem; +class QPushButton; +class QTimer; + +/** + * @brief Dialog to edit a list of Nepomuk tags. + * + * It is possible for the user to add existing tags, + * create new tags or to remove tags. + * + * @see KMetaDataConfigurationDialog + */ +class KEditTagsDialog : public KDialog +{ + Q_OBJECT + +public: + KEditTagsDialog(const QList<Nepomuk::Tag>& tags, + QWidget* parent = 0, + Qt::WFlags flags = 0); + + virtual ~KEditTagsDialog(); + + QList<Nepomuk::Tag> tags() const; + + virtual bool eventFilter(QObject* watched, QEvent* event); + +protected slots: + virtual void slotButtonClicked(int button); + +private slots: + void slotTextEdited(const QString& text); + void slotItemEntered(QListWidgetItem* item); + void showDeleteButton(); + void deleteTag(); + +private: + void loadTags(); + void removeNewTagItem(); + +private: + QList<Nepomuk::Tag> m_tags; + QListWidget* m_tagsList; + QListWidgetItem* m_newTagItem; + QListWidgetItem* m_deleteCandidate; + KLineEdit* m_newTagEdit; + + QPushButton* m_deleteButton; + QTimer* m_deleteButtonTimer; +}; + +#endif Modification de propriétés sur nepomuk/core/ui/kedittagsdialog_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/tagwidget.h =================================================================== --- nepomuk/core/ui/tagwidget.h (révision 0) +++ nepomuk/core/ui/tagwidget.h (révision 0) @@ -0,0 +1,237 @@ +/* + * This file is part of the Nepomuk KDE project. + * Copyright (C) 2006-2010 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_TAG_WIDGET_H_ +#define _NEPOMUK_TAG_WIDGET_H_ + +#include "nepomuk_export.h" + +#include <QtGui/QWidget> + +namespace Nepomuk { + class Resource; + class Tag; + class TagWidgetPrivate; + + /** + * \class TagWidget tagwidget.h Nepomuk/TagWidget + * + * \brief Allows to change a selection of tags. + * + * TagWidget provides a simple GUI interface to assign tags. + * It has two basic modes: + * \li If resources are set via setTaggedResource() or setTaggedResources() + * the changes in the tag selection are automatically assigned to the + * selected resources. + * \li If no resources have been set the widget simply emits the selectionChanged() + * signal. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT TagWidget : public QWidget + { + Q_OBJECT + + public: + /** + * Creates a new TagWidget for resource. The assigned tags are loaded + * instantly. + */ + explicit TagWidget( const Resource& resource, QWidget* parent = 0 ); + + /** + * Constructor + */ + TagWidget( QWidget* parent = 0 ); + + /** + * Desctructor + */ + ~TagWidget(); + + /** + * \return The resources that are supposed to be tagged or an empty + * list if none have been set. + */ + QList<Resource> taggedResources() const; + + /** + * \deprecated use selectedTags() instead + */ + KDE_DEPRECATED QList<Tag> assignedTags() const; + + /** + * The list of selected tags. + * + * \return The list of all tags that are currently selected. In case + * resources to be tagged have been selected this list matches the + * tags assigned to the resources. + * + * \sa setTaggedResource, taggedResource, Resource::getTags + * + * \since 4.5 + */ + QList<Nepomuk::Tag> selectedTags() const; + + /** + * By default the TagWidget shows the most often used tags in the + * main window and allows access to all tags via an additional button. + * This is the maximum number of tags that should be shown unless they + * are selected. + * + * \sa setMaxTagsShown() + * + * \since 4.5 + */ + int maxTagsShown() const; + + /** + * The alignment of the tags in the widget. + * + * \since 4.5 + */ + Qt::Alignment alignment() const; + + /** + * Flags to configure the widget. + * + * \since 4.5 + */ + enum ModeFlag { + /** + * The mini mode which tries to + * display the tags on the least + * space possible. + */ + MiniMode = 0x1, + + /** + * The standard mode which is used by default + * provides a set of check boxes for the most + * frequently used tags. + */ + StandardMode = 0x2, + + /** + * Read only mode which prevents the changing + * of tags by the user. + */ + ReadOnly = 0x4, + + /** + * Disable the clicking of the tags. This will + * also disable the emitting of the tagClicked() + * signal. + */ + DisableTagClicking = 0x8 + }; + Q_DECLARE_FLAGS( ModeFlags, ModeFlag ) + + /** + * Flags the widget is configured with. + * + * \sa setModeFlags() + * + * \since 4.5 + */ + ModeFlags modeFlags() const; + + Q_SIGNALS: + /** + * This signal is emitted whenever a tag is clicked. + */ + void tagClicked( Nepomuk::Tag ); + + /** + * Emitted whenever the selection of tags changes. + * + * \since 4.5 + */ + void selectionChanged( const QList<Nepomuk::Tag>& tags ); + + public Q_SLOTS: + /** + * Set the Resource to be tagged. The assigned tags will be loaded + * instantly. + */ + void setTaggedResource( const Resource& resource ); + + /** + * Set the resources to be tagged. If the list of resources is + * empty TagWidget will only emit the selectionChanged() signal. + */ + void setTaggedResources( const QList<Resource>& resources ); + + /** + * \deprecated use setSelectedTags() instead + */ + KDE_DEPRECATED void setAssignedTags( const QList<Nepomuk::Tag>& tags ); + + /** + * Set the list of selected tags. In case resources have been + * set via setTaggedResource() or setTaggedResources() their + * list of tags is changed automatically. + * + * \since 4.5 + */ + void setSelectedTags( const QList<Nepomuk::Tag>& tags ); + + /** + * By default the TagWidget shows the most often used tags in the + * main window and allows access to all tags via an additional button. + * + * The number of tags that are shown by default can be changed. + * + * \param max The maximum number of tags that should be shown in the + * main window. Set to 0 for no limit. Be aware that more tags might be + * shown since selected tags are always shown. + * + * \since 4.5 + */ + void setMaxTagsShown( int max ); + + /** + * Set the alignment to use. Only horizontal alignment flags make a + * difference. + * + * \since 4.5 + */ + void setAlignment( Qt::Alignment alignment ); + + /** + * Set flags to change the behaviour and look of the tag widget. + * + * \since 4.5 + */ + void setModeFlags( ModeFlags flags ); + + private Q_SLOTS: + void slotShowAll(); + void slotTagUpdateDone(); + void slotTagStateChanged( const Nepomuk::Tag&, int ); + + private: + TagWidgetPrivate* const d; + }; +} + +Q_DECLARE_OPERATORS_FOR_FLAGS( Nepomuk::TagWidget::ModeFlags ) + +#endif Modification de propriétés sur nepomuk/core/ui/tagwidget.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/kratingpainter.h =================================================================== --- nepomuk/core/ui/kratingpainter.h (révision 1130118) +++ nepomuk/core/ui/kratingpainter.h (copie de travail) @@ -33,6 +33,8 @@ /** + * \class KRatingPainter kratingpainter.h Nepomuk/KRatingPainter + * * \brief Utility class that draws a row of stars for a rating value. * * The KRatingPainter also allows to determine a rating value from @@ -54,7 +56,7 @@ * should be sufficient. */ KRatingPainter(); - + /** * Destructor */ @@ -86,7 +88,7 @@ /** * The layout direction. If RTL the stars - * representing the rating value will be drawn from the + * representing the rating value will be drawn from the * right. * * \sa setLayoutDirection @@ -134,7 +136,7 @@ * one rating step corresponds to half a star. */ void setHalfStepsEnabled( bool enabled ); - + /** * The alignment of the stars in the drawing rect. * All alignment flags are supported. Index: nepomuk/core/ui/tagcheckbox.h =================================================================== --- nepomuk/core/ui/tagcheckbox.h (révision 0) +++ nepomuk/core/ui/tagcheckbox.h (révision 0) @@ -0,0 +1,78 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _NEPOMUK_TAG_CHECKBOX_H_ +#define _NEPOMUK_TAG_CHECKBOX_H_ + +#include <QtGui/QWidget> +#include <QtGui/QFont> + +#include "../tag.h" +#include "tagwidget_p.h" + +class QMouseEvent; +class QLabel; + +namespace Nepomuk { +class TagCheckBox : public QWidget +{ + Q_OBJECT + +public: + TagCheckBox( const Tag& tag, TagWidgetPrivate* tagWidget, QWidget* parent = 0 ); + ~TagCheckBox(); + + Tag tag() const { return m_tag; } + + bool isChecked() const; + +public Q_SLOTS: + void setChecked( bool checked ); + +Q_SIGNALS: + void tagClicked( const Nepomuk::Tag& tag ); + void tagStateChanged( const Nepomuk::Tag& tag, int state ); + +protected: + void leaveEvent( QEvent* event ); + bool eventFilter( QObject* watched, QEvent* event ); + +private Q_SLOTS: + void slotStateChanged( int state ); + +private: + QRect tagRect() const; + void enableUrlHover( bool enabled ); + + // two modes: checkbox and simple label + QLabel* m_label; + class CheckBoxWithPublicInitStyleOption; + CheckBoxWithPublicInitStyleOption* m_checkBox; + QWidget* m_child; + + Tag m_tag; + bool m_urlHover; + QFont m_font; + TagWidgetPrivate* m_tagWidget; +}; +} + +#endif Modification de propriétés sur nepomuk/core/ui/tagcheckbox.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/core/ui/CMakeLists.txt =================================================================== --- nepomuk/core/ui/CMakeLists.txt (révision 1130118) +++ nepomuk/core/ui/CMakeLists.txt (copie de travail) @@ -15,6 +15,8 @@ kmetadatatagwidget.h ktagdisplaywidget.h kratingpainter.h + nepomukmassupdatejob.h + tagwidget.h DESTINATION ${INCLUDE_INSTALL_DIR}/nepomuk COMPONENT Devel ) Index: nepomuk/Mainpage.dox =================================================================== --- nepomuk/Mainpage.dox (révision 1130118) +++ nepomuk/Mainpage.dox (copie de travail) @@ -3,7 +3,7 @@ * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ * * This file is part of the Nepomuk KDE project. - * Copyright (C) 2006-2009 Sebastian Trueg <trueg@kde.org> + * Copyright (C) 2006-2010 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 published by @@ -314,6 +314,34 @@ Nepomuk::Query::FileQuery fileQuery( term ); \endcode + +Any other term can be used as sub term in a ComparisonTerm (%Vocabulary namespace generated via \ref nepomuk-rcgen). +The following query does return all resources related to person contacts that are tagged with \p tag. + +\code +Nepomuk::Query::AndTerm andTerm; +andTerm.addSubTerm( Nepomuk::Query::ResourceTypeTerm( Nepomuk::Vocabulary::NCO::PersonContact() ) ); +andTerm.addSubTerm( Nepomuk::Query::ComparisonTerm( Soprano::Vocabulary::NAO::hasTag(), + Nepomuk::Query::ResourceTerm( tag ) ) ); +Nepomuk::Query::ComparisonTerm cterm( Nepomuk::Vocabulary::NAO::isRelated(), + andTerm ); +\endcode + + +To make matters even more complex the above ComparisonTerm can be inverted: + +\code +cterm.setInverted(true); +\endcode + +This will not match resources related to some tagged person contact but match +resources that some tagged person contact is related to (sounds confusing but +remember that the properties are not symmetric by default, i.e. the graph of +data is directed.) + + +\subsection query_examples_file Listing Files + Restrict the search to a specific folder: \code @@ -330,6 +358,19 @@ fileQuery.setTerm( Nepomuk::Query::AndTerm( fileQuery.term(), noFolderTerm ) ); \endcode +List all query results in a KDirModel: + +\code +KDirModel* model = getFancyDirModel(); +Nepomuk::Query::Query query = buildFancyQuery(); +KUrl searchUrl = query.toSearchUrl(); +model->dirLister()->open( searchUrl ); +\endcode + +KIO will use the \p nepomuksearch:/ slave to list search results as file entries. + +\subsection query_examples_misc Misc Query Examples + Match all EmailAddress instances with a specific email address: \code Nepomuk::Query::ComparisonTerm email( Vocabulary::NCO::emailAddress(), Soprano::LiteralValue( "trueg@kde.org" ) ); @@ -344,17 +385,6 @@ \code Nepomuk::Query::AndTerm( type, Nepomuk::Query::ComparisonTerm( Vocabulary::NCO::hasEmailAddress(), email ) ); \endcode - -List all query results in a KDirModel: - -\code -KDirModel* model = getFancyDirModel(); -Nepomuk::Query::Query query = buildFancyQuery(); -KUrl searchUrl = query.toSearchUrl(); -model->dirLister()->open( searchUrl ); -\endcode - -KIO will use the \p nepomuksearch:/ slave to list search results as file entries. */ @@ -487,17 +517,20 @@ // DOXYGEN_SET_FILE_PATTERNS = *.h // DOXYGEN_SET_INPUT = @topdir@/nepomuk/Mainpage.dox // DOXYGEN_SET_INPUT += @topdir@/nepomuk/core -// DOXYGEN_SET_INPUT += @topdir@/nepomuk/core/ui -// DOXYGEN_SET_INPUT += @topdir@/nepomuk/core/ontology +// DOXYGEN_SET_INPUT += @topdir@/nepomuk/ui +// DOXYGEN_SET_INPUT += @topdir@/nepomuk/types // DOXYGEN_SET_INPUT += @topdir@/nepomuk/query // DOXYGEN_SET_EXCLUDE = @topdir@/nepomuk/core/resourcedata.h // DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/nepomukmainmodel.h // DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/resourcefiltermodel.h // DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/nie.h -// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/ontology/entitymanager.h -// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/ui/nepomukmassupdatejob.h -// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/ui/kautoscrollarea.h -// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/core/ui/kblocklayout.h +// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/types/entitymanager.h +// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/ui/nepomukmassupdatejob.h +// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/ui/tagcheckbox.h +// DOXYGEN_SET_EXCLUDE += @topdir@/nepomuk/ui/kblocklayout.h +// DOXYGEN_SET_EXCLUDE_PATTERNS += @topdir@/nepomuk/core/*_p.h +// DOXYGEN_SET_EXCLUDE_PATTERNS += @topdir@/nepomuk/types/*_p.h +// DOXYGEN_SET_EXCLUDE_PATTERNS += @topdir@/nepomuk/ui/*_p.h // DOXYGEN_SET_EXCLUDE_PATTERNS += @topdir@/nepomuk/query/*_p.h // DOXYGEN_SET_PROJECT_NAME = Nepomuk // vim:ts=4:sw=4:expandtab:filetype=doxygen Index: nepomuk/CMakeLists.txt =================================================================== --- nepomuk/CMakeLists.txt (révision 1130118) +++ nepomuk/CMakeLists.txt (copie de travail) @@ -4,11 +4,156 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") +add_definitions(-DKDE_DEFAULT_DEBUG_AREA=300000) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/core + ${CMAKE_CURRENT_SOURCE_DIR}/types + ${CMAKE_CURRENT_SOURCE_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/query + ${kdecore_SOURCE_DIR}/utils + ${CMAKE_SOURCE_DIR} + ${KDE4_INCLUDES} + ${KDE4_KIO_INCLUDES} + ${QT_INCLUDES} + ${SOPRANO_INCLUDE_DIR} +) + +set(nepomuk_core_SRCS + core/variant.cpp + core/resourcedata.cpp + core/resourcemanager.cpp + core/resourcefiltermodel.cpp + core/nepomukmainmodel.cpp + core/tools.cpp + core/dbusconnectionpool.cpp + core/resource.cpp + core/thing.cpp + core/tag.cpp + core/nepomukservice.cpp + core/graphwrapper.cpp +) + +set(nepomuk_ui_SRCS + ui/kratingwidget.cpp + ui/ktagcloudwidget.cpp + ui/kblocklayout.cpp + ui/kmetadatatagcloud.cpp + ui/ktagdisplaywidget.cpp + ui/kratingpainter.cpp + ui/nepomukmassupdatejob.cpp + ui/tagwidget.cpp + ui/kedittagsdialog.cpp + ui/tagcheckbox.cpp +) + +set(nepomuk_types_SRCS + types/entity.cpp + types/ontology.cpp + types/class.cpp + types/property.cpp + types/literal.cpp + types/ontologyloader.cpp + types/ontologymanager.cpp + types/nepomukontologyloader.cpp + types/fileontologyloader.cpp + types/desktopontologyloader.cpp + types/global.cpp + types/entitymanager.cpp +) + +set(nepomuk_query_SRCS + query/term.cpp + query/negationterm.cpp + query/orterm.cpp + query/andterm.cpp + query/comparisonterm.cpp + query/simpleterm.cpp + query/groupterm.cpp + query/resourceterm.cpp + query/literalterm.cpp + query/resourcetypeterm.cpp + query/optionalterm.cpp + query/query.cpp + query/query_p.cpp + query/filequery.cpp + query/queryparser.cpp + query/dateparser.cpp + query/result.cpp + query/queryserviceclient.cpp + query/dbusoperators.cpp +) + +set(nepomuk_LIB_SRCS + ${nepomuk_core_SRCS} + ${nepomuk_ui_SRCS} + ${nepomuk_types_SRCS} +# ${nepomuk_query_SRCS} +) + +soprano_add_ontology(nepomuk_LIB_SRCS "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nie.trig" "NIE" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(nepomuk_LIB_SRCS "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nfo.trig" "NFO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(nepomuk_LIB_SRCS "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nco.trig" "NCO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(nepomuk_LIB_SRCS "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/pimo/pimo.trig" "PIMO" "Nepomuk::Vocabulary" "trig") +soprano_add_ontology(nepomuk_LIB_SRCS "${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nepomuk/nuao.trig" "NUAO" "Nepomuk::Vocabulary" "trig") + +kde4_add_library(nepomuk SHARED ${nepomuk_LIB_SRCS}) + +target_link_libraries(nepomuk + ${SOPRANO_LIBRARIES} + ${SOPRANO_CLIENT_LIBRARIES} + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + ${QT_QTDBUS_LIBRARY} + kdecore + kdeui +) + +target_link_libraries(nepomuk + LINK_INTERFACE_LIBRARIES + kdeui + ${SOPRANO_LIBRARIES}) + + +set_target_properties(nepomuk PROPERTIES + VERSION ${GENERIC_LIB_VERSION} + SOVERSION ${GENERIC_LIB_SOVERSION} +) + +install(TARGETS nepomuk EXPORT kdelibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS}) + install(FILES nepomuk_export.h + core/variant.h + core/resourcemanager.h + core/tools.h + core/nepomukservice.h + core/resource.h + core/thing.h + core/tag.h + types/entity.h + types/class.h + types/property.h + types/ontology.h + types/literal.h + types/ontologymanager.h + types/ontologyloader.h + types/nepomukontologyloader.h + types/fileontologyloader.h + types/desktopontologyloader.h + types/global.h + ui/kratingwidget.h + ui/ktagcloudwidget.h + ui/kmetadatatagcloud.h + ui/kmetadatatagwidget.h + ui/ktagdisplaywidget.h + ui/kratingpainter.h + ui/nepomukmassupdatejob.h + ui/tagwidget.h DESTINATION ${INCLUDE_INSTALL_DIR}/nepomuk COMPONENT Devel ) add_subdirectory(rcgen) -add_subdirectory(core) add_subdirectory(query) +add_subdirectory(test) Index: nepomuk/ui/kedittagsdialog.cpp =================================================================== --- nepomuk/ui/kedittagsdialog.cpp (révision 0) +++ nepomuk/ui/kedittagsdialog.cpp (révision 0) @@ -0,0 +1,259 @@ +/***************************************************************************** + * Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> * + * * + * 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 "kedittagsdialog_p.h" + +#include <kicon.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include <QEvent> +#include <QHBoxLayout> +#include <QLabel> +#include <QListWidget> +#include <QPushButton> +#include <QTimer> +#include <QVBoxLayout> +#include <QWidget> + +KEditTagsDialog::KEditTagsDialog(const QList<Nepomuk::Tag>& tags, + QWidget* parent, + Qt::WFlags flags) : + KDialog(parent, flags), + m_tags(tags), + m_tagsList(0), + m_newTagItem(0), + m_deleteCandidate(0), + m_newTagEdit(0), + m_deleteButtonTimer(0) +{ + + const QString caption = (tags.count() > 0) ? + i18nc("@title:window", "Change Tags") : + i18nc("@title:window", "Add Tags"); + setCaption(caption); + setButtons(KDialog::Ok | KDialog::Cancel); + setDefaultButton(KDialog::Ok); + + QWidget* mainWidget = new QWidget(this); + QVBoxLayout* topLayout = new QVBoxLayout(mainWidget); + + QLabel* label = new QLabel(i18nc("@label:textbox", + "Configure which tags should " + "be applied."), this); + + m_tagsList = new QListWidget(mainWidget); + m_tagsList->setMouseTracking(true); + m_tagsList->setSortingEnabled(true); + m_tagsList->setSelectionMode(QAbstractItemView::NoSelection); + m_tagsList->installEventFilter(this); + connect(m_tagsList, SIGNAL(itemEntered(QListWidgetItem*)), + this, SLOT(slotItemEntered(QListWidgetItem*))); + connect(m_tagsList, SIGNAL(itemEntered(QListWidgetItem*)), + this, SLOT(slotItemEntered(QListWidgetItem*))); + + QLabel* newTagLabel = new QLabel(i18nc("@label", "Create new tag:")); + m_newTagEdit = new KLineEdit(this); + m_newTagEdit->setClearButtonShown(true); + connect(m_newTagEdit, SIGNAL(textEdited(const QString&)), + this, SLOT(slotTextEdited(const QString&))); + + QHBoxLayout* newTagLayout = new QHBoxLayout(); + newTagLayout->addWidget(newTagLabel); + newTagLayout->addWidget(m_newTagEdit, 1); + + topLayout->addWidget(label); + topLayout->addWidget(m_tagsList); + topLayout->addLayout(newTagLayout); + + setMainWidget(mainWidget); + + loadTags(); + + // create the delete button, which is shown when + // hovering the items + m_deleteButton = new QPushButton(m_tagsList->viewport()); + m_deleteButton->setIcon(KIcon("edit-delete")); + m_deleteButton->setToolTip(i18nc("@info", "Delete tag")); + m_deleteButton->hide(); + connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(deleteTag())); + + m_deleteButtonTimer = new QTimer(this); + m_deleteButtonTimer->setSingleShot(true); + m_deleteButtonTimer->setInterval(500); + connect(m_deleteButtonTimer, SIGNAL(timeout()), this, SLOT(showDeleteButton())); +} + +KEditTagsDialog::~KEditTagsDialog() +{ +} + +QList<Nepomuk::Tag> KEditTagsDialog::tags() const +{ + return m_tags; +} + +bool KEditTagsDialog::eventFilter(QObject* watched, QEvent* event) +{ + if ((watched == m_tagsList) && (event->type() == QEvent::Leave)) { + m_deleteButtonTimer->stop(); + m_deleteButton->hide(); + } + return KDialog::eventFilter(watched, event); +} + +void KEditTagsDialog::slotButtonClicked(int button) +{ + if (button == KDialog::Ok) { + // update m_tags with the checked values, so + // that the caller of the KEditTagsDialog can + // receive the tags by KEditTagsDialog::tags() + m_tags.clear(); + + const int count = m_tagsList->count(); + for (int i = 0; i < count; ++i) { + QListWidgetItem* item = m_tagsList->item(i); + if (item->checkState() == Qt::Checked) { + const QString label = item->data(Qt::UserRole).toString(); + Nepomuk::Tag tag(label); + tag.setLabel(label); + m_tags.append(tag); + } + } + + accept(); + } else { + KDialog::slotButtonClicked(button); + } +} + +void KEditTagsDialog::slotTextEdited(const QString& text) +{ + // Remove unnecessary spaces from a new tag is + // mandatory, as the user cannot see the difference + // between a tag "Test" and "Test ". + const QString tagText = text.simplified(); + if (tagText.isEmpty()) { + removeNewTagItem(); + return; + } + + // Check whether the new tag already exists. If this + // is the case, remove the new tag item. + const int count = m_tagsList->count(); + for (int i = 0; i < count; ++i) { + const QListWidgetItem* item = m_tagsList->item(i); + const bool remove = (item->text() == tagText) && + ((m_newTagItem == 0) || (m_newTagItem != item)); + if (remove) { + m_tagsList->scrollToItem(item); + removeNewTagItem(); + return; + } + } + + // There is no tag in the list with the the passed text. + if (m_newTagItem == 0) { + m_newTagItem = new QListWidgetItem(tagText, m_tagsList); + } else { + m_newTagItem->setText(tagText); + } + m_newTagItem->setData(Qt::UserRole, tagText); + m_newTagItem->setCheckState(Qt::Checked); + m_tagsList->scrollToItem(m_newTagItem); +} + +void KEditTagsDialog::slotItemEntered(QListWidgetItem* item) +{ + // align the delete-button to stay on the right border + // of the item + const QRect rect = m_tagsList->visualItemRect(item); + const int size = rect.height(); + const int x = rect.right() - size; + const int y = rect.top(); + m_deleteButton->setGeometry(x, y, size, size); + + m_deleteCandidate = item; + m_deleteButtonTimer->start(); +} + +void KEditTagsDialog::showDeleteButton() +{ + m_deleteButton->show(); +} + +void KEditTagsDialog::deleteTag() +{ + Q_ASSERT(m_deleteCandidate != 0); + const QString text = i18nc("@info", + "Should the tag <resource>%1</resource> really be deleted for all files?", + m_deleteCandidate->text()); + const QString caption = i18nc("@title", "Delete tag"); + const KGuiItem deleteItem(i18nc("@action:button", "Delete"), KIcon("edit-delete")); + const KGuiItem cancelItem(i18nc("@action:button", "Cancel"), KIcon("dialog-cancel")); + if (KMessageBox::warningYesNo(this, text, caption, deleteItem, cancelItem) == KMessageBox::Yes) { + const QString label = m_deleteCandidate->data(Qt::UserRole).toString(); + Nepomuk::Tag tag(label); + tag.remove(); + + delete m_deleteCandidate; + m_deleteCandidate = 0; + } +} + +static bool tagLabelLessThan( const Nepomuk::Tag& t1, const Nepomuk::Tag& t2 ) +{ + return t1.genericLabel() < t2.genericLabel(); +} + +void KEditTagsDialog::loadTags() +{ + // load all available tags and mark those tags as checked + // that have been passed to the KEditTagsDialog + QList<Nepomuk::Tag> tags = Nepomuk::Tag::allTags(); + qSort( tags.begin(), tags.end(), tagLabelLessThan ); + + foreach (const Nepomuk::Tag& tag, tags) { + const QString label = tag.genericLabel(); + + QListWidgetItem* item = new QListWidgetItem(label, m_tagsList); + item->setData(Qt::UserRole, label); + + bool check = false; + foreach (const Nepomuk::Tag& selectedTag, m_tags) { + if (selectedTag == tag) { + check = true; + break; + } + } + item->setCheckState(check ? Qt::Checked : Qt::Unchecked); + } +} + +void KEditTagsDialog::removeNewTagItem() +{ + if (m_newTagItem != 0) { + const int row = m_tagsList->row(m_newTagItem); + m_tagsList->takeItem(row); + delete m_newTagItem; + m_newTagItem = 0; + } +} + +#include "kedittagsdialog_p.moc" Modification de propriétés sur nepomuk/ui/kedittagsdialog.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kmetadatatagwidget.h =================================================================== --- nepomuk/ui/kmetadatatagwidget.h (révision 0) +++ nepomuk/ui/kmetadatatagwidget.h (révision 0) @@ -0,0 +1,2 @@ +// backwards compatibility +#include "tagwidget.h" Modification de propriétés sur nepomuk/ui/kmetadatatagwidget.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/nepomukmassupdatejob.cpp =================================================================== --- nepomuk/ui/nepomukmassupdatejob.cpp (révision 0) +++ nepomuk/ui/nepomukmassupdatejob.cpp (révision 0) @@ -0,0 +1,164 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright 2008-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "nepomukmassupdatejob.h" + +#include "klocale.h" +#include "kdebug.h" + +#include "tag.h" +#include "tools.h" + + +Nepomuk::MassUpdateJob::MassUpdateJob( QObject* parent ) + : KJob( parent ), + m_index( -1 ) +{ + kDebug(); + setCapabilities( Killable|Suspendable ); + connect( &m_processTimer, SIGNAL( timeout() ), + this, SLOT( slotNext() ) ); +} + + +Nepomuk::MassUpdateJob::~MassUpdateJob() +{ + kDebug(); +} + + +void Nepomuk::MassUpdateJob::setFiles( const KUrl::List& urls ) +{ + m_resources.clear(); + foreach( const KUrl &url, urls ) { + m_resources.append( Resource( url ) ); + } + setTotalAmount( KJob::Files, m_resources.count() ); +} + + +void Nepomuk::MassUpdateJob::setResources( const QList<Nepomuk::Resource>& rl ) +{ + m_resources = rl; + setTotalAmount( KJob::Files, m_resources.count() ); +} + + +void Nepomuk::MassUpdateJob::setProperties( const QList<QPair<QUrl,Nepomuk::Variant> >& props ) +{ + m_properties = props; +} + + +void Nepomuk::MassUpdateJob::start() +{ + if ( m_index < 0 ) { + kDebug(); + emit description( this, + i18n("Changing annotations") ); + m_index = 0; + m_processTimer.start(); + } + else { + kDebug() << "Job has already been started"; + } +} + + +bool Nepomuk::MassUpdateJob::doKill() +{ + if ( m_index > 0 ) { + m_processTimer.stop(); + m_index = -1; + return true; + } + else { + return false; + } +} + + +bool Nepomuk::MassUpdateJob::doSuspend() +{ + m_processTimer.stop(); + return true; +} + + +bool Nepomuk::MassUpdateJob::doResume() +{ + if ( m_index > 0 ) { + m_processTimer.start(); + return true; + } + else { + return false; + } +} + + +void Nepomuk::MassUpdateJob::slotNext() +{ + if ( !isSuspended() ) { + if ( m_index < m_resources.count() ) { + Nepomuk::Resource& res = m_resources[m_index]; + for ( int i = 0; i < m_properties.count(); ++i ) { + res.setProperty( m_properties[i].first, m_properties[i].second ); + } + ++m_index; + setProcessedAmount( KJob::Files, m_index ); + } + else if ( m_index >= m_resources.count() ) { + kDebug() << "done"; + m_index = -1; + m_processTimer.stop(); + emitResult(); + } + } +} + + +Nepomuk::MassUpdateJob* Nepomuk::MassUpdateJob::tagResources( const QList<Nepomuk::Resource>& rl, const QList<Nepomuk::Tag>& tags ) +{ + Nepomuk::MassUpdateJob* job = new Nepomuk::MassUpdateJob(); + job->setResources( rl ); + job->setProperties( QList<QPair<QUrl,Nepomuk::Variant> >() << qMakePair( QUrl( Nepomuk::Resource::tagUri() ), Nepomuk::Variant( convertResourceList<Tag>( tags ) ) ) ); + return job; +} + + +Nepomuk::MassUpdateJob* Nepomuk::MassUpdateJob::rateResources( const QList<Nepomuk::Resource>& rl, int rating ) +{ + Nepomuk::MassUpdateJob* job = new Nepomuk::MassUpdateJob(); + job->setResources( rl ); + job->setProperties( QList<QPair<QUrl,Nepomuk::Variant> >() << qMakePair( QUrl( Nepomuk::Resource::ratingUri() ), Nepomuk::Variant( rating ) ) ); + return job; +} + +Nepomuk::MassUpdateJob* Nepomuk::MassUpdateJob::commentResources( const QList<Nepomuk::Resource>& rl, const QString& comment ) +{ + Nepomuk::MassUpdateJob* job = new Nepomuk::MassUpdateJob(); + job->setResources( rl ); + job->setProperties( QList<QPair<QUrl,Nepomuk::Variant> >() << qMakePair( QUrl( Nepomuk::Resource::descriptionUri() ), Nepomuk::Variant( comment ) ) ); + return job; +} + +#include "nepomukmassupdatejob.moc" Modification de propriétés sur nepomuk/ui/nepomukmassupdatejob.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/tagwidget_p.h =================================================================== --- nepomuk/ui/tagwidget_p.h (révision 0) +++ nepomuk/ui/tagwidget_p.h (révision 0) @@ -0,0 +1,70 @@ +/* + * This file is part of the Nepomuk KDE project. + * Copyright (C) 2006-2010 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_TAG_WIDGET_P_H_ +#define _NEPOMUK_TAG_WIDGET_P_H_ + +#include "tagwidget.h" +#include "tag.h" + +#include <QtCore/QList> +#include <QtCore/QMap> + +class QPushButton; +class QLabel; +class KBlockLayout; + +namespace Nepomuk { + +class TagCheckBox; + +class TagWidgetPrivate +{ +public: + void init( TagWidget* parent ); + void rebuild(); + void buildTagHash( const QList<Tag>& tags ); + QList<Tag> loadTags( int max ); + QList<Tag> intersectResourceTags(); + + /// lookup (and if necessary create) checkbox for tag + TagCheckBox* getTagCheckBox( const Tag& tag ); + + /// check the corresponding checkboxes and even + /// add missing checkboxes + void selectTags( const QList<Tag>& tags ); + + /// start a massupdate job to set the selected tags on the resources + void updateResources(); + + QList<Resource> m_resources; + int m_maxTags; + TagWidget::ModeFlags m_flags; + bool m_blockSelectionChangedSignal; + + QMap<Tag, TagCheckBox*> m_checkBoxHash; + QPushButton* m_showAllButton; + QLabel* m_showAllLinkLabel; + KBlockLayout* m_flowLayout; + TagWidget* q; +}; +} + +#endif Modification de propriétés sur nepomuk/ui/tagwidget_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kblocklayout.cpp =================================================================== --- nepomuk/ui/kblocklayout.cpp (révision 0) +++ nepomuk/ui/kblocklayout.cpp (révision 0) @@ -0,0 +1,264 @@ +/* + * 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. + */ + +/* + KBlockLayout is based on the FlowLayout example from QT4. + Copyright (C) 2004-2006 Trolltech ASA. All rights reserved. + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + All rights reserved. + Contact: Nokia Corporation (qt-info@nokia.com) +*/ + +#include "kblocklayout.h" + +#include <QtCore/QList> +#include <QtGui/QStyle> +#include <QtGui/QWidget> + +class KBlockLayout::Private +{ +public: + Private() + : alignment(Qt::AlignLeft|Qt::AlignTop) { + } + + int smartSpacing(QStyle::PixelMetric pm) const + { + QObject *parent = q->parent(); + if (!parent) { + return -1; + } else if (parent->isWidgetType()) { + QWidget *pw = static_cast<QWidget *>(parent); + return pw->style()->pixelMetric(pm, 0, pw); + } else { + return static_cast<QLayout *>(parent)->spacing(); + } + } + + QList<QLayoutItem*> itemList; + + int m_hSpace; + int m_vSpace; + + Qt::Alignment alignment; + + KBlockLayout* q; +}; + + +KBlockLayout::KBlockLayout( QWidget* parent, int margin, int hSpacing, int vSpacing ) + : QLayout(parent), + d( new Private() ) +{ + d->q = this; + setMargin(margin); + setSpacing(hSpacing, vSpacing); +} + +KBlockLayout::KBlockLayout( int margin, int hSpacing, int vSpacing ) + : d( new Private() ) +{ + d->q = this; + setMargin(margin); + setSpacing(hSpacing, vSpacing); +} + +KBlockLayout::~KBlockLayout() +{ + QLayoutItem* item; + while ((item = takeAt(0))) + delete item; + delete d; +} + +void KBlockLayout::setAlignment( Qt::Alignment a ) +{ + d->alignment = a; +} + +Qt::Alignment KBlockLayout::alignment() const +{ + return d->alignment; +} + +int KBlockLayout::horizontalSpacing() const +{ + if (d->m_hSpace >= 0) { + return d->m_hSpace; + } else { + return d->smartSpacing(QStyle::PM_LayoutHorizontalSpacing); + } +} + +int KBlockLayout::verticalSpacing() const +{ + if (d->m_vSpace >= 0) { + return d->m_vSpace; + } else { + return d->smartSpacing(QStyle::PM_LayoutVerticalSpacing); + } +} + +void KBlockLayout::setSpacing( int h, int v ) +{ + d->m_hSpace = h; + d->m_vSpace = v; + QLayout::setSpacing( h ); +} + +void KBlockLayout::addItem( QLayoutItem* item ) +{ + d->itemList.append(item); +} + +int KBlockLayout::count() const +{ + return d->itemList.size(); +} + +QLayoutItem *KBlockLayout::itemAt( int index ) const +{ + return d->itemList.value(index); +} + +QLayoutItem *KBlockLayout::takeAt( int index ) +{ + if (index >= 0 && index < d->itemList.size()) + return d->itemList.takeAt(index); + else + return 0; +} + +Qt::Orientations KBlockLayout::expandingDirections() const +{ + return 0; +} + +bool KBlockLayout::hasHeightForWidth() const +{ + return true; +} + +int KBlockLayout::heightForWidth( int width ) const +{ + int height = doLayout(QRect(0, 0, width, 0), true); + return height; +} + +void KBlockLayout::setGeometry( const QRect& rect ) +{ + QLayout::setGeometry(rect); + doLayout(rect, false); +} + +QSize KBlockLayout::sizeHint() const +{ + return minimumSize(); +} + +QSize KBlockLayout::minimumSize() const +{ + QSize size; + QLayoutItem *item; + foreach (item, d->itemList) { + const QSize itemSize = item->minimumSize(); + size.rwidth() += itemSize.width(); + if (itemSize.height() > size.height()) { + size.setHeight(itemSize.height()); + } + } + + size.rwidth() += horizontalSpacing() * d->itemList.count(); + size += QSize(2*margin(), 2*margin()); + return size; +} + +struct Row { + Row( const QList<QLayoutItem*>& i, int h, int w ) + : items(i), height(h), width(w) { + } + + QList<QLayoutItem*> items; + int height; + int width; +}; + +int KBlockLayout::doLayout( const QRect& rect, bool testOnly ) const +{ + int x = rect.x(); + int y = rect.y(); + int lineHeight = 0; + + // 1. calculate lines + QList<Row> rows; + QList<QLayoutItem*> rowItems; + for( int i = 0; i < d->itemList.count(); ++i ) { + QLayoutItem* item = d->itemList[i]; + int nextX = x + item->sizeHint().width() + horizontalSpacing(); + if (nextX - horizontalSpacing() > rect.right() && lineHeight > 0) { + rows.append( Row( rowItems, lineHeight, x - horizontalSpacing() ) ); + rowItems.clear(); + + x = rect.x(); + y = y + lineHeight + verticalSpacing(); + nextX = x + item->sizeHint().width() + horizontalSpacing(); + lineHeight = 0; + } + + rowItems.append( item ); + + x = nextX; + lineHeight = qMax(lineHeight, item->sizeHint().height()); + } + // append the last row + rows.append( Row( rowItems, lineHeight, x-horizontalSpacing() ) ); + + int finalHeight = y + lineHeight - rect.y(); + if( testOnly ) + return finalHeight; + + // 2. place the items + y = rect.y(); + foreach( const Row &row, rows ) { + x = rect.x(); + if( alignment() & Qt::AlignRight ) + x += (rect.width() - row.width); + else if( alignment() & Qt::AlignHCenter ) + x += (rect.width() - row.width)/2; + + foreach( QLayoutItem* item, row.items ) { + int yy = y; + if( alignment() & Qt::AlignBottom ) + yy += (row.height - item->sizeHint().height()); + else if( alignment() & Qt::AlignVCenter ) + yy += (row.height - item->sizeHint().height())/2; + item->setGeometry(QRect(QPoint(x, yy), item->sizeHint())); + + x += item->sizeHint().width() + horizontalSpacing(); + + if( alignment() & Qt::AlignJustify ) + x += (rect.width() - row.width)/qMax(row.items.count()-1,1); + } + + y = y + row.height + verticalSpacing(); + } + + return finalHeight; +} Modification de propriétés sur nepomuk/ui/kblocklayout.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kratingwidget.cpp =================================================================== --- nepomuk/ui/kratingwidget.cpp (révision 0) +++ nepomuk/ui/kratingwidget.cpp (révision 0) @@ -0,0 +1,261 @@ +/* + * 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 "kratingwidget.h" +#include "kratingpainter.h" + +#include <QtGui/QPainter> +#include <QtGui/QPixmap> +#include <QtGui/QKeyEvent> +#include <QtGui/QImage> +#include <QtGui/QIcon> + +#include <kiconeffect.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kstandarddirs.h> + +class KRatingWidget::Private +{ +public: + Private() + : rating(0), + hoverRating(-1), + pixSize( 16 ) { + } + + int rating; + int hoverRating; + int pixSize; + + KRatingPainter ratingPainter; +}; + + + +KRatingWidget::KRatingWidget( QWidget* parent ) + : QFrame( parent ), + d( new Private() ) +{ + setMouseTracking( true ); +} + + +KRatingWidget::~KRatingWidget() +{ + delete d; +} + + +void KRatingWidget::setPixmap( const QPixmap& pix ) +{ + setCustomPixmap( pix ); +} + + +void KRatingWidget::setCustomPixmap( const QPixmap& pix ) +{ + d->ratingPainter.setCustomPixmap( pix ); + update(); +} + + +void KRatingWidget::setIcon( const QIcon& icon ) +{ + d->ratingPainter.setIcon( icon ); + update(); +} + + +void KRatingWidget::setPixmapSize( int size ) +{ + d->pixSize = size; + updateGeometry(); +} + + +int KRatingWidget::spacing() const +{ + return d->ratingPainter.spacing(); +} + + +QIcon KRatingWidget::icon() const +{ + return d->ratingPainter.icon(); +} + + +void KRatingWidget::setSpacing( int s ) +{ + d->ratingPainter.setSpacing( s ); + update(); +} + + +Qt::Alignment KRatingWidget::alignment() const +{ + return d->ratingPainter.alignment(); +} + + +void KRatingWidget::setAlignment( Qt::Alignment align ) +{ + d->ratingPainter.setAlignment( align ); + update(); +} + + +Qt::LayoutDirection KRatingWidget::layoutDirection() const +{ + return d->ratingPainter.layoutDirection(); +} + + +void KRatingWidget::setLayoutDirection( Qt::LayoutDirection direction ) +{ + d->ratingPainter.setLayoutDirection( direction ); + update(); +} + + +unsigned int KRatingWidget::rating() const +{ + return d->rating; +} + + +int KRatingWidget::maxRating() const +{ + return d->ratingPainter.maxRating(); +} + + +bool KRatingWidget::halfStepsEnabled() const +{ + return d->ratingPainter.halfStepsEnabled(); +} + + +void KRatingWidget::setRating( unsigned int rating ) +{ + setRating( (int)rating ); +} + + +void KRatingWidget::setRating( int rating ) +{ + if ( rating != d->rating ) { + d->rating = rating; + d->hoverRating = rating; + emit ratingChanged( rating ); + emit ratingChanged( (unsigned int)rating ); + update(); + } +} + + +void KRatingWidget::setMaxRating( unsigned int max ) +{ + setMaxRating( (int)max ); +} + + +void KRatingWidget::setMaxRating( int max ) +{ + d->ratingPainter.setMaxRating( max ); + update(); +} + + +void KRatingWidget::setHalfStepsEnabled( bool enabled ) +{ + d->ratingPainter.setHalfStepsEnabled( enabled ); + update(); +} + + +void KRatingWidget::setOnlyPaintFullSteps( bool fs ) +{ + setHalfStepsEnabled( !fs ); +} + + +void KRatingWidget::mousePressEvent( QMouseEvent* e ) +{ + if ( e->button() == Qt::LeftButton ) { + d->hoverRating = d->ratingPainter.ratingFromPosition( contentsRect(), e->pos() ); + setRating( d->hoverRating ); + } +} + + +void KRatingWidget::mouseMoveEvent( QMouseEvent* e ) +{ + // when moving the mouse we show the user what the result of clicking will be + const int prevHoverRating = d->hoverRating; + d->hoverRating = d->ratingPainter.ratingFromPosition( contentsRect(), e->pos() ); + if ( d->hoverRating != prevHoverRating ) { + update(); + } + if ( d->hoverRating >= 0 && e->buttons() & Qt::LeftButton ) { + setRating( d->hoverRating ); + } +} + + +void KRatingWidget::leaveEvent( QEvent* ) +{ + d->hoverRating = -1; + update(); +} + + +void KRatingWidget::paintEvent( QPaintEvent* e ) +{ + QFrame::paintEvent( e ); + QPainter p( this ); + d->ratingPainter.setEnabled( isEnabled() ); + d->ratingPainter.paint( &p, contentsRect(), d->rating, d->hoverRating ); +} + + +QSize KRatingWidget::sizeHint() const +{ + int numPix = d->ratingPainter.maxRating(); + if( d->ratingPainter.halfStepsEnabled() ) + numPix /= 2; + + QSize pixSize( d->pixSize, d->pixSize ); + if ( !d->ratingPainter.customPixmap().isNull() ) { + pixSize = d->ratingPainter.customPixmap().size(); + } + + return QSize( pixSize.width()*numPix + spacing()*(numPix-1) + frameWidth()*2, + pixSize.height() + frameWidth()*2 ); +} + + +void KRatingWidget::resizeEvent( QResizeEvent* e ) +{ + QFrame::resizeEvent( e ); +} + +#include "kratingwidget.moc" Modification de propriétés sur nepomuk/ui/kratingwidget.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/nepomukmassupdatejob.h =================================================================== --- nepomuk/ui/nepomukmassupdatejob.h (révision 0) +++ nepomuk/ui/nepomukmassupdatejob.h (révision 0) @@ -0,0 +1,103 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright 2008-2009 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _NEPOMUK_MASS_UPDATE_JOB_H_ +#define _NEPOMUK_MASS_UPDATE_JOB_H_ + +#include "kjob.h" +#include "kurl.h" + +#include <QtCore/QList> +#include <QtCore/QPair> +#include <QtCore/QTimer> + +#include "resource.h" +#include "variant.h" + + +namespace Nepomuk { + /** + * \class MassUpdateJob nepomukmassupdatejob.h Nepomuk/MassUpdateJob + * + * \brief A KJob to set Nepomuk properties on a set of resources at once. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT MassUpdateJob : public KJob + { + Q_OBJECT + + public: + /** + * Default constructor. Normally there is no need to use this. + * Use tagResources(), rateResources(), or commentResources() + * instead. + */ + MassUpdateJob( QObject* parent = 0 ); + + /** + * Destructor + */ + ~MassUpdateJob(); + + /** + * Set a list of files to change + * This has the same effect as using setResources + * with a list of manually created resources. + */ + void setFiles( const KUrl::List& urls ); + + /** + * Set a list of resources to change. + */ + void setResources( const QList<Nepomuk::Resource>& ); + + /** + * Set the properties to change in the mass update. + */ + void setProperties( const QList<QPair<QUrl, Nepomuk::Variant> >& props ); + + /** + * Actually start the job. + */ + void start(); + + static MassUpdateJob* tagResources( const QList<Nepomuk::Resource>&, const QList<Nepomuk::Tag>& tags ); + static MassUpdateJob* rateResources( const QList<Nepomuk::Resource>&, int rating ); + static MassUpdateJob* commentResources( const QList<Nepomuk::Resource>&, const QString& comment); + + protected: + bool doKill(); + bool doSuspend(); + bool doResume(); + + private Q_SLOTS: + void slotNext(); + + private: + QList<Nepomuk::Resource> m_resources; + QList<QPair<QUrl,Nepomuk::Variant> > m_properties; + int m_index; + QTimer m_processTimer; + }; +} + +#endif Modification de propriétés sur nepomuk/ui/nepomukmassupdatejob.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kblocklayout.h =================================================================== --- nepomuk/ui/kblocklayout.h (révision 0) +++ nepomuk/ui/kblocklayout.h (révision 0) @@ -0,0 +1,76 @@ +/* + * 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. + */ + +/* + KBlockLayout is based on the FlowLayout example from QT4. + Copyright (C) 2004-2006 Trolltech ASA. All rights reserved. +*/ + +#ifndef KBLOCKLAYOUT_H +#define KBLOCKLAYOUT_H + +#include <QtGui/QLayout> +#include <QtGui/QLayoutItem> + +/** + * The KBlockLayout arranges widget in rows and columns like a text + * editor does. + */ +class KBlockLayout : public QLayout +{ + public: + explicit KBlockLayout( QWidget *parent, int margin = 0, int hSpacing = -1, int vSpacing = -1 ); + KBlockLayout( int margin = 0, int hSpacing = -1, int vSpacing = -1 ); + ~KBlockLayout(); + + /** + * Set the alignment to use. It can be a combination of a horizontal and + * a vertical alignment flag. The vertical flag is used to arrange widgets + * that do not fill the complete height of a row. + * + * The default alignment is Qt::AlignLeft|Qt::AlignTop + */ + void setAlignment( Qt::Alignment ); + Qt::Alignment alignment() const; + + int horizontalSpacing() const; + int verticalSpacing() const; + + void setSpacing( int h, int v ); + + void addItem( QLayoutItem* item ); + Qt::Orientations expandingDirections() const; + bool hasHeightForWidth() const; + int heightForWidth(int) const; + int count() const; + QLayoutItem* itemAt( int index ) const; + QSize minimumSize() const; + void setGeometry( const QRect& rect ); + QSize sizeHint() const; + QLayoutItem* takeAt( int index ); + + private: + int doLayout( const QRect& rect, bool testOnly ) const; + + class Private; + Private* const d; +}; + +#endif Modification de propriétés sur nepomuk/ui/kblocklayout.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kratingwidget.h =================================================================== --- nepomuk/ui/kratingwidget.h (révision 0) +++ nepomuk/ui/kratingwidget.h (révision 0) @@ -0,0 +1,202 @@ +/* + * 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 KRATINGWIDGET_H +#define KRATINGWIDGET_H + +#include <QtGui/QFrame> + +#include "nepomuk_export.h" + +/** + * \class KRatingWidget kratingwidget.h Nepomuk/KRatingWidget + * + * \brief Displays a rating value as a row of pixmaps. + * + * The KRatingWidget displays a range of stars or other arbitrary + * pixmaps and allows the user to select a certain number by mouse. + * + * \sa KRatingPainter + * + * \author Sebastian Trueg <trueg@kde.org> + */ +class NEPOMUK_EXPORT KRatingWidget : public QFrame +{ + Q_OBJECT + + public: + /** + * Creates a new rating widget. + */ + KRatingWidget( QWidget* parent = 0 ); + + /** + * Destructor + */ + ~KRatingWidget(); + + /** + * \return The current rating. + */ + unsigned int rating() const; + + /** + * \return the maximum possible rating. + */ + int maxRating() const; + + /** + * The alignment of the stars. + * + * \sa setAlignment + */ + Qt::Alignment alignment() const; + + /** + * The layout direction. If RTL the stars + * representing the rating value will be drawn from the + * right. + * + * \sa setLayoutDirection + */ + Qt::LayoutDirection layoutDirection() const; + + /** + * The spacing between the rating stars. + * + * \sa setSpacing + */ + int spacing() const; + + QSize sizeHint() const; + + /** + * If half steps are enabled one star equals to 2 rating + * points and uneven rating values result in half-stars being + * drawn. + * + * \sa setHalfStepsEnabled + */ + bool halfStepsEnabled() const; + + /** + * The icon used to draw a star. In case a custom pixmap has been set + * this value is ignored. + * + * \sa setIcon, setCustomPixmap + */ + QIcon icon() const; + + Q_SIGNALS: + /** + * This signal is emitted when the rating is changed. + */ + void ratingChanged( unsigned int rating ); + void ratingChanged( int rating ); + + public Q_SLOTS: + /** + * Set the current rating. Calling this method will trigger the + * ratingChanged signal if @p rating is different from the previous rating. + */ + void setRating( int rating ); + + /** + * \deprecated use setRating( int rating ) + */ + KDE_DEPRECATED void setRating( unsigned int rating ); + + /** + * Set the maximum allowed rating value. The default is 10 which means + * that a rating from 1 to 10 is selectable. If \a max is uneven steps + * are automatically only allowed full. + */ + void setMaxRating( int max ); + + /** + * \deprecated use setMaxRating( int max ) + */ + KDE_DEPRECATED void setMaxRating( unsigned int max ); + + /** + * If half steps are enabled (the default) then + * one rating step corresponds to half a star. + */ + void setHalfStepsEnabled( bool enabled ); + + /** + * \deprecated Use setHalfStepsEnabled + */ + KDE_DEPRECATED void setOnlyPaintFullSteps( bool ); + + /** + * Set the spacing between the pixmaps. The default is 0. + */ + void setSpacing( int ); + + /** + * The alignment of the stars in the drawing rect. + * All alignment flags are supported. + */ + void setAlignment( Qt::Alignment align ); + + /** + * LTR or RTL + */ + void setLayoutDirection( Qt::LayoutDirection direction ); + + /** + * Set a custom icon. Defaults to "rating". + */ + void setIcon( const QIcon& icon ); + + /** + * Set a custom pixmap. + */ + void setCustomPixmap( const QPixmap& pixmap ); + + /** + * Set the pixap to be used to display a rating step. + * By default the "rating" pixmap is loaded. + * + * \deprecated use setCustomPixmap + */ + KDE_DEPRECATED void setPixmap( const QPixmap& ); + + /** + * Set the recommended size of the pixmaps. This is + * only used for the sizeHint. The actual size is always + * dependent on the size of the widget itself. + */ + void setPixmapSize( int size ); + + protected: + void mousePressEvent( QMouseEvent* e ); + void mouseMoveEvent( QMouseEvent* e ); + void leaveEvent( QEvent* e ); + void paintEvent( QPaintEvent* e ); + void resizeEvent( QResizeEvent* e ); + + private: + class Private; + Private* const d; +}; + +#endif Modification de propriétés sur nepomuk/ui/kratingwidget.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kmetadatatagcloud.cpp =================================================================== --- nepomuk/ui/kmetadatatagcloud.cpp (révision 0) +++ nepomuk/ui/kmetadatatagcloud.cpp (révision 0) @@ -0,0 +1,109 @@ +/* + * 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 "kmetadatatagcloud.h" +#include "resourcemanager.h" + +#include "tag.h" + +#include <QtCore/QTimer> + +#include <Soprano/Model> + + +class Nepomuk::TagCloud::Private +{ +public: + Private() + : autoUpdate(false) { + } + QTimer* updateTimer; + bool autoUpdate; +}; + + +Nepomuk::TagCloud::TagCloud( QWidget* parent ) + : KTagCloudWidget( parent ), + d( new Private() ) +{ + updateTags(); + setAutoUpdate( true ); +} + + +Nepomuk::TagCloud::~TagCloud() +{ + delete d; +} + + +bool Nepomuk::TagCloud::autoUpdate() const +{ + return d->autoUpdate; +} + + +void Nepomuk::TagCloud::updateTags() +{ + // clear the tag cloud + clear(); + + // retrieve the list of all tags + QList<Tag> tags = Tag::allTags(); + + // count the number of usages of the tags and add them to the cloud + for( QList<Tag>::iterator it = tags.begin(); + it != tags.end(); ++it ) { + Tag& tag = *it; + if ( tag.label().isEmpty() ) { + tag.setLabel( tag.genericLabel() ); + } + addTag( tag.label(), tag.tagOf().count() ); + } +} + + +void Nepomuk::TagCloud::setAutoUpdate( bool enable ) +{ + if ( enable != d->autoUpdate ) { + if( !enable ) { + disconnect( ResourceManager::instance()->mainModel(), SIGNAL(statementsAdded()), + this, SLOT(updateTags()) ); + disconnect( ResourceManager::instance()->mainModel(), SIGNAL(statementsRemoved()), + this, SLOT(updateTags()) ); + } + else { + connect( ResourceManager::instance()->mainModel(), SIGNAL(statementsAdded()), + this, SLOT(updateTags()) ); + connect( ResourceManager::instance()->mainModel(), SIGNAL(statementsRemoved()), + this, SLOT(updateTags()) ); + } + + d->autoUpdate = enable; + } +} + + +void Nepomuk::TagCloud::slotTagClicked( const QString& tag ) +{ + emit tagClicked( Tag(tag) ); +} + +#include "kmetadatatagcloud.moc" Modification de propriétés sur nepomuk/ui/kmetadatatagcloud.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/tagwidget.cpp =================================================================== --- nepomuk/ui/tagwidget.cpp (révision 0) +++ nepomuk/ui/tagwidget.cpp (révision 0) @@ -0,0 +1,387 @@ +/* + * This file is part of the Nepomuk KDE project. + * Copyright (C) 2006-2010 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 "tagwidget.h" +#include "tagwidget_p.h" +#include "kblocklayout.h" +#include "nepomukmassupdatejob.h" +#include "kedittagsdialog_p.h" +#include "tagcheckbox.h" + +#include "tools.h" +#include "tag.h" +#include "resourcemanager.h" + +#include <karrowbutton.h> +#include <kinputdialog.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kglobalsettings.h> +#include <kdebug.h> + +#include <QtGui/QPushButton> +#include <QtGui/QBoxLayout> +#include <QtGui/QLabel> +#include <QtCore/QSet> + +#include <Soprano/QueryResultIterator> +#include <Soprano/Node> +#include <Soprano/Model> +#include <Soprano/Vocabulary/NAO> + + +void Nepomuk::TagWidgetPrivate::init( TagWidget* parent ) +{ + q = parent; + m_maxTags = 10; + m_flags = TagWidget::StandardMode; + m_blockSelectionChangedSignal = false; + m_showAllLinkLabel = 0; + + QGridLayout* mainLayout = new QGridLayout( q ); + mainLayout->setMargin(0); + m_flowLayout = new KBlockLayout( 0, KDialog::spacingHint()*3 ); + m_showAllButton = new QPushButton( i18nc("@label", "Show all tags..."), q ); + q->connect( m_showAllButton, SIGNAL(clicked()), SLOT(slotShowAll()) ); + mainLayout->addLayout( m_flowLayout, 0, 0, 1, 2 ); + mainLayout->addWidget( m_showAllButton, 1, 1, 1, 1 ); + mainLayout->setColumnStretch( 0, 1 ); + + rebuild(); +} + + +void Nepomuk::TagWidgetPrivate::rebuild() +{ + if( m_flags & TagWidget::MiniMode ) { + buildTagHash( q->selectedTags() ); + } + else { + QList<Tag> tags = q->selectedTags(); + buildTagHash( loadTags( m_maxTags ) ); + selectTags( tags ); + } +} + + +void Nepomuk::TagWidgetPrivate::buildTagHash( const QList<Tag>& tags ) +{ + qDeleteAll(m_checkBoxHash); + m_checkBoxHash.clear(); + + foreach( const Nepomuk::Tag& tag, tags ) { + getTagCheckBox( tag ); + } + + delete m_showAllLinkLabel; + m_showAllLinkLabel = 0; + + if( m_flags & TagWidget::MiniMode ) { + if( !(m_flags&TagWidget::ReadOnly) ) { + m_showAllLinkLabel = new QLabel( q ); + m_flowLayout->addWidget( m_showAllLinkLabel ); + QFont f(q->font()); + f.setUnderline(true); + m_showAllLinkLabel->setFont(f); + m_showAllLinkLabel->setText( QLatin1String("<a href=\"add_tags\">") + + ( m_checkBoxHash.isEmpty() ? i18nc("@label", "Add Tags...") : i18nc("@label", "Change...") ) + + QLatin1String("</a>") ); + q->connect( m_showAllLinkLabel, SIGNAL(linkActivated(QString)), SLOT(slotShowAll()) ); + m_showAllButton->hide(); + } + } + else { + m_showAllButton->setShown( !(m_flags&TagWidget::ReadOnly) ); + } +} + + +QList<Nepomuk::Tag> Nepomuk::TagWidgetPrivate::loadTags( int max ) +{ + // get the "max" first tags with the most resources + QString query = QString::fromLatin1("select ?r count(distinct ?f) as ?c where { " + "?r a %1 . " + "?f %2 ?r . " + "} ORDER BY DESC(?c) LIMIT %3") + .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::Tag()), + Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::hasTag())) + .arg( max ); + QList<Nepomuk::Tag> tags; + Soprano::QueryResultIterator it = ResourceManager::instance()->mainModel()->executeQuery( query, Soprano::Query::QueryLanguageSparql ); + while( it.next() ) { + // workaround for bug in Virtuoso where resources are returned as strings if a count() is in the select clause + tags << Tag( KUrl(it["r"].toString()) ); + } + return tags; +} + + +QList<Nepomuk::Tag> Nepomuk::TagWidgetPrivate::intersectResourceTags() +{ + if ( m_resources.count() == 1 ) { + return m_resources.first().tags(); + } + else if ( !m_resources.isEmpty() ) { + // determine the tags used for all resources + QSet<Tag> tags = QSet<Tag>::fromList( m_resources.first().tags() ); + QList<Resource>::const_iterator it = m_resources.constBegin(); + for ( ++it; it != m_resources.constEnd(); ++it ) { + tags.intersect( QSet<Tag>::fromList( (*it).tags() ) ); + } + return tags.values(); + } + else { + return QList<Tag>(); + } +} + + +Nepomuk::TagCheckBox* Nepomuk::TagWidgetPrivate::getTagCheckBox( const Tag& tag ) +{ + QMap<Tag, TagCheckBox*>::iterator it = m_checkBoxHash.find(tag); + if( it == m_checkBoxHash.end() ) { + kDebug() << "Creating checkbox for" << tag.genericLabel(); + TagCheckBox* checkBox = new TagCheckBox( tag, this, q ); + q->connect( checkBox, SIGNAL(tagClicked(Nepomuk::Tag)), SIGNAL(tagClicked(Nepomuk::Tag)) ); + q->connect( checkBox, SIGNAL(tagStateChanged(Nepomuk::Tag, int)), SLOT(slotTagStateChanged(Nepomuk::Tag, int)) ); + m_checkBoxHash.insert( tag, checkBox ); + m_flowLayout->addWidget( checkBox ); + return checkBox; + } + else { + return it.value(); + } +} + +namespace Nepomuk { +/// operator necessary for QMap::erase +bool operator<(const Tag& t1, const Tag& t2) { + return t1.resourceUri() < t2.resourceUri(); +} +} + +void Nepomuk::TagWidgetPrivate::selectTags( const QList<Tag>& tags ) +{ + m_blockSelectionChangedSignal = true; + + if( m_flags & TagWidget::MiniMode ) { + buildTagHash( tags ); + } + else { + foreach( TagCheckBox* checkBox, m_checkBoxHash ) { + checkBox->setChecked( false ); + } + + foreach( const Tag& tag, tags ) { + getTagCheckBox(tag)->setChecked( true ); + } + + // remove the previously added check boxes which are not amongst + // the top 10 or remove as many check boxes as possible to get down to + // m_maxTags + if( !m_checkBoxHash.isEmpty() ) { + int r = qMax( m_checkBoxHash.count() - m_maxTags, 0 ); + QMap<Tag, TagCheckBox*>::iterator it = m_checkBoxHash.end(); + --it; + while( r > 0 ) { + + // stop the loop when we reach the beginning of the hash + bool end = ( it == m_checkBoxHash.begin() ); + + // remove unused checkboxes + if( !it.value()->isChecked() ) { + delete it.value(); + it = m_checkBoxHash.erase(it); + --r; + } + + if( end ) { + break; + } + else { + --it; + } + } + } + } + + m_blockSelectionChangedSignal = false; +} + + +void Nepomuk::TagWidgetPrivate::updateResources() +{ + if ( !m_resources.isEmpty() ) { + Nepomuk::MassUpdateJob* job = Nepomuk::MassUpdateJob::tagResources( m_resources, q->selectedTags() ); + q->connect( job, SIGNAL( result( KJob* ) ), + SLOT( slotTagUpdateDone() ) ); + q->setEnabled( false ); // no updates during execution + job->start(); + } +} + + +Nepomuk::TagWidget::TagWidget( const Resource& resource, QWidget* parent ) + : QWidget( parent ), + d( new TagWidgetPrivate() ) +{ + d->init( this ); + setTaggedResource( resource ); +} + + +Nepomuk::TagWidget::TagWidget( QWidget* parent ) + : QWidget( parent ), + d( new TagWidgetPrivate() ) +{ + d->init( this ); +} + + +Nepomuk::TagWidget::~TagWidget() +{ + delete d; +} + + +QList<Nepomuk::Resource> Nepomuk::TagWidget::taggedResources() const +{ + return d->m_resources; +} + + +QList<Nepomuk::Tag> Nepomuk::TagWidget::assignedTags() const +{ + return selectedTags(); +} + + +QList<Nepomuk::Tag> Nepomuk::TagWidget::selectedTags() const +{ + QList<Nepomuk::Tag> tags; + QMapIterator<Tag, TagCheckBox*> it( d->m_checkBoxHash ); + while( it.hasNext() ) { + it.next(); + if( it.value()->isChecked() ) + tags << it.key(); + } + return tags; +} + + +int Nepomuk::TagWidget::maxTagsShown() const +{ + return d->m_maxTags; +} + + +Qt::Alignment Nepomuk::TagWidget::alignment() const +{ + return d->m_flowLayout->alignment(); +} + + +Nepomuk::TagWidget::ModeFlags Nepomuk::TagWidget::modeFlags() const +{ + return d->m_flags; +} + + +void Nepomuk::TagWidget::setTaggedResource( const Resource& resource ) +{ + QList<Resource> l; + l.append( resource ); + setTaggedResources( l ); +} + + +void Nepomuk::TagWidget::setTaggedResources( const QList<Resource>& resources ) +{ + // reset selection to a sensible default + d->buildTagHash( d->loadTags( d->m_maxTags ) ); + + d->m_resources = resources; + if ( !resources.isEmpty() ) { + d->selectTags( d->intersectResourceTags() ); + } + else { + d->selectTags( QList<Tag>() ); + } +} + + +void Nepomuk::TagWidget::setAssignedTags( const QList<Tag>& tags ) +{ + setSelectedTags( tags ); +} + + +void Nepomuk::TagWidget::setSelectedTags( const QList<Nepomuk::Tag>& tags ) +{ + d->selectTags( tags ); + d->updateResources(); +} + + +void Nepomuk::TagWidget::setMaxTagsShown( int max ) +{ + d->m_maxTags = max; + setTaggedResources( d->m_resources ); +} + + +void Nepomuk::TagWidget::setAlignment( Qt::Alignment alignment ) +{ + d->m_flowLayout->setAlignment( alignment ); +} + + +void Nepomuk::TagWidget::setModeFlags( ModeFlags flags ) +{ + d->m_flags = flags; + d->rebuild(); +} + + +void Nepomuk::TagWidget::slotTagUpdateDone() +{ + setEnabled( true ); +} + + +void Nepomuk::TagWidget::slotShowAll() +{ + KEditTagsDialog dlg( selectedTags(), this ); + if( dlg.exec() ) { + setSelectedTags( dlg.tags() ); + emit selectionChanged( selectedTags() ); + } +} + + +void Nepomuk::TagWidget::slotTagStateChanged( const Nepomuk::Tag&, int ) +{ + if( !d->m_blockSelectionChangedSignal ) { + d->updateResources(); + emit selectionChanged( selectedTags() ); + } +} + +#include "tagwidget.moc" Modification de propriétés sur nepomuk/ui/tagwidget.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/ktagdisplaywidget.cpp =================================================================== --- nepomuk/ui/ktagdisplaywidget.cpp (révision 0) +++ nepomuk/ui/ktagdisplaywidget.cpp (révision 0) @@ -0,0 +1,119 @@ +/* + * 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 "ktagdisplaywidget.h" + +#include <kurllabel.h> + +#include <QtGui/QBoxLayout> + + +class KTagDisplayWidget::Private +{ +public: + Private( KTagDisplayWidget* _parent ) + : parent( _parent ) { + layout = new QHBoxLayout( parent ); + layout->setMargin( 0 ); + } + + void buildDisplay() { + // delete all the children + foreach( QWidget* w, wl ) + delete w; + wl.clear(); + + // remove the stretch we added in the last call + if ( QLayoutItem* item = layout->takeAt( 0 ) ) + delete item; + + // create new labels + for( QStringList::const_iterator it = tags.constBegin(); + it != tags.constEnd(); ++it ) { + if ( it != tags.constBegin() ) { + QLabel* label = new QLabel( "-", parent ); + wl.append( label ); + layout->addWidget( label ); // FIXME: display some nicer symbol like a big dot + } + KUrlLabel* label = new KUrlLabel( *it, *it, parent ); + wl.append( label ); + label->setUnderline( false ); + layout->addWidget( label ); + + connect( label, SIGNAL(leftClickedUrl(const QString&)), + parent, SIGNAL(tagClicked(const QString&)) ); + } + + layout->addStretch( 1 ); + } + + QStringList tags; + QList<QWidget*> wl; + QHBoxLayout* layout; + +private: + KTagDisplayWidget* parent; +}; + + +KTagDisplayWidget::KTagDisplayWidget( QWidget* parent ) + : QWidget( parent ), + d( new Private( this ) ) +{ +} + + +KTagDisplayWidget::~KTagDisplayWidget() +{ + delete d; +} + + +void KTagDisplayWidget::setTags( const QStringList& tags ) +{ + d->tags = tags; + d->buildDisplay(); +} + + +void KTagDisplayWidget::addTag( const QString& tag ) +{ + if ( !d->tags.contains( tag ) ) + d->tags.append( tag ); + d->buildDisplay(); +} + + +void KTagDisplayWidget::addTags( const QStringList& tags ) +{ + foreach( const QString &tag, tags ) + if ( !d->tags.contains( tag ) ) + d->tags.append( tag ); + d->buildDisplay(); +} + + +void KTagDisplayWidget::clear() +{ + d->tags.clear(); + d->buildDisplay(); +} + +#include "ktagdisplaywidget.moc" Modification de propriétés sur nepomuk/ui/ktagdisplaywidget.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/ktagcloudwidget.cpp =================================================================== --- nepomuk/ui/ktagcloudwidget.cpp (révision 0) +++ nepomuk/ui/ktagcloudwidget.cpp (révision 0) @@ -0,0 +1,179 @@ +/* + * 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 "ktagcloudwidget.h" +#include "kblocklayout.h" + +#include <kurllabel.h> + +#include <QtGui/QBoxLayout> + + +class KTagCloudWidget::Private +{ +public: + Private() + : minFontSize(8), + maxFontSize(22) { + } + + QMap<QString,int> tagMap; + QMap<QString,KUrlLabel*> labelMap; + QMap<QString,double> weightMap; + + KBlockLayout* mainLay; + + int minFontSize; + int maxFontSize; + + void buildWeightMap() { + weightMap.clear(); + + int max = 0; + int min = 0; + + // determine max + for( QMap<QString,int>::const_iterator it = tagMap.constBegin(); + it != tagMap.constEnd(); ++it ) { + max = qMax( max, it.value() ); + min = qMin( min, it.value() ); + } + + // normalize weights + for( QMap<QString,int>::const_iterator it = tagMap.constBegin(); + it != tagMap.constEnd(); ++it ) { + weightMap[it.key()] = (double)(it.value() - min) / (double)qMax(max - min, 1); + } + } + + KUrlLabel* createLabel( QWidget* parent, const QString& tag ) { + KUrlLabel* label = new KUrlLabel( tag, tag, parent ); + QFont font( label->font() ); + font.setPointSize( minFontSize + (int)((double)(maxFontSize-minFontSize)*weightMap[tag]) ); + if( weightMap[tag] > 0.8 ) + font.setBold( true ); + label->setFont( font ); + label->setUnderline(false); + return label; + } +}; + + +KTagCloudWidget::KTagCloudWidget( QWidget* parent ) + : QWidget( parent ), + d( new Private() ) +{ + d->mainLay = new KBlockLayout( this ); + d->mainLay->setAlignment( Qt::AlignJustify|Qt::AlignVCenter ); +} + + +KTagCloudWidget::~KTagCloudWidget() +{ + delete d; +} + + +void KTagCloudWidget::setMaxFontSize( int pointSize ) +{ + d->maxFontSize = pointSize; + buildTagCloud(); +} + + +void KTagCloudWidget::setMinFontSize( int pointSize ) +{ + d->minFontSize = pointSize; + buildTagCloud(); +} + + +int KTagCloudWidget::tagWeight( const QString& tag ) const +{ + return d->tagMap[tag]; +} + + +void KTagCloudWidget::addTag( const QString& tag, int weight ) +{ + d->tagMap[tag] = weight; + buildTagCloud(); +} + + +void KTagCloudWidget::addTags( const QMap<QString,int>& tags ) +{ + for( QMap<QString,int>::const_iterator it = tags.constBegin(); + it != tags.constEnd(); ++it ) + d->tagMap[it.key()] = it.value(); + buildTagCloud(); +} + + +void KTagCloudWidget::clear() +{ + d->tagMap.clear(); + buildTagCloud(); +} + + +void KTagCloudWidget::resizeEvent( QResizeEvent* e ) +{ + QWidget::resizeEvent( e ); +} + + +void KTagCloudWidget::buildTagCloud() +{ + // Brute force: delete all existing labels + for( QMap<QString,KUrlLabel*>::iterator it = d->labelMap.begin(); + it != d->labelMap.end(); ++it ) + delete it.value(); + + d->labelMap.clear(); + + d->buildWeightMap(); + + // now rebuild the cloud + QStringList tags; + for( QMap<QString,int>::const_iterator it = d->tagMap.constBegin(); + it != d->tagMap.constEnd(); ++it ) { + tags.append( it.key() ); + d->labelMap[it.key()] = d->createLabel( this, it.key() ); + connect( d->labelMap[it.key()], SIGNAL(leftClickedUrl(const QString&)), + this, SIGNAL(tagClicked(const QString&)) ); + } + + // for now we display the tags sorted alphabetically + qSort( tags.begin(), tags.end() ); + + int x = 0; + foreach( const QString &tag, tags ) { + KUrlLabel* label = d->labelMap[tag]; + if( x + label->width() > width() ) { + // new line + x = 0; + } + d->mainLay->addWidget( label ); + x += label->width(); + } +} + +#include "ktagcloudwidget.moc" Modification de propriétés sur nepomuk/ui/ktagcloudwidget.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/tagcheckbox.cpp =================================================================== --- nepomuk/ui/tagcheckbox.cpp (révision 0) +++ nepomuk/ui/tagcheckbox.cpp (révision 0) @@ -0,0 +1,169 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "tagcheckbox.h" +#include "tagwidget.h" +#include "tagwidget_p.h" + +#include <kcursor.h> +#include <kcolorscheme.h> +#include <kglobalsettings.h> + +#include <QtGui/QMouseEvent> +#include <QtGui/QStyleOptionButton> +#include <QtGui/QHBoxLayout> +#include <QtGui/QCheckBox> +#include <QtGui/QLabel> + + +class Nepomuk::TagCheckBox::CheckBoxWithPublicInitStyleOption : public QCheckBox +{ +public: + CheckBoxWithPublicInitStyleOption( const QString& text, QWidget* parent ) + : QCheckBox( text, parent ) { + } + + void initStyleOption( QStyleOptionButton* so ) { + QCheckBox::initStyleOption( so ); + } +}; + + +Nepomuk::TagCheckBox::TagCheckBox( const Tag& tag, TagWidgetPrivate* tagWidget, QWidget* parent ) + : QWidget( parent ), + m_label(0), + m_checkBox(0), + m_tag(tag), + m_urlHover(false), + m_tagWidget(tagWidget) +{ + QHBoxLayout* layout = new QHBoxLayout(this); + layout->setMargin(0); + if( tagWidget->m_flags & TagWidget::MiniMode ) { + setFont(KGlobalSettings::smallestReadableFont()); + m_label = new QLabel( tag.genericLabel(), this ); + m_label->setMouseTracking(true); + m_child = m_label; + } + else { + m_checkBox = new CheckBoxWithPublicInitStyleOption( tag.genericLabel(), this ); + m_child = m_checkBox; + connect(m_checkBox, SIGNAL(stateChanged(int)), this, SLOT(slotStateChanged(int))); + } + m_child->installEventFilter( this ); + m_child->setMouseTracking(true); + layout->addWidget( m_child ); + m_font = font(); +} + + +Nepomuk::TagCheckBox::~TagCheckBox() +{ +} + + +bool Nepomuk::TagCheckBox::isChecked() const +{ + if( m_checkBox ) + return m_checkBox->isChecked(); + else + return true; +} + + +void Nepomuk::TagCheckBox::setChecked( bool checked ) +{ + if( m_checkBox ) + m_checkBox->setChecked( checked ); +} + + +void Nepomuk::TagCheckBox::leaveEvent( QEvent* event ) +{ + QWidget::leaveEvent( event ); + enableUrlHover( false ); +} + + +bool Nepomuk::TagCheckBox::eventFilter( QObject* watched, QEvent* event ) +{ + if( watched == m_child ) { + switch( event->type() ) { + case QEvent::MouseMove: { + QMouseEvent* me = static_cast<QMouseEvent*>(event); + if( !(m_tagWidget->m_flags & TagWidget::DisableTagClicking) ) + enableUrlHover( tagRect().contains(me->pos()) ); + } + + case QEvent::MouseButtonRelease: { + QMouseEvent* me = static_cast<QMouseEvent*>(event); + if( !(m_tagWidget->m_flags & TagWidget::DisableTagClicking) && + me->button() == Qt::LeftButton && + tagRect().contains(me->pos()) ) { + emit tagClicked( m_tag ); + return true; + } + } + + default: + // do nothing + break; + } + } + + return QWidget::eventFilter( watched, event ); +} + + +void Nepomuk::TagCheckBox::slotStateChanged( int state ) +{ + emit tagStateChanged( m_tag, state ); +} + + +QRect Nepomuk::TagCheckBox::tagRect() const +{ + if( m_checkBox ) { + QStyleOptionButton opt; + m_checkBox->initStyleOption(&opt); + return style()->subElementRect(QStyle::SE_CheckBoxContents, + &opt, + m_checkBox); + } + else { + return QRect(QPoint(0, 0), m_label->size()); + } +} + + +void Nepomuk::TagCheckBox::enableUrlHover( bool enable ) +{ + if( m_urlHover != enable ) { + m_urlHover = enable; + QFont f(m_font); + if(enable) + f.setUnderline(true); + m_child->setFont(f); + m_child->setCursor( enable ? Qt::PointingHandCursor : Qt::ArrowCursor ); + } +} + +#include "tagcheckbox.moc" Modification de propriétés sur nepomuk/ui/tagcheckbox.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kratingpainter.cpp =================================================================== --- nepomuk/ui/kratingpainter.cpp (révision 0) +++ nepomuk/ui/kratingpainter.cpp (révision 0) @@ -0,0 +1,356 @@ +/* + This file is part of the Nepomuk KDE project. + 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 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 "kratingpainter.h" + +#include <QtGui/QPainter> +#include <QtGui/QPixmap> +#include <QtGui/QIcon> +#include <QtCore/QRect> +#include <QtCore/QPoint> + +#include <kicon.h> +#include <kiconeffect.h> +#include <kdebug.h> + + +class KRatingPainter::Private +{ +public: + Private() + : maxRating(10), + isEnabled( true ), + bHalfSteps(true), + alignment(Qt::AlignCenter), + direction(Qt::LeftToRight), + spacing(0) { + } + + QPixmap getPixmap( int size ); + + int maxRating; + QIcon icon; + bool isEnabled; + bool bHalfSteps; + Qt::Alignment alignment; + Qt::LayoutDirection direction; + QPixmap customPixmap; + int spacing; +}; + + +QPixmap KRatingPainter::Private::getPixmap( int size ) +{ + if ( !customPixmap.isNull() ) { + return customPixmap.scaled( QSize( size, size ) ); + } + else { + QIcon _icon( icon ); + if ( _icon.isNull() ) { + _icon = KIcon( "rating" ); + } + return _icon.pixmap( size ); + } +} + + +KRatingPainter::KRatingPainter() + : d(new Private()) +{ +} + + +KRatingPainter::~KRatingPainter() +{ + delete d; +} + + +int KRatingPainter::maxRating() const +{ + return d->maxRating; +} + + +bool KRatingPainter::halfStepsEnabled() const +{ + return d->bHalfSteps; +} + + +Qt::Alignment KRatingPainter::alignment() const +{ + return d->alignment; +} + + +Qt::LayoutDirection KRatingPainter::layoutDirection() const +{ + return d->direction; +} + + +QIcon KRatingPainter::icon() const +{ + return d->icon; +} + + +bool KRatingPainter::isEnabled() const +{ + return d->isEnabled; +} + + +QPixmap KRatingPainter::customPixmap() const +{ + return d->customPixmap; +} + + +int KRatingPainter::spacing() const +{ + return d->spacing; +} + + +void KRatingPainter::setMaxRating( int max ) +{ + d->maxRating = max; +} + + +void KRatingPainter::setHalfStepsEnabled( bool enabled ) +{ + d->bHalfSteps = enabled; +} + + +void KRatingPainter::setAlignment( Qt::Alignment align ) +{ + d->alignment = align; +} + + +void KRatingPainter::setLayoutDirection( Qt::LayoutDirection direction ) +{ + d->direction = direction; +} + + +void KRatingPainter::setIcon( const QIcon& icon ) +{ + d->icon = icon; +} + + +void KRatingPainter::setEnabled( bool enabled ) +{ + d->isEnabled = enabled; +} + + +void KRatingPainter::setCustomPixmap( const QPixmap& pixmap ) +{ + d->customPixmap = pixmap; +} + + +void KRatingPainter::setSpacing( int s ) +{ + d->spacing = qMax( 0, s ); +} + + +void KRatingPainter::paint( QPainter* painter, const QRect& rect, int rating, int hoverRating ) const +{ + rating = qMin( rating, d->maxRating ); + hoverRating = qMin( hoverRating, d->maxRating ); + + int numUsedStars = d->bHalfSteps ? d->maxRating/2 : d->maxRating; + + if ( hoverRating > 0 && hoverRating < rating ) { + int tmp = hoverRating; + hoverRating = rating; + rating = tmp; + } + + int usedSpacing = d->spacing; + + // get the rating pixmaps + int maxHSizeOnePix = ( rect.width() - (numUsedStars-1)*usedSpacing ) / numUsedStars; + QPixmap ratingPix = d->getPixmap( qMin( rect.height(), maxHSizeOnePix ) ); + + QPixmap disabledRatingPix = KIconEffect().apply( ratingPix, KIconEffect::ToGray, 1.0, QColor(), false ); + QPixmap hoverPix; + + // if we are disabled we become gray and more transparent + if ( !d->isEnabled ) { + ratingPix = disabledRatingPix; + KIconEffect::semiTransparent( disabledRatingPix ); + } + + bool half = d->bHalfSteps && rating%2; + int numRatingStars = d->bHalfSteps ? rating/2 : rating; + + int numHoverStars = 0; + bool halfHover = false; + if ( hoverRating > 0 && rating != hoverRating && d->isEnabled ) { + numHoverStars = d->bHalfSteps ? hoverRating/2 : hoverRating; + halfHover = d->bHalfSteps && hoverRating%2; + hoverPix = KIconEffect().apply( ratingPix, KIconEffect::ToGray, 0.5, QColor(), false ); + } + + if ( d->alignment & Qt::AlignJustify ) { + int w = rect.width(); + w -= numUsedStars * ratingPix.width(); + usedSpacing = w / ( numUsedStars-1 ); + } + + int ratingAreaWidth = ratingPix.width()*numUsedStars + usedSpacing*(numUsedStars-1); + + int i = 0; + int x = rect.x(); + if ( d->alignment & Qt::AlignRight ) { + x += ( rect.width() - ratingAreaWidth ); + } + else if ( d->alignment & Qt::AlignHCenter ) { + x += ( rect.width() - ratingAreaWidth )/2; + } + + int xInc = ratingPix.width() + usedSpacing; + if ( d->direction == Qt::RightToLeft ) { + x = rect.width() - ratingPix.width() - x; + xInc = -xInc; + } + + int y = rect.y(); + if( d->alignment & Qt::AlignVCenter ) { + y += ( rect.height() / 2 - ratingPix.height() / 2 ); + } + else if ( d->alignment & Qt::AlignBottom ) { + y += ( rect.height() - ratingPix.height() ); + } + for(; i < numRatingStars; ++i ) { + painter->drawPixmap( x, y, ratingPix ); + x += xInc; + } + if( half ) { + painter->drawPixmap( x, y, ratingPix.width()/2, ratingPix.height(), + d->direction == Qt::LeftToRight ? ratingPix : ( numHoverStars > 0 ? hoverPix : disabledRatingPix ), + 0, 0, ratingPix.width()/2, ratingPix.height() ); + painter->drawPixmap( x + ratingPix.width()/2, y, ratingPix.width()/2, ratingPix.height(), + d->direction == Qt::LeftToRight ? ( numHoverStars > 0 ? hoverPix : disabledRatingPix ) : ratingPix, + ratingPix.width()/2, 0, ratingPix.width()/2, ratingPix.height() ); + x += xInc; + ++i; + } + for(; i < numHoverStars; ++i ) { + painter->drawPixmap( x, y, hoverPix ); + x += xInc; + } + if( halfHover ) { + painter->drawPixmap( x, y, ratingPix.width()/2, ratingPix.height(), + d->direction == Qt::LeftToRight ? hoverPix : disabledRatingPix, + 0, 0, ratingPix.width()/2, ratingPix.height() ); + painter->drawPixmap( x + ratingPix.width()/2, y, ratingPix.width()/2, ratingPix.height(), + d->direction == Qt::LeftToRight ? disabledRatingPix : hoverPix, + ratingPix.width()/2, 0, ratingPix.width()/2, ratingPix.height() ); + x += xInc; + ++i; + } + for(; i < numUsedStars; ++i ) { + painter->drawPixmap( x, y, disabledRatingPix ); + x += xInc; + } +} + + +int KRatingPainter::ratingFromPosition( const QRect& rect, const QPoint& pos ) const +{ + int usedSpacing = d->spacing; + int numUsedStars = d->bHalfSteps ? d->maxRating/2 : d->maxRating; + int maxHSizeOnePix = ( rect.width() - (numUsedStars-1)*usedSpacing ) / numUsedStars; + QPixmap ratingPix = d->getPixmap( qMin( rect.height(), maxHSizeOnePix ) ); + + int ratingAreaWidth = ratingPix.width()*numUsedStars + usedSpacing*(numUsedStars-1); + + QRect usedRect( rect ); + if ( d->alignment & Qt::AlignRight ) { + usedRect.setLeft( rect.right() - ratingAreaWidth ); + } + else if ( d->alignment & Qt::AlignHCenter ) { + int x = ( rect.width() - ratingAreaWidth )/2; + usedRect.setLeft( rect.left() + x ); + usedRect.setRight( rect.right() - x ); + } + else { // d->alignment & Qt::AlignLeft + usedRect.setRight( rect.left() + ratingAreaWidth - 1 ); + } + + if ( d->alignment & Qt::AlignBottom ) { + usedRect.setTop( rect.bottom() - ratingPix.height() + 1 ); + } + else if ( d->alignment & Qt::AlignVCenter ) { + int x = ( rect.height() - ratingPix.height() )/2; + usedRect.setTop( rect.top() + x ); + usedRect.setBottom( rect.bottom() - x ); + } + else { // d->alignment & Qt::AlignTop + usedRect.setBottom( rect.top() + ratingPix.height() - 1 ); + } + + if ( usedRect.contains( pos ) ) { + int x = 0; + if ( d->direction == Qt::RightToLeft ) { + x = usedRect.right() - pos.x(); + } + else { + x = pos.x() - usedRect.left(); + } + + double one = ( double )usedRect.width() / ( double )d->maxRating; + +// kDebug() << "rating:" << ( int )( ( double )x/one + 0.5 ); + + return ( int )( ( double )x/one + 0.5 ); + } + else { + return -1; + } +} + + +void KRatingPainter::paintRating( QPainter* painter, const QRect& rect, Qt::Alignment align, int rating, int hoverRating ) +{ + KRatingPainter rp; + rp.setAlignment( align ); + rp.setLayoutDirection( painter->layoutDirection() ); + rp.paint( painter, rect, rating, hoverRating ); +} + + +int KRatingPainter::getRatingFromPosition( const QRect& rect, Qt::Alignment align, Qt::LayoutDirection direction, const QPoint& pos ) +{ + KRatingPainter rp; + rp.setAlignment( align ); + rp.setLayoutDirection( direction ); + return rp.ratingFromPosition( rect, pos ); +} Modification de propriétés sur nepomuk/ui/kratingpainter.cpp ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kmetadatatagcloud.h =================================================================== --- nepomuk/ui/kmetadatatagcloud.h (révision 0) +++ nepomuk/ui/kmetadatatagcloud.h (révision 0) @@ -0,0 +1,91 @@ +/* + * 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 KMETADATATAGCLOUD_H +#define KMETADATATAGCLOUD_H + +#include <nepomuk/nepomuk_export.h> + +#include "ktagcloudwidget.h" + +namespace Nepomuk { + class Tag; + + /** + * Tag cloud widget that displays all tags stored in the + * local Nepomuk store. + */ + class NEPOMUK_EXPORT TagCloud : public KTagCloudWidget + { + Q_OBJECT + + public: + /** + * Create a new TagCloud widget. + * The widget will be populated immediately. + */ + TagCloud( QWidget* parent = 0 ); + ~TagCloud(); + + /** + * \return true if auto updating is enabled (the default). + * + * \sa setAutoUpdate + */ + bool autoUpdate() const; + + public Q_SLOTS: + /** + * Update the tag cloud, ie. reload all tags from the store + * and recalculate their importance. + * + * There is no need to call this unless auto updating is + * disabled. + * + * \sa setAutoUpdate + */ + void updateTags(); + + /** + * If auto updating is enabled the tag cloud is updated + * regularly to keep in sync with the local Nepomuk store. + * + * \sa updateTags + */ + void setAutoUpdate( bool enable ); + + Q_SIGNALS: + /** + * This signal is emitted whenever a tag is clicked. + * + * \sa KTagCloudWidget::tagClicked + */ + void tagClicked( Tag ); + + private Q_SLOTS: + void slotTagClicked( const QString& tag ); + + private: + class Private; + Private* const d; + }; +} + +#endif // KMETADATATAGCLOUD_H Modification de propriétés sur nepomuk/ui/kmetadatatagcloud.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kedittagsdialog_p.h =================================================================== --- nepomuk/ui/kedittagsdialog_p.h (révision 0) +++ nepomuk/ui/kedittagsdialog_p.h (révision 0) @@ -0,0 +1,78 @@ +/***************************************************************************** + * Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> * + * * + * 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 KEDIT_TAGS_DIALOG_H +#define KEDIT_TAGS_DIALOG_H + +#include <kdialog.h> +#include <tag.h> + +class KLineEdit; +class QListWidget; +class QListWidgetItem; +class QPushButton; +class QTimer; + +/** + * @brief Dialog to edit a list of Nepomuk tags. + * + * It is possible for the user to add existing tags, + * create new tags or to remove tags. + * + * @see KMetaDataConfigurationDialog + */ +class KEditTagsDialog : public KDialog +{ + Q_OBJECT + +public: + KEditTagsDialog(const QList<Nepomuk::Tag>& tags, + QWidget* parent = 0, + Qt::WFlags flags = 0); + + virtual ~KEditTagsDialog(); + + QList<Nepomuk::Tag> tags() const; + + virtual bool eventFilter(QObject* watched, QEvent* event); + +protected slots: + virtual void slotButtonClicked(int button); + +private slots: + void slotTextEdited(const QString& text); + void slotItemEntered(QListWidgetItem* item); + void showDeleteButton(); + void deleteTag(); + +private: + void loadTags(); + void removeNewTagItem(); + +private: + QList<Nepomuk::Tag> m_tags; + QListWidget* m_tagsList; + QListWidgetItem* m_newTagItem; + QListWidgetItem* m_deleteCandidate; + KLineEdit* m_newTagEdit; + + QPushButton* m_deleteButton; + QTimer* m_deleteButtonTimer; +}; + +#endif Modification de propriétés sur nepomuk/ui/kedittagsdialog_p.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/tagwidget.h =================================================================== --- nepomuk/ui/tagwidget.h (révision 0) +++ nepomuk/ui/tagwidget.h (révision 0) @@ -0,0 +1,237 @@ +/* + * This file is part of the Nepomuk KDE project. + * Copyright (C) 2006-2010 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_TAG_WIDGET_H_ +#define _NEPOMUK_TAG_WIDGET_H_ + +#include "nepomuk_export.h" + +#include <QtGui/QWidget> + +namespace Nepomuk { + class Resource; + class Tag; + class TagWidgetPrivate; + + /** + * \class TagWidget tagwidget.h Nepomuk/TagWidget + * + * \brief Allows to change a selection of tags. + * + * TagWidget provides a simple GUI interface to assign tags. + * It has two basic modes: + * \li If resources are set via setTaggedResource() or setTaggedResources() + * the changes in the tag selection are automatically assigned to the + * selected resources. + * \li If no resources have been set the widget simply emits the selectionChanged() + * signal. + * + * \author Sebastian Trueg <trueg@kde.org> + */ + class NEPOMUK_EXPORT TagWidget : public QWidget + { + Q_OBJECT + + public: + /** + * Creates a new TagWidget for resource. The assigned tags are loaded + * instantly. + */ + explicit TagWidget( const Resource& resource, QWidget* parent = 0 ); + + /** + * Constructor + */ + TagWidget( QWidget* parent = 0 ); + + /** + * Destructor + */ + ~TagWidget(); + + /** + * \return The resources that are supposed to be tagged or an empty + * list if none have been set. + */ + QList<Resource> taggedResources() const; + + /** + * \deprecated use selectedTags() instead + */ + KDE_DEPRECATED QList<Tag> assignedTags() const; + + /** + * The list of selected tags. + * + * \return The list of all tags that are currently selected. In case + * resources to be tagged have been selected this list matches the + * tags assigned to the resources. + * + * \sa setTaggedResource, taggedResource, Resource::getTags + * + * \since 4.5 + */ + QList<Nepomuk::Tag> selectedTags() const; + + /** + * By default the TagWidget shows the most often used tags in the + * main window and allows access to all tags via an additional button. + * This is the maximum number of tags that should be shown unless they + * are selected. + * + * \sa setMaxTagsShown() + * + * \since 4.5 + */ + int maxTagsShown() const; + + /** + * The alignment of the tags in the widget. + * + * \since 4.5 + */ + Qt::Alignment alignment() const; + + /** + * Flags to configure the widget. + * + * \since 4.5 + */ + enum ModeFlag { + /** + * The mini mode which tries to + * display the tags on the least + * space possible. + */ + MiniMode = 0x1, + + /** + * The standard mode which is used by default + * provides a set of check boxes for the most + * frequently used tags. + */ + StandardMode = 0x2, + + /** + * Read only mode which prevents the changing + * of tags by the user. + */ + ReadOnly = 0x4, + + /** + * Disable the clicking of the tags. This will + * also disable the emitting of the tagClicked() + * signal. + */ + DisableTagClicking = 0x8 + }; + Q_DECLARE_FLAGS( ModeFlags, ModeFlag ) + + /** + * Flags the widget is configured with. + * + * \sa setModeFlags() + * + * \since 4.5 + */ + ModeFlags modeFlags() const; + + Q_SIGNALS: + /** + * This signal is emitted whenever a tag is clicked. + */ + void tagClicked( Nepomuk::Tag ); + + /** + * Emitted whenever the selection of tags changes. + * + * \since 4.5 + */ + void selectionChanged( const QList<Nepomuk::Tag>& tags ); + + public Q_SLOTS: + /** + * Set the Resource to be tagged. The assigned tags will be loaded + * instantly. + */ + void setTaggedResource( const Resource& resource ); + + /** + * Set the resources to be tagged. If the list of resources is + * empty TagWidget will only emit the selectionChanged() signal. + */ + void setTaggedResources( const QList<Resource>& resources ); + + /** + * \deprecated use setSelectedTags() instead + */ + KDE_DEPRECATED void setAssignedTags( const QList<Nepomuk::Tag>& tags ); + + /** + * Set the list of selected tags. In case resources have been + * set via setTaggedResource() or setTaggedResources() their + * list of tags is changed automatically. + * + * \since 4.5 + */ + void setSelectedTags( const QList<Nepomuk::Tag>& tags ); + + /** + * By default the TagWidget shows the most often used tags in the + * main window and allows access to all tags via an additional button. + * + * The number of tags that are shown by default can be changed. + * + * \param max The maximum number of tags that should be shown in the + * main window. Set to 0 for no limit. Be aware that more tags might be + * shown since selected tags are always shown. + * + * \since 4.5 + */ + void setMaxTagsShown( int max ); + + /** + * Set the alignment to use. Only horizontal alignment flags make a + * difference. + * + * \since 4.5 + */ + void setAlignment( Qt::Alignment alignment ); + + /** + * Set flags to change the behaviour and look of the tag widget. + * + * \since 4.5 + */ + void setModeFlags( ModeFlags flags ); + + private Q_SLOTS: + void slotShowAll(); + void slotTagUpdateDone(); + void slotTagStateChanged( const Nepomuk::Tag&, int ); + + private: + TagWidgetPrivate* const d; + }; +} + +Q_DECLARE_OPERATORS_FOR_FLAGS( Nepomuk::TagWidget::ModeFlags ) + +#endif Modification de propriétés sur nepomuk/ui/tagwidget.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/ktagdisplaywidget.h =================================================================== --- nepomuk/ui/ktagdisplaywidget.h (révision 0) +++ nepomuk/ui/ktagdisplaywidget.h (révision 0) @@ -0,0 +1,70 @@ +/* + * 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 _KTAG_DISPLAY_WIDGET_H_ +#define _KTAG_DISPLAY_WIDGET_H_ + +#include <QtGui/QWidget> + +#include <nepomuk/nepomuk_export.h> + +/** + * The KTagDisplayWidget shows a list of tags and allows clicking each of them. + */ +class NEPOMUK_EXPORT KTagDisplayWidget : public QWidget +{ + Q_OBJECT + + public: + KTagDisplayWidget( QWidget* parent = 0 ); + ~KTagDisplayWidget(); + + public Q_SLOTS: + /** + * Set \a tags to be displayed. + */ + void setTags( const QStringList& tags ); + + /** + * Add \a tag to be displayed. + * Existing tags with the same name will be overwritten. + */ + void addTag( const QString& tag ); + + /** + * Add a set of tags to be displayed. + * Existing tags with the same name will be overwritten. + */ + void addTags( const QStringList& tags ); + + /** + * Remove all tags. + */ + void clear(); + + Q_SIGNALS: + void tagClicked( const QString& tag ); + + private: + class Private; + Private* const d; +}; + +#endif Modification de propriétés sur nepomuk/ui/ktagdisplaywidget.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/ktagcloudwidget.h =================================================================== --- nepomuk/ui/ktagcloudwidget.h (révision 0) +++ nepomuk/ui/ktagcloudwidget.h (révision 0) @@ -0,0 +1,84 @@ +/* + * 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 KTAGCLOUDWIDGET_H +#define KTAGCLOUDWIDGET_H + +#include <QtGui/QWidget> +#include <QtCore/QMap> + +#include <nepomuk/nepomuk_export.h> + +class NEPOMUK_EXPORT KTagCloudWidget : public QWidget +{ + Q_OBJECT + + public: + KTagCloudWidget( QWidget* parent = 0 ); + ~KTagCloudWidget(); + + /** + * Retrieve the weight for a certain tag + */ + int tagWeight( const QString& tag ) const; + + public Q_SLOTS: + /** + * Add \a tag to the cloud using the weight factor \a weight. + * Existing tags with the same name will be overwritten. + */ + void addTag( const QString& tag, int weight ); + + /** + * Add a set of tags with weight factors + */ + void addTags( const QMap<QString,int>& tags ); + + /** + * Remove all tags from the cloud. + */ + void clear(); + + /** + * Set the maximum font size to be used for the most popular tags. + * Default is 22. + */ + void setMaxFontSize( int pointSize ); + + /** + * Set the minimum font size to be used for the most unpopular tags. + * Default is 8. + */ + void setMinFontSize( int pointSize ); + + Q_SIGNALS: + void tagClicked( const QString& tag ); + + protected: + void resizeEvent( QResizeEvent* e ); + + private: + void buildTagCloud(); + + class Private; + Private* const d; +}; + +#endif Modification de propriétés sur nepomuk/ui/ktagcloudwidget.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/kratingpainter.h =================================================================== --- nepomuk/ui/kratingpainter.h (révision 0) +++ nepomuk/ui/kratingpainter.h (révision 0) @@ -0,0 +1,219 @@ +/* + This file is part of the Nepomuk KDE project. + 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 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_RATING_PAINTER_H_ +#define _NEPOMUK_RATING_PAINTER_H_ + +#include "nepomuk_export.h" + +#include <QtCore/Qt> + +class QIcon; +class QPixmap; +class QPainter; +class QPoint; +class QRect; + + +/** + * \class KRatingPainter kratingpainter.h Nepomuk/KRatingPainter + * + * \brief Utility class that draws a row of stars for a rating value. + * + * The KRatingPainter also allows to determine a rating value from + * a position in the draw area. it supports all different alignments + * and custom icons. + * + * For showing a rating in a widget see KRatingWidget. + * + * \author Sebastian Trueg <trueg@kde.org> + * + * \since 4.1 + */ +class NEPOMUK_EXPORT KRatingPainter +{ +public: + /** + * Create a new KRatingPainter. + * For most cases the static methods paintRating and getRatingFromPosition + * should be sufficient. + */ + KRatingPainter(); + + /** + * Destructor + */ + ~KRatingPainter(); + + /** + * The maximum rating, i.e. how many stars are drawn + * in total. + * + * \sa setMaxRating + */ + int maxRating() const; + + /** + * If half steps are enabled one star equals to 2 rating + * points and uneven rating values result in half-stars being + * drawn. + * + * \sa setHalfStepsEnabled + */ + bool halfStepsEnabled() const; + + /** + * The alignment of the stars. + * + * \sa setAlignment + */ + Qt::Alignment alignment() const; + + /** + * The layout direction. If RTL the stars + * representing the rating value will be drawn from the + * right. + * + * \sa setLayoutDirection + */ + Qt::LayoutDirection layoutDirection() const; + + /** + * The icon used to draw a star. In case a custom pixmap has been set + * this value is ignored. + * + * \sa setIcon, setCustomPixmap + */ + QIcon icon() const; + + /** + * The rating can be painted in a disabled state where no color + * is used and hover ratings are ignored. + * + * \sa setEnabled + */ + bool isEnabled() const; + + /** + * The custom pixmap set to draw a star. If no custom + * pixmap has been set, an invalid pixmap is returned. + * + * \sa setCustomPixmap + */ + QPixmap customPixmap() const; + + /** + * The spacing between rating pixmaps. + * + * \sa setSpacing + */ + int spacing() const; + + /** + * The maximum rating. Defaults to 10. + */ + void setMaxRating( int max ); + + /** + * If half steps are enabled (the default) then + * one rating step corresponds to half a star. + */ + void setHalfStepsEnabled( bool enabled ); + + /** + * The alignment of the stars in the drawing rect. + * All alignment flags are supported. + */ + void setAlignment( Qt::Alignment align ); + + /** + * LTR or RTL + */ + void setLayoutDirection( Qt::LayoutDirection direction ); + + /** + * Set a custom icon. Defaults to "rating". + */ + void setIcon( const QIcon& icon ); + + /** + * Enable or disable the rating. Default is enabled. + */ + void setEnabled( bool enabled ); + + /** + * Set a custom pixmap. + */ + void setCustomPixmap( const QPixmap& pixmap ); + + /** + * Set the spacing between rating pixmaps. Be aware that + * for justified horizontal alignment this values may be + * ignored. + */ + void setSpacing( int spacing ); + + /** + * Draw the rating. + * + * \param painter The painter to draw the rating to. + * \param rect The geometry of the rating. The alignment of the rating is used relative + * to this value. + * \param rating The actual rating value to draw. + * \param hoverRating The hover rating indicates the position the user hovers the mouse + * pointer at. This will provide visual feedback about the new rating + * if the user would actually click as well as the difference to the + * current rating. + */ + void paint( QPainter* painter, const QRect& rect, int rating, int hoverRating = -1 ) const; + + /** + * Calculate the rating value from mouse position pos. + * + * \return The rating corresponding to pos or -1 if pos is + * outside of the configured rect. + */ + int ratingFromPosition( const QRect& rect, const QPoint& pos ) const; + + /** + * Convenience method that paints a rating into the given rect. + * + * LayoutDirection is read from QPainter. + * + * \param align can be aligned vertically and horizontally. Using Qt::AlignJustify will insert spacing + * between the stars. + */ + static void paintRating( QPainter* p, const QRect& rect, Qt::Alignment align, int rating, int hoverRating = -1 ); + + /** + * Get the rating that would be selected if the user clicked position pos + * within rect if the rating has been drawn with paintRating() using the same + * rect and align values. + * + * \return The new rating or -1 if pos is outside of the rating area. + */ + static int getRatingFromPosition( const QRect& rect, Qt::Alignment align, Qt::LayoutDirection direction, const QPoint& pos ); + +private: + class Private; + Private* const d; +}; + +#endif Modification de propriétés sur nepomuk/ui/kratingpainter.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/ui/tagcheckbox.h =================================================================== --- nepomuk/ui/tagcheckbox.h (révision 0) +++ nepomuk/ui/tagcheckbox.h (révision 0) @@ -0,0 +1,78 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2010 Sebastian Trueg <trueg@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _NEPOMUK_TAG_CHECKBOX_H_ +#define _NEPOMUK_TAG_CHECKBOX_H_ + +#include <QtGui/QWidget> +#include <QtGui/QFont> + +#include "tag.h" +#include "tagwidget_p.h" + +class QMouseEvent; +class QLabel; + +namespace Nepomuk { +class TagCheckBox : public QWidget +{ + Q_OBJECT + +public: + TagCheckBox( const Tag& tag, TagWidgetPrivate* tagWidget, QWidget* parent = 0 ); + ~TagCheckBox(); + + Tag tag() const { return m_tag; } + + bool isChecked() const; + +public Q_SLOTS: + void setChecked( bool checked ); + +Q_SIGNALS: + void tagClicked( const Nepomuk::Tag& tag ); + void tagStateChanged( const Nepomuk::Tag& tag, int state ); + +protected: + void leaveEvent( QEvent* event ); + bool eventFilter( QObject* watched, QEvent* event ); + +private Q_SLOTS: + void slotStateChanged( int state ); + +private: + QRect tagRect() const; + void enableUrlHover( bool enabled ); + + // two modes: checkbox and simple label + QLabel* m_label; + class CheckBoxWithPublicInitStyleOption; + CheckBoxWithPublicInitStyleOption* m_checkBox; + QWidget* m_child; + + Tag m_tag; + bool m_urlHover; + QFont m_font; + TagWidgetPrivate* m_tagWidget; +}; +} + +#endif Modification de propriétés sur nepomuk/ui/tagcheckbox.h ___________________________________________________________________ Ajouté : svn:eol-style + native Index: nepomuk/rcgen/templates/source_safe.tpl =================================================================== --- nepomuk/rcgen/templates/source_safe.tpl (révision 1130118) +++ nepomuk/rcgen/templates/source_safe.tpl (copie de travail) @@ -87,7 +87,7 @@ QString Nepomuk::NEPOMUK_RESOURCENAME::resourceTypeUri() { - return "NEPOMUK_RESOURCETYPEURI"; + return QLatin1String("NEPOMUK_RESOURCETYPEURI"); } NEPOMUK_METHODS Index: nepomuk/rcgen/fastcode.cpp =================================================================== --- nepomuk/rcgen/fastcode.cpp (révision 1130118) +++ nepomuk/rcgen/fastcode.cpp (copie de travail) @@ -29,6 +29,9 @@ QString FastCode::propertyGetterDeclaration( const Property* property, const ResourceClass* rc, const QString &nameSpace ) const { + Q_UNUSED( property ); + Q_UNUSED( rc ); + Q_UNUSED( nameSpace ); return QString(); } @@ -43,11 +46,16 @@ QString FastCode::propertyReversePropertyGetterDeclaration( const Property* property, const ResourceClass* rc, const QString &nameSpace ) const { + Q_UNUSED( property ); + Q_UNUSED( rc ); + Q_UNUSED( nameSpace ); return QString(); } QString FastCode::resourceAllResourcesDeclaration( const ResourceClass* rc, const QString &nameSpace ) const { + Q_UNUSED( rc ); + Q_UNUSED( nameSpace ); return QString(); } @@ -90,6 +98,8 @@ QString FastCode::propertyGetterDefinition( const Property* property, const ResourceClass* rc ) const { + Q_UNUSED( property ); + Q_UNUSED( rc ); return QString(); } @@ -110,11 +120,14 @@ QString FastCode::propertyReversePropertyGetterDefinition( const Property* property, const ResourceClass* rc ) const { + Q_UNUSED( property ); + Q_UNUSED( rc ); return QString(); } QString FastCode::resourceAllResourcesDefinition( const ResourceClass* rc ) const { + Q_UNUSED( rc ); return QString(); } --- includes/CMakeLists.txt~ 2009-12-31 14:29:15.000000000 +0100 +++ includes/CMakeLists.txt 2010-05-09 21:04:20.000000000 +0200 @@ -1000,6 +1000,7 @@ Nepomuk/Query/Result Nepomuk/Query/SimpleTerm Nepomuk/Query/Term + Nepomuk/Query/OptionalTerm DESTINATION ${INCLUDE_INSTALL_DIR}/KDE/Nepomuk/Query COMPONENT Devel) --- /dev/null 2006-08-21 11:51:14.000000000 +0200 +++ includes/Nepomuk/Query/OptionalTerm 2010-05-09 21:05:46.000000000 +0200 @@ -0,0 +1 @@ +#include "../../../nepomuk/optionalterm.h" Index: nepomuk/core/resourcedata.cpp =================================================================== --- nepomuk/core/resourcedata.cpp +++ nepomuk/core/resourcedata.cpp 2010-12-01 09:52:59.000000000 +0100 @@ -29,6 +29,7 @@ #include "pimo.h" #include "nepomukmainmodel.h" #include "dbusconnectionpool.h" +#include "class.h" #include <Soprano/Statement> #include <Soprano/StatementIterator> @@ -39,8 +40,6 @@ #include <Soprano/Vocabulary/Xesam> #include <Soprano/Vocabulary/NAO> -#include "ontology/class.h" - #include <QtCore/QFile> #include <QtCore/QDateTime> #include <QtCore/QMutexLocker> @@ -53,34 +52,13 @@ using namespace Soprano; -#define MAINMODEL m_rm->resourceFilterModel +#define MAINMODEL static_cast<ResourceFilterModel*>(m_rm->m_manager->mainModel()) -static Nepomuk::Variant nodeToVariant( const Soprano::Node& node ) -{ - // - // We cannot put in Resource objects here since then nie:url file:/ URLs would - // get converted back to the actual resource URIs which would be useless. - // That is why Variant treats QUrl and Resource pretty much as similar. - // - if ( node.isResource() ) { - return Nepomuk::Variant( node.uri() ); - } - else if ( node.isLiteral() ) { - return Nepomuk::Variant( node.literal().variant() ); - } - else { - return Nepomuk::Variant(); - } -} - - -Nepomuk::ResourceData::ResourceData( const QUrl& uri, const QString& uriOrId, const QUrl& type, ResourceManagerPrivate* rm ) - : m_kickoffId( uriOrId ), - m_kickoffUri( uri ), +Nepomuk::ResourceData::ResourceData( const QUrl& uri, const QUrl& kickOffUri, const QUrl& type, ResourceManagerPrivate* rm ) + : m_uri(uri), m_mainType( type ), m_modificationMutex(QMutex::Recursive), - m_proxyData(0), m_cacheDirty(true), m_pimoThing(0), m_groundingOccurence(0), @@ -96,6 +74,14 @@ m_rm->cleanupCache(); m_rm->dataCnt.ref(); + + if( !uri.isEmpty() ) { + m_kickoffUris.insert( uri ); + } + if( !kickOffUri.isEmpty() ) { + m_kickoffUris.insert( kickOffUri ); + } + m_rm->addToKickOffList( this, m_kickoffUris ); } @@ -109,7 +95,8 @@ bool Nepomuk::ResourceData::isFile() { return( m_uri.scheme() == QLatin1String("file") || - m_kickoffUri.scheme() == QLatin1String("file") || + m_nieUrl.scheme() == QLatin1String("file") || + (!m_kickoffUris.isEmpty() && (*m_kickoffUris.begin()).scheme() == QLatin1String("file")) || constHasType( Soprano::Vocabulary::Xesam::File() ) || constHasType( Nepomuk::Vocabulary::NFO::FileDataObject() ) ); } @@ -117,16 +104,12 @@ QUrl Nepomuk::ResourceData::uri() const { - if( m_proxyData ) - return m_proxyData->uri(); return m_uri; } QUrl Nepomuk::ResourceData::type() { - if( m_proxyData ) - return m_proxyData->type(); load(); return m_mainType; } @@ -134,8 +117,6 @@ QList<QUrl> Nepomuk::ResourceData::allTypes() { - if( m_proxyData ) - return m_proxyData->allTypes(); load(); return m_types; } @@ -143,57 +124,41 @@ void Nepomuk::ResourceData::setTypes( const QList<QUrl>& types ) { - if( m_proxyData ) { - m_proxyData->setTypes( types ); - } - else if ( store() ) { - QMutexLocker lock(&m_modificationMutex); + store(); - // reset types - m_types.clear(); - m_mainType = Soprano::Vocabulary::RDFS::Resource(); + QMutexLocker lock(&m_modificationMutex); - QList<Node> nodes; - // load types (and set maintype) - foreach( const QUrl& url, types ) { - loadType( url ); - nodes << Node( url ); - } + // reset types + m_types.clear(); + m_mainType = Soprano::Vocabulary::RDFS::Resource(); - // update the data store - MAINMODEL->updateProperty( m_uri, Soprano::Vocabulary::RDF::type(), nodes ); + QList<Node> nodes; + // load types (and set maintype) + foreach( const QUrl& url, types ) { + loadType( url ); + nodes << Node( url ); } + + // update the data store + MAINMODEL->updateProperty( m_uri, Soprano::Vocabulary::RDF::type(), nodes ); } void Nepomuk::ResourceData::resetAll( bool isDelete ) { - // reset proxy - bool hadProxy = false; - if( m_proxyData ) { - hadProxy = true; - if( !m_proxyData->deref() && - rm()->dataCacheFull() ) - delete m_proxyData; - m_proxyData = 0; - } - // remove us from all caches (store() will re-insert us later if necessary) m_rm->mutex.lock(); - if( !m_uri.isEmpty() && !hadProxy ) // if we had a proxy we were not in m_initializedData ourselves + if( !m_uri.isEmpty() ) m_rm->m_initializedData.remove( m_uri ); - if( !m_kickoffUri.isEmpty() ) - m_rm->m_uriKickoffData.remove( m_kickoffUri ); - if( !m_kickoffId.isEmpty() ) - m_rm->m_idKickoffData.remove( m_kickoffId ); + Q_FOREACH( const KUrl& uri, m_kickoffUris ) + m_rm->m_uriKickoffData.remove( uri ); m_rm->mutex.unlock(); // reset all variables m_uri = QUrl(); - m_fileUrl = KUrl(); - m_kickoffId.truncate(0); - m_kickoffUri = QUrl(); + m_nieUrl = KUrl(); + m_kickoffUris.clear(); m_cache.clear(); m_cacheDirty = false; m_types.clear(); @@ -202,7 +167,7 @@ m_groundingOccurence = 0; // when we are being deleted the value of m_mainType is not important - // andmore. Also since ResourceManager is a global static it might be + // anymore. Also since ResourceManager is a global static it might be // deleted after the global static behind Soprano::Vocabulary::RDFS // which results in a crash. if( !isDelete ) @@ -212,34 +177,40 @@ QHash<QUrl, Nepomuk::Variant> Nepomuk::ResourceData::allProperties() { - if( m_proxyData ) - return m_proxyData->allProperties(); - load(); - return m_cache; } bool Nepomuk::ResourceData::hasProperty( const QUrl& uri ) { - if( m_proxyData ) - return m_proxyData->hasProperty( uri ); + load(); + QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri ); + if( it == m_cache.constEnd() ) + return false; - if ( determineUri() ) { - return MAINMODEL->containsAnyStatement( Soprano::Statement( m_uri, uri, Soprano::Node() ) ); - } - else { + return true; +} + + +bool Nepomuk::ResourceData::hasProperty( const QUrl& p, const Variant& v ) +{ + QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( p ); + if( it == m_cache.constEnd() ) return false; + + QList<Variant> thisVals = it.value().toVariantList(); + QList<Variant> vals = v.toVariantList(); + Q_FOREACH( const Variant& val, vals ) { + if( !thisVals.contains(val) ) + return false; } + return true; } bool Nepomuk::ResourceData::hasType( const QUrl& uri ) { - if( m_proxyData ) - return m_proxyData->hasType( uri ); - load(); return constHasType( uri ); } @@ -265,39 +236,19 @@ Nepomuk::Variant Nepomuk::ResourceData::property( const QUrl& uri ) { - if( m_proxyData ) - return m_proxyData->property( uri ); + load(); - if ( load() ) { - // we need to protect the reading, too. load my be triggered from another thread's - // connection to a Soprano statement signal - QMutexLocker lock(&m_modificationMutex); + // we need to protect the reading, too. load my be triggered from another thread's + // connection to a Soprano statement signal + QMutexLocker lock(&m_modificationMutex); - QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri ); - if ( it == m_cache.constEnd() ) { - return Variant(); - } - else { - return *it; - } + QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri ); + if ( it == m_cache.constEnd() ) { + return Variant(); } else { - return Variant(); + return *it; } - -// Variant v; - -// if ( determineUri() ) { -// Soprano::Model* model = m_rm->m_manager->mainModel(); -// Soprano::StatementIterator it = model->listStatements( Soprano::Statement( m_uri, QUrl(uri), Soprano::Node() ) ); - -// while ( it.next() ) { -// Statement statement = *it; -// v.append( nodeToVariant( statement.object() ) ); -// } -// it.close(); -// } -// return v; } @@ -305,7 +256,7 @@ { QMutexLocker lock(&m_modificationMutex); - if ( !determineUri() ) { + if ( m_uri.isEmpty() ) { QMutexLocker rmlock(&m_rm->mutex); // create a random URI and add us to the initialized data, i.e. make us "valid" m_uri = m_rm->m_manager->generateUniqueUri( QString() ); @@ -313,9 +264,9 @@ // each initialized resource has to be in a kickoff list // thus, we make sure that is the case. - if( m_kickoffUri.isEmpty() && m_kickoffId.isEmpty() ) { - m_kickoffUri = m_uri; - m_rm->m_uriKickoffData.insert( m_uri, this ); + if( m_kickoffUris.isEmpty() ) { + m_kickoffUris.insert( m_uri ); + m_rm->addToKickOffList( this, m_kickoffUris ); } } @@ -326,14 +277,18 @@ statements.append( Statement( m_uri, Soprano::Vocabulary::NAO::created(), Soprano::LiteralValue( QDateTime::currentDateTime() ) ) ); // save the kickoff identifier (other identifiers are stored via setProperty) - if ( !m_kickoffId.isEmpty() ) { - statements.append( Statement( m_uri, Soprano::Vocabulary::NAO::identifier(), LiteralValue(m_kickoffId) ) ); + Q_FOREACH ( const KUrl & url, m_kickoffUris ) { + if( url.scheme().isEmpty() ) { + statements.append( Statement( m_uri, Soprano::Vocabulary::NAO::identifier(), LiteralValue(url.url()) ) ); + break; + } } // the only situation in which determineUri keeps the kickoff URI is for file URLs. - if ( m_fileUrl.isValid() ) { - statements.append( Statement( m_uri, Nepomuk::Vocabulary::NIE::url(), m_fileUrl ) ); - if ( m_mainType == Soprano::Vocabulary::RDFS::Resource() ) { + if ( m_nieUrl.isValid() ) { + statements.append( Statement( m_uri, Nepomuk::Vocabulary::NIE::url(), m_nieUrl ) ); + if ( m_nieUrl.isLocalFile() && + m_mainType == Soprano::Vocabulary::RDFS::Resource() ) { m_mainType = Nepomuk::Vocabulary::NFO::FileDataObject(); } } @@ -350,7 +305,7 @@ // that m_types contains more than one element: if we loaded them) // The first type, however, can be set at creation time to any value if ( m_mainType != Soprano::Vocabulary::RDFS::Resource() && - !MAINMODEL->containsAnyStatement( m_uri, Soprano::Vocabulary::RDF::type(), m_mainType ) ) { + !MAINMODEL->containsAnyStatement( m_uri, Soprano::Vocabulary::RDF::type(), m_mainType ) ) { statements.append( Statement( m_uri, Soprano::Vocabulary::RDF::type(), m_mainType ) ); } @@ -412,7 +367,7 @@ if ( m_cacheDirty ) { m_cache.clear(); - if ( determineUri() ) { + if ( m_uri.isValid() ) { Soprano::QueryResultIterator it = MAINMODEL->executeQuery(QString("select distinct ?p ?o where { " "%1 ?p ?o . " "}").arg(Soprano::Node::resourceToN3(m_uri)), @@ -426,10 +381,8 @@ } } else { - if ( p == Nepomuk::Vocabulary::NIE::url() ) { - m_fileUrl = o.uri(); - } - m_cache[p].append( nodeToVariant( o ) ); + updateKickOffLists( p, o.uri() ); + m_cache[p].append( Variant::fromNode( o ) ); } } @@ -467,11 +420,8 @@ { Q_ASSERT( uri.isValid() ); - if( m_proxyData ) - return m_proxyData->setProperty( uri, value ); - - // step 0: make sure this resource is in the store - if ( store() ) { + if( store() ) { + // step 0: make sure this resource is in the store QMutexLocker lock(&m_modificationMutex); QList<Node> valueNodes; @@ -510,10 +460,16 @@ } // update the cache for now - m_cache[uri] = value; + if( value.isValid() ) + m_cache[uri] = value; + else + m_cache.remove(uri); // update the store MAINMODEL->updateProperty( m_uri, uri, valueNodes ); + + // update the kickofflists + updateKickOffLists( uri, value.toUrl() ); } } @@ -521,45 +477,26 @@ void Nepomuk::ResourceData::removeProperty( const QUrl& uri ) { Q_ASSERT( uri.isValid() ); + if( !m_uri.isEmpty() ) { + QMutexLocker lock(&m_modificationMutex); - if( m_proxyData ) - return m_proxyData->removeProperty( uri ); - - QMutexLocker lock(&m_modificationMutex); - - if ( determineUri() ) { m_cache.remove( uri ); MAINMODEL->removeProperty( m_uri, uri ); + + // update the kickofflists + updateKickOffLists( uri, QUrl() ); } } void Nepomuk::ResourceData::remove( bool recursive ) { - // trueg: there is one problem we somehow need to work around: - // if we have a resource with URI X and indentifier Y and we - // create two ResourceData objects, one from X and one from Y - // without loading them. - // Then when we delete the latter the first will stay valid - // and hang around as zombie. - // The perfect solution would be to handle that in invalidateCache() - // but that would mean a lot of query work all the time. - // Thus, instead we make sure all ResourceData instances are loaded. - // That way the proxy handling will take care of the rest. - m_rm->determineAllUris(); - - if( m_proxyData ) { - m_proxyData->remove( recursive ); - } - else { - QMutexLocker lock(&m_modificationMutex); - + QMutexLocker lock(&m_modificationMutex); - if ( determineUri() ) { - MAINMODEL->removeAllStatements( Statement( m_uri, Node(), Node() ) ); - if ( recursive ) { - MAINMODEL->removeAllStatements( Statement( Node(), Node(), m_uri ) ); - } + if( !m_uri.isEmpty() ) { + MAINMODEL->removeAllStatements( Statement( m_uri, Node(), Node() ) ); + if ( recursive ) { + MAINMODEL->removeAllStatements( Statement( Node(), Node(), m_uri ) ); } } @@ -569,120 +506,90 @@ bool Nepomuk::ResourceData::exists() { - if( m_proxyData ) - return m_proxyData->exists(); - - if( determineUri() ) { + if( m_uri.isValid() ) { return MAINMODEL->containsAnyStatement( Statement( m_uri, Node(), Node() ) ); } - else + else { return false; + } } bool Nepomuk::ResourceData::isValid() const { - if( m_proxyData ) - return m_proxyData->isValid(); - - return( !m_mainType.isEmpty() && ( !m_uri.isEmpty() || !m_kickoffUri.isEmpty() || !m_kickoffId.isEmpty() ) ); + return( !m_mainType.isEmpty() && ( !m_uri.isEmpty() || !m_kickoffUris.isEmpty() ) ); } -bool Nepomuk::ResourceData::determineUri() +Nepomuk::ResourceData* Nepomuk::ResourceData::determineUri() { - if( m_proxyData ) - return m_proxyData->determineUri(); - - else { - // - // Preconditions: - // 1. m_kickoffId is not a local file path or URL (use m_kickoffUri for that) - // - // Now for the hard part - // We have the following possible situations: - // 1. m_uri is already valid - // -> simple, nothing to do - // - // 2. m_uri is not valid - // -> we need to determine the URI - // - // 2.1. m_kickoffId is valid - // 2.1.1. m_kickoffId is a resource URI - // -> use it as m_uri - // 2.1.2. m_kickoffId is a nao:identifier for r - // -> use r as m_uri - // 2.1.3. m_kickoffId is not found - // -> create new random m_uri and save m_kickoffId as nao:identifier - // - // 2.2. m_kickoffUri is valid - // 2.2.1. it is a file URL - // 2.2.1.1. it is nie:url for r - // -> use r as m_uri - // 2.2.1.2. it points to a file on a removable device for which we have a filex:/ URL - // -> use the r in r nie:url filex:/... - // 2.2.1.3. it is a file which is not an object in some nie:url relation - // -> create new random m_uri and use kickoffUriOrId() as m_fileUrl - // - QMutexLocker lock(&m_determineUriMutex); - - if( m_uri.isEmpty() ) { + // We have the following possible situations: + // 1. m_uri is already valid + // -> simple, nothing to do + // + // 2. m_uri is not valid + // -> we need to determine the URI + // + // 2.1. m_kickoffUri is valid + // 2.1.1. it is a file URL + // 2.1.1.1. it is nie:url for r + // -> use r as m_uri + // 2.1.1.2. it points to a file on a removable device for which we have a filex:/ URL + // -> use the r in r nie:url filex:/... + // 2.1.1.3. it is a file which is not an object in some nie:url relation + // -> create new random m_uri and use kickoffUriOrId() as m_nieUrl + // 2.1.2. it is a resource URI + // -> use it as m_uri + // + // 2.2. m_kickOffUri is not valid + // 2.2.1. m_kickOffUri is a nao:identifier for r + // -> use r as m_uri + // - Soprano::Model* model = MAINMODEL; + if( m_uri.isEmpty() ) { + Soprano::Model* model = MAINMODEL; - if( !m_kickoffId.isEmpty() ) { + if( !m_kickoffUris.isEmpty() ) { + KUrl kickOffUri = *m_kickoffUris.begin(); + if( kickOffUri.scheme().isEmpty() ) { // - // The kickoffUriOrId is actually a URI + // Not valid. Checking for nao:identifier // - KUrl uriFromKickoffId(m_kickoffId); - if( model->containsAnyStatement( uriFromKickoffId, Node(), Node() )) { - m_uri = uriFromKickoffId; - } + QString query = QString::fromLatin1("select distinct ?r where { ?r %1 %2. } LIMIT 1") + .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::identifier()) ) + .arg( Soprano::Node::literalToN3( kickOffUri.url() ) ); - // - // Check if the kickoffUriOrId is a resource identifier or a resource URI - // - else { - QString query = QString::fromLatin1("select distinct ?r ?o where { { ?r %1 %2 . } UNION { %3 ?p ?o . } . } LIMIT 1") - .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::identifier()) ) - .arg( Soprano::Node::literalToN3(m_kickoffId) ) - .arg( Soprano::Node::resourceToN3(KUrl(m_kickoffId)) ); - Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql ); - if( it.next() ) { - m_uri = it["r"].uri(); - if( m_uri.isEmpty() ) { - m_uri = KUrl(m_kickoffId); - } - it.close(); - } + Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql ); + if( it.next() ) { + m_uri = it["r"].uri(); + it.close(); } } - - else if( !m_kickoffUri.isEmpty() ) { + else { // // In one query determine if the URI is already used as resource URI or as // nie:url // QString query = QString::fromLatin1("select distinct ?r ?o where { " - "{ ?r %1 %2 . } " + "{ ?r %1 %2 . FILTER(?r!=%2) . } " "UNION " "{ %2 ?p ?o . } " "} LIMIT 1") - .arg( Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NIE::url()) ) - .arg( Soprano::Node::resourceToN3(m_kickoffUri) ); + .arg( Soprano::Node::resourceToN3( Nepomuk::Vocabulary::NIE::url() ) ) + .arg( Soprano::Node::resourceToN3( kickOffUri ) ); Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql ); if( it.next() ) { QUrl uri = it["r"].uri(); if( uri.isEmpty() ) { - m_uri = m_kickoffUri; + m_uri = kickOffUri; } else { m_uri = uri; - m_fileUrl = m_kickoffUri; + m_nieUrl = kickOffUri; } it.close(); } - else if( m_kickoffUri.scheme() == QLatin1String("file") ) { + else if( kickOffUri.scheme() == QLatin1String("file") ) { // // This is the hard part: The file may still be saved using a filex:/ URL // We have to determine if that is the case. For that we need to look if the URL @@ -701,54 +608,46 @@ QLatin1String("org.kde.nepomuk.RemovableStorage"), DBusConnectionPool::threadConnection()) .call( QLatin1String("resourceUriFromLocalFileUrl"), - m_kickoffUri.url() ) ).value(); + kickOffUri.url() ) ).value(); if( !resourceUri.isEmpty() ) { m_uri = resourceUri; } - m_fileUrl = m_kickoffUri; + m_nieUrl = kickOffUri; } - else { - // for everything else we simply use the kickoff URI as resource URI - m_uri = m_kickoffUri; - } - } - - else { - // no kickoff values. We will only create a new random URI in store() - return false; - } - - // - // Move us to the final data hash now that the URI is known - // - if( !m_uri.isEmpty() ) { - QMutexLocker rmlock(&m_rm->mutex); - - if( !m_rm->m_initializedData.contains( m_uri ) ) { - m_rm->m_initializedData.insert( m_uri, this ); + else if( kickOffUri.scheme() == QLatin1String("nepomuk") ) { + // for nepomuk URIs we simply use the kickoff URI as resource URI + m_uri = kickOffUri; } else { - m_proxyData = m_rm->m_initializedData.value( m_uri ); - m_proxyData->ref(); + // for everything else we use m_kickoffUri as nie:url with a new random m_uri + m_nieUrl = kickOffUri; } } } + } + + // + // Move us to the final data hash now that the URI is known + // + if( !m_uri.isEmpty() ) { + QMutexLocker rmlock(&m_rm->mutex); - return !m_uri.isEmpty(); + ResourceDataHash::iterator it = m_rm->m_initializedData.find(m_uri); + if( it == m_rm->m_initializedData.end() ) { + m_rm->m_initializedData.insert( m_uri, this ); + } + else { + return it.value(); + } } + + return this; } void Nepomuk::ResourceData::invalidateCache() { - // - // TODO: Resources might be deleted or only parts of resources might be deleted while we have local - // instances of them. - // If a resource's identifier is deleted and this instance was created using exactly that then the id - // is in m_rm->m_idKickoffData and this instance will be found again via that (now invalid) id! - // The same is true for completely deleted resources which are found again via their ids and their urls! - // m_cacheDirty = true; } @@ -758,7 +657,7 @@ load(); if( !m_pimoThing ) { if( hasType( Vocabulary::PIMO::Thing() ) ) { - kDebug() << "we are already a thing. Creating link to ourself" << m_uri << this; +// kDebug() << "we are already a thing. Creating link to ourself" << m_uri << this; // we are out own thing m_pimoThing = new Thing(this); } @@ -769,11 +668,11 @@ m_pimoThing = new Thing(this); } else { - kDebug() << "creating new thing for" << m_uri << m_types << this; +// kDebug() << "creating new thing for" << m_uri << m_types << this; m_pimoThing = new Thing(); } m_pimoThing->m_data->m_groundingOccurence = this; - kDebug() << "created thing" << m_pimoThing->m_data << "with grounding occurence" << m_pimoThing->m_data->m_groundingOccurence; +// kDebug() << "created thing" << m_pimoThing->m_data << "with grounding occurence" << m_pimoThing->m_data->m_groundingOccurence; } return *m_pimoThing; } @@ -781,31 +680,25 @@ bool Nepomuk::ResourceData::operator==( const ResourceData& other ) const { - const ResourceData* that = this; - if( m_proxyData ) - that = m_proxyData; - - if( that == &other ) + if( this == &other ) return true; - return( that->m_uri == other.m_uri && - that->m_mainType == other.m_mainType && - that->m_kickoffUri == other.m_kickoffUri && - that->m_kickoffId == other.m_kickoffId ); + return( m_uri == other.m_uri && + m_mainType == other.m_mainType && + m_kickoffUris == other.m_kickoffUris ); } QDebug Nepomuk::ResourceData::operator<<( QDebug dbg ) const { - dbg << QString::fromLatin1("[kickoffid: %1, kickoffuri: %2, uri: %3, type: %4, ref: %5") - .arg(m_kickoffId, - m_kickoffUri.url(), - m_uri.url(), - m_mainType.toString()) - .arg(m_ref); - if(m_proxyData) - dbg << QLatin1String(", proxy: " ) << *m_proxyData; - return dbg << QLatin1String("]"); + KUrl::List list = m_kickoffUris.toList(); + dbg << QString::fromLatin1("[kickoffuri: %1; uri: %2; type: %3; ref: %4]") + .arg( list.toStringList().join(QLatin1String(",")), + m_uri.url(), + m_mainType.toString() ) + .arg( m_ref ); + + return dbg; } @@ -813,3 +706,36 @@ { return data.operator<<( dbg ); } + + +void Nepomuk::ResourceData::updateKickOffLists(const QUrl& prop, const QUrl& newUrl) +{ + KUrl oldUrl; + if( prop == Nepomuk::Vocabulary::NIE::url() ) { + oldUrl = m_nieUrl; + m_nieUrl = newUrl; + } + else if( prop == Soprano::Vocabulary::NAO::identifier() ) { + Q_FOREACH( const KUrl& url, m_kickoffUris ) { + if( url.scheme().isEmpty() ) { + oldUrl = url; + break; + } + } + } + else { + return; + } + + if( oldUrl != newUrl ) { + QMutexLocker rmlock(&m_rm->mutex); + + m_kickoffUris.remove( oldUrl ); + m_rm->m_uriKickoffData.remove( oldUrl ); + + if( !newUrl.isEmpty() ) { + m_kickoffUris.insert( newUrl ); + m_rm->m_uriKickoffData.insert( newUrl, this ); + } + } +} Index: nepomuk/core/variant.cpp =================================================================== --- nepomuk/core/variant.cpp +++ nepomuk/core/variant.cpp 2010-12-01 09:51:54.000000000 +0100 @@ -22,6 +22,7 @@ #include "resource.h" #include <soprano/literalvalue.h> +#include <soprano/node.h> #include <kdebug.h> @@ -1312,6 +1313,7 @@ } +// static Nepomuk::Variant Nepomuk::Variant::fromString( const QString& value, int type ) { // first check the types that are not supported by Soprano since they are not literal types @@ -1328,6 +1330,26 @@ } } + +// static +Nepomuk::Variant Nepomuk::Variant::fromNode( const Soprano::Node& node ) +{ + // + // We cannot put in Resource objects here since then nie:url file:/ URLs would + // get converted back to the actual resource URIs which would be useless. + // That is why Variant treats QUrl and Resource pretty much as similar. + // + if ( node.isResource() ) { + return Nepomuk::Variant( node.uri() ); + } + else if ( node.isLiteral() ) { + return Nepomuk::Variant( node.literal().variant() ); + } + else { + return Nepomuk::Variant(); + } +} + bool Nepomuk::Variant::operator==( const Variant& other ) const {