diff --git a/akonadi/CMakeLists.txt b/akonadi/CMakeLists.txt index c64bd683c..c529bb526 100644 --- a/akonadi/CMakeLists.txt +++ b/akonadi/CMakeLists.txt @@ -1,242 +1,244 @@ project(akonadi-kde) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}" ) if(CMAKE_COMPILE_GCOV) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") endif(CMAKE_COMPILE_GCOV) if (KDE4_BUILD_TESTS) # only with this macro the AKONADI_TESTS_EXPORT macro will do something add_definitions(-DCOMPILING_TESTS) add_subdirectory( tests ) endif (KDE4_BUILD_TESTS) add_definitions( -DQT_NO_CAST_FROM_ASCII ) add_definitions( -DQT_NO_CAST_TO_ASCII ) add_subdirectory( kabc ) add_subdirectory( kmime ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${QT_QTDBUS_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${KDE4_INCLUDE_DIR} ${AKONADI_INCLUDE_DIR} ${AKONADI_INCLUDE_DIR}/akonadi/private ) # libakonadi-kde set( akonadikde_LIB_SRC entity.cpp # keep it at top to not break enable-final agentbase.cpp agentfilterproxymodel.cpp agentinstance.cpp agentinstancecreatejob.cpp agentinstancemodel.cpp agentinstancewidget.cpp agentmanager.cpp agenttype.cpp agenttypemodel.cpp agenttypewidget.cpp agenttypedialog.cpp attribute.cpp attributefactory.cpp cachepolicy.cpp cachepolicypage.cpp changerecorder.cpp collection.cpp collectioncopyjob.cpp collectioncreatejob.cpp collectiondeletejob.cpp collectiondialog.cpp collectionfilterproxymodel.cpp collectiongeneralpropertiespage.cpp collectionfetchjob.cpp collectionmodel.cpp collectionmodel_p.cpp collectionmodifyjob.cpp collectionmovejob.cpp collectionpathresolver.cpp collectionpropertiesdialog.cpp collectionpropertiespage.cpp collectionrequester.cpp collectionrightsattribute.cpp collectionselectjob.cpp collectionstatistics.cpp collectionstatisticsdelegate.cpp collectionstatisticsjob.cpp collectionstatisticsmodel.cpp collectionsync.cpp collectionview.cpp control.cpp entitydisplayattribute.cpp #entitysortfilterproxymodel.cpp erroroverlay.cpp exception.cpp expungejob.cpp firstrun.cpp flatcollectionproxymodel.cpp item.cpp itemcreatejob.cpp itemcopyjob.cpp itemdeletejob.cpp itemfetchjob.cpp itemfetchscope.cpp itemmodel.cpp itemmonitor.cpp itemmovejob.cpp itemserializer.cpp itemserializerplugin.cpp itemmodifyjob.cpp itemsync.cpp itemview.cpp job.cpp linkjob.cpp + filteractionjob.cpp mimetypechecker.cpp monitor.cpp monitor_p.cpp pastehelper.cpp protocolhelper.cpp resourcebase.cpp resourcescheduler.cpp resourceselectjob.cpp searchcreatejob.cpp selftestdialog.cpp session.cpp servermanager.cpp standardactionmanager.cpp subscriptionjob.cpp subscriptionchangeproxymodel.cpp subscriptiondialog.cpp subscriptionmodel.cpp transactionjobs.cpp transactionsequence.cpp transportresource.cpp unlinkjob.cpp # Temporary until ported to Qt-plugin framework pluginloader.cpp ) # DBus interfaces and adaptors set(akonadi_xml ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.NotificationManager.xml) set_source_files_properties(${akonadi_xml} PROPERTIES INCLUDE "notificationmessage_p.h") qt4_add_dbus_interface( akonadikde_LIB_SRC ${akonadi_xml} notificationmanagerinterface ) qt4_add_dbus_interfaces( akonadikde_LIB_SRC ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.AgentManager.xml ) qt4_add_dbus_interfaces( akonadikde_LIB_SRC ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.Tracer.xml ) qt4_add_dbus_adaptor( akonadikde_LIB_SRC ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.Resource.xml resourcebase.h Akonadi::ResourceBase ) qt4_add_dbus_adaptor( akonadikde_LIB_SRC ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.Agent.Status.xml agentbase.h Akonadi::AgentBase ) # TODO move this to kdesupport/akonadi/interfaces qt4_add_dbus_adaptor( akonadikde_LIB_SRC interfaces/org.freedesktop.Akonadi.Resource.Transport.xml transportresource.h Akonadi::TransportResource ) # TODO merge with Akonadi.Control in kdesupport/akonadi/interfaces qt4_add_dbus_adaptor( akonadikde_LIB_SRC interfaces/org.freedesktop.Akonadi.Agent.Control.xml agentbase.h Akonadi::AgentBase ) #qt4_add_dbus_adaptor( akonadikde_LIB_SRC ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.Agent.Control.xml agentbase.h Akonadi::AgentBase ) kde4_add_ui_files( akonadikde_LIB_SRC cachepolicypage.ui collectiongeneralpropertiespage.ui subscriptiondialog.ui controlprogressindicator.ui selftestdialog.ui ) kde4_add_library( akonadi-kde SHARED ${akonadikde_LIB_SRC} ) macro_ensure_version( "4.2.0" ${KDE_VERSION} KDE_IS_AT_LEAST_42 ) target_link_libraries( akonadi-kde ${KDE4_SOLID_LIBS} ${QT_QTNETWORK_LIBRARY} ${QT_QTDBUS_LIBRARY} ${QT_QTSQL_LIBRARY} ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${AKONADI_COMMON_LIBRARIES} ) set( AKONADI_KDE_DEPS ${KDE4_KDEUI_LIBS} ${QT_QTDBUS_LIBRARY} ${QT_QTCORE_LIBRARY} ) if(${KDE_IS_AT_LEAST_42}) target_link_libraries( akonadi-kde LINK_INTERFACE_LIBRARIES ${AKONADI_KDE_DEPS}) else(${KDE_IS_AT_LEAST_42}) target_link_libraries( akonadi-kde ${AKONADI_KDE_DEPS}) endif(${KDE_IS_AT_LEAST_42}) set_target_properties( akonadi-kde PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) install( TARGETS akonadi-kde EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) ########### install files ############### install( FILES akonadi_export.h agentbase.h agentfilterproxymodel.h agentinstance.h agentinstancecreatejob.h agentinstancemodel.h agentinstancewidget.h agentmanager.h agenttype.h agenttypemodel.h agenttypewidget.h agenttypedialog.h attribute.h attributefactory.h cachepolicy.h changerecorder.h collection.h collectioncopyjob.h collectioncreatejob.h collectiondeletejob.h collectiondialog.h collectionfilterproxymodel.h collectionfetchjob.h collectionmodel.h collectionmodifyjob.h collectionpropertiesdialog.h collectionpropertiespage.h collectionrequester.h collectionstatisticsdelegate.h collectionstatisticsmodel.h collectionstatistics.h collectionstatisticsjob.h collectionview.h control.h entity.h entitydisplayattribute.h # entitysortfilterproxymodel.h exception.h item.h itemcreatejob.h itemcopyjob.h itemdeletejob.h itemfetchjob.h itemfetchscope.h itemmodel.h itemmodifyjob.h itemmonitor.h itemmovejob.h itempayloadinternals_p.h itemserializerplugin.h itemsync.h itemview.h job.h linkjob.h + filteractionjob.h mimetypechecker.h monitor.h qtest_akonadi.h resourcebase.h searchcreatejob.h session.h servermanager.h standardactionmanager.h transactionjobs.h transactionsequence.h transportresource.h unlinkjob.h DESTINATION ${INCLUDE_INSTALL_DIR}/akonadi COMPONENT Devel ) install( FILES collectionpathresolver_p.h DESTINATION ${INCLUDE_INSTALL_DIR}/akonadi/private COMPONENT Devel ) install( FILES kcfg2dbus.xsl DESTINATION ${DATA_INSTALL_DIR}/akonadi-kde ) diff --git a/akonadi/filteractionjob.cpp b/akonadi/filteractionjob.cpp new file mode 100644 index 000000000..c01197221 --- /dev/null +++ b/akonadi/filteractionjob.cpp @@ -0,0 +1,149 @@ +/* + Copyright (c) 2009 Constantin Berzan + + 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 "filteractionjob.h" + +#include "collection.h" +#include "itemfetchjob.h" +#include "itemfetchscope.h" +#include "job_p.h" + +#include + +using namespace Akonadi; + +class Akonadi::FilterActionJob::Private +{ + public: + Private( FilterActionJob *qq ) + : q( qq ) + , functor( 0 ) + { + } + + ~Private() + { + delete functor; + } + + FilterActionJob *q; + Collection collection; + Item::List items; + FilterAction *functor; + ItemFetchScope fetchScope; + + // slots: + void fetchResult( KJob *job ); + + void traverseItems(); +}; + +void FilterActionJob::Private::fetchResult( KJob *job ) +{ + if ( job->error() ) { + // KCompositeJob takes care of errors. + return; + } + + ItemFetchJob *fjob = dynamic_cast( job ); + Q_ASSERT( fjob ); + Q_ASSERT( items.isEmpty() ); + items = fjob->items(); + traverseItems(); +} + +void FilterActionJob::Private::traverseItems() +{ + Q_ASSERT( functor ); + kDebug() << "Traversing" << items.count() << "items."; + foreach( const Item &item, items ) { + if( functor->itemAccepted( item ) ) { + q->addSubjob( functor->itemAction( item ) ); + kDebug() << "Added subjob for item" << item.id(); + } + } + if( q->subjobs().isEmpty() ) { + kDebug() << "No subjobs; I am done."; + q->emitResult(); + } else { + kDebug() << "Have subjobs; calling commit()."; + q->commit(); + } +} + + + +FilterAction::~FilterAction() +{ +} + + + +FilterActionJob::FilterActionJob( const Item &item, FilterAction *functor, QObject *parent ) + : TransactionSequence( parent ) + , d( new Private( this ) ) +{ + d->functor = functor; + d->items << item; +} + +FilterActionJob::FilterActionJob( const Item::List &items, FilterAction *functor, QObject *parent ) + : TransactionSequence( parent ) + , d( new Private( this ) ) +{ + d->functor = functor; + d->items = items; +} + +FilterActionJob::FilterActionJob( const Collection &collection, FilterAction *functor, QObject *parent ) + : TransactionSequence( parent ) + , d( new Private( this ) ) +{ + d->functor = functor; + Q_ASSERT( collection.isValid() ); + d->collection = collection; +} + +FilterActionJob::~FilterActionJob() +{ + delete d; +} + +#if 0 +Item::List FilterActionJob::items() +{ + return d->items; +} +#endif + +void FilterActionJob::doStart() +{ + if( d->collection.isValid() ) { + kDebug() << "Fetching collection" << d->collection.id(); + ItemFetchJob *fjob = new ItemFetchJob( d->collection, this ); + Q_ASSERT( d->functor ); + d->fetchScope = d->functor->fetchScope(); + fjob->setFetchScope( d->fetchScope ); + connect( fjob, SIGNAL(result(KJob*)), this, SLOT(fetchResult(KJob*)) ); + } else { + d->traverseItems(); + } +} + +#include "filteractionjob.moc" diff --git a/akonadi/filteractionjob.h b/akonadi/filteractionjob.h new file mode 100644 index 000000000..26b643f5d --- /dev/null +++ b/akonadi/filteractionjob.h @@ -0,0 +1,96 @@ +/* + Copyright (c) 2009 Constantin Berzan + + 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 AKONADI_FILTERACTIONJOB_H +#define AKONADI_FILTERACTIONJOB_H + +#include "item.h" +#include "transactionsequence.h" + +namespace Akonadi { + +class Collection; +class ItemFetchScope; +class Job; + +/** + Abstract functor for a FilterActionJob. Subclass it and implement the virtual + methods. + + // TODO docu + + // TODO example +*/ +class AKONADI_EXPORT FilterAction +{ + public: + /// only used if FilterActionJob created with collection constructor + virtual Akonadi::ItemFetchScope fetchScope() const = 0; + virtual bool itemAccepted( const Akonadi::Item &item ) const = 0; + virtual Akonadi::Job *itemAction( const Akonadi::Item &item ) const = 0; + virtual ~FilterAction(); +}; + + +/** + A job to filter and apply an action on a set of items. The filter and action + are provided by a functor derived from FilterAction. + + // TODO docu + + // TODO example +*/ +class AKONADI_EXPORT FilterActionJob : public TransactionSequence +{ + Q_OBJECT + + public: + FilterActionJob( const Item &item, FilterAction *functor, QObject *parent = 0 ); + FilterActionJob( const Item::List &items, FilterAction *functor, QObject *parent = 0 ); + FilterActionJob( const Collection &collection, FilterAction *functor, QObject *parent = 0 ); + ~FilterActionJob(); + + // TODO I would like to provide a list of modified items, but there is no + // easy way to get those, because FilterAction::itemAction() can return any + // kind of Job, not only an ItemModifyJob. + // Restrict it to modify jobs only? + // Re-fetch the accepted items after all jobs are done? + //Item::List items() const; + + // TODO provide setFunctor? + + // TODO provide forceFetch for the Item and Item::List constructors? + + protected: + virtual void doStart(); + + private: + //@cond PRIVATE + class Private; + Private *const d; + + Q_PRIVATE_SLOT( d, void fetchResult( KJob* ) ) + //@endcond +}; + +} + + +#endif + diff --git a/akonadi/tests/CMakeLists.txt b/akonadi/tests/CMakeLists.txt index f4f128bd9..2fbe42172 100644 --- a/akonadi/tests/CMakeLists.txt +++ b/akonadi/tests/CMakeLists.txt @@ -1,123 +1,124 @@ if(${EXECUTABLE_OUTPUT_PATH}) set( PREVIOUS_EXEC_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH} ) else(${EXECUTABLE_OUTPUT_PATH}) set( PREVIOUS_EXEC_OUTPUT_PATH . ) endif(${EXECUTABLE_OUTPUT_PATH}) set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}" ) include_directories( ${CMAKE_SOURCE_DIR}/akonadi ${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/../ ${Boost_INCLUDE_DIR} ${AKONADI_INCLUDE_DIR} ) # add testrunner (application for managing a self-contained test # environment) add_subdirectory(testrunner) # add benchmarker add_subdirectory(benchmarker) # convenience macro to add akonadi demo application macro(add_akonadi_demo _source) set(_test ${_source}) get_filename_component(_name ${_source} NAME_WE) kde4_add_executable(${_name} TEST ${_test}) target_link_libraries(${_name} akonadi-kde akonadi-kmime ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBS}) endmacro(add_akonadi_demo) # convenience macro to add akonadi qtestlib unit-tests macro(add_akonadi_test _source) set(_test ${_source}) get_filename_component(_name ${_source} NAME_WE) kde4_add_unit_test(${_name} TESTNAME akonadi-${_name} ${_test}) target_link_libraries(${_name} akonadi-kde akonadi-kmime ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDECORE_LIBS} ${AKONADI_COMMON_LIBRARIES}) endmacro(add_akonadi_test) # convenience macro to add akonadi testrunner unit-tests macro(add_akonadi_isolated_test _source) set(_test ${_source}) get_filename_component(_name ${_source} NAME_WE) kde4_add_executable(${_name} TEST ${_test}) target_link_libraries(${_name} akonadi-kde akonadi-kmime ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDECORE_LIBS} ${AKONADI_COMMON_LIBRARIES}) # based on kde4_add_unit_test if (WIN32) get_target_property( _loc ${_name} LOCATION ) set(_executable ${_loc}.bat) set(_testrunner ${PREVIOUS_EXEC_OUTPUT_PATH}/akonaditest.bat) else (WIN32) set(_executable ${EXECUTABLE_OUTPUT_PATH}/${_name}) set(_testrunner ${PREVIOUS_EXEC_OUTPUT_PATH}/akonaditest) endif (WIN32) if (UNIX) set(_executable ${_executable}.shell) set(_testrunner ${_testrunner}.shell) endif (UNIX) add_test( akonadi-db-${_name} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config-db.xml ${_executable} ) add_test( akonadi-fs-${_name} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config-fs.xml ${_executable} ) #add_test( akonadi-sqlite-${_name} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config-sqlite.xml ${_executable} ) endmacro(add_akonadi_isolated_test) # demo applications add_akonadi_demo(itemdumper.cpp) add_akonadi_demo(subscriber.cpp) add_akonadi_demo(headfetcher.cpp) add_akonadi_demo(agentinstancewidgettest.cpp) add_akonadi_demo(agenttypewidgettest.cpp) add_akonadi_demo(pluginloadertest.cpp) add_akonadi_demo(selftester.cpp) kde4_add_executable( akonadi-firstrun TEST ../firstrun.cpp firstrunner.cpp ) target_link_libraries( akonadi-firstrun akonadi-kde ${KDE4_KDEUI_LIBS} ) # qtestlib unit tests add_akonadi_test(imapparsertest.cpp) add_akonadi_test(imapsettest.cpp) add_akonadi_test(itemhydratest.cpp) add_akonadi_test(itemtest.cpp) add_akonadi_test(itemserializertest.cpp) add_akonadi_test(mimetypecheckertest.cpp) add_akonadi_test(protocolhelpertest.cpp) # qtestlib tests that need non-exported stuff from akonadi-kde kde4_add_unit_test(resourceschedulertest TESTNAME akonadi-resourceschedulertest resourceschedulertest.cpp ../resourcescheduler.cpp) target_link_libraries(resourceschedulertest akonadi-kde ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDECORE_LIBS} ${AKONADI_COMMON_LIBRARIES}) # testrunner tests add_akonadi_isolated_test(testenvironmenttest.cpp) add_akonadi_isolated_test(autoincrementtest.cpp) add_akonadi_isolated_test(attributefactorytest.cpp) add_akonadi_isolated_test(collectionjobtest.cpp) add_akonadi_isolated_test(collectionpathresolvertest.cpp) add_akonadi_isolated_test(collectionattributetest.cpp) add_akonadi_isolated_test(itemfetchtest.cpp) add_akonadi_isolated_test(itemappendtest.cpp) add_akonadi_isolated_test(itemstoretest.cpp) add_akonadi_isolated_test(itemdeletetest.cpp) add_akonadi_isolated_test(monitortest.cpp) add_akonadi_isolated_test(searchjobtest.cpp) add_akonadi_isolated_test(changerecordertest.cpp) add_akonadi_isolated_test(resourcetest.cpp) add_akonadi_isolated_test(subscriptiontest.cpp) add_akonadi_isolated_test(transactiontest.cpp) +add_akonadi_isolated_test(filteractiontest.cpp) add_akonadi_isolated_test(itemcopytest.cpp) add_akonadi_isolated_test(itemmovetest.cpp) add_akonadi_isolated_test(collectioncopytest.cpp) add_akonadi_isolated_test(collectionmovetest.cpp) add_akonadi_isolated_test(collectionsynctest.cpp) add_akonadi_isolated_test(itemsynctest.cpp) add_akonadi_isolated_test(linktest.cpp) add_akonadi_isolated_test(cachetest.cpp) add_akonadi_isolated_test(servermanagertest.cpp) add_akonadi_isolated_test(collectioncreator.cpp) add_akonadi_isolated_test(itembenchmark.cpp) diff --git a/akonadi/tests/filteractiontest.cpp b/akonadi/tests/filteractiontest.cpp new file mode 100644 index 000000000..41b3f09e5 --- /dev/null +++ b/akonadi/tests/filteractiontest.cpp @@ -0,0 +1,206 @@ +/* + Copyright (c) 2009 Constantin Berzan + + 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 "filteractiontest.h" +#include "collectionpathresolver_p.h" +#include "testattribute.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Akonadi; + +QTEST_AKONADIMAIN( FilterActionTest, NoGUI ) + +static const QByteArray acceptable = "acceptable"; +static const QByteArray unacceptable = "unacceptable"; +static const QByteArray modified = "modified"; +static Collection res1; + +class MyFunctor : public FilterAction +{ + virtual Akonadi::ItemFetchScope fetchScope() const + { + ItemFetchScope scope; + scope.fetchAttribute(); + return scope; + } + + virtual bool itemAccepted( const Akonadi::Item &item ) const + { + if( !item.hasAttribute() ) { + return false; + } + return ( item.attribute()->data == acceptable ); + } + + virtual Akonadi::Job *itemAction( const Akonadi::Item &item ) const + { + Item cp( item ); + TestAttribute *newa = new TestAttribute; + newa->data = modified; + cp.addAttribute( newa ); + return new ItemModifyJob( cp ); + } +}; + +void FilterActionTest::initTestCase() +{ + AttributeFactory::registerAttribute(); + + CollectionPathResolver *resolver = new CollectionPathResolver( "res1", this ); + QVERIFY( resolver->exec() ); + res1 = Collection( resolver->collection() ); +} + +void FilterActionTest::testMassModifyItem() +{ + Collection col = createCollection( "testMassModifyItem" ); + + // Test acceptable item. + Item item = createItem( col, true ); + FilterActionJob *mjob = new FilterActionJob( item, new MyFunctor, this ); + AKVERIFYEXEC( mjob ); + ItemFetchJob *fjob = new ItemFetchJob( item, this ); + fjob->fetchScope().fetchAllAttributes(); + AKVERIFYEXEC( fjob ); + QCOMPARE( fjob->items().count(), 1 ); + item = fjob->items().first(); + QVERIFY( item.hasAttribute() ); + TestAttribute *attr = item.attribute(); + QCOMPARE( attr->data, modified ); + + // Test unacceptable item. + item = createItem( col, false ); + mjob = new FilterActionJob( item, new MyFunctor, this ); + AKVERIFYEXEC( mjob ); + fjob = new ItemFetchJob( item, this ); + fjob->fetchScope().fetchAllAttributes(); + AKVERIFYEXEC( fjob ); + QCOMPARE( fjob->items().count(), 1 ); + item = fjob->items().first(); + QVERIFY( item.hasAttribute() ); + attr = item.attribute(); + QCOMPARE( attr->data, unacceptable ); +} + +void FilterActionTest::testMassModifyItems() +{ + Collection col = createCollection( "testMassModifyItems" ); + + // Test a bunch of acceptable and unacceptable items. + Item::List acc, unacc; + for( int i = 0; i < 5; i++ ) { + acc.append( createItem( col, true ) ); + unacc.append( createItem( col, false ) ); + } + Item::List all = acc + unacc; + QCOMPARE( all.count(), 10 ); + FilterActionJob *mjob = new FilterActionJob( all, new MyFunctor, this ); + AKVERIFYEXEC( mjob ); + ItemFetchJob *fjob = new ItemFetchJob( col, this ); + fjob->fetchScope().fetchAllAttributes(); + AKVERIFYEXEC( fjob ); + QCOMPARE( fjob->items().count(), 10 ); + foreach( const Item &item, fjob->items() ) { + QVERIFY( item.hasAttribute() ); + const QByteArray data = item.attribute()->data; + if( data == unacceptable ) { + QVERIFY( unacc.contains( item ) ); + unacc.removeAll( item ); + } else if( data == modified ) { + QVERIFY( acc.contains( item ) ); + acc.removeAll( item ); + } else { + QVERIFY2( false, "Got bad data \"" + data + '\"' ); + } + } + QCOMPARE( acc.count(), 0 ); + QCOMPARE( unacc.count(), 0 ); +} + +void FilterActionTest::testMassModifyCollection() +{ + Collection col = createCollection( "testMassModifyCollection" ); + + // Test a bunch of acceptable and unacceptable items. + Item::List acc, unacc; + for( int i = 0; i < 5; i++ ) { + acc.append( createItem( col, true ) ); + unacc.append( createItem( col, false ) ); + } + FilterActionJob *mjob = new FilterActionJob( col, new MyFunctor, this ); + kDebug() << "Executing FilterActionJob."; + AKVERIFYEXEC( mjob ); + ItemFetchJob *fjob = new ItemFetchJob( col, this ); + fjob->fetchScope().fetchAllAttributes(); + AKVERIFYEXEC( fjob ); + QCOMPARE( fjob->items().count(), 10 ); + foreach( const Item &item, fjob->items() ) { + QVERIFY( item.hasAttribute() ); + const QByteArray data = item.attribute()->data; + if( data == unacceptable ) { + QVERIFY( unacc.contains( item ) ); + unacc.removeAll( item ); + } else if( data == modified ) { + QVERIFY( acc.contains( item ) ); + acc.removeAll( item ); + } else { + QVERIFY2( false, "Got bad data \"" + data + '\"' ); + } + } + QCOMPARE( acc.count(), 0 ); + QCOMPARE( unacc.count(), 0 ); +} + +Collection FilterActionTest::createCollection( const QString &name ) +{ + Collection col; + col.setParent( res1 ); + col.setName( name ); + CollectionCreateJob *ccjob = new CollectionCreateJob( col, this ); + Q_ASSERT( ccjob->exec() ); + return ccjob->collection(); +} + +Item FilterActionTest::createItem( const Collection &col, bool accept ) +{ + Q_ASSERT( col.isValid() ); + + Item item; + item.setMimeType( "text/directory" ); + TestAttribute *attr = new TestAttribute; + if( accept ) { + attr->data = acceptable; + } else { + attr->data = unacceptable; + } + item.addAttribute( attr ); + ItemCreateJob *cjob = new ItemCreateJob( item, col, this ); + Q_ASSERT( cjob->exec() ); + return cjob->item(); +} + +#include "filteractiontest.moc" diff --git a/akonadi/tests/filteractiontest.h b/akonadi/tests/filteractiontest.h new file mode 100644 index 000000000..82d041508 --- /dev/null +++ b/akonadi/tests/filteractiontest.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2009 Constantin Berzan + + 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 FILTERACTIONTEST_H +#define FILTERACTIONTEST_H + +#include +#include + +#include +#include + +class KJob; + +class FilterActionTest : public QObject +{ + Q_OBJECT + + private slots: + void initTestCase(); + void testMassModifyItem(); + void testMassModifyItems(); + void testMassModifyCollection(); + + private: + Akonadi::Collection createCollection( const QString &name ); + Akonadi::Item createItem( const Akonadi::Collection &col, bool accept ); + +}; + + +#endif