diff --git a/akonadi/CMakeLists.txt b/akonadi/CMakeLists.txt index ca2bb3990..20585fa8d 100644 --- a/akonadi/CMakeLists.txt +++ b/akonadi/CMakeLists.txt @@ -1,235 +1,236 @@ 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 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 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 ) 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 mimetypechecker.h monitor.h qtest_akonadi.h resourcebase.h searchcreatejob.h session.h servermanager.h standardactionmanager.h transactionjobs.h transactionsequence.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/collectionmovejob.cpp b/akonadi/collectionmovejob.cpp new file mode 100644 index 000000000..e6427259d --- /dev/null +++ b/akonadi/collectionmovejob.cpp @@ -0,0 +1,63 @@ +/* + Copyright (c) 2009 Volker Krause + + 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 "collectionmovejob.h" +#include "collection.h" +#include "job_p.h" + +using namespace Akonadi; + +class Akonadi::CollectionMoveJobPrivate : public JobPrivate +{ + public: + CollectionMoveJobPrivate( CollectionMoveJob *parent ) + : JobPrivate( parent ) + { + } + + Collection collection; + Collection destination; +}; + +CollectionMoveJob::CollectionMoveJob( const Collection &collection, const Collection &destination, QObject * parent ) + : Job( new CollectionMoveJobPrivate( this ), parent ) +{ + Q_D( CollectionMoveJob ); + + Q_ASSERT( collection.isValid() ); + d->collection = collection; + d->destination = destination; +} + +void CollectionMoveJob::doStart() +{ + Q_D( CollectionMoveJob ); + if ( !d->collection.isValid() || !d->destination.isValid() ) { + setError( Unknown ); + setErrorText( QLatin1String("Invalid collection specified") ); + emitResult(); + return; + } + + const QByteArray command = d->newTag() + " COLMOVE " + QByteArray::number( d->collection.id() ) + + ' ' + QByteArray::number( d->destination.id() ) + '\n'; + d->writeData( command ); +} + +#include "collectionmovejob.moc" diff --git a/akonadi/collectionmovejob.h b/akonadi/collectionmovejob.h new file mode 100644 index 000000000..f81bacd10 --- /dev/null +++ b/akonadi/collectionmovejob.h @@ -0,0 +1,60 @@ +/* + Copyright (c) 2009 Volker Krause + + 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_COLLECTIONMOVEJOB_H +#define AKONADI_COLLECTIONMOVEJOB_H + +#include "akonadi_export.h" + +#include + +namespace Akonadi { + +class Collection; +class CollectionMoveJobPrivate; + +/** + * @short Job that moves a collection in the Akonadi storage to a new parent collection. + * + * This job moves an existing collection to a new parent collection. + */ +class AKONADI_EXPORT CollectionMoveJob : public Job +{ + Q_OBJECT + + public: + /** + * Creates a new collection move job for the given collection and destination + * + * @param collection The collection to move. + * @param destination The destination collection where @p collection should be moved to. + * @param parent The parent object. + */ + CollectionMoveJob( const Collection &collection, const Collection &destination, QObject *parent = 0 ); + + protected: + virtual void doStart(); + + private: + Q_DECLARE_PRIVATE( CollectionMoveJob ) +}; + +} + +#endif diff --git a/akonadi/pastehelper.cpp b/akonadi/pastehelper.cpp index a54bd9ed6..a35930649 100644 --- a/akonadi/pastehelper.cpp +++ b/akonadi/pastehelper.cpp @@ -1,114 +1,113 @@ /* Copyright (c) 2008 Volker Krause 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 "pastehelper_p.h" #include "collectioncopyjob.h" -#include "collectionmodifyjob.h" +#include "collectionmovejob.h" #include "item.h" #include "itemcreatejob.h" #include "itemcopyjob.h" #include "itemmodifyjob.h" #include "itemmovejob.h" #include "transactionsequence.h" #include #include #include #include #include using namespace Akonadi; bool PasteHelper::canPaste(const QMimeData * mimeData, const Collection & collection) { if ( !mimeData || !collection.isValid() ) return false; // TODO check acls depending on mimetype if ( (collection.rights() & (Collection::CanCreateItem | Collection::CanCreateCollection) ) == 0 ) return false; if ( KUrl::List::canDecode( mimeData ) ) return true; foreach ( const QString &format, mimeData->formats() ) if ( collection.contentMimeTypes().contains( format ) ) return true; return false; } KJob* PasteHelper::paste(const QMimeData * mimeData, const Collection & collection, bool copy) { if ( !canPaste( mimeData, collection ) ) return 0; // we try to drop data not coming with the akonadi:// url // find a type the target collection supports foreach ( const QString &type, mimeData->formats() ) { if ( !collection.contentMimeTypes().contains( type ) ) continue; QByteArray item = mimeData->data( type ); // HACK for some unknown reason the data is sometimes 0-terminated... if ( !item.isEmpty() && item.at( item.size() - 1 ) == 0 ) item.resize( item.size() - 1 ); Item it; it.setMimeType( type ); it.setPayloadFromData( item ); ItemCreateJob *job = new ItemCreateJob( it, collection ); return job; } if ( !KUrl::List::canDecode( mimeData ) ) return 0; // data contains an url list TransactionSequence *transaction = new TransactionSequence(); KUrl::List urls = KUrl::List::fromMimeData( mimeData ); foreach ( const KUrl &url, urls ) { if ( Collection::fromUrl( url ).isValid() ) { Collection col = Collection::fromUrl( url ); if ( !copy ) { - col.setParent( collection ); - CollectionModifyJob *job = new CollectionModifyJob( col, transaction ); + new CollectionMoveJob( col, collection, transaction ); } else { new CollectionCopyJob( col, collection, transaction ); } } else if ( Item::fromUrl( url ).isValid() ) { // TODO Extract mimetype from url and check if collection accepts it const Item item = Item::fromUrl( url ); if ( !copy ) { new ItemMoveJob( item, collection, transaction ); } else { new ItemCopyJob( item, collection, transaction ); } } else { // non-akonadi URL // TODO kDebug() << "Implement me!"; } } return transaction; } diff --git a/akonadi/session_p.h b/akonadi/session_p.h index 77ad8b2fe..4b667b5f6 100644 --- a/akonadi/session_p.h +++ b/akonadi/session_p.h @@ -1,115 +1,115 @@ /* Copyright (c) 2007 Volker Krause 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_SESSION_P_H #define AKONADI_SESSION_P_H #include "session.h" #include "imapparser_p.h" #include #include #include #include class QLocalSocket; namespace Akonadi { /** * @internal */ class SessionPrivate { public: SessionPrivate( Session *parent ) : mParent( parent ), mConnectionSettings( 0 ), protocolVersion( 0 ) { parser = new ImapParser(); } ~SessionPrivate() { delete parser; delete mConnectionSettings; } void startNext(); void reconnect(); void socketDisconnected(); void socketError( QLocalSocket::LocalSocketError error ); void dataReceived(); void doStartNext(); void startJob( Job* job ); void jobDone( KJob* job ); void jobWriteFinished( Akonadi::Job* job ); void jobDestroyed( QObject *job ); bool canPipelineNext(); /** * Creates a new default session for this thread with * the given @p sessionId. The session can be accessed * later by defaultSession(). * * You only need to call this method if you want that the * default session has a special custom id, otherwise a random unique * id is used automatically. */ static void createDefaultSession( const QByteArray &sessionId ); /** Associates the given Job object with this session. */ void addJob( Job* job ); /** Returns the next IMAP tag. */ int nextTag(); /** Sends the given raw data. */ void writeData( const QByteArray &data ); - static int minimumProtocolVersion() { return 13; } + static int minimumProtocolVersion() { return 14; } Session *mParent; QByteArray sessionId; QSettings *mConnectionSettings; QLocalSocket* socket; bool connected; int theNextTag; int protocolVersion; // job management QQueue queue; QQueue pipeline; Job* currentJob; bool jobRunning; // parser stuff ImapParser *parser; }; } #endif diff --git a/akonadi/tests/collectionmovetest.cpp b/akonadi/tests/collectionmovetest.cpp index f990d515b..be21e5f46 100644 --- a/akonadi/tests/collectionmovetest.cpp +++ b/akonadi/tests/collectionmovetest.cpp @@ -1,151 +1,147 @@ /* Copyright (c) 2006, 2009 Volker Krause 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 "test_utils.h" #include "collection.h" #include "collectionfetchjob.h" -#include "collectionmodifyjob.h" +#include "collectionmovejob.h" #include "item.h" #include "itemfetchjob.h" #include "itemfetchscope.h" #include using namespace Akonadi; class CollectionMoveTest : public QObject { Q_OBJECT private slots: void testIllegalMove_data() { QTest::addColumn( "source" ); QTest::addColumn( "destination" ); const Collection res1( collectionIdFromPath( "res1" ) ); const Collection res1foo( collectionIdFromPath( "res1/foo" ) ); const Collection res1bla( collectionIdFromPath( "res1/foo/bar/bla" ) ); QTest::newRow( "non-existing-target" ) << res1 << Collection( INT_MAX ); QTest::newRow( "root" ) << Collection::root() << res1; QTest::newRow( "move-into-child" ) << res1 << res1foo; QTest::newRow( "same-name-in-target" ) << res1bla << res1foo; QTest::newRow( "non-existing-source" ) << Collection( INT_MAX ) << res1; } void testIllegalMove() { QFETCH( Collection, source ); QFETCH( Collection, destination ); QVERIFY( source.isValid() ); QVERIFY( destination.isValid() ); - source.setParent( destination ); - CollectionModifyJob* mod = new CollectionModifyJob( source, this ); + CollectionMoveJob* mod = new CollectionMoveJob( source, destination, this ); QVERIFY( !mod->exec() ); } void testMove_data() { QTest::addColumn( "source" ); QTest::addColumn( "destination" ); QTest::addColumn( "crossResource" ); QTest::newRow( "inter-resource" ) << Collection( collectionIdFromPath( "res1" ) ) << Collection( collectionIdFromPath( "res2" ) ) << true; QTest::newRow( "intra-resource" ) << Collection( collectionIdFromPath( "res1/foo/bla" ) ) << Collection( collectionIdFromPath( "res1/foo/bar/bla" ) ) << false; } // TODO: test signals void testMove() { QFETCH( Collection, source ); QFETCH( Collection, destination ); QFETCH( bool, crossResource ); QVERIFY( source.isValid() ); QVERIFY( destination.isValid() ); CollectionFetchJob *fetch = new CollectionFetchJob( source, CollectionFetchJob::Base, this ); - QVERIFY( fetch->exec() ); + AKVERIFYEXEC( fetch ); QCOMPARE( fetch->collections().count(), 1 ); source = fetch->collections().first(); // obtain reference listing fetch = new CollectionFetchJob( source, CollectionFetchJob::Recursive ); - QVERIFY( fetch->exec() ); + AKVERIFYEXEC( fetch ); QHash referenceData; foreach ( const Collection c, fetch->collections() ) { ItemFetchJob *job = new ItemFetchJob( c, this ); - QVERIFY( job->exec() ); + AKVERIFYEXEC( job ); referenceData.insert( c, job->items() ); } // move collection - Collection col( source ); - col.setParent( destination ); - CollectionModifyJob *mod = new CollectionModifyJob( col, this ); - QVERIFY( mod->exec() ); + CollectionMoveJob *mod = new CollectionMoveJob( source, destination, this ); + AKVERIFYEXEC( mod ); // check if source was modified correctly CollectionFetchJob *ljob = new CollectionFetchJob( source, CollectionFetchJob::Base ); - QVERIFY( ljob->exec() ); + AKVERIFYEXEC( ljob ); Collection::List list = ljob->collections(); QCOMPARE( list.count(), 1 ); - col = list.first(); + Collection col = list.first(); QCOMPARE( col.name(), source.name() ); QCOMPARE( col.parent(), destination.id() ); // list destination and check if everything is still there ljob = new CollectionFetchJob( destination, CollectionFetchJob::Recursive ); - QVERIFY( ljob->exec() ); + AKVERIFYEXEC( ljob ); list = ljob->collections(); QVERIFY( list.count() >= referenceData.count() ); for ( QHash::ConstIterator it = referenceData.constBegin(); it != referenceData.constEnd(); ++it ) { QVERIFY( list.contains( it.key() ) ); if ( crossResource ) { QVERIFY( list[ list.indexOf( it.key() ) ].resource() != it.key().resource() ); } else { QCOMPARE( list[ list.indexOf( it.key() ) ].resource(), it.key().resource() ); } ItemFetchJob *job = new ItemFetchJob( it.key(), this ); job->fetchScope().fetchFullPayload(); - QVERIFY( job->exec() ); + AKVERIFYEXEC( job ); QCOMPARE( job->items().count(), it.value().count() ); foreach ( const Item item, job->items() ) { QVERIFY( it.value().contains( item ) ); QVERIFY( item.hasPayload() ); } } // cleanup - col.setParent( source.parent() ); - mod = new CollectionModifyJob( col, this ); - QVERIFY( mod->exec() ); + mod = new CollectionMoveJob( col, Collection( source.parent() ), this ); + AKVERIFYEXEC( mod ); } }; QTEST_AKONADIMAIN( CollectionMoveTest, NoGUI ) #include "collectionmovetest.moc"