diff --git a/akonadi/CMakeLists.txt b/akonadi/CMakeLists.txt index ca2bb3990..107584c4b 100644 --- a/akonadi/CMakeLists.txt +++ b/akonadi/CMakeLists.txt @@ -1,235 +1,235 @@ 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 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") +set_source_files_properties(${akonadi_xml} PROPERTIES INCLUDE "akonadi/private/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/agentbase.cpp b/akonadi/agentbase.cpp index 73ed4cd34..e07ee2069 100644 --- a/akonadi/agentbase.cpp +++ b/akonadi/agentbase.cpp @@ -1,525 +1,525 @@ /* Copyright (c) 2006 Till Adam Copyright (c) 2007 Volker Krause Copyright (c) 2007 Bruno Virlet Copyright (c) 2008 Kevin Krammer 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 "agentbase.h" #include "agentbase_p.h" #include "controladaptor.h" #include "statusadaptor.h" #include "monitor_p.h" -#include "xdgbasedirs_p.h" +#include #include "session.h" #include "session_p.h" #include "changerecorder.h" #include "itemfetchjob.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace Akonadi; static AgentBase *sAgentBase = 0; AgentBase::Observer::Observer() { } AgentBase::Observer::~Observer() { } void AgentBase::Observer::itemAdded( const Item &item, const Collection &collection ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( item ); Q_UNUSED( collection ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::itemChanged( const Item &item, const QSet &partIdentifiers ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( item ); Q_UNUSED( partIdentifiers ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::itemRemoved( const Item &item ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( item ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( collection ); Q_UNUSED( parent ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::collectionChanged( const Collection &collection ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( collection ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::collectionRemoved( const Collection &collection ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( collection ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } //@cond PRIVATE AgentBasePrivate::AgentBasePrivate( AgentBase *parent ) : q_ptr( parent ), mStatusCode( AgentBase::Idle ), mProgress( 0 ), mNeedsNetwork( false ), mOnline( false ), mSettings( 0 ), mObserver( 0 ) { } AgentBasePrivate::~AgentBasePrivate() { mMonitor->setConfig( 0 ); delete mSettings; } void AgentBasePrivate::init() { Q_Q( AgentBase ); /** * Create a default session for this process. */ SessionPrivate::createDefaultSession( mId.toLatin1() ); mTracer = new org::freedesktop::Akonadi::Tracer( QLatin1String( "org.freedesktop.Akonadi" ), QLatin1String( "/tracing" ), QDBusConnection::sessionBus(), q ); new ControlAdaptor( q ); new StatusAdaptor( q ); if ( !QDBusConnection::sessionBus().registerObject( QLatin1String( "/" ), q, QDBusConnection::ExportAdaptors ) ) q->error( QString::fromLatin1( "Unable to register object at dbus: %1" ).arg( QDBusConnection::sessionBus().lastError().message() ) ); mSettings = new QSettings( QString::fromLatin1( "%1/agent_config_%2" ).arg( XdgBaseDirs::saveDir( "config", QLatin1String( "akonadi" ) ), mId ), QSettings::IniFormat ); mMonitor = new ChangeRecorder( q ); mMonitor->ignoreSession( Session::defaultSession() ); mMonitor->itemFetchScope().setCacheOnly( true ); mMonitor->setConfig( mSettings ); mOnline = mSettings->value( QLatin1String( "Agent/Online" ), true ).toBool(); connect( mMonitor, SIGNAL( itemAdded( const Akonadi::Item&, const Akonadi::Collection& ) ), SLOT( itemAdded( const Akonadi::Item&, const Akonadi::Collection& ) ) ); connect( mMonitor, SIGNAL( itemChanged( const Akonadi::Item&, const QSet& ) ), SLOT( itemChanged( const Akonadi::Item&, const QSet& ) ) ); connect( mMonitor, SIGNAL( itemRemoved( const Akonadi::Item& ) ), SLOT( itemRemoved( const Akonadi::Item& ) ) ); connect( mMonitor, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)), SLOT(collectionAdded(Akonadi::Collection,Akonadi::Collection)) ); connect( mMonitor, SIGNAL( collectionChanged( const Akonadi::Collection& ) ), SLOT( collectionChanged( const Akonadi::Collection& ) ) ); connect( mMonitor, SIGNAL( collectionRemoved( const Akonadi::Collection& ) ), SLOT( collectionRemoved( const Akonadi::Collection& ) ) ); connect( q, SIGNAL( status( int, QString ) ), q, SLOT( slotStatus( int, QString ) ) ); connect( q, SIGNAL( percent( int ) ), q, SLOT( slotPercent( int ) ) ); connect( q, SIGNAL( warning( QString ) ), q, SLOT( slotWarning( QString ) ) ); connect( q, SIGNAL( error( QString ) ), q, SLOT( slotError( QString ) ) ); // Use reference counting to allow agents to finish internal jobs when the // agent is stopped. KGlobal::ref(); KGlobal::setAllowQuit(true); QTimer::singleShot( 0, q, SLOT( delayedInit() ) ); } void AgentBasePrivate::delayedInit() { Q_Q( AgentBase ); if ( !QDBusConnection::sessionBus().registerService( QLatin1String( "org.freedesktop.Akonadi.Agent." ) + mId ) ) kFatal() << "Unable to register service at dbus:" << QDBusConnection::sessionBus().lastError().message(); q->setOnline( mOnline ); } void AgentBasePrivate::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->itemAdded( item, collection ); } void AgentBasePrivate::itemChanged( const Akonadi::Item &item, const QSet &partIdentifiers ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->itemChanged( item, partIdentifiers ); } void AgentBasePrivate::itemRemoved( const Akonadi::Item &item ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->itemRemoved( item ); } void AgentBasePrivate::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->collectionAdded( collection, parent ); } void AgentBasePrivate::collectionChanged( const Akonadi::Collection &collection ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->collectionChanged( collection ); } void AgentBasePrivate::collectionRemoved( const Akonadi::Collection &collection ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->collectionRemoved( collection ); } void AgentBasePrivate::changeProcessed() { mMonitor->changeProcessed(); QTimer::singleShot( 0, mMonitor, SLOT( replayNext() ) ); } void AgentBasePrivate::slotStatus( int status, const QString &message ) { mStatusMessage = message; mStatusCode = 0; switch ( status ) { case AgentBase::Idle: if ( mStatusMessage.isEmpty() ) mStatusMessage = defaultReadyMessage(); mStatusCode = 0; break; case AgentBase::Running: if ( mStatusMessage.isEmpty() ) mStatusMessage = defaultSyncingMessage(); mStatusCode = 1; break; case AgentBase::Broken: if ( mStatusMessage.isEmpty() ) mStatusMessage = defaultErrorMessage(); mStatusCode = 2; break; default: Q_ASSERT( !"Unknown status passed" ); break; } } void AgentBasePrivate::slotPercent( int progress ) { mProgress = progress; } void AgentBasePrivate::slotWarning( const QString& message ) { mTracer->warning( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message ); } void AgentBasePrivate::slotError( const QString& message ) { mTracer->error( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message ); } void AgentBasePrivate::slotNetworkStatusChange( Solid::Networking::Status stat ) { Q_Q( AgentBase ); q->setOnline( stat == Solid::Networking::Connected ); } AgentBase::AgentBase( const QString & id ) : d_ptr( new AgentBasePrivate( this ) ) { sAgentBase = this; d_ptr->mId = id; d_ptr->init(); if ( KApplication::kApplication() ) KApplication::kApplication()->disableSessionManagement(); } AgentBase::AgentBase( AgentBasePrivate* d, const QString &id ) : d_ptr( d ) { sAgentBase = this; d_ptr->mId = id; d_ptr->init(); } AgentBase::~AgentBase() { delete d_ptr; } static char* sAgentAppName = 0; QString AgentBase::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 ); } sAgentAppName = qstrdup( identifier.toLatin1().constData() ); KCmdLineArgs::init( argc, argv, sAgentAppName, 0, ki18n("Akonadi Agent"),"0.1" , ki18n("Akonadi Agent") ); KCmdLineOptions options; options.add("identifier ", ki18n("Agent identifier")); KCmdLineArgs::addCmdLineOptions( options ); return identifier; } // @endcond int AgentBase::init( AgentBase *r ) { QApplication::setQuitOnLastWindowClosed( false ); KGlobal::locale()->insertCatalog( QLatin1String("libakonadi") ); int rv = kapp->exec(); delete r; delete[] sAgentAppName; return rv; } int AgentBase::status() const { Q_D( const AgentBase ); return d->mStatusCode; } QString AgentBase::statusMessage() const { Q_D( const AgentBase ); return d->mStatusMessage; } int AgentBase::progress() const { Q_D( const AgentBase ); return d->mProgress; } QString AgentBase::progressMessage() const { Q_D( const AgentBase ); return d->mProgressMessage; } bool AgentBase::isOnline() const { Q_D( const AgentBase ); return d->mOnline; } void AgentBase::setNeedsNetwork( bool needsNetwork ) { Q_D( AgentBase ); d->mNeedsNetwork = needsNetwork; if ( d->mNeedsNetwork ) { connect( Solid::Networking::notifier() , SIGNAL( statusChanged( Solid::Networking::Status ) ) , this, SLOT( slotNetworkStatusChange( Solid::Networking::Status ) ) ); } else { disconnect( Solid::Networking::notifier(), 0, 0, 0 ); setOnline( true ); } } void AgentBase::setOnline( bool state ) { Q_D( AgentBase ); d->mOnline = state; d->mSettings->setValue( QLatin1String( "Agent/Online" ), state ); doSetOnline( state ); emit onlineChanged( state ); } void AgentBase::doSetOnline( bool online ) { Q_UNUSED( online ); } void AgentBase::configure( WId windowId ) { Q_UNUSED( windowId ); } #ifdef Q_OS_WIN //krazy:exclude=cpp void AgentBase::configure( qlonglong windowId ) { configure( reinterpret_cast( windowId ) ); } #endif WId AgentBase::winIdForDialogs() const { bool registered = QDBusConnection::sessionBus().interface()->isServiceRegistered( QLatin1String("org.freedesktop.akonaditray") ); if ( !registered ) return 0; QDBusInterface dbus( QLatin1String("org.freedesktop.akonaditray"), QLatin1String("/Actions"), QLatin1String("org.freedesktop.Akonadi.Tray") ); QDBusMessage reply = dbus.call( QLatin1String("getWinId") ); if ( reply.type() == QDBusMessage::ErrorMessage ) return 0; WId winid = (WId)reply.arguments().at( 0 ).toLongLong(); return winid; } void AgentBase::quit() { Q_D( AgentBase ); aboutToQuit(); if ( d->mSettings ) { d->mMonitor->setConfig( 0 ); d->mSettings->sync(); } KGlobal::deref(); } void AgentBase::aboutToQuit() { } void AgentBase::cleanup() { Q_D( AgentBase ); aboutToQuit(); const QString fileName = d->mSettings->fileName(); /* * First destroy the settings object... */ d->mMonitor->setConfig( 0 ); delete d->mSettings; d->mSettings = 0; /* * ... then remove the file from hd. */ QFile::remove( fileName ); /* * ... and also remove the agent configuration file if there is one. */ QString configFile = KStandardDirs::locateLocal( "config", KGlobal::config()->name() ); QFile::remove( configFile ); KGlobal::deref(); } void AgentBase::registerObserver( Observer *observer ) { kDebug() << "observer=" << (void*) observer << "this=" << (void*) this; d_ptr->mObserver = observer; } QString AgentBase::identifier() const { return d_ptr->mId; } void AgentBase::changeProcessed() { Q_D( AgentBase ); d->changeProcessed(); } ChangeRecorder * AgentBase::changeRecorder() const { return d_ptr->mMonitor; } void AgentBase::reconfigure() { emit reloadConfiguration(); } #include "agentbase.moc" #include "agentbase_p.moc" diff --git a/akonadi/collectioncreatejob.cpp b/akonadi/collectioncreatejob.cpp index 6a926da32..20aa0f2db 100644 --- a/akonadi/collectioncreatejob.cpp +++ b/akonadi/collectioncreatejob.cpp @@ -1,101 +1,101 @@ /* Copyright (c) 2006 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 "collectioncreatejob.h" -#include "imapparser_p.h" +#include #include "protocolhelper_p.h" #include "job_p.h" #include using namespace Akonadi; class Akonadi::CollectionCreateJobPrivate : public JobPrivate { public: CollectionCreateJobPrivate( CollectionCreateJob *parent ) : JobPrivate( parent ) { } Collection mCollection; }; CollectionCreateJob::CollectionCreateJob( const Collection &collection, QObject * parent ) : Job( new CollectionCreateJobPrivate( this ), parent ) { Q_D( CollectionCreateJob ); d->mCollection = collection; } CollectionCreateJob::~CollectionCreateJob( ) { } void CollectionCreateJob::doStart( ) { Q_D( CollectionCreateJob ); QByteArray command = d->newTag() + " CREATE \"" + d->mCollection.name().toUtf8() + "\" "; command += QByteArray::number( d->mCollection.parent() ); command += " ("; if ( !d->mCollection.contentMimeTypes().isEmpty() ) { QList cList; foreach( const QString &s, d->mCollection.contentMimeTypes() ) cList << s.toLatin1(); command += "MIMETYPE (" + ImapParser::join( cList, QByteArray(" ") ) + ')'; } command += " REMOTEID \"" + d->mCollection.remoteId().toUtf8() + '"'; foreach ( Attribute* attr, d->mCollection.attributes() ) command += ' ' + attr->type() + ' ' + ImapParser::quote( attr->serialized() ); command += ' ' + ProtocolHelper::cachePolicyToByteArray( d->mCollection.cachePolicy() ); command += ")\n"; d->writeData( command ); emitWriteFinished(); } Collection CollectionCreateJob::collection() const { Q_D( const CollectionCreateJob ); return d->mCollection; } void CollectionCreateJob::doHandleResponse(const QByteArray & tag, const QByteArray & data) { Q_D( CollectionCreateJob ); if ( tag == "*" ) { Collection col; ProtocolHelper::parseCollection( data, col ); if ( !col.isValid() ) return; col.setParent( d->mCollection.parent() ); col.setName( d->mCollection.name() ); col.setRemoteId( d->mCollection.remoteId() ); d->mCollection = col; } else { Job::doHandleResponse( tag, data ); } } #include "collectioncreatejob.moc" diff --git a/akonadi/collectionfetchjob.cpp b/akonadi/collectionfetchjob.cpp index 7fe9ab653..39f2b1da3 100644 --- a/akonadi/collectionfetchjob.cpp +++ b/akonadi/collectionfetchjob.cpp @@ -1,214 +1,214 @@ /* Copyright (c) 2006 - 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 "collectionfetchjob.h" -#include "imapparser_p.h" +#include #include "job_p.h" -#include "protocol_p.h" +#include #include "protocolhelper_p.h" #include "entity_p.h" #include #include #include #include using namespace Akonadi; class Akonadi::CollectionFetchJobPrivate : public JobPrivate { public: CollectionFetchJobPrivate( CollectionFetchJob *parent ) : JobPrivate( parent ), mUnsubscribed( false ) { } Q_DECLARE_PUBLIC( CollectionFetchJob ) CollectionFetchJob::Type mType; Collection mBase; Collection::List mBaseList; Collection::List mCollections; QString mResource; Collection::List mPendingCollections; QTimer *mEmitTimer; bool mUnsubscribed; void timeout() { Q_Q( CollectionFetchJob ); mEmitTimer->stop(); // in case we are called by result() if ( !mPendingCollections.isEmpty() ) { emit q->collectionsReceived( mPendingCollections ); mPendingCollections.clear(); } } }; CollectionFetchJob::CollectionFetchJob( const Collection &collection, Type type, QObject *parent ) : Job( new CollectionFetchJobPrivate( this ), parent ) { Q_D( CollectionFetchJob ); d->mBase = collection; d->mType = type; d->mEmitTimer = new QTimer( this ); d->mEmitTimer->setSingleShot( true ); d->mEmitTimer->setInterval( 100 ); connect( d->mEmitTimer, SIGNAL(timeout()), this, SLOT(timeout()) ); connect( this, SIGNAL(result(KJob*)), this, SLOT(timeout()) ); } CollectionFetchJob::CollectionFetchJob( const Collection::List & cols, QObject * parent ) : Job( new CollectionFetchJobPrivate( this ), parent ) { Q_D( CollectionFetchJob ); Q_ASSERT( !cols.isEmpty() ); if ( cols.size() == 1 ) { d->mBase = cols.first(); d->mType = CollectionFetchJob::Base; } else { d->mBaseList = cols; } d->mEmitTimer = new QTimer( this ); d->mEmitTimer->setSingleShot( true ); d->mEmitTimer->setInterval( 100 ); connect( d->mEmitTimer, SIGNAL(timeout()), this, SLOT(timeout()) ); connect( this, SIGNAL(result(KJob*)), this, SLOT(timeout()) ); } CollectionFetchJob::~CollectionFetchJob() { } Collection::List CollectionFetchJob::collections() const { Q_D( const CollectionFetchJob ); return d->mCollections; } void CollectionFetchJob::doStart() { Q_D( CollectionFetchJob ); if ( !d->mBaseList.isEmpty() ) { foreach ( const Collection &col, d->mBaseList ) { new CollectionFetchJob( col, CollectionFetchJob::Base, this ); } return; } if ( !d->mBase.isValid() && d->mBase.remoteId().isEmpty() ) { setError( Unknown ); setErrorText( QLatin1String( "Invalid collection given." ) ); emitResult(); return; } QByteArray command = d->newTag(); if ( !d->mBase.isValid() ) command += " " AKONADI_CMD_RID; if ( d->mUnsubscribed ) command += " X-AKLIST "; else command += " X-AKLSUB "; if ( d->mBase.isValid() ) command += QByteArray::number( d->mBase.id() ); else command += ImapParser::quote( d->mBase.remoteId().toUtf8() ); command += ' '; switch ( d->mType ) { case Base: command += "0 ("; break; case FirstLevel: command += "1 ("; break; case Recursive: command += "INF ("; break; default: Q_ASSERT( false ); } if ( !d->mResource.isEmpty() ) { command += "RESOURCE \""; command += d->mResource.toUtf8(); command += '"'; } command += ")\n"; d->writeData( command ); } void CollectionFetchJob::doHandleResponse( const QByteArray & tag, const QByteArray & data ) { Q_D( CollectionFetchJob ); if ( tag == "*" ) { Collection collection; ProtocolHelper::parseCollection( data, collection ); if ( !collection.isValid() ) return; collection.d_ptr->resetChangeLog(); d->mCollections.append( collection ); d->mPendingCollections.append( collection ); if ( !d->mEmitTimer->isActive() ) d->mEmitTimer->start(); return; } kDebug( 5250 ) << "Unhandled server response" << tag << data; } void CollectionFetchJob::setResource(const QString & resource) { Q_D( CollectionFetchJob ); d->mResource = resource; } void CollectionFetchJob::slotResult(KJob * job) { Q_D( CollectionFetchJob ); CollectionFetchJob *list = dynamic_cast( job ); Q_ASSERT( job ); d->mCollections += list->collections(); Job::slotResult( job ); if ( !job->error() && !hasSubjobs() ) emitResult(); } void CollectionFetchJob::includeUnsubscribed(bool include) { Q_D( CollectionFetchJob ); d->mUnsubscribed = include; } #include "collectionfetchjob.moc" diff --git a/akonadi/collectionmodifyjob.cpp b/akonadi/collectionmodifyjob.cpp index 639810d96..97dcbf383 100644 --- a/akonadi/collectionmodifyjob.cpp +++ b/akonadi/collectionmodifyjob.cpp @@ -1,84 +1,84 @@ /* Copyright (c) 2006 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 "collectionmodifyjob.h" -#include "imapparser_p.h" +#include #include "job_p.h" #include "protocolhelper_p.h" #include "collectionstatistics.h" #include "collection_p.h" using namespace Akonadi; class Akonadi::CollectionModifyJobPrivate : public JobPrivate { public: CollectionModifyJobPrivate( CollectionModifyJob *parent ) : JobPrivate( parent ) { } Collection mCollection; }; CollectionModifyJob::CollectionModifyJob( const Collection &collection, QObject * parent ) : Job( new CollectionModifyJobPrivate( this ), parent ) { Q_D( CollectionModifyJob ); Q_ASSERT( collection.isValid() ); d->mCollection = collection; } CollectionModifyJob::~CollectionModifyJob() { } void CollectionModifyJob::doStart() { Q_D( CollectionModifyJob ); QByteArray command = d->newTag() + " MODIFY " + QByteArray::number( d->mCollection.id() ); QByteArray changes; if ( d->mCollection.d_func()->contentTypesChanged ) { QList bList; foreach( const QString &s, d->mCollection.contentMimeTypes() ) bList << s.toLatin1(); changes += " MIMETYPE (" + ImapParser::join( bList, " " ) + ')'; } if ( d->mCollection.parent() >= 0 ) changes += " PARENT " + QByteArray::number( d->mCollection.parent() ); if ( !d->mCollection.name().isEmpty() ) changes += " NAME " + ImapParser::quote( d->mCollection.name().toUtf8() ); if ( !d->mCollection.remoteId().isNull() ) changes += " REMOTEID " + ImapParser::quote( d->mCollection.remoteId().toUtf8() ); if ( d->mCollection.d_func()->cachePolicyChanged ) changes += ' ' + ProtocolHelper::cachePolicyToByteArray( d->mCollection.cachePolicy() ); if ( d->mCollection.attributes().count() > 0 ) changes += ' ' + ProtocolHelper::attributesToByteArray( d->mCollection ); foreach ( const QByteArray &b, d->mCollection.d_func()->mDeletedAttributes ) changes += " -" + b; if ( changes.isEmpty() ) { emitResult(); return; } command += changes + '\n'; d->writeData( command ); } #include "collectionmodifyjob.moc" diff --git a/akonadi/collectionselectjob.cpp b/akonadi/collectionselectjob.cpp index 9c4f40754..5f0415f0e 100644 --- a/akonadi/collectionselectjob.cpp +++ b/akonadi/collectionselectjob.cpp @@ -1,107 +1,107 @@ /* Copyright (c) 2006 - 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 "collectionselectjob_p.h" #include "job_p.h" -#include "protocol_p.h" +#include #include using namespace Akonadi; class Akonadi::CollectionSelectJobPrivate : public JobPrivate { public: CollectionSelectJobPrivate( CollectionSelectJob *parent ) : JobPrivate( parent ), mUnseen( -1 ), mSilent( true ) { } Collection mCollection; int mUnseen; bool mSilent; }; CollectionSelectJob::CollectionSelectJob( const Collection &collection, QObject *parent ) : Job( new CollectionSelectJobPrivate( this ), parent ) { Q_D( CollectionSelectJob ); d->mCollection = collection; } CollectionSelectJob::~CollectionSelectJob( ) { } void CollectionSelectJob::doStart( ) { Q_D( CollectionSelectJob ); if ( d->mCollection.isValid() ) { QByteArray command( d->newTag() + " SELECT " ); if ( d->mSilent ) command += "SILENT "; d->writeData( command + QByteArray::number( d->mCollection.id() ) + '\n' ); } else if ( !d->mCollection.remoteId().isEmpty() ) { QByteArray command( d->newTag() + " " AKONADI_CMD_RID " SELECT " ); if ( d->mSilent ) command += "SILENT "; d->writeData( command + d->mCollection.remoteId().toUtf8() + '\n' ); } else { setError( Unknown ); setErrorText( QLatin1String("Invalid collection specified") ); emitResult(); } } void CollectionSelectJob::doHandleResponse( const QByteArray & tag, const QByteArray & data ) { Q_D( CollectionSelectJob ); if ( tag == "*" ) { if ( data.startsWith( "OK [UNSEEN" ) ) { //krazy:exclude=strings int begin = data.indexOf( ' ', 4 ); int end = data.indexOf( ']' ); QByteArray number = data.mid( begin + 1, end - begin - 1 ); d->mUnseen = number.toInt(); return; } } } int CollectionSelectJob::unseen( ) const { Q_D( const CollectionSelectJob ); return d->mUnseen; } void CollectionSelectJob::setRetrieveStatus(bool status) { Q_D( CollectionSelectJob ); d->mSilent = !status; } #include "collectionselectjob_p.moc" diff --git a/akonadi/collectionstatisticsjob.cpp b/akonadi/collectionstatisticsjob.cpp index ea7fc1c68..bc5fc540f 100644 --- a/akonadi/collectionstatisticsjob.cpp +++ b/akonadi/collectionstatisticsjob.cpp @@ -1,106 +1,106 @@ /* Copyright (c) 2006 - 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 "collectionstatisticsjob.h" #include "collection.h" #include "collectionstatistics.h" -#include "imapparser_p.h" +#include #include "job_p.h" #include using namespace Akonadi; class Akonadi::CollectionStatisticsJobPrivate : public JobPrivate { public: CollectionStatisticsJobPrivate( CollectionStatisticsJob *parent ) : JobPrivate( parent ) { } Collection mCollection; CollectionStatistics mStatistics; }; CollectionStatisticsJob::CollectionStatisticsJob( const Collection &collection, QObject * parent ) : Job( new CollectionStatisticsJobPrivate( this ), parent ) { Q_D( CollectionStatisticsJob ); d->mCollection = collection; } CollectionStatisticsJob::~CollectionStatisticsJob() { } void CollectionStatisticsJob::doStart( ) { Q_D( CollectionStatisticsJob ); d->writeData( d->newTag() + " STATUS " + QByteArray::number( d->mCollection.id() ) + " (MESSAGES UNSEEN)\n" ); } void CollectionStatisticsJob::doHandleResponse( const QByteArray & tag, const QByteArray & data ) { Q_D( CollectionStatisticsJob ); if ( tag == "*" ) { QByteArray token; int current = ImapParser::parseString( data, token ); if ( token == "STATUS" ) { // folder path current = ImapParser::parseString( data, token, current ); // result list QList list; current = ImapParser::parseParenthesizedList( data, list, current ); for ( int i = 0; i < list.count() - 1; i += 2 ) { if ( list[i] == "MESSAGES" ) { d->mStatistics.setCount( list[i+1].toLongLong() ); } else if ( list[i] == "UNSEEN" ) { d->mStatistics.setUnreadCount( list[i+1].toLongLong() ); } else { kDebug( 5250 ) << "Unknown STATUS response: " << list[i]; } } d->mCollection.setStatistics( d->mStatistics ); return; } } kDebug( 5250 ) << "Unhandled response: " << tag << data; } Collection CollectionStatisticsJob::collection() const { Q_D( const CollectionStatisticsJob ); return d->mCollection; } CollectionStatistics Akonadi::CollectionStatisticsJob::statistics() const { Q_D( const CollectionStatisticsJob ); return d->mStatistics; } #include "collectionstatisticsjob.moc" diff --git a/akonadi/entitydisplayattribute.cpp b/akonadi/entitydisplayattribute.cpp index 4e51478a1..867ac2cc9 100644 --- a/akonadi/entitydisplayattribute.cpp +++ b/akonadi/entitydisplayattribute.cpp @@ -1,98 +1,98 @@ /* 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 "entitydisplayattribute.h" -#include "imapparser_p.h" +#include #include using namespace Akonadi; class EntityDisplayAttribute::Private { public: QString name; QString icon; }; EntityDisplayAttribute::EntityDisplayAttribute() : d( new Private ) { } EntityDisplayAttribute::~ EntityDisplayAttribute() { delete d; } QString EntityDisplayAttribute::displayName() const { return d->name; } void EntityDisplayAttribute::setDisplayName(const QString & name) { d->name = name; } KIcon EntityDisplayAttribute::icon() const { return KIcon( d->icon ); } QString EntityDisplayAttribute::iconName() const { return d->icon; } void EntityDisplayAttribute::setIconName(const QString & icon) { d->icon = icon; } QByteArray Akonadi::EntityDisplayAttribute::type() const { return "ENTITYDISPLAY"; } EntityDisplayAttribute * EntityDisplayAttribute::clone() const { EntityDisplayAttribute *attr = new EntityDisplayAttribute(); attr->d->name = d->name; attr->d->icon = d->icon; return attr; } QByteArray EntityDisplayAttribute::serialized() const { QList l; l << ImapParser::quote( d->name.toUtf8() ); l << ImapParser::quote( d->icon.toUtf8() ); return '(' + ImapParser::join( l, " " ) + ')'; } void EntityDisplayAttribute::deserialize(const QByteArray &data) { QList l; ImapParser::parseParenthesizedList( data, l ); Q_ASSERT( l.count() >= 2 ); d->name = QString::fromUtf8( l[0] ); d->icon = QString::fromUtf8( l[1] ); } diff --git a/akonadi/item.cpp b/akonadi/item.cpp index 8650e5ad3..d7b27c8ea 100644 --- a/akonadi/item.cpp +++ b/akonadi/item.cpp @@ -1,210 +1,210 @@ /* Copyright (c) 2006 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 "item.h" #include "item_p.h" #include "itemserializer_p.h" -#include "protocol_p.h" +#include #include #include using namespace Akonadi; // Change to something != RFC822 as soon as the server supports it const char* Item::FullPayload = "RFC822"; Item::Item() : Entity( new ItemPrivate ) { } Item::Item( Id id ) : Entity( new ItemPrivate( id ) ) { } Item::Item( const QString & mimeType ) : Entity( new ItemPrivate ) { d_func()->mMimeType = mimeType; } Item::Item( const Item &other ) : Entity( other ) { } Item::~Item() { } Item::Flags Item::flags() const { return d_func()->mFlags; } void Item::setFlag( const QByteArray & name ) { Q_D( Item ); d->mFlags.insert( name ); if ( !d->mFlagsOverwritten ) d->mAddedFlags.insert( name ); } void Item::clearFlag( const QByteArray & name ) { Q_D( Item ); d->mFlags.remove( name ); if ( !d->mFlagsOverwritten ) d->mDeletedFlags.insert( name ); } void Item::setFlags( const Flags &flags ) { Q_D( Item ); d->mFlags = flags; d->mFlagsOverwritten = true; } void Item::clearFlags() { Q_D( Item ); d->mFlags.clear(); d->mFlagsOverwritten = true; } QDateTime Item::modificationTime() const { return d_func()->mModificationTime; } void Item::setModificationTime( const QDateTime &datetime ) { d_func()->mModificationTime = datetime; } bool Item::hasFlag( const QByteArray & name ) const { return d_func()->mFlags.contains( name ); } QSet Item::loadedPayloadParts() const { return ItemSerializer::parts( *this ); } QByteArray Item::payloadData() const { int version = 0; QByteArray data; ItemSerializer::serialize( *this, FullPayload, data, version ); return data; } void Item::setPayloadFromData( const QByteArray &data ) { ItemSerializer::deserialize( *this, FullPayload, data, 0, false ); } int Item::revision() const { return d_func()->mRevision; } void Item::setRevision( int rev ) { d_func()->mRevision = rev; } Entity::Id Item::collectionId() const { return d_func()->mCollectionId; } void Item::setCollectionId( Entity::Id collectionId ) { d_func()->mCollectionId = collectionId; } QString Item::mimeType() const { return d_func()->mMimeType; } void Item::setSize( qint64 size ) { d_func()->mSize = size; } qint64 Item::size() const { return d_func()->mSize; } void Item::setMimeType( const QString & mimeType ) { d_func()->mMimeType = mimeType; } bool Item::hasPayload() const { return d_func()->mPayload != 0; } KUrl Item::url( UrlType type ) const { KUrl url; url.setProtocol( QString::fromLatin1("akonadi") ); url.addQueryItem( QLatin1String( "item" ), QString::number( id() ) ); if ( type == UrlWithMimeType ) url.addQueryItem( QLatin1String( "type" ), mimeType() ); return url; } Item Item::fromUrl( const KUrl &url ) { if ( url.protocol() != QLatin1String( "akonadi" ) ) return Item(); const QString itemStr = url.queryItem( QLatin1String( "item" ) ); bool ok = false; Item::Id itemId = itemStr.toLongLong( &ok ); if ( !ok ) return Item(); return Item( itemId ); } PayloadBase* Item::payloadBase() const { return d_func()->mPayload; } void Item::setPayloadBase( PayloadBase* p ) { Q_D( Item ); delete d->mPayload; d->mPayload = p; } AKONADI_DEFINE_PRIVATE( Item ) diff --git a/akonadi/itemcopyjob.cpp b/akonadi/itemcopyjob.cpp index 62f75aea6..10b7c7aff 100644 --- a/akonadi/itemcopyjob.cpp +++ b/akonadi/itemcopyjob.cpp @@ -1,80 +1,80 @@ /* 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 "itemcopyjob.h" #include "collection.h" -#include "imapset_p.h" +#include #include "job_p.h" using namespace Akonadi; class Akonadi::ItemCopyJobPrivate : public JobPrivate { public: ItemCopyJobPrivate( ItemCopyJob *parent ) : JobPrivate( parent ) { } Item::List mItems; Collection mTarget; }; ItemCopyJob::ItemCopyJob(const Item & item, const Collection & target, QObject * parent) : Job( new ItemCopyJobPrivate( this ), parent ) { Q_D( ItemCopyJob ); d->mItems << item; d->mTarget = target; } ItemCopyJob::ItemCopyJob(const Item::List & items, const Collection & target, QObject * parent) : Job( new ItemCopyJobPrivate( this ), parent ) { Q_D( ItemCopyJob ); d->mItems = items; d->mTarget = target; } ItemCopyJob::~ItemCopyJob() { } void ItemCopyJob::doStart() { Q_D( ItemCopyJob ); QList ids; foreach ( const Item &item, d->mItems ) ids << item.id(); ImapSet set; set.add( ids ); QByteArray cmd( d->newTag() ); cmd += " COPY "; cmd += set.toImapSequenceSet(); cmd += ' '; cmd += QByteArray::number( d->mTarget.id() ); cmd += '\n'; d->writeData( cmd ); } #include "itemcopyjob.moc" diff --git a/akonadi/itemcreatejob.cpp b/akonadi/itemcreatejob.cpp index 440613c11..f6964eec4 100644 --- a/akonadi/itemcreatejob.cpp +++ b/akonadi/itemcreatejob.cpp @@ -1,168 +1,168 @@ /* Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2007 Robert Zwerus 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 "itemcreatejob.h" #include "collection.h" -#include "imapparser_p.h" +#include #include "item.h" #include "itemserializer_p.h" #include "job_p.h" #include "protocolhelper_p.h" #include #include using namespace Akonadi; class Akonadi::ItemCreateJobPrivate : public JobPrivate { public: ItemCreateJobPrivate( ItemCreateJob *parent ) : JobPrivate( parent ) { } Collection mCollection; Item mItem; QSet mParts; Item::Id mUid; QDateTime mDatetime; QByteArray mData; }; ItemCreateJob::ItemCreateJob( const Item &item, const Collection &collection, QObject * parent ) : Job( new ItemCreateJobPrivate( this ), parent ) { Q_D( ItemCreateJob ); Q_ASSERT( !item.mimeType().isEmpty() ); d->mItem = item; d->mParts = d->mItem.loadedPayloadParts(); d->mCollection = collection; } ItemCreateJob::~ItemCreateJob() { } void ItemCreateJob::doStart() { Q_D( ItemCreateJob ); QByteArray remoteId; QList flags; flags.append( "\\MimeType[" + d->mItem.mimeType().toLatin1() + ']' ); if ( !d->mItem.remoteId().isEmpty() ) flags.append( ImapParser::quote( "\\RemoteId[" + d->mItem.remoteId().toUtf8() + ']' ) ); flags += d->mItem.flags().toList(); // switch between a normal APPEND and a multipart X-AKAPPEND, based on the number of parts if ( d->mItem.attributes().isEmpty() && ( d->mParts.isEmpty() || (d->mParts.size() == 1 && d->mParts.contains( Item::FullPayload )) ) ) { if ( d->mItem.hasPayload() ) { int version = 0; ItemSerializer::serialize( d->mItem, Item::FullPayload, d->mData, version ); } int dataSize = d->mData.size(); d->writeData( d->newTag() + " APPEND " + QByteArray::number( d->mCollection.id() ) + ' ' + QByteArray::number( d->mItem.size() ) + " (" + ImapParser::join( flags, " " ) + ") {" + QByteArray::number( dataSize ) + "}\n" ); } else { // do a multipart X-AKAPPEND QByteArray command = d->newTag() + " X-AKAPPEND " + QByteArray::number( d->mCollection.id() ) + ' ' + QByteArray::number( d->mItem.size() ) + " (" + ImapParser::join( flags, " " ) + ") "; QList partSpecs; int totalSize = 0; foreach( const QByteArray &partName, d->mParts ) { QByteArray partData; int version = 0; ItemSerializer::serialize( d->mItem, partName, partData, version ); totalSize += partData.size(); const QByteArray partId = ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartPayload, partName, version ); partSpecs.append( ImapParser::quote( partId ) + ':' + QByteArray::number( partData.size() ) ); d->mData += partData; } foreach ( const Attribute* attr, d->mItem.attributes() ) { const QByteArray data = attr->serialized(); totalSize += data.size(); const QByteArray partId = ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartAttribute, attr->type() ); partSpecs.append( ImapParser::quote( partId ) + ':' + QByteArray::number( data.size() ) ); d->mData += data; } command += '(' + ImapParser::join( partSpecs, "," ) + ") " + '{' + QByteArray::number( totalSize ) + "}\n"; d->writeData( command ); } } void ItemCreateJob::doHandleResponse( const QByteArray & tag, const QByteArray & data ) { Q_D( ItemCreateJob ); if ( tag == "+" ) { // ready for literal data d->writeData( d->mData ); if ( !d->mData.endsWith( '\n' ) ) d->writeData( "\n" ); return; } if ( tag == d->tag() ) { int uidNextPos = data.indexOf( "UIDNEXT" ); if ( uidNextPos != -1 ) { bool ok = false; ImapParser::parseNumber( data, d->mUid, &ok, uidNextPos + 7 ); if ( !ok ) { kDebug( 5250 ) << "Invalid UIDNEXT response to APPEND command: " << tag << data; } } int dateTimePos = data.indexOf( "DATETIME" ); if ( dateTimePos != -1 ) { int resultPos = ImapParser::parseDateTime( data, d->mDatetime, dateTimePos + 8 ); if ( resultPos == (dateTimePos + 8) ) { kDebug( 5250 ) << "Invalid DATETIME response to APPEND command: " << tag << data; } } } } Item ItemCreateJob::item() const { Q_D( const ItemCreateJob ); if ( d->mUid == 0 ) return Item(); Item item( d->mItem ); item.setId( d->mUid ); item.setRevision( 0 ); item.setModificationTime( d->mDatetime ); return item; } #include "itemcreatejob.moc" diff --git a/akonadi/itemfetchjob.cpp b/akonadi/itemfetchjob.cpp index 7c1f42dac..909626db9 100644 --- a/akonadi/itemfetchjob.cpp +++ b/akonadi/itemfetchjob.cpp @@ -1,319 +1,319 @@ /* Copyright (c) 2006 - 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 "itemfetchjob.h" #include "attributefactory.h" #include "collection.h" #include "collectionselectjob_p.h" -#include "imapparser_p.h" +#include #include "itemfetchscope.h" #include "itemserializer_p.h" #include "itemserializerplugin.h" #include "job_p.h" #include "entity_p.h" -#include "protocol_p.h" +#include #include "protocolhelper_p.h" #include #include #include #include #include using namespace Akonadi; class Akonadi::ItemFetchJobPrivate : public JobPrivate { public: ItemFetchJobPrivate( ItemFetchJob *parent ) : JobPrivate( parent ) { } void timeout() { Q_Q( ItemFetchJob ); mEmitTimer->stop(); // in case we are called by result() if ( !mPendingItems.isEmpty() ) { emit q->itemsReceived( mPendingItems ); mPendingItems.clear(); } } void startFetchJob(); void selectDone( KJob * job ); Q_DECLARE_PUBLIC( ItemFetchJob ) Collection mCollection; Item mItem; Item::List mItems; ItemFetchScope mFetchScope; Item::List mPendingItems; // items pending for emitting itemsReceived() QTimer* mEmitTimer; }; void ItemFetchJobPrivate::startFetchJob() { QByteArray command = newTag(); if ( mItem.isValid() ) command += " " AKONADI_CMD_UID " " AKONADI_CMD_ITEMFETCH " " + QByteArray::number( mItem.id() ); else if ( !mItem.remoteId().isEmpty() ) command += " " AKONADI_CMD_RID " " AKONADI_CMD_ITEMFETCH " " + mItem.remoteId().toUtf8(); else command += " " AKONADI_CMD_ITEMFETCH " 1:*"; if ( mFetchScope.fullPayload() ) command += " " AKONADI_PARAM_FULLPAYLOAD; if ( mFetchScope.allAttributes() ) command += " " AKONADI_PARAM_ALLATTRIBUTES; if ( mFetchScope.cacheOnly() ) command += " " AKONADI_PARAM_CACHEONLY; //TODO: detect somehow if server supports external payload attribute command += " " AKONADI_PARAM_EXTERNALPAYLOAD; command += " (UID REMOTEID COLLECTIONID FLAGS SIZE DATETIME"; foreach ( const QByteArray &part, mFetchScope.payloadParts() ) command += ' ' + ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartPayload, part ); foreach ( const QByteArray &part, mFetchScope.attributes() ) command += ' ' + ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartAttribute, part ); command += ")\n"; writeData( command ); } void ItemFetchJobPrivate::selectDone( KJob * job ) { if ( !job->error() ) // the collection is now selected, fetch the message(s) startFetchJob(); } ItemFetchJob::ItemFetchJob( const Collection &collection, QObject * parent ) : Job( new ItemFetchJobPrivate( this ), parent ) { Q_D( ItemFetchJob ); d->mEmitTimer = new QTimer( this ); d->mEmitTimer->setSingleShot( true ); d->mEmitTimer->setInterval( 100 ); connect( d->mEmitTimer, SIGNAL(timeout()), this, SLOT(timeout()) ); connect( this, SIGNAL(result(KJob*)), this, SLOT(timeout()) ); d->mCollection = collection; } ItemFetchJob::ItemFetchJob( const Item & item, QObject * parent) : Job( new ItemFetchJobPrivate( this ), parent ) { Q_D( ItemFetchJob ); d->mEmitTimer = new QTimer( this ); d->mEmitTimer->setSingleShot( true ); d->mEmitTimer->setInterval( 100 ); connect( d->mEmitTimer, SIGNAL(timeout()), this, SLOT(timeout()) ); connect( this, SIGNAL(result(KJob*)), this, SLOT(timeout()) ); d->mCollection = Collection::root(); d->mItem = item; } ItemFetchJob::~ItemFetchJob() { } void ItemFetchJob::doStart() { Q_D( ItemFetchJob ); if ( !d->mItem.isValid() ) { // collection content listing if ( d->mCollection == Collection::root() ) { setErrorText( QLatin1String("Cannot list root collection.") ); setError( Unknown ); emitResult(); } CollectionSelectJob *job = new CollectionSelectJob( d->mCollection, this ); connect( job, SIGNAL(result(KJob*)), SLOT(selectDone(KJob*)) ); addSubjob( job ); } else d->startFetchJob(); } void ItemFetchJob::doHandleResponse( const QByteArray & tag, const QByteArray & data ) { Q_D( ItemFetchJob ); if ( tag == "*" ) { int begin = data.indexOf( "FETCH" ); if ( begin >= 0 ) { // split fetch response into key/value pairs QList fetchResponse; ImapParser::parseParenthesizedList( data, fetchResponse, begin + 6 ); // create a new item object Item::Id uid = -1; int rev = -1; QString rid; QString mimeType; Entity::Id cid = -1; for ( int i = 0; i < fetchResponse.count() - 1; i += 2 ) { const QByteArray key = fetchResponse.value( i ); const QByteArray value = fetchResponse.value( i + 1 ); if ( key == "UID" ) uid = value.toLongLong(); else if ( key == "REV" ) rev = value.toInt(); else if ( key == "REMOTEID" ) { if ( !value.isEmpty() ) rid = QString::fromUtf8( value ); else rid.clear(); } else if ( key == "COLLECTIONID" ) { cid = value.toInt(); } else if ( key == "MIMETYPE" ) mimeType = QString::fromLatin1( value ); } if ( uid < 0 || rev < 0 || mimeType.isEmpty() ) { kWarning( 5250 ) << "Broken fetch response: UID, RID, REV or MIMETYPE missing!"; return; } Item item( uid ); item.setRemoteId( rid ); item.setRevision( rev ); item.setMimeType( mimeType ); item.setCollectionId( cid ); if ( !item.isValid() ) return; // parse fetch response fields for ( int i = 0; i < fetchResponse.count() - 1; i += 2 ) { const QByteArray key = fetchResponse.value( i ); // skip stuff we dealt with already if ( key == "UID" || key == "REV" || key == "REMOTEID" || key == "MIMETYPE" || key == "COLLECTIONID") continue; // flags if ( key == "FLAGS" ) { QList flags; ImapParser::parseParenthesizedList( fetchResponse[i + 1], flags ); foreach ( const QByteArray &flag, flags ) { item.setFlag( flag ); } } else if ( key == "SIZE" ) { const quint64 size = fetchResponse[i + 1].toLongLong(); item.setSize( size ); } else if ( key == "DATETIME" ) { QDateTime datetime; ImapParser::parseDateTime( fetchResponse[i + 1], datetime ); item.setModificationTime( datetime ); } else { int version = 0; QByteArray plainKey( key ); ProtocolHelper::PartNamespace ns; ImapParser::splitVersionedKey( key, plainKey, version ); plainKey = ProtocolHelper::decodePartIdentifier( plainKey, ns ); switch ( ns ) { case ProtocolHelper::PartPayload: { bool isExternal = false; QByteArray fileKey = fetchResponse.value( i + 1 ); if (fileKey == "[FILE]") { isExternal = true; i++; kDebug( 5250 ) << "Payload is external: " << isExternal << " filename: " << fetchResponse.value( i + 1 ); } ItemSerializer::deserialize( item, plainKey, fetchResponse.value( i + 1 ), version, isExternal ); break; } case ProtocolHelper::PartAttribute: { Attribute* attr = AttributeFactory::createAttribute( plainKey ); Q_ASSERT( attr ); if ( fetchResponse.value( i + 1 ) == "[FILE]" ) { ++i; QFile f( QString::fromUtf8( fetchResponse.value( i + 1 ) ) ); if ( f.open( QFile::ReadOnly ) ) attr->deserialize( f.readAll() ); else { kWarning() << "Failed to open attribute file: " << fetchResponse.value( i + 1 ); delete attr; } } else { attr->deserialize( fetchResponse.value( i + 1 ) ); } item.addAttribute( attr ); break; } case ProtocolHelper::PartGlobal: default: kWarning() << "Unknown item part type:" << key; } } } item.d_ptr->resetChangeLog(); d->mItems.append( item ); d->mPendingItems.append( item ); if ( !d->mEmitTimer->isActive() ) d->mEmitTimer->start(); return; } } kDebug( 5250 ) << "Unhandled response: " << tag << data; } Item::List ItemFetchJob::items() const { Q_D( const ItemFetchJob ); return d->mItems; } void ItemFetchJob::setFetchScope( ItemFetchScope &fetchScope ) { Q_D( ItemFetchJob ); d->mFetchScope = fetchScope; } ItemFetchScope &ItemFetchJob::fetchScope() { Q_D( ItemFetchJob ); return d->mFetchScope; } void ItemFetchJob::setCollection(const Akonadi::Collection& collection) { Q_D( ItemFetchJob ); d->mCollection = collection; } #include "itemfetchjob.moc" diff --git a/akonadi/itemmodifyjob.cpp b/akonadi/itemmodifyjob.cpp index 157838f8f..d9a6c8dde 100644 --- a/akonadi/itemmodifyjob.cpp +++ b/akonadi/itemmodifyjob.cpp @@ -1,230 +1,230 @@ /* Copyright (c) 2006 - 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 "itemmodifyjob.h" #include "itemmodifyjob_p.h" #include "collection.h" #include "entity_p.h" -#include "imapparser_p.h" +#include #include "itemserializer_p.h" #include "job_p.h" #include "item_p.h" #include "protocolhelper_p.h" #include using namespace Akonadi; ItemModifyJobPrivate::ItemModifyJobPrivate( ItemModifyJob *parent, const Item &item ) : JobPrivate( parent ), mItem( item ), mRevCheck( true ), mIgnorePayload( false ) { mParts = mItem.loadedPayloadParts(); } void ItemModifyJobPrivate::setClean() { mOperations.insert( Dirty ); } QByteArray ItemModifyJobPrivate::nextPartHeader() { QByteArray command; if ( !mParts.isEmpty() ) { QSetIterator it( mParts ); const QByteArray label = it.next(); mParts.remove( label ); mPendingData.clear(); int version = 0; ItemSerializer::serialize( mItem, label, mPendingData, version ); command += ' ' + ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartPayload, label, version ); command += ".SILENT"; if ( mPendingData.size() > 0 ) { command += " {" + QByteArray::number( mPendingData.size() ) + "}\n"; } else { if ( mPendingData.isNull() ) command += " NIL"; else command += " \"\""; command += nextPartHeader(); } } else { command += ")\n"; } return command; } ItemModifyJob::ItemModifyJob( const Item &item, QObject * parent ) : Job( new ItemModifyJobPrivate( this, item ), parent ) { Q_D( ItemModifyJob ); d->mOperations.insert( ItemModifyJobPrivate::RemoteId ); } ItemModifyJob::~ItemModifyJob() { } void ItemModifyJob::doStart() { Q_D( ItemModifyJob ); QList changes; foreach ( int op, d->mOperations ) { switch ( op ) { case ItemModifyJobPrivate::RemoteId: if ( !d->mItem.remoteId().isNull() ) { changes << "REMOTEID.SILENT"; changes << ImapParser::quote( d->mItem.remoteId().toUtf8() ); } break; case ItemModifyJobPrivate::Dirty: changes << "DIRTY.SILENT"; changes << "false"; break; } } if ( d->mItem.d_func()->mFlagsOverwritten ) { changes << "FLAGS.SILENT"; changes << '(' + ImapParser::join( d->mItem.flags(), " " ) + ')'; } else { if ( !d->mItem.d_func()->mAddedFlags.isEmpty() ) { changes << "+FLAGS.SILENT"; changes << '(' + ImapParser::join( d->mItem.d_func()->mAddedFlags, " " ) + ')'; } if ( !d->mItem.d_func()->mDeletedFlags.isEmpty() ) { changes << "-FLAGS.SILENT"; changes << '(' + ImapParser::join( d->mItem.d_func()->mDeletedFlags, " " ) + ')'; } } if ( !d->mItem.d_func()->mDeletedAttributes.isEmpty() ) { changes << "-PARTS.SILENT"; QList attrs; foreach ( const QByteArray &attr, d->mItem.d_func()->mDeletedAttributes ) attrs << ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartAttribute, attr ); changes << '(' + ImapParser::join( attrs, " " ) + ')'; } // nothing to do if ( changes.isEmpty() && d->mParts.isEmpty() && d->mItem.attributes().isEmpty() ) { emitResult(); return; } d->mTag = d->newTag(); QByteArray command = d->mTag; command += " UID STORE " + QByteArray::number( d->mItem.id() ) + ' '; if ( !d->mRevCheck ) { command += "NOREV "; } else { command += "REV " + QByteArray::number( d->mItem.revision() ) + ' '; } command += "SIZE " + QByteArray::number( d->mItem.size() ); command += " (" + ImapParser::join( changes, " " ); const QByteArray attrs = ProtocolHelper::attributesToByteArray( d->mItem, true ); if ( !attrs.isEmpty() ) command += ' ' + attrs; command += d->nextPartHeader(); d->writeData( command ); d->newTag(); // hack to circumvent automatic response handling } void ItemModifyJob::doHandleResponse(const QByteArray &_tag, const QByteArray & data) { Q_D( ItemModifyJob ); if ( _tag == "+" ) { // ready for literal data d->writeData( d->mPendingData ); d->writeData( d->nextPartHeader() ); return; } if ( _tag == d->mTag ) { if ( data.startsWith( "OK" ) ) { //krazy:exclude=strings QDateTime modificationDateTime; int dateTimePos = data.indexOf( "DATETIME" ); if ( dateTimePos != -1 ) { int resultPos = ImapParser::parseDateTime( data, modificationDateTime, dateTimePos + 8 ); if ( resultPos == (dateTimePos + 8) ) { kDebug( 5250 ) << "Invalid DATETIME response to STORE command: " << _tag << data; } } // increase item revision of own copy of item d->mItem.setRevision( d->mItem.revision() + 1 ); d->mItem.setModificationTime( modificationDateTime ); d->mItem.d_ptr->resetChangeLog(); } else { setError( Unknown ); setErrorText( QString::fromUtf8( data ) ); } emitResult(); return; } kDebug( 5250 ) << "Unhandled response: " << _tag << data; } void ItemModifyJob::setIgnorePayload( bool ignore ) { Q_D( ItemModifyJob ); if ( d->mIgnorePayload == ignore ) return; d->mIgnorePayload = ignore; if ( d->mIgnorePayload ) d->mParts = QSet(); else { Q_ASSERT( !d->mItem.mimeType().isEmpty() ); d->mParts = d->mItem.loadedPayloadParts(); } } bool ItemModifyJob::ignorePayload() const { Q_D( const ItemModifyJob ); return d->mIgnorePayload; } void ItemModifyJob::disableRevisionCheck() { Q_D( ItemModifyJob ); d->mRevCheck = false; } Item ItemModifyJob::item() const { Q_D( const ItemModifyJob ); return d->mItem; } #include "itemmodifyjob.moc" diff --git a/akonadi/job.cpp b/akonadi/job.cpp index f462f690c..15ffbbb8d 100644 --- a/akonadi/job.cpp +++ b/akonadi/job.cpp @@ -1,290 +1,290 @@ /* Copyright (c) 2006 Tobias Koenig 2006 Marc Mutz 2006 - 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 "job.h" #include "job_p.h" -#include "imapparser_p.h" +#include #include "session.h" #include "session_p.h" #include #include #include #include #include #include #include #include #include using namespace Akonadi; static QDBusAbstractInterface *s_jobtracker = 0; //@cond PRIVATE void JobPrivate::handleResponse( const QByteArray & tag, const QByteArray & data ) { Q_Q( Job ); if ( mCurrentSubJob ) { mCurrentSubJob->d_ptr->handleResponse( tag, data ); return; } if ( tag == mTag ) { if ( data.startsWith( "NO " ) || data.startsWith( "BAD " ) ) { //krazy:exclude=strings QString msg = QString::fromUtf8( data ); msg.remove( 0, msg.startsWith( QLatin1String( "NO " ) ) ? 3 : 4 ); if ( msg.endsWith( QLatin1String( "\r\n" ) ) ) msg.chop( 2 ); q->setError( Job::Unknown ); q->setErrorText( msg ); q->emitResult(); return; } else if ( data.startsWith( "OK" ) ) { //krazy:exclude=strings q->emitResult(); return; } } q->doHandleResponse( tag, data ); } void JobPrivate::init( QObject *parent ) { Q_Q( Job ); mParentJob = dynamic_cast( parent ); mSession = dynamic_cast( parent ); if ( !mSession ) { if ( !mParentJob ) mSession = Session::defaultSession(); else mSession = mParentJob->d_ptr->mSession; } if ( !mParentJob ) mSession->d->addJob( q ); else mParentJob->addSubjob( q ); // if there's a job tracer running, tell it about the new job if ( !s_jobtracker && QDBusConnection::sessionBus().interface()->isServiceRegistered(QLatin1String("org.kde.akonadiconsole") ) ) { s_jobtracker = new QDBusInterface( QLatin1String("org.kde.akonadiconsole"), QLatin1String("/jobtracker"), QLatin1String("org.freedesktop.Akonadi.JobTracker"), QDBusConnection::sessionBus(), 0 ); } QMetaObject::invokeMethod( q, "signalCreationToJobTracker", Qt::QueuedConnection ); } void JobPrivate::signalCreationToJobTracker() { Q_Q( Job ); if ( s_jobtracker ) { // We do these dbus calls manually, so as to avoid having to install (or copy) the console's // xml interface document. Since this is purely a debugging aid, that seems preferable to // publishing something not intended for public consumption. QList argumentList; argumentList << QLatin1String( mSession->sessionId() ) << QString::number(reinterpret_cast( q ), 16) << ( mParentJob ? QString::number( reinterpret_cast( mParentJob ), 16) : QString() ) << QString::fromLatin1( q->metaObject()->className() ); s_jobtracker->asyncCallWithArgumentList(QLatin1String("jobCreated"), argumentList); } } void JobPrivate::startQueued() { Q_Q( Job ); mStarted = true; emit q->aboutToStart( q ); q->doStart(); QTimer::singleShot( 0, q, SLOT(startNext()) ); // if there's a job tracer running, tell it a job started if ( s_jobtracker ) { QList argumentList; argumentList << QString::number(reinterpret_cast( q ), 16); s_jobtracker->asyncCallWithArgumentList(QLatin1String("jobStarted"), argumentList); } } void JobPrivate::lostConnection() { Q_Q( Job ); if ( mCurrentSubJob ) { mCurrentSubJob->d_ptr->lostConnection(); } else { q->setError( Job::ConnectionFailed ); q->kill( KJob::EmitResult ); } } void JobPrivate::slotSubJobAboutToStart( Job * job ) { Q_ASSERT( mCurrentSubJob == 0 ); mCurrentSubJob = job; } void JobPrivate::startNext() { Q_Q( Job ); if ( mStarted && !mCurrentSubJob && q->hasSubjobs() ) { Job *job = dynamic_cast( q->subjobs().first() ); Q_ASSERT( job ); job->d_ptr->startQueued(); } } QByteArray JobPrivate::newTag( ) { if ( mParentJob ) mTag = mParentJob->d_ptr->newTag(); else mTag = QByteArray::number( mSession->d->nextTag() ); return mTag; } QByteArray JobPrivate::tag() const { return mTag; } void JobPrivate::writeData( const QByteArray & data ) { Q_ASSERT_X( !mWriteFinished, "Job::writeData()", "Calling writeData() after emitting writeFinished()" ); mSession->d->writeData( data ); } //@endcond Job::Job( QObject *parent ) : KCompositeJob( parent ), d_ptr( new JobPrivate( this ) ) { d_ptr->init( parent ); } Job::Job( JobPrivate *dd, QObject *parent ) : KCompositeJob( parent ), d_ptr( dd ) { d_ptr->init( parent ); } Job::~Job() { delete d_ptr; // if there is a job tracer listening, tell it the job is done now if ( s_jobtracker ) { QList argumentList; argumentList << QString::number(reinterpret_cast( this ), 16) << errorString(); s_jobtracker->asyncCallWithArgumentList(QLatin1String("jobEnded"), argumentList); } } void Job::start() { } bool Job::doKill() { return true; } QString Job::errorString() const { QString str; switch ( error() ) { case NoError: break; case ConnectionFailed: str = i18n( "Cannot connect to the Akonadi service." ); break; case ProtocolVersionMismatch: str = i18n( "The protocol version of the Akonadi server is incompatible. Make sure you have a compatible version installed." ); break; case UserCanceled: str = i18n( "User canceled operation." ); break; case Unknown: default: str = i18n( "Unknown error." ); break; } if ( !errorText().isEmpty() ) { str += QString::fromLatin1( " (%1)" ).arg( errorText() ); } return str; } bool Job::addSubjob( KJob * job ) { bool rv = KCompositeJob::addSubjob( job ); if ( rv ) { connect( job, SIGNAL(aboutToStart(Akonadi::Job*)), SLOT(slotSubJobAboutToStart(Akonadi::Job*)) ); QTimer::singleShot( 0, this, SLOT(startNext()) ); } return rv; } bool Job::removeSubjob(KJob * job) { bool rv = KCompositeJob::removeSubjob( job ); if ( job == d_ptr->mCurrentSubJob ) { d_ptr->mCurrentSubJob = 0; QTimer::singleShot( 0, this, SLOT(startNext()) ); } return rv; } void Job::doHandleResponse(const QByteArray & tag, const QByteArray & data) { kDebug( 5250 ) << "Unhandled response: " << tag << data; } void Job::slotResult(KJob * job) { Q_ASSERT( job == d_ptr->mCurrentSubJob ); d_ptr->mCurrentSubJob = 0; KCompositeJob::slotResult( job ); if ( !job->error() ) QTimer::singleShot( 0, this, SLOT(startNext()) ); } void Job::emitWriteFinished() { d_ptr->mWriteFinished = true; emit writeFinished( this ); } #include "job.moc" diff --git a/akonadi/linkjob.cpp b/akonadi/linkjob.cpp index cad06813d..561bc6c05 100644 --- a/akonadi/linkjob.cpp +++ b/akonadi/linkjob.cpp @@ -1,68 +1,68 @@ /* 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 "linkjob.h" #include "collection.h" #include "job_p.h" -#include +#include using namespace Akonadi; class Akonadi::LinkJobPrivate : public JobPrivate { public: LinkJobPrivate( LinkJob *parent ) : JobPrivate( parent ) { } Collection collection; ImapSet set; }; LinkJob::LinkJob( const Collection &collection, const Item::List &items, QObject *parent ) : Job( new LinkJobPrivate( this ), parent ) { Q_D( LinkJob ); d->collection = collection; QList ids; foreach ( const Item &item, items ) ids << item.id(); d->set.add( ids ); } LinkJob::~LinkJob() { } void LinkJob::doStart() { Q_D( LinkJob ); QByteArray command = d->newTag(); command += " LINK "; command += QByteArray::number( d->collection.id() ); command += ' '; command += d->set.toImapSequenceSet(); command += '\n'; d->writeData( command ); } #include "linkjob.moc" diff --git a/akonadi/monitor.cpp b/akonadi/monitor.cpp index aa9769434..2100841a3 100644 --- a/akonadi/monitor.cpp +++ b/akonadi/monitor.cpp @@ -1,158 +1,158 @@ /* Copyright (c) 2006 - 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 "monitor.h" #include "monitor_p.h" #include "itemfetchjob.h" -#include "notificationmessage_p.h" +#include #include "session.h" #include #include #include #include #include using namespace Akonadi; #define d d_ptr Monitor::Monitor( QObject *parent ) : QObject( parent ), d_ptr( new MonitorPrivate( this ) ) { d_ptr->connectToNotificationManager(); } //@cond PRIVATE Monitor::Monitor(MonitorPrivate * d, QObject *parent) : QObject( parent ), d_ptr( d ) { } //@endcond Monitor::~Monitor() { delete d; } void Monitor::setCollectionMonitored( const Collection &collection, bool monitored ) { if ( monitored ) d->collections << collection; else d->collections.removeAll( collection ); emit collectionMonitored( collection, monitored ); } void Monitor::setItemMonitored( const Item & item, bool monitored ) { if ( monitored ) d->items.insert( item.id() ); else d->items.remove( item.id() ); emit itemMonitored( item, monitored ); } void Monitor::setResourceMonitored( const QByteArray & resource, bool monitored ) { if ( monitored ) d->resources.insert( resource ); else d->resources.remove( resource ); emit resourceMonitored( resource, monitored ); } void Monitor::setMimeTypeMonitored( const QString & mimetype, bool monitored ) { if ( monitored ) d->mimetypes.insert( mimetype ); else d->mimetypes.remove( mimetype ); emit mimeTypeMonitored( mimetype, monitored ); } void Akonadi::Monitor::setAllMonitored( bool monitored ) { d->monitorAll = monitored; emit allMonitored( monitored ); } void Monitor::ignoreSession(Session * session) { d->sessions << session->sessionId(); } void Monitor::fetchCollection(bool enable) { d->fetchCollection = enable; } void Monitor::fetchCollectionStatistics(bool enable) { d->fetchCollectionStatistics = enable; } void Monitor::setItemFetchScope( const ItemFetchScope &fetchScope ) { d->mItemFetchScope = fetchScope; } ItemFetchScope &Monitor::itemFetchScope() { return d->mItemFetchScope; } Collection::List Monitor::collectionsMonitored() const { return d->collections; } QList Monitor::itemsMonitored() const { return d->items.toList(); } QStringList Monitor::mimeTypesMonitored() const { return d->mimetypes.toList(); } QList Monitor::resourcesMonitored() const { return d->resources.toList(); } bool Monitor::isAllMonitored() const { return d->monitorAll; } #undef d #include "monitor.moc" diff --git a/akonadi/monitor_p.cpp b/akonadi/monitor_p.cpp index 286b8b4b5..9ec22d66f 100644 --- a/akonadi/monitor_p.cpp +++ b/akonadi/monitor_p.cpp @@ -1,390 +1,390 @@ /* Copyright (c) 2007 Tobias Koenig 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. */ // @cond PRIVATE #include "monitor_p.h" #include "collectionfetchjob.h" #include "collectionstatistics.h" #include "itemfetchjob.h" -#include "notificationmessage_p.h" +#include #include "session.h" #include using namespace Akonadi; MonitorPrivate::MonitorPrivate(Monitor * parent) : q_ptr( parent ), nm( 0 ), monitorAll( false ), fetchCollection( false ), fetchCollectionStatistics( false ) { } bool MonitorPrivate::connectToNotificationManager() { NotificationMessage::registerDBusTypes(); if ( !nm ) nm = new org::freedesktop::Akonadi::NotificationManager( QLatin1String( "org.freedesktop.Akonadi" ), QLatin1String( "/notifications" ), QDBusConnection::sessionBus(), q_ptr ); else return true; if ( !nm ) { kWarning( 5250 ) << "Unable to connect to notification manager"; } else { QObject::connect( nm, SIGNAL(notify(Akonadi::NotificationMessage::List)), q_ptr, SLOT(slotNotify(Akonadi::NotificationMessage::List)) ); return true; } return false; } bool MonitorPrivate::acceptNotification(const NotificationMessage & msg) { if ( isSessionIgnored( msg.sessionId() ) ) return false; switch ( msg.type() ) { case NotificationMessage::InvalidType: kWarning( 5250 ) << "Received invalid change notification!"; return false; case NotificationMessage::Item: return isItemMonitored( msg.uid(), msg.parentCollection(), msg.parentDestCollection(), msg.mimeType(), msg.resource() ) || isCollectionMonitored( msg.parentCollection(), msg.resource() ) || isCollectionMonitored( msg.parentDestCollection(), msg.resource() ); case NotificationMessage::Collection: return isCollectionMonitored( msg.uid(), msg.resource() ) || isCollectionMonitored( msg.parentCollection(), msg.resource() ) || isCollectionMonitored( msg.parentDestCollection(), msg.resource() ); } Q_ASSERT( false ); return false; } bool MonitorPrivate::processNotification(const NotificationMessage & msg) { if ( !acceptNotification( msg ) ) return false; if ( msg.type() == NotificationMessage::Item ) { notifyCollectionStatisticsWatchers( msg.parentCollection(), msg.resource() ); if ( !mItemFetchScope.isEmpty() && ( msg.operation() == NotificationMessage::Add || msg.operation() == NotificationMessage::Move || msg.operation() == NotificationMessage::Link ) ) { Item item( msg.uid() ); item.setRemoteId( msg.remoteId() ); ItemCollectionFetchJob *job = new ItemCollectionFetchJob( item, msg.parentCollection(), msg.parentDestCollection(), q_ptr ); job->setFetchScope( mItemFetchScope ); pendingJobs.insert( job, msg ); QObject::connect( job, SIGNAL(result(KJob*)), q_ptr, SLOT(slotItemJobFinished(KJob*)) ); return true; } if ( !mItemFetchScope.isEmpty() && msg.operation() == NotificationMessage::Modify ) { Item item( msg.uid() ); item.setRemoteId( msg.remoteId() ); ItemFetchJob *job = new ItemFetchJob( item, q_ptr ); job->setFetchScope( mItemFetchScope ); pendingJobs.insert( job, msg ); QObject::connect( job, SIGNAL(result(KJob*)), q_ptr, SLOT(slotItemJobFinished(KJob*)) ); return true; } emitItemNotification( msg ); return true; } else if ( msg.type() == NotificationMessage::Collection ) { if ( msg.operation() != NotificationMessage::Remove && fetchCollection ) { Collection::List list; list << Collection( msg.uid() ); if ( msg.operation() == NotificationMessage::Add ) list << Collection( msg.parentCollection() ); CollectionFetchJob *job = new CollectionFetchJob( list, q_ptr ); pendingJobs.insert( job, msg ); QObject::connect( job, SIGNAL(result(KJob*)), q_ptr, SLOT(slotCollectionJobFinished(KJob*)) ); return true; } if ( msg.operation() == NotificationMessage::Remove ) { // no need for statistics updates anymore recentlyChangedCollections.remove( msg.uid() ); } emitCollectionNotification( msg ); return true; } else { kWarning( 5250 ) << "Received unknown change notification!"; } return false; } void MonitorPrivate::sessionDestroyed( QObject * object ) { Session* session = qobject_cast( object ); if ( session ) sessions.removeAll( session->sessionId() ); } void MonitorPrivate::slotStatisticsChangedFinished( KJob* job ) { if ( job->error() ) { kWarning( 5250 ) << "Error on fetching collection statistics: " << job->errorText(); } else { CollectionStatisticsJob *statisticsJob = static_cast( job ); emit q_ptr->collectionStatisticsChanged( statisticsJob->collection().id(), statisticsJob->statistics() ); } } void MonitorPrivate::slotFlushRecentlyChangedCollections() { foreach( Collection::Id collection, recentlyChangedCollections ) { if ( fetchCollectionStatistics ) { fetchStatistics( collection ); } else { static const CollectionStatistics dummyStatistics; emit q_ptr->collectionStatisticsChanged( collection, dummyStatistics ); } } recentlyChangedCollections.clear(); } void MonitorPrivate::slotNotify( const NotificationMessage::List &msgs ) { foreach ( const NotificationMessage &msg, msgs ) processNotification( msg ); } void MonitorPrivate::emitItemNotification( const NotificationMessage &msg, const Item &item, const Collection &collection, const Collection &collectionDest ) { Q_ASSERT( msg.type() == NotificationMessage::Item ); Collection col = collection; Collection colDest = collectionDest; if ( !col.isValid() ) { col = Collection( msg.parentCollection() ); col.setResource( QString::fromUtf8( msg.resource() ) ); } if ( !colDest.isValid() ) { colDest = Collection( msg.parentDestCollection() ); // FIXME setResource here required ? } Item it = item; if ( !it.isValid() ) { it = Item( msg.uid() ); it.setRemoteId( msg.remoteId() ); it.setMimeType( msg.mimeType() ); } switch ( msg.operation() ) { case NotificationMessage::Add: emit q_ptr->itemAdded( it, col ); break; case NotificationMessage::Modify: emit q_ptr->itemChanged( it, msg.itemParts() ); break; case NotificationMessage::Move: emit q_ptr->itemMoved( it, col, colDest ); break; case NotificationMessage::Remove: emit q_ptr->itemRemoved( it ); break; case NotificationMessage::Link: emit q_ptr->itemLinked( it, col ); break; case NotificationMessage::Unlink: emit q_ptr->itemUnlinked( it, col ); break; default: kDebug() << "Unknown operation type" << msg.operation() << "in item change notification"; break; } } void MonitorPrivate::emitCollectionNotification( const NotificationMessage &msg, const Collection &col, const Collection &par ) { Q_ASSERT( msg.type() == NotificationMessage::Collection ); Collection collection = col; if ( !collection.isValid() ) { collection = Collection( msg.uid() ); collection.setParent( msg.parentCollection() ); collection.setResource( QString::fromUtf8( msg.resource() ) ); collection.setRemoteId( msg.remoteId() ); } Collection parent = par; if ( !parent.isValid() ) parent = Collection( msg.parentCollection() ); switch ( msg.operation() ) { case NotificationMessage::Add: emit q_ptr->collectionAdded( collection, parent ); break; case NotificationMessage::Modify: emit q_ptr->collectionChanged( collection ); break; case NotificationMessage::Remove: emit q_ptr->collectionRemoved( collection ); break; default: Q_ASSERT_X( false, "MonitorPrivate::emitCollectionNotification", "Invalid enum value" ); } } void MonitorPrivate::slotItemJobFinished( KJob* job ) { if ( !pendingJobs.contains( job ) ) { kWarning( 5250 ) << "Unknown job - wtf is going on here?"; return; } NotificationMessage msg = pendingJobs.take( job ); Item item; Collection col; Collection destCol; if ( job->error() ) { kWarning( 5250 ) << "Error on fetching item:" << job->errorText(); } else { ItemFetchJob *fetchJob = qobject_cast( job ); if ( fetchJob && fetchJob->items().count() > 0 ) item = fetchJob->items().first(); ItemCollectionFetchJob *cfjob = qobject_cast( job ); if ( cfjob ) { item = cfjob->item(); col = cfjob->collection(); destCol = cfjob->destCollection(); } } emitItemNotification( msg, item, col, destCol ); } void MonitorPrivate::slotCollectionJobFinished( KJob* job ) { if ( !pendingJobs.contains( job ) ) { kWarning( 5250 ) << "Unknown job - wtf is going on here?"; return; } NotificationMessage msg = pendingJobs.take( job ); if ( job->error() ) { kWarning( 5250 ) << "Error on fetching collection:" << job->errorText(); } else { Collection col, parent; CollectionFetchJob *listJob = qobject_cast( job ); if ( listJob && listJob->collections().count() > 0 ) col = listJob->collections().first(); if ( listJob && listJob->collections().count() > 1 && msg.operation() == NotificationMessage::Add ) { parent = listJob->collections().at( 1 ); if ( col.id() != msg.uid() ) qSwap( col, parent ); } emitCollectionNotification( msg, col, parent ); } } ItemCollectionFetchJob::ItemCollectionFetchJob( const Item &item, Collection::Id collectionId, Collection::Id destCollectionId, QObject *parent ) : Job( parent ), mReferenceItem( item ), mCollectionId( collectionId ), mDestCollectionId( destCollectionId ) { } ItemCollectionFetchJob::~ItemCollectionFetchJob() { } Item ItemCollectionFetchJob::item() const { return mItem; } Collection ItemCollectionFetchJob::collection() const { return mCollection; } Collection ItemCollectionFetchJob::destCollection() const { return mDestCollection; } void ItemCollectionFetchJob::setFetchScope( const ItemFetchScope &fetchScope ) { mFetchScope = fetchScope; } void ItemCollectionFetchJob::doStart() { CollectionFetchJob *listJob = new CollectionFetchJob( Collection( mCollectionId ), CollectionFetchJob::Base, this ); connect( listJob, SIGNAL( result( KJob* ) ), SLOT( collectionJobDone( KJob* ) ) ); addSubjob( listJob ); if ( mDestCollectionId > 0 ) { CollectionFetchJob *destListJob = new CollectionFetchJob( Collection( mDestCollectionId ), CollectionFetchJob::Base, this ); connect( destListJob, SIGNAL( result( KJob* ) ), SLOT( destCollectionJobDone( KJob* ) ) ); addSubjob( destListJob ); } ItemFetchJob *fetchJob = new ItemFetchJob( mReferenceItem, this ); fetchJob->setFetchScope( mFetchScope ); connect( fetchJob, SIGNAL( result( KJob* ) ), SLOT( itemJobDone( KJob* ) ) ); addSubjob( fetchJob ); } void ItemCollectionFetchJob::collectionJobDone( KJob* job ) { if ( !job->error() ) { CollectionFetchJob *listJob = qobject_cast( job ); if ( listJob->collections().isEmpty() ) { setError( 1 ); setErrorText( QLatin1String( "No collection found" ) ); } else mCollection = listJob->collections().first(); } } void ItemCollectionFetchJob::destCollectionJobDone( KJob* job ) { if ( !job->error() ) { CollectionFetchJob *listJob = qobject_cast( job ); if ( listJob->collections().isEmpty() ) { setError( 1 ); setErrorText( QLatin1String( "No collection found" ) ); } else mDestCollection = listJob->collections().first(); } } void ItemCollectionFetchJob::itemJobDone( KJob* job ) { if ( !job->error() ) { ItemFetchJob *fetchJob = qobject_cast( job ); if ( fetchJob->items().isEmpty() ) { setError( 2 ); setErrorText( QLatin1String( "No item found" ) ); } else mItem = fetchJob->items().first(); emitResult(); } } // @endcond #include "monitor_p.moc" diff --git a/akonadi/resourcebase.cpp b/akonadi/resourcebase.cpp index cde7a3dcc..04e3ef7a5 100644 --- a/akonadi/resourcebase.cpp +++ b/akonadi/resourcebase.cpp @@ -1,574 +1,574 @@ /* 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 "collectiondeletejob.h" #include "collectionsync_p.h" #include "itemsync.h" #include "resourcescheduler_p.h" #include "tracerinterface.h" -#include "xdgbasedirs_p.h" +#include #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 ), scheduler( 0 ), mItemSyncer( 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 ); QString mName; // synchronize states Collection currentCollection; ResourceScheduler *scheduler; ItemSync *mItemSyncer; }; ResourceBase::ResourceBase( const QString & id ) : AgentBase( new ResourceBasePrivate( this ), id ) { Q_D( ResourceBase ); new ResourceAdaptor( this ); const QString name = d->mSettings->value( QLatin1String( "Resource/Name" ) ).toString(); if ( !name.isEmpty() ) d->mName = name; 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(Akonadi::Collection)), SLOT(slotSynchronizeCollection(Akonadi::Collection)) ); connect( d->scheduler, SIGNAL(executeItemFetch(Akonadi::Item,QSet)), SLOT(retrieveItem(Akonadi::Item,QSet)) ); connect( d->scheduler, SIGNAL(executeResourceCollectionDeletion()), SLOT(slotDeleteResourceCollection()) ); connect( d->scheduler, SIGNAL( status( int, QString ) ), SIGNAL( status( int, QString ) ) ); connect( d->scheduler, SIGNAL(executeChangeReplay()), d->mMonitor, SLOT(replayNext()) ); connect( d->scheduler, SIGNAL(fullSyncComplete()), SIGNAL(synchronized()) ); connect( this, SIGNAL(synchronized()), d->scheduler, SLOT(taskDone()) ); 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::setName( const QString &name ) { Q_D( ResourceBase ); if ( name == d->mName ) return; // TODO: rename collection d->mName = name; if ( d->mName.isEmpty() || d->mName == d->mId ) d->mSettings->remove( QLatin1String( "Resource/Name" ) ); else d->mSettings->setValue( QLatin1String( "Resource/Name" ), d->mName ); d->mSettings->sync(); emit nameChanged( d->mName ); } QString ResourceBase::name() const { Q_D( const ResourceBase ); if ( d->mName.isEmpty() ) return d->mId; else return d->mName; } static char* sAppName = 0; 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 ); } sAppName = qstrdup( identifier.toLatin1().constData() ); KCmdLineArgs::init( argc, argv, sAppName, 0, 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; delete[] sAppName; 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 ); CollectionSync *syncer = new CollectionSync( d->mId ); syncer->setRemoteCollections( collections ); connect( syncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) ); } void ResourceBase::collectionsRetrievedIncremental(const Collection::List & changedCollections, const Collection::List & removedCollections) { Q_D( ResourceBase ); CollectionSync *syncer = new CollectionSync( d->mId ); syncer->setRemoteCollections( changedCollections, removedCollections ); connect( syncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) ); } void ResourceBasePrivate::slotCollectionSyncDone(KJob * job) { Q_Q( ResourceBase ); 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::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::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/resourceselectjob.cpp b/akonadi/resourceselectjob.cpp index 40762bc5b..e9e58a27d 100644 --- a/akonadi/resourceselectjob.cpp +++ b/akonadi/resourceselectjob.cpp @@ -1,54 +1,54 @@ /* 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 "resourceselectjob_p.h" -#include "imapparser_p.h" +#include #include "job_p.h" -#include "protocol_p.h" +#include #include using namespace Akonadi; class Akonadi::ResourceSelectJobPrivate : public JobPrivate { public: ResourceSelectJobPrivate( ResourceSelectJob *parent ) : JobPrivate( parent ) {} QString resourceId; }; ResourceSelectJob::ResourceSelectJob(const QString& identifier, QObject* parent) : Job( new ResourceSelectJobPrivate( this ), parent ) { Q_D( ResourceSelectJob ); d->resourceId = identifier; } void ResourceSelectJob::doStart() { Q_D( ResourceSelectJob ); d->writeData( d->newTag() + " " AKONADI_CMD_RESOURCESELECT " " + ImapParser::quote( d->resourceId.toUtf8() ) + '\n' ); emitWriteFinished(); } #include "resourceselectjob_p.moc" diff --git a/akonadi/searchcreatejob.cpp b/akonadi/searchcreatejob.cpp index 0feb717eb..3151e03d8 100644 --- a/akonadi/searchcreatejob.cpp +++ b/akonadi/searchcreatejob.cpp @@ -1,64 +1,64 @@ /* 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 "searchcreatejob.h" -#include "imapparser_p.h" +#include #include "job_p.h" using namespace Akonadi; class Akonadi::SearchCreateJobPrivate : public JobPrivate { public: SearchCreateJobPrivate( SearchCreateJob *parent ) : JobPrivate( parent ) { } QString mName; QString mQuery; }; SearchCreateJob::SearchCreateJob(const QString & name, const QString & query, QObject * parent) : Job( new SearchCreateJobPrivate( this ), parent ) { Q_D( SearchCreateJob ); d->mName = name; d->mQuery = query; } SearchCreateJob::~SearchCreateJob() { } void SearchCreateJob::doStart() { Q_D( SearchCreateJob ); QByteArray command = d->newTag() + " SEARCH_STORE "; command += ImapParser::quote( d->mName.toUtf8() ); command += ' '; command += ImapParser::quote( d->mQuery.toUtf8() ); command += '\n'; d->writeData( command ); } #include "searchcreatejob.moc" diff --git a/akonadi/session.cpp b/akonadi/session.cpp index a911cb2a3..87a87e035 100644 --- a/akonadi/session.cpp +++ b/akonadi/session.cpp @@ -1,304 +1,304 @@ /* 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 "session.h" #include "session_p.h" -#include "imapparser_p.h" +#include #include "job.h" #include "job_p.h" #include "servermanager_p.h" -#include "xdgbasedirs_p.h" +#include #include #include #include #include #include #include #include #include #define PIPELINE_LENGTH 2 using namespace Akonadi; //@cond PRIVATE void SessionPrivate::startNext() { QTimer::singleShot( 0, mParent, SLOT(doStartNext()) ); } void SessionPrivate::reconnect() { // should be checking connection method and value validity if ( socket->state() != QLocalSocket::ConnectedState && socket->state() != QLocalSocket::ConnectingState ) { #ifdef Q_OS_WIN //krazy:exclude=cpp const QString namedPipe = mConnectionSettings->value( QLatin1String( "Data/NamedPipe" ), QLatin1String( "Akonadi" ) ).toString(); socket->connectToServer( namedPipe ); #else const QString defaultSocketDir = XdgBaseDirs::saveDir( "data", QLatin1String( "akonadi" ) ); const QString path = mConnectionSettings->value( QLatin1String( "Data/UnixPath" ), defaultSocketDir + QLatin1String( "/akonadiserver.socket" ) ).toString(); socket->connectToServer( path ); #endif } } void SessionPrivate::socketError( QLocalSocket::LocalSocketError error ) { Q_ASSERT( mParent->sender() == socket ); kWarning( 5250 ) << "Socket error occurred:" << socket->errorString(); socketDisconnected(); } void SessionPrivate::socketDisconnected() { if ( currentJob ) currentJob->d_ptr->lostConnection(); connected = false; QTimer::singleShot( 1000, mParent, SLOT(reconnect()) ); } void SessionPrivate::dataReceived() { while ( socket->bytesAvailable() > 0 ) { if ( parser->continuationSize() > 1 ) { const QByteArray data = socket->read( qMin( socket->bytesAvailable(), parser->continuationSize() - 1 ) ); parser->parseBlock( data ); } else if ( socket->canReadLine() ) { if ( !parser->parseNextLine( socket->readLine() ) ) continue; // response not yet completed // handle login response if ( parser->tag() == QByteArray("0") ) { if ( parser->data().startsWith( "OK" ) ) { //krazy:exclude=strings connected = true; startNext(); } else { kWarning( 5250 ) << "Unable to login to Akonadi server:" << parser->data(); socket->close(); QTimer::singleShot( 1000, mParent, SLOT(reconnect()) ); } } // send login command if ( parser->tag() == "*" && parser->data().startsWith( "OK Akonadi" ) ) { const int pos = parser->data().indexOf( "[PROTOCOL" ); if ( pos > 0 ) { qint64 tmp = 0; ImapParser::parseNumber( parser->data(), tmp, 0, pos + 9 ); protocolVersion = tmp; Internal::setServerProtocolVersion( tmp ); } kDebug( 5250 ) << "Server protocol version is:" << protocolVersion; writeData( "0 LOGIN " + sessionId + '\n' ); // work for the current job } else { if ( currentJob ) currentJob->d_ptr->handleResponse( parser->tag(), parser->data() ); } // reset parser stuff parser->reset(); } else { break; // nothing we can do for now } } } bool SessionPrivate::canPipelineNext() { if ( queue.isEmpty() || pipeline.count() >= PIPELINE_LENGTH ) return false; if ( pipeline.isEmpty() && currentJob ) return currentJob->d_ptr->mWriteFinished; if ( !pipeline.isEmpty() ) return pipeline.last()->d_ptr->mWriteFinished; return false; } void SessionPrivate::doStartNext() { if ( !connected || (queue.isEmpty() && pipeline.isEmpty()) ) return; if ( canPipelineNext() ) { Akonadi::Job *nextJob = queue.dequeue(); pipeline.enqueue( nextJob ); startJob( nextJob ); } if ( jobRunning ) return; jobRunning = true; if ( !pipeline.isEmpty() ) { currentJob = pipeline.dequeue(); } else { currentJob = queue.dequeue(); startJob( currentJob ); } } void SessionPrivate::startJob( Job *job ) { if ( protocolVersion < minimumProtocolVersion() ) { job->setError( Job::ProtocolVersionMismatch ); job->setErrorText( i18n( "Protocol version %1 found, expected at least %2", protocolVersion, minimumProtocolVersion() ) ); job->emitResult(); } else { job->d_ptr->startQueued(); } } void SessionPrivate::jobDone(KJob * job) { if( job == currentJob ) { if ( pipeline.isEmpty() ) { jobRunning = false; currentJob = 0; } else { currentJob = pipeline.dequeue(); } startNext(); } // ### better handle the other cases too, user might have canceled jobs else { kDebug( 5250 ) << job << "Non-current job finished."; } } void SessionPrivate::jobWriteFinished( Akonadi::Job* job ) { Q_ASSERT( (job == currentJob && pipeline.isEmpty()) || (job = pipeline.last()) ); startNext(); } void SessionPrivate::jobDestroyed(QObject * job) { queue.removeAll( static_cast( job ) ); // ### likely not enough to really cancel already running jobs pipeline.removeAll( static_cast( job ) ); if ( currentJob == job ) currentJob = 0; } void SessionPrivate::addJob(Job * job) { queue.append( job ); QObject::connect( job, SIGNAL(result(KJob*)), mParent, SLOT(jobDone(KJob*)) ); QObject::connect( job, SIGNAL(writeFinished(Akonadi::Job*)), mParent, SLOT(jobWriteFinished(Akonadi::Job*)) ); QObject::connect( job, SIGNAL(destroyed(QObject*)), mParent, SLOT(jobDestroyed(QObject*)) ); startNext(); } int SessionPrivate::nextTag() { return theNextTag++; } void SessionPrivate::writeData(const QByteArray & data) { socket->write( data ); } //@endcond Session::Session(const QByteArray & sessionId, QObject * parent) : QObject( parent ), d( new SessionPrivate( this ) ) { if ( !sessionId.isEmpty() ) { d->sessionId = sessionId; } else { d->sessionId = QCoreApplication::instance()->applicationName().toUtf8() + '-' + QByteArray::number( qrand() ); } d->connected = false; d->theNextTag = 1; d->currentJob = 0; d->jobRunning = false; const QString connectionConfigFile = XdgBaseDirs::akonadiConnectionConfigFile(); QFileInfo fileInfo( connectionConfigFile ); if ( !fileInfo.exists() ) { kWarning( 5250 ) << "Akonadi Client Session: connection config file '" << "akonadi/akonadiconnectionrc can not be found in '" << XdgBaseDirs::homePath( "config" ) << "' nor in any of " << XdgBaseDirs::systemPathList( "config" ); } d->mConnectionSettings = new QSettings( connectionConfigFile, QSettings::IniFormat ); // should check connection method d->socket = new QLocalSocket( this ); connect( d->socket, SIGNAL(disconnected()), SLOT(socketDisconnected()) ); connect( d->socket, SIGNAL(error(QLocalSocket::LocalSocketError)), SLOT(socketError(QLocalSocket::LocalSocketError)) ); connect( d->socket, SIGNAL(readyRead()), SLOT(dataReceived()) ); d->reconnect(); } Session::~Session() { clear(); delete d; } QByteArray Session::sessionId() const { return d->sessionId; } QThreadStorage instances; void SessionPrivate::createDefaultSession( const QByteArray &sessionId ) { Q_ASSERT_X( !sessionId.isEmpty(), "SessionPrivate::createDefaultSession", "You tried to create a default session with empty session id!" ); Q_ASSERT_X( !instances.hasLocalData(), "SessionPrivate::createDefaultSession", "You tried to create a default session twice!" ); instances.setLocalData( new Session( sessionId ) ); } Session* Session::defaultSession() { if ( !instances.hasLocalData() ) instances.setLocalData( new Session() ); return instances.localData(); } void Session::clear() { foreach ( Job* job, d->queue ) job->kill( KJob::EmitResult ); d->queue.clear(); if ( d->currentJob ) d->currentJob->kill( KJob::EmitResult ); } #include "session.moc" diff --git a/akonadi/session_p.h b/akonadi/session_p.h index d02d946d0..83710d33b 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 #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 12; } 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/unlinkjob.cpp b/akonadi/unlinkjob.cpp index f895a3c43..8e77a8100 100644 --- a/akonadi/unlinkjob.cpp +++ b/akonadi/unlinkjob.cpp @@ -1,68 +1,68 @@ /* 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 "unlinkjob.h" #include "collection.h" #include "job_p.h" -#include +#include using namespace Akonadi; class Akonadi::UnlinkJobPrivate : public JobPrivate { public: UnlinkJobPrivate( UnlinkJob *parent ) : JobPrivate( parent ) { } Collection collection; ImapSet set; }; UnlinkJob::UnlinkJob( const Collection &collection, const Item::List &items, QObject *parent ) : Job( new UnlinkJobPrivate( this ), parent ) { Q_D( UnlinkJob ); d->collection = collection; QList ids; foreach ( const Item &item, items ) ids << item.id(); d->set.add( ids ); } UnlinkJob::~UnlinkJob() { } void UnlinkJob::doStart() { Q_D( UnlinkJob ); QByteArray command = d->newTag(); command += " UNLINK "; command += QByteArray::number( d->collection.id() ); command += ' '; command += d->set.toImapSequenceSet(); command += '\n'; d->writeData( command ); } #include "unlinkjob.moc"