diff --git a/akonadi/CMakeLists.txt b/akonadi/CMakeLists.txt
index c529bb526..37c42a213 100644
--- a/akonadi/CMakeLists.txt
+++ b/akonadi/CMakeLists.txt
@@ -1,244 +1,242 @@
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 )
+qt4_add_dbus_adaptor( akonadikde_LIB_SRC interfaces/org.freedesktop.Akonadi.Resource.Transport.xml resourcebase.h Akonadi::ResourceBase )
# 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/interfaces/org.freedesktop.Akonadi.Resource.Transport.xml b/akonadi/interfaces/org.freedesktop.Akonadi.Resource.Transport.xml
index cdf40ffc9..bafc74baa 100644
--- a/akonadi/interfaces/org.freedesktop.Akonadi.Resource.Transport.xml
+++ b/akonadi/interfaces/org.freedesktop.Akonadi.Resource.Transport.xml
@@ -1,13 +1,14 @@
+
diff --git a/akonadi/resourcebase.cpp b/akonadi/resourcebase.cpp
index 8c4eccee6..90a868484 100644
--- a/akonadi/resourcebase.cpp
+++ b/akonadi/resourcebase.cpp
@@ -1,606 +1,641 @@
/*
Copyright (c) 2006 Till Adam
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.
*/
#include "resourcebase.h"
#include "agentbase_p.h"
#include "resourceadaptor.h"
+#include "transportadaptor.h"
#include "collectiondeletejob.h"
#include "collectionsync_p.h"
#include "itemsync.h"
#include "resourcescheduler_p.h"
#include "tracerinterface.h"
#include "xdgbasedirs_p.h"
#include "changerecorder.h"
#include "collectionfetchjob.h"
#include "collectionmodifyjob.h"
#include "itemfetchjob.h"
#include "itemfetchscope.h"
#include "itemmodifyjob.h"
#include "itemmodifyjob_p.h"
#include "session.h"
#include "resourceselectjob_p.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace Akonadi;
class Akonadi::ResourceBasePrivate : public AgentBasePrivate
{
public:
ResourceBasePrivate( ResourceBase *parent )
: AgentBasePrivate( parent ),
+ mTransport( 0 ),
scheduler( 0 ),
mItemSyncer( 0 ),
mCollectionSyncer( 0 )
{
mStatusMessage = defaultReadyMessage();
}
Q_DECLARE_PUBLIC( ResourceBase )
void delayedInit()
{
if ( !QDBusConnection::sessionBus().registerService( QLatin1String( "org.freedesktop.Akonadi.Resource." ) + mId ) )
kFatal() << "Unable to register service at D-Bus: " << QDBusConnection::sessionBus().lastError().message();
AgentBasePrivate::delayedInit();
}
virtual void changeProcessed()
{
mMonitor->changeProcessed();
if ( !mMonitor->isEmpty() )
scheduler->scheduleChangeReplay();
scheduler->taskDone();
}
void slotDeliveryDone( KJob* job );
void slotCollectionSyncDone( KJob *job );
void slotLocalListDone( KJob *job );
void slotSynchronizeCollection( const Collection &col );
void slotCollectionListDone( KJob *job );
void slotItemSyncDone( KJob *job );
void slotPercent( KJob* job, unsigned long percent );
void slotDeleteResourceCollection();
void slotDeleteResourceCollectionDone( KJob *job );
void slotCollectionDeletionDone( KJob *job );
// synchronize states
Collection currentCollection;
+ ResourceBase::Transport *mTransport;
ResourceScheduler *scheduler;
ItemSync *mItemSyncer;
CollectionSync *mCollectionSyncer;
};
+ResourceBase::Transport::Transport()
+{
+}
+
+ResourceBase::Transport::~Transport()
+{
+}
+
ResourceBase::ResourceBase( const QString & id )
: AgentBase( new ResourceBasePrivate( this ), id )
{
Q_D( ResourceBase );
new ResourceAdaptor( this );
d->scheduler = new ResourceScheduler( this );
d->mMonitor->setChangeRecordingEnabled( true );
connect( d->mMonitor, SIGNAL( changesAdded() ),
d->scheduler, SLOT( scheduleChangeReplay() ) );
d->mMonitor->setResourceMonitored( d->mId.toLatin1() );
connect( d->scheduler, SIGNAL( executeFullSync() ),
SLOT( retrieveCollections() ) );
connect( d->scheduler, SIGNAL( executeCollectionTreeSync() ),
SLOT( retrieveCollections() ) );
connect( d->scheduler, SIGNAL( executeCollectionSync( const Akonadi::Collection& ) ),
SLOT( slotSynchronizeCollection( const Akonadi::Collection& ) ) );
connect( d->scheduler, SIGNAL( executeItemFetch( const Akonadi::Item&, const QSet& ) ),
SLOT( retrieveItem( const Akonadi::Item&, const QSet& ) ) );
connect( d->scheduler, SIGNAL( executeResourceCollectionDeletion() ),
SLOT( slotDeleteResourceCollection() ) );
connect( d->scheduler, SIGNAL( status( int, const QString& ) ),
SIGNAL( status( int, const QString& ) ) );
connect( d->scheduler, SIGNAL( executeChangeReplay() ),
d->mMonitor, SLOT( replayNext() ) );
connect( d->scheduler, SIGNAL( fullSyncComplete() ), SIGNAL( synchronized() ) );
connect( d->mMonitor, SIGNAL( nothingToReplay() ), d->scheduler, SLOT( taskDone() ) );
connect( this, SIGNAL( synchronized() ), d->scheduler, SLOT( taskDone() ) );
connect( this, SIGNAL( agentNameChanged( const QString& ) ),
this, SIGNAL( nameChanged( const QString& ) ) );
d->scheduler->setOnline( d->mOnline );
if ( !d->mMonitor->isEmpty() )
d->scheduler->scheduleChangeReplay();
new ResourceSelectJob( identifier() );
}
ResourceBase::~ResourceBase()
{
}
void ResourceBase::synchronize()
{
d_func()->scheduler->scheduleFullSync();
}
+void ResourceBase::registerTransport( Transport *transport )
+{
+ static bool adaptorCreated = false;
+ if( !adaptorCreated ) {
+ new TransportAdaptor( this );
+ adaptorCreated = true;
+ }
+ kDebug() << "transport=" << (void*) transport << "this=" << (void*) this;
+ d_func()->mTransport = transport;
+}
+
void ResourceBase::setName( const QString &name )
{
AgentBase::setAgentName( name );
}
QString ResourceBase::name() const
{
return AgentBase::agentName();
}
QString ResourceBase::parseArguments( int argc, char **argv )
{
QString identifier;
if ( argc < 3 ) {
kDebug( 5250 ) << "Not enough arguments passed...";
exit( 1 );
}
for ( int i = 1; i < argc - 1; ++i ) {
if ( QLatin1String( argv[ i ] ) == QLatin1String( "--identifier" ) )
identifier = QLatin1String( argv[ i + 1 ] );
}
if ( identifier.isEmpty() ) {
kDebug( 5250 ) << "Identifier argument missing";
exit( 1 );
}
QByteArray catalog;
char *p = strrchr( argv[0], '/' );
if ( p )
catalog = QByteArray( p + 1 );
else
catalog = QByteArray( argv[0] );
KCmdLineArgs::init( argc, argv, identifier.toLatin1(), catalog,
ki18nc("@title, application name", "Akonadi Resource"), "0.1",
ki18nc("@title, application description", "Akonadi Resource") );
KCmdLineOptions options;
options.add( "identifier ",
ki18nc("@label, commandline option", "Resource identifier") );
KCmdLineArgs::addCmdLineOptions( options );
return identifier;
}
int ResourceBase::init( ResourceBase *r )
{
QApplication::setQuitOnLastWindowClosed( false );
int rv = kapp->exec();
delete r;
return rv;
}
void ResourceBase::itemRetrieved( const Item &item )
{
Q_D( ResourceBase );
Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::FetchItem );
if ( !item.isValid() ) {
QDBusMessage reply( d->scheduler->currentTask().dbusMsg );
reply << false;
QDBusConnection::sessionBus().send( reply );
d->scheduler->taskDone();
return;
}
Item i( item );
QSet requestedParts = d->scheduler->currentTask().itemParts;
foreach ( const QByteArray &part, requestedParts ) {
if ( !item.loadedPayloadParts().contains( part ) ) {
kWarning( 5250 ) << "Item does not provide part" << part;
}
}
ItemModifyJob *job = new ItemModifyJob( i );
// FIXME: remove once the item with which we call retrieveItem() has a revision number
job->disableRevisionCheck();
connect( job, SIGNAL( result( KJob* ) ), SLOT( slotDeliveryDone( KJob* ) ) );
}
void ResourceBasePrivate::slotDeliveryDone(KJob * job)
{
Q_Q( ResourceBase );
Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::FetchItem );
QDBusMessage reply( scheduler->currentTask().dbusMsg );
if ( job->error() ) {
emit q->error( QLatin1String( "Error while creating item: " ) + job->errorString() );
reply << false;
} else {
reply << true;
}
QDBusConnection::sessionBus().send( reply );
scheduler->taskDone();
}
void ResourceBasePrivate::slotDeleteResourceCollection()
{
Q_Q( ResourceBase );
CollectionFetchJob *job = new CollectionFetchJob( Collection::root(), CollectionFetchJob::FirstLevel );
job->setResource( q->identifier() );
connect( job, SIGNAL( result( KJob* ) ), q, SLOT( slotDeleteResourceCollectionDone( KJob* ) ) );
}
void ResourceBasePrivate::slotDeleteResourceCollectionDone( KJob *job )
{
Q_Q( ResourceBase );
if ( job->error() ) {
emit q->error( job->errorString() );
scheduler->taskDone();
} else {
const CollectionFetchJob *fetchJob = static_cast( job );
if ( !fetchJob->collections().isEmpty() ) {
CollectionDeleteJob *job = new CollectionDeleteJob( fetchJob->collections().first() );
connect( job, SIGNAL( result( KJob* ) ), q, SLOT( slotCollectionDeletionDone( KJob* ) ) );
} else {
// there is no resource collection, so just ignore the request
scheduler->taskDone();
}
}
}
void ResourceBasePrivate::slotCollectionDeletionDone( KJob *job )
{
Q_Q( ResourceBase );
if ( job->error() ) {
emit q->error( job->errorString() );
}
scheduler->taskDone();
}
void ResourceBase::changeCommitted( const Item& item )
{
Q_D( ResourceBase );
ItemModifyJob *job = new ItemModifyJob( item );
job->d_func()->setClean();
job->disableRevisionCheck(); // TODO: remove, but where/how do we handle the error?
job->ignorePayload(); // we only want to reset the dirty flag and update the remote id
d->changeProcessed();
}
void ResourceBase::changeCommitted( const Collection &collection )
{
Q_D( ResourceBase );
CollectionModifyJob *job = new CollectionModifyJob( collection );
Q_UNUSED( job );
//TODO: error checking
d->changeProcessed();
}
bool ResourceBase::requestItemDelivery( qint64 uid, const QString & remoteId,
const QString &mimeType, const QStringList &_parts )
{
Q_D( ResourceBase );
if ( !isOnline() ) {
emit error( i18nc( "@info", "Cannot fetch item in offline mode." ) );
return false;
}
setDelayedReply( true );
// FIXME: we need at least the revision number too
Item item( uid );
item.setMimeType( mimeType );
item.setRemoteId( remoteId );
QSet parts;
Q_FOREACH( const QString &str, _parts )
parts.insert( str.toLatin1() );
d->scheduler->scheduleItemFetch( item, parts, message().createReply() );
return true;
}
void ResourceBase::collectionsRetrieved( const Collection::List & collections )
{
Q_D( ResourceBase );
Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
"ResourceBase::collectionsRetrieved()",
"Calling collectionsRetrieved() although no collection retrieval is in progress" );
if ( !d->mCollectionSyncer ) {
d->mCollectionSyncer = new CollectionSync( identifier() );
connect( d->mCollectionSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
connect( d->mCollectionSyncer, SIGNAL( result( KJob* ) ), SLOT( slotCollectionSyncDone( KJob* ) ) );
}
d->mCollectionSyncer->setRemoteCollections( collections );
}
void ResourceBase::collectionsRetrievedIncremental( const Collection::List & changedCollections,
const Collection::List & removedCollections )
{
Q_D( ResourceBase );
Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
"ResourceBase::collectionsRetrievedIncremental()",
"Calling collectionsRetrievedIncremental() although no collection retrieval is in progress" );
if ( !d->mCollectionSyncer ) {
d->mCollectionSyncer = new CollectionSync( identifier() );
connect( d->mCollectionSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
connect( d->mCollectionSyncer, SIGNAL( result( KJob* ) ), SLOT( slotCollectionSyncDone( KJob* ) ) );
}
d->mCollectionSyncer->setRemoteCollections( changedCollections, removedCollections );
}
void ResourceBase::setCollectionStreamingEnabled( bool enable )
{
Q_D( ResourceBase );
Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
"ResourceBase::setCollectionStreamingEnabled()",
"Calling setCollectionStreamingEnabled() although no collection retrieval is in progress" );
if ( !d->mCollectionSyncer ) {
d->mCollectionSyncer = new CollectionSync( identifier() );
connect( d->mCollectionSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
connect( d->mCollectionSyncer, SIGNAL( result( KJob* ) ), SLOT( slotCollectionSyncDone( KJob* ) ) );
}
d->mCollectionSyncer->setStreamingEnabled( enable );
}
void ResourceBase::collectionsRetrievalDone()
{
Q_D( ResourceBase );
Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
"ResourceBase::collectionsRetrievalDone()",
"Calling collectionsRetrievalDone() although no collection retrieval is in progress" );
// streaming enabled, so finalize the sync
if ( d->mCollectionSyncer ) {
d->mCollectionSyncer->retrievalDone();
}
// user did the sync himself, we are done now
else {
d->scheduler->taskDone();
}
}
void ResourceBasePrivate::slotCollectionSyncDone( KJob * job )
{
Q_Q( ResourceBase );
mCollectionSyncer = 0;
if ( job->error() ) {
emit q->error( job->errorString() );
} else {
if ( scheduler->currentTask().type == ResourceScheduler::SyncAll ) {
CollectionFetchJob *list = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive );
list->setResource( mId );
q->connect( list, SIGNAL( result( KJob* ) ), q, SLOT( slotLocalListDone( KJob* ) ) );
return;
}
}
scheduler->taskDone();
}
void ResourceBasePrivate::slotLocalListDone( KJob * job )
{
Q_Q( ResourceBase );
if ( job->error() ) {
emit q->error( job->errorString() );
} else {
Collection::List cols = static_cast( job )->collections();
foreach ( const Collection &col, cols ) {
scheduler->scheduleSync( col );
}
scheduler->scheduleFullSyncCompletion();
}
scheduler->taskDone();
}
void ResourceBasePrivate::slotSynchronizeCollection( const Collection &col )
{
Q_Q( ResourceBase );
currentCollection = col;
// check if this collection actually can contain anything
QStringList contentTypes = currentCollection.contentMimeTypes();
contentTypes.removeAll( Collection::mimeType() );
if ( !contentTypes.isEmpty() ) {
emit q->status( AgentBase::Running, i18nc( "@info:status", "Syncing collection '%1'", currentCollection.name() ) );
q->retrieveItems( currentCollection );
return;
}
scheduler->taskDone();
}
void ResourceBase::itemsRetrievalDone()
{
Q_D( ResourceBase );
// streaming enabled, so finalize the sync
if ( d->mItemSyncer ) {
d->mItemSyncer->deliveryDone();
}
// user did the sync himself, we are done now
else {
d->scheduler->taskDone();
}
}
void ResourceBase::clearCache()
{
Q_D( ResourceBase );
d->scheduler->scheduleResourceCollectionDeletion();
}
Collection ResourceBase::currentCollection() const
{
Q_D( const ResourceBase );
Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection ,
"ResourceBase::currentCollection()",
"Trying to access current collection although no item retrieval is in progress" );
return d->currentCollection;
}
Item ResourceBase::currentItem() const
{
Q_D( const ResourceBase );
Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::FetchItem ,
"ResourceBase::currentItem()",
"Trying to access current item although no item retrieval is in progress" );
return d->scheduler->currentTask().item;
}
void ResourceBase::synchronizeCollectionTree()
{
d_func()->scheduler->scheduleCollectionTreeSync();
}
void ResourceBase::cancelTask()
{
Q_D( ResourceBase );
switch ( d->scheduler->currentTask().type ) {
case ResourceScheduler::FetchItem:
itemRetrieved( Item() ); // sends the error reply and
break;
case ResourceScheduler::ChangeReplay:
d->changeProcessed();
break;
default:
d->scheduler->taskDone();
}
}
void ResourceBase::cancelTask( const QString &msg )
{
cancelTask();
emit error( msg );
}
void ResourceBase::deferTask()
{
Q_D( ResourceBase );
d->scheduler->deferTask();
}
void ResourceBase::doSetOnline( bool state )
{
d_func()->scheduler->setOnline( state );
}
+void ResourceBase::emitTransportResult( Akonadi::Item::Id &item, bool success, const QString &message )
+{
+ emit transportResult( item, success, message );
+}
+
void ResourceBase::synchronizeCollection( qint64 collectionId )
{
CollectionFetchJob* job = new CollectionFetchJob( Collection( collectionId ), CollectionFetchJob::Base );
job->setResource( identifier() );
connect( job, SIGNAL( result( KJob* ) ), SLOT( slotCollectionListDone( KJob* ) ) );
}
void ResourceBasePrivate::slotCollectionListDone( KJob *job )
{
if ( !job->error() ) {
Collection::List list = static_cast( job )->collections();
if ( !list.isEmpty() ) {
Collection col = list.first();
scheduler->scheduleSync( col );
}
}
// TODO: error handling
}
void ResourceBase::setTotalItems( int amount )
{
kDebug() << amount;
Q_D( ResourceBase );
setItemStreamingEnabled( true );
d->mItemSyncer->setTotalItems( amount );
}
void ResourceBase::setItemStreamingEnabled( bool enable )
{
Q_D( ResourceBase );
Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection,
"ResourceBase::setItemStreamingEnabled()",
"Calling setItemStreamingEnabled() although no item retrieval is in progress" );
if ( !d->mItemSyncer ) {
d->mItemSyncer = new ItemSync( currentCollection() );
connect( d->mItemSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
connect( d->mItemSyncer, SIGNAL( result( KJob* ) ), SLOT( slotItemSyncDone( KJob* ) ) );
}
d->mItemSyncer->setStreamingEnabled( enable );
}
void ResourceBase::itemsRetrieved( const Item::List &items )
{
Q_D( ResourceBase );
Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection,
"ResourceBase::itemsRetrieved()",
"Calling itemsRetrieved() although no item retrieval is in progress" );
if ( !d->mItemSyncer ) {
d->mItemSyncer = new ItemSync( currentCollection() );
connect( d->mItemSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
connect( d->mItemSyncer, SIGNAL( result( KJob* ) ), SLOT( slotItemSyncDone( KJob* ) ) );
}
d->mItemSyncer->setFullSyncItems( items );
}
+void ResourceBase::send( Item::Id message )
+{
+ kDebug() << "id" << message;
+ Q_D( ResourceBase );
+ Q_ASSERT( d->mTransport );
+ d->mTransport->sendItem( message );
+}
+
void ResourceBase::itemsRetrievedIncremental( const Item::List &changedItems, const Item::List &removedItems )
{
Q_D( ResourceBase );
Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection,
"ResourceBase::itemsRetrievedIncremental()",
"Calling itemsRetrievedIncremental() although no item retrieval is in progress" );
if ( !d->mItemSyncer ) {
d->mItemSyncer = new ItemSync( currentCollection() );
connect( d->mItemSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
connect( d->mItemSyncer, SIGNAL( result( KJob* ) ), SLOT( slotItemSyncDone( KJob* ) ) );
}
d->mItemSyncer->setIncrementalSyncItems( changedItems, removedItems );
}
void ResourceBasePrivate::slotItemSyncDone( KJob *job )
{
mItemSyncer = 0;
Q_Q( ResourceBase );
if ( job->error() ) {
emit q->error( job->errorString() );
}
scheduler->taskDone();
}
void ResourceBasePrivate::slotPercent( KJob *job, unsigned long percent )
{
Q_Q( ResourceBase );
Q_UNUSED( job );
emit q->percent( percent );
}
#include "resourcebase.moc"
diff --git a/akonadi/resourcebase.h b/akonadi/resourcebase.h
index b92b44895..1689a7da7 100644
--- a/akonadi/resourcebase.h
+++ b/akonadi/resourcebase.h
@@ -1,467 +1,534 @@
/*
This file is part of akonadiresources.
Copyright (c) 2006 Till Adam
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_RESOURCEBASE_H
#define AKONADI_RESOURCEBASE_H
#include "akonadi_export.h"
#include
#include
#include
class KJob;
class ResourceAdaptor;
+class TransportAdaptor;
namespace Akonadi {
class ResourceBasePrivate;
/**
* @short The base class for all Akonadi resources.
*
* This class should be used as a base class by all resource agents,
* because it encapsulates large parts of the protocol between
* resource agent, agent manager and the Akonadi storage.
*
* It provides many convenience methods to make implementing a
* new Akonadi resource agent as simple as possible.
*
* How to write a resource
*
* The following provides an overview of what you need to do to implement
* your own Akonadi resource. In the following, the term 'backend' refers
* to the entity the resource connects with Akonadi, be it a single file
* or a remote server.
*
* @todo Complete this (online/offline state management)
*
* Basic %Resource Framework
*
* The following is needed to create a new resource:
* - A new class deriving from Akonadi::ResourceBase, implementing at least all
* pure-virtual methods, see below for further details.
* - call init() in your main() function.
* - a .desktop file similar to the following example
* \code
* [Desktop Entry]
* Encoding=UTF-8
* Name=My Akonadi Resource
* Type=AkonadiResource
* Exec=akonadi_my_resource
* Icon=my-icon
*
* X-Akonadi-MimeTypes=
* X-Akonadi-Capabilities=Resource
* X-Akonadi-Identifier=akonadi_my_resource
* \endcode
*
* Handling PIM Items
*
* To follow item changes in the backend, the following steps are necessary:
* - Implement retrieveItems() to synchronize all items in the given
* collection. If the backend supports incremental retrieval,
* implementing support for that is recommended to improve performance.
* - Convert the items provided by the backend to Akonadi items.
* This typically happens either in retrieveItems() if you retrieved
* the collection synchronously (not recommended for network backends) or
* in the result slot of the asynchronous retrieval job.
* Converting means to create Akonadi::Item objects for every retrieved
* item. It's very important that every object has its remote identifier set.
* - Call itemsRetrieved() or itemsRetrievedIncremental() respectively
* with the item objects created above. The Akonadi storage will then be
* updated automatically. Note that it is usually not necessary to manipulate
* any item in the Akonadi storage manually.
*
* To fetch item data on demand, the method retrieveItem() needs to be
* reimplemented. Fetch the requested data there and call itemRetrieved()
* with the result item.
*
* To write local changes back to the backend, you need to re-implement
* the following three methods:
* - itemAdded()
* - itemChanged()
* - itemRemoved()
* Note that these three functions don't get the full payload of the items by default,
* you need to change the item fetch scope of the change recorder to fetch the full
* payload. This can be expensive with big payloads, though.
* Once you have handled changes in these methods call changeCommitted().
* These methods are called whenever a local item related to this resource is
* added, modified or deleted. They are only called if the resource is online, otherwise
* all changes are recorded and replayed as soon the resource is online again.
*
* Handling Collections
*
* To follow collection changes in the backend, the following steps are necessary:
* - Implement retrieveCollections() to retrieve collections from the backend.
* If the backend supports incremental collections updates, implementing
* support for that is recommended to improve performance.
* - Convert the collections of the backend to Akonadi collections.
* This typically happens either in retrieveCollections() if you retrieved
* the collection synchronously (not recommended for network backends) or
* in the result slot of the asynchronous retrieval job.
* Converting means to create Akonadi::Collection objects for every retrieved
* collection. It's very important that every object has its remote identifier
* and its parent remote identifier set.
* - Call collectionsRetrieved() or collectionsRetrievedIncremental() respectively
* with the collection objects created above. The Akonadi storage will then be
* updated automatically. Note that it is usually not necessary to manipulate
* any collection in the Akonadi storage manually.
*
*
* To write local collection changes back to the backend, you need to re-implement
* the following three methods:
* - collectionAdded()
* - collectionChanged()
* - collectionRemoved()
* Once you have handled changes in these methods call changeCommitted().
* These methods are called whenever a local collection related to this resource is
* added, modified or deleted. They are only called if the resource is online, otherwise
* all changes are recorded and replayed as soon the resource is online again.
*
* @todo Convenience base class for collection-less resources
*/
// FIXME_API: API dox need to be updated for Observer approach (kevin)
class AKONADI_EXPORT ResourceBase : public AgentBase
{
Q_OBJECT
public:
+ /**
+ * @short Interface for resources supporting sending messages.
+ *
+ * A Transport object attached to a resource tells MailTransport that
+ * the resource supports sending messages. The resource must also have
+ * the "MailTransport" capability flag.
+ *
+ * To implement a transport-enabled resource, inherit from both
+ * ResourceBase and ResourceBase::Transport, implement the virtual method
+ * sendItem(), and call emitTransportResult() when finished sending.
+ *
+ * @todo add code example
+ *
+ * TODO figure out what to do about data, from, to, cc, bcc from
+ * TransportManager::TransportJob. See comments in MT/AkonadiJob.
+ *
+ * @author Constantin Berzan
+ * @since 4.4
+ */
+ class AKONADI_EXPORT Transport
+ {
+ public:
+ Transport();
+ virtual ~Transport();
+
+ virtual void sendItem( Akonadi::Item::Id message ) = 0;
+ };
+
/**
* Use this method in the main function of your resource
* application to initialize your resource subclass.
* This method also takes care of creating a KApplication
* object and parsing command line arguments.
*
* @note In case the given class is also derived from AgentBase::Observer
* it gets registered as its own observer (see AgentBase::Observer), e.g.
* resourceInstance->registerObserver( resourceInstance );
*
* @code
*
* class MyResource : public ResourceBase
* {
* ...
* };
*
* int main( int argc, char **argv )
* {
* return ResourceBase::init( argc, argv );
* }
*
* @endcode
*/
template
static int init( int argc, char **argv )
{
const QString id = parseArguments( argc, argv );
KApplication app;
T* r = new T( id );
// check if T also inherits AgentBase::Observer and
// if it does, automatically register it on itself
Observer *observer = dynamic_cast( r );
if ( observer != 0 )
r->registerObserver( observer );
+
+ // Check if T also inherits ResourceBase::Transport and
+ // if it does, automatically register it on itself.
+ Transport *transport = dynamic_cast( r );
+ if ( transport != 0 )
+ r->registerTransport( r );
+
return init( r );
}
+ /**
+ * Registers the given transport object for sending messages.
+ */
+ void registerTransport( Transport *transport );
+
/**
* This method is used to set the name of the resource.
*/
//FIXME_API: make sure location is renamed to this by resourcebase
void setName( const QString &name );
/**
* Returns the name of the resource.
*/
QString name() const;
Q_SIGNALS:
/**
* This signal is emitted whenever the name of the resource has changed.
*
* @param name The new name of the resource.
*/
void nameChanged( const QString &name );
/**
* Emitted when a full synchronization has been completed.
*/
void synchronized();
+ /**
+ * Emitted when an item has been sent.
+ * @param item The id of the item that was sent.
+ * @param success The success of the sending operation.
+ * @param message An optional textual explanation of the result.
+ * @see Transport.
+ * @since 4.4
+ */
+ void transportResult( qlonglong item, bool success, const QString &message );
+
protected Q_SLOTS:
/**
* Retrieve the collection tree from the remote server and supply it via
* collectionsRetrieved() or collectionsRetrievedIncremental().
* @see collectionsRetrieved(), collectionsRetrievedIncremental()
*/
virtual void retrieveCollections() = 0;
/**
* Retrieve all (new/changed) items in collection @p collection.
* It is recommended to use incremental retrieval if the backend supports that
* and provide the result by calling itemsRetrievedIncremental().
* If incremental retrieval is not possible, provide the full listing by calling
* itemsRetrieved( const Item::List& ).
* In any case, ensure that all items have a correctly set remote identifier
* to allow synchronizing with items already existing locally.
* In case you don't want to use the built-in item syncing code, store the retrieved
* items manually and call itemsRetrieved() once you are done.
* @param collection The collection whose items to retrieve.
* @see itemsRetrieved( const Item::List& ), itemsRetrievedIncremental(), itemsRetrieved(), currentCollection()
*/
virtual void retrieveItems( const Akonadi::Collection &collection ) = 0;
/**
* Retrieve a single item from the backend. The item to retrieve is provided as @p item.
* Add the requested payload parts and call itemRetrieved() when done.
* @param item The empty item whose payload should be retrieved. Use this object when delivering
* the result instead of creating a new item to ensure conflict detection will work.
* @param parts The item parts that should be retrieved.
* @return false if there is an immediate error when retrieving the item.
* @see itemRetrieved()
*/
virtual bool retrieveItem( const Akonadi::Item &item, const QSet &parts ) = 0;
protected:
/**
* Creates a base resource.
*
* @param id The instance id of the resource.
*/
ResourceBase( const QString & id );
/**
* Destroys the base resource.
*/
~ResourceBase();
/**
* Call this method from retrieveItem() once the result is available.
*
* @param item The retrieved item.
*/
void itemRetrieved( const Item &item );
/**
* Resets the dirty flag of the given item and updates the remote id.
*
* Call whenever you have successfully written changes back to the server.
* This implicitly calls changeProcessed().
* @param item The changed item.
*/
void changeCommitted( const Item &item );
/**
* Call whenever you have successfully handled or ignored a collection
* change notification.
*
* This will update the remote identifier of @p collection if necessary,
* as well as any other collection attributes.
* This implicitly calls changeProcessed().
* @param collection The collection which changes have been handled.
*/
void changeCommitted( const Collection &collection );
/**
* Call this to supply the full folder tree retrieved from the remote server.
*
* @param collections A list of collections.
* @see collectionsRetrievedIncremental()
*/
void collectionsRetrieved( const Collection::List &collections );
/**
* Call this to supply incrementally retrieved collections from the remote server.
*
* @param changedCollections Collections that have been added or changed.
* @param removedCollections Collections that have been deleted.
* @see collectionsRetrieved()
*/
void collectionsRetrievedIncremental( const Collection::List &changedCollections,
const Collection::List &removedCollections );
/**
* Enable collection streaming, that is collections don't have to be delivered at once
* as result of a retrieveCollections() call but can be delivered by multiple calls
* to collectionsRetrieved() or collectionsRetrievedIncremental(). When all collections
* have been retrieved, call collectionsRetrievalDone().
* @param enable @c true if collection streaming should be enabled, @c false by default
*/
void setCollectionStreamingEnabled( bool enable );
/**
* Call this method to indicate you finished synchronizing the collection tree.
*
* This is not needed if you use the built in syncing without collection streaming
* and call collectionsRetrieved() or collectionRetrievedIncremental() instead.
* If collection streaming is enabled, call this method once all collections have been delivered
* using collectionsRetrieved() or collectionsRetrievedIncremental().
*/
void collectionsRetrievalDone();
/**
* Call this method to supply the full collection listing from the remote server.
*
* If the remote server supports incremental listing, it's strongly
* recommended to use itemsRetrievedIncremental() instead.
* @param items A list of items.
* @see itemsRetrievedIncremental().
*/
void itemsRetrieved( const Item::List &items );
/**
* Call this method when you want to use the itemsRetrieved() method
* in streaming mode and indicate the amount of items that will arrive
* that way.
* @deprecated Use setItemStreamingEnabled( true ) + itemsRetrieved[Incremental]()
* + itemsRetrieved() instead.
*/
void setTotalItems( int amount );
/**
* Enable item streaming.
* Item streaming is disabled by default.
* @param enable @c true if items are delivered in chunks rather in one big block.
*/
void setItemStreamingEnabled( bool enable );
/**
* Call this method to supply incrementally retrieved items from the remote server.
*
* @param changedItems Items changed in the backend.
* @param removedItems Items removed from the backend.
*/
void itemsRetrievedIncremental( const Item::List &changedItems,
const Item::List &removedItems );
/**
* Call this method to indicate you finished synchronizing the current collection.
*
* This is not needed if you use the built in syncing without item streaming
* and call itemsRetrieved() or itemsRetrievedIncremental() instead.
* If item streaming is enabled, call this method once all items have been delivered
* using itemsRetrieved() or itemsRetrievedIncremental().
* @see retrieveItems()
*/
void itemsRetrievalDone();
/**
* Call this method to remove all items and collections of the resource from the
* server cache.
*
* The method should be used whenever the configuration of the resource has changed
* and therefor the cached items might not be valid any longer.
*
* @since 4.3
*/
void clearCache();
/**
* Returns the collection that is currently synchronized.
*/
Collection currentCollection() const;
/**
* Returns the item that is currently retrieved.
*/
Item currentItem() const;
/**
* This method is called whenever the resource should start synchronize all data.
*/
void synchronize();
/**
* This method is called whenever the collection with the given @p id
* shall be synchronized.
*/
void synchronizeCollection( qint64 id );
/**
* Refetches the Collections.
*/
void synchronizeCollectionTree();
/**
* Stops the execution of the current task and continues with the next one.
*/
void cancelTask();
/**
* Stops the execution of the current task and continues with the next one.
* Additionally an error message is emitted.
*/
void cancelTask( const QString &error );
/**
* Stops the execution of the current task and continues with the next one.
* The current task will be tried again later.
*
* @since 4.3
*/
void deferTask();
/**
* Inherited from AgentBase.
*/
void doSetOnline( bool online );
+ /**
+ * Emits the transportResult() signal.
+ * Call this if you resource inherits from ResourceBase::Transport.
+ * @param item The id of the item that was sent.
+ * @param success True if the sending operation succeeded.
+ * @param message An optional textual explanation of the result.
+ * @see Transport.
+ * @since 4.4
+ */
+ void emitTransportResult( Akonadi::Item::Id &item, bool success,
+ const QString &message = QString() );
+
private:
static QString parseArguments( int, char** );
static int init( ResourceBase *r );
// dbus resource interface
friend class ::ResourceAdaptor;
+ friend class ::TransportAdaptor;
+
+ // D-Bus calls:
+ void send( Akonadi::Item::Id message );
bool requestItemDelivery( qint64 uid, const QString &remoteId, const QString &mimeType, const QStringList &parts );
private:
Q_DECLARE_PRIVATE( ResourceBase )
Q_PRIVATE_SLOT( d_func(), void slotDeliveryDone( KJob* ) )
Q_PRIVATE_SLOT( d_func(), void slotCollectionSyncDone( KJob* ) )
Q_PRIVATE_SLOT( d_func(), void slotDeleteResourceCollection() )
Q_PRIVATE_SLOT( d_func(), void slotDeleteResourceCollectionDone( KJob* ) )
Q_PRIVATE_SLOT( d_func(), void slotCollectionDeletionDone( KJob* ) )
Q_PRIVATE_SLOT( d_func(), void slotLocalListDone( KJob* ) )
Q_PRIVATE_SLOT( d_func(), void slotSynchronizeCollection( const Akonadi::Collection& ) )
Q_PRIVATE_SLOT( d_func(), void slotCollectionListDone( KJob* ) )
Q_PRIVATE_SLOT( d_func(), void slotItemSyncDone( KJob* ) )
Q_PRIVATE_SLOT( d_func(), void slotPercent( KJob*, unsigned long ) )
};
}
#ifndef AKONADI_RESOURCE_MAIN
/**
* Convenience Macro for the most common main() function for Akonadi resources.
*/
#define AKONADI_RESOURCE_MAIN( resourceClass ) \
int main( int argc, char **argv ) \
{ \
return Akonadi::ResourceBase::init( argc, argv ); \
}
#endif
#endif
diff --git a/akonadi/transportresource.cpp b/akonadi/transportresource.cpp
deleted file mode 100644
index 8f8764b34..000000000
--- a/akonadi/transportresource.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- 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 "transportresource.h"
-
-#include "transportadaptor.h"
-
-#include
-#include
-
-using namespace Akonadi;
-
-TransportResource::TransportResource( const QString &id )
- : ResourceBase( id )
-{
- new TransportAdaptor( this );
-}
-
-void TransportResource::emitResult( KJob *job )
-{
- if( job->error() ) {
- emit transportResult( false, job->errorString() );
- } else {
- emit transportResult( true, i18n( "Sending succeeded." ) );
- }
-}
-
-#include "transportresource.moc"
diff --git a/akonadi/transportresource.h b/akonadi/transportresource.h
deleted file mode 100644
index 4868fcb5e..000000000
--- a/akonadi/transportresource.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- 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_TRANSPORTRESOURCE_H
-#define AKONADI_TRANSPORTRESOURCE_H
-
-#include "akonadi_export.h"
-
-#include
-
-#include
-#include
-
-class KJob;
-
-namespace Akonadi {
-
-/**
- * @short Resource implementing mail transport capability.
- *
- * If your resource supports sending email, inherit from this class instead
- * of ResourceBase. Then implement the virtual method send().
- *
- * For an example of a transport-enabled resource, see
- * kdepim/akonadi/resources/mailtransport_dummy.
- */
-
-/*
- DESIGN NOTES:
-
- There seem to be three ways to implement transport-enabled resources:
- 1) new class TransportResource (this):
- Pros:
- + Straight-forward API, no need to connect to weird signals, just
- reimplement a virtual method.
- + The TransportAdaptor is taken care of here, and resources need not
- worry about it.
- Cons:
- - If there will ever be SomeOtherNiftyFeatureResource derived from
- ResourceBase, then it will be hard to combine the Transport ability
- (this class) with SomeOtherNiftyFeature.
- 2) add the stuff to ResourceBase:
- Pros:
- + No additional class, so further extensions seem possible.
- Cons:
- - The TransportAdaptor either has to be merged with ResourceAdaptor;
- added in ResourceBase; or compiled from xml and added by each
- transport-enabled resource. This means either useless weight to all
- resources, or added complexity and dependencies for transport-enabled
- resources.
- - Weird API. Transport-enabled resources will need to connect to a
- transportItem() signal, and there is no guarantee that this is done
- properly (unlike a virtual function).
- 3) do it with ObserverV2:
- How?
-*/
-
-class AKONADI_EXPORT TransportResource : public ResourceBase
-{
- Q_OBJECT
-
- Q_SIGNALS:
- /**
- Emitted when the resource has finished sending the message.
- @param result The success of the operation.
- @param message An optional textual explanation of the result.
- */
- void transportResult( bool result, const QString &message );
-
- public Q_SLOTS:
- /**
- Reimplement in your resource, to begin the actual sending operation.
- Connect the transport job's result() signal to emitResult(), or emit
- transportResult() manually when you are done.
- @param message The ID of the message to be sent.
- @see emitResult.
- @see transportResult.
- */
- virtual void send( Akonadi::Item::Id message ) = 0;
-
- protected:
- /**
- Constructs a new TransportResource.
- @param id The instance id of the resource.
- */
- TransportResource( const QString &id );
-
- protected Q_SLOTS:
- /**
- Utility function to emit transportResult. If your sending operation is
- a KJob, you can connect its result() signal to this slot, and it will
- emit transportResult with the proper parameters.
- @param job The transport job.
- */
- void emitResult( KJob *job );
-
- private:
- // TODO probably need a private class.
-
-};
-
-} // namespace Akonadi
-
-#endif // AKONADI_TRANSPORTRESOURCE_H