diff --git a/akonadi/CMakeLists.txt b/akonadi/CMakeLists.txt index 86c47c9a9..475ac7edb 100644 --- a/akonadi/CMakeLists.txt +++ b/akonadi/CMakeLists.txt @@ -1,251 +1,254 @@ project(akonadi-kde) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}" ) if(CMAKE_COMPILE_GCOV) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") endif(CMAKE_COMPILE_GCOV) if (KDE4_BUILD_TESTS) # only with this macro the AKONADI_TESTS_EXPORT macro will do something add_definitions(-DCOMPILING_TESTS) add_subdirectory( tests ) endif (KDE4_BUILD_TESTS) add_definitions( -DQT_NO_CAST_FROM_ASCII ) add_definitions( -DQT_NO_CAST_TO_ASCII ) add_subdirectory( kabc ) add_subdirectory( kmime ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${QT_QTDBUS_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${KDE4_INCLUDE_DIR} ${AKONADI_INCLUDE_DIR} ${AKONADI_INCLUDE_DIR}/akonadi/private ) # libakonadi-kde set( akonadikde_LIB_SRC entity.cpp # keep it at top to not break enable-final agentbase.cpp agentfilterproxymodel.cpp agentinstance.cpp agentinstancecreatejob.cpp agentinstancemodel.cpp agentinstancewidget.cpp agentmanager.cpp agenttype.cpp agenttypemodel.cpp agenttypewidget.cpp agenttypedialog.cpp attribute.cpp attributefactory.cpp cachepolicy.cpp cachepolicypage.cpp changerecorder.cpp collection.cpp collectioncopyjob.cpp collectioncreatejob.cpp collectiondeletejob.cpp collectiondialog.cpp collectionfilterproxymodel.cpp collectiongeneralpropertiespage.cpp collectionfetchjob.cpp collectionmodel.cpp collectionmodel_p.cpp collectionmodifyjob.cpp collectionmovejob.cpp collectionpathresolver.cpp collectionpropertiesdialog.cpp collectionpropertiespage.cpp collectionrequester.cpp collectionrightsattribute.cpp collectionselectjob.cpp collectionstatistics.cpp collectionstatisticsdelegate.cpp collectionstatisticsjob.cpp collectionstatisticsmodel.cpp collectionsync.cpp collectionview.cpp control.cpp descendantsproxymodel.cpp entitydisplayattribute.cpp entitytreemodel.cpp entitytreemodel_p.cpp entityfilterproxymodel.cpp entitytreeviewstatesaver.cpp erroroverlay.cpp exception.cpp expungejob.cpp favoritecollectionsmodel.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 + preprocessorbase.cpp protocolhelper.cpp resourcebase.cpp resourcescheduler.cpp resourceselectjob.cpp searchcreatejob.cpp selectionproxymodel.cpp selftestdialog.cpp session.cpp servermanager.cpp standardactionmanager.cpp statisticsproxymodel.cpp statisticstooltipproxymodel.cpp subscriptionjob.cpp subscriptionchangeproxymodel.cpp subscriptiondialog.cpp subscriptionmodel.cpp transactionjobs.cpp transactionsequence.cpp unlinkjob.cpp # Temporary until ported to Qt-plugin framework pluginloader.cpp ) # DBus interfaces and adaptors set(akonadi_xml ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.NotificationManager.xml) set_source_files_properties(${akonadi_xml} PROPERTIES INCLUDE "notificationmessage_p.h") qt4_add_dbus_interface( akonadikde_LIB_SRC ${akonadi_xml} notificationmanagerinterface ) qt4_add_dbus_interfaces( akonadikde_LIB_SRC ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.AgentManager.xml ) qt4_add_dbus_interfaces( akonadikde_LIB_SRC ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.Tracer.xml ) qt4_add_dbus_adaptor( akonadikde_LIB_SRC ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.Resource.xml resourcebase.h Akonadi::ResourceBase ) +qt4_add_dbus_adaptor( akonadikde_LIB_SRC ${AKONADI_DBUS_INTERFACES_DIR}/org.freedesktop.Akonadi.Preprocessor.xml preprocessorbase.h Akonadi::PreprocessorBase ) 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 descendantsproxymodel.h entity.h entitydisplayattribute.h entitytreemodel.h entityfilterproxymodel.h entitytreeviewstatesaver.h exception.h favoritecollectionsmodel.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 + preprocessorbase.h resourcebase.h searchcreatejob.h selectionproxymodel.h session.h servermanager.h standardactionmanager.h statisticsproxymodel.h statisticstooltipproxymodel.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/preprocessorbase.cpp b/akonadi/preprocessorbase.cpp new file mode 100644 index 000000000..5264fe499 --- /dev/null +++ b/akonadi/preprocessorbase.cpp @@ -0,0 +1,111 @@ +/****************************************************************************** + * + * File : preprocessorbase.cpp + * Creation date : Sun 19 Jul 2009 22:39:13 + * + * Copyright (c) 2009 Szymon Stefanek + * + * 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 "preprocessorbase.h" + +#include "agentbase_p.h" + +#include "preprocessoradaptor.h" + +#include + +namespace Akonadi +{ + + +class PreprocessorBasePrivate : public AgentBasePrivate +{ +public: + bool mInDelayedProcessing; + qlonglong mDelayedProcessingItemId; + +public: + PreprocessorBasePrivate( PreprocessorBase *parent ) + : AgentBasePrivate( parent ), + mInDelayedProcessing( false ), + mDelayedProcessingItemId( 0 ) + { + } + + Q_DECLARE_PUBLIC( PreprocessorBase ) + + void delayedInit() + { + if ( !QDBusConnection::sessionBus().registerService( QLatin1String( "org.freedesktop.Akonadi.Preprocessor." ) + mId ) ) + kFatal() << "Unable to register service at D-Bus: " << QDBusConnection::sessionBus().lastError().message(); + AgentBasePrivate::delayedInit(); + } + +}; // class PreprocessorBasePrivate + + +PreprocessorBase::PreprocessorBase( const QString &id ) + : AgentBase( new PreprocessorBasePrivate( this ), id ) +{ + new PreprocessorAdaptor( this ); +} + +PreprocessorBase::~PreprocessorBase() +{ + +} + +void PreprocessorBase::processingTerminated( ProcessingResult result ) +{ + Q_D( PreprocessorBase ); + + Q_ASSERT_X( result != ProcessingDelayed, "PreprocessorBase::processingTerminated", "You should never pass ProcessingDelayed to this function" ); + Q_ASSERT_X( d->mInDelayedProcessing, "PreprocessorBase::processingTerminated", "processingTerminated() called while not in delayed processing mode" ); + + d->mInDelayedProcessing = false; + emit itemProcessed( d->mDelayedProcessingItemId ); +} + +void PreprocessorBase::beginProcessItem( qlonglong id ) +{ + Q_D( PreprocessorBase ); + + qDebug() << "PreprocessorBase: about to process item " << id; + + switch( processItem( Item( id ) ) ) + { + case ProcessingFailed: + case ProcessingRefused: + case ProcessingCompleted: + qDebug() << "PreprocessorBase: item processed, emitting signal (" << id << ")"; + + emit itemProcessed( id ); + + qDebug() << "PreprocessorBase: item processed, signal emitted (" << id << ")"; + break; + case ProcessingDelayed: + qDebug() << "PreprocessorBase: item processing delayed (" << id << ")"; + + d->mInDelayedProcessing = true; + d->mDelayedProcessingItemId = id; + break; + } +} + +} // namespace Akonadi diff --git a/akonadi/preprocessorbase.h b/akonadi/preprocessorbase.h new file mode 100644 index 000000000..dd2be6eb7 --- /dev/null +++ b/akonadi/preprocessorbase.h @@ -0,0 +1,177 @@ +/****************************************************************************** + * + * File : preprocessorbase.h + * Creation date : Sun 19 Jul 2009 22:39:13 + * + * Copyright (c) 2009 Szymon Stefanek + * + * 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 _PREPROCESSORBASE_H_ +#define _PREPROCESSORBASE_H_ + +#include "akonadi_export.h" + +#include +#include +#include + +class PreprocessorAdaptor; + +namespace Akonadi +{ + +class PreprocessorBasePrivate; + +/** + * @short The base class for all Akonadi preprocessors. + * + * This class should be used as a base class by all preprocessor agents + * since it encapsulates large parts of the protocol between + * preprocessor agent, agent manager and the Akonadi storage. + * + * The method all the preprocessors must implement is processItem(). + */ +class AKONADI_EXPORT PreprocessorBase : public AgentBase +{ + friend class PreprocessorAdaptor; + + Q_OBJECT + +public: + + /** + * Creates an instance of a PreprocessorBase. + * You don't need to call this explicitly if you + * use the AKONADI_PREPROCESSOR_MAIN macro below. + */ + PreprocessorBase( const QString &id ); + + /** + * Destroys the PreprocessorBase instance. + */ + virtual ~PreprocessorBase(); + +public: + + /** + * The possible results of your processItem() function. + */ + enum ProcessingResult + { + /** + * Processing completed succesfully for this item. + * The Akonadi server will push in a new item when it's available. + */ + ProcessingCompleted, + + /** + * Processing was delayed to a later stage. + * This is what you want to return when implementing + * asynchronous preprocessing. + * + * If you return this value then you're responsible of calling + * processingTerminated() when you're done. + */ + ProcessingDelayed, + + /** + * Processing for this item failed (and the failure is unrecoverable). + * The Akonadi server will push in a new item when it's available, + * after possibly logging the failure. + */ + ProcessingFailed, + + /** + * Processing for this item was refused. This is very + * similar to ProcessingFailed above but additionally remarks + * that the item that the Akonadi server pushed in wasn't + * meant for this Preprocessor. + * The Akonadi server will push in a new item when it's available, + * after possibly logging the failure and maybe taking some additional action. + */ + ProcessingRefused + + }; + + /** + * This is the pure virtual you need to implement + * in your preprocessor. + * + * Return ProcessingCompleted on success, ProcessingDelayed + * if you're implementing asynchronous preprocessing and + * ProcessingRefused or ProcessingFailed if the processing + * didn't complete. + * + * If you return ProcessingDelayed then you also MUST + * call processingTerminated() when you're asynchronous + * elaboration completes. + */ + virtual ProcessingResult processItem( const Item &item ) = 0; + + /** + * You need to call this function if you are implementing an asynchronous + * preprocessor. In processItem() you trigger your async work + * and return ProcessingDelayed. The framework will then assume + * that you're busy until you call this function. + * + * Possible values for result are ProcessingCompleted, + * PocessingRefused and ProcessingFailed. Passing ProcessingDelayed + * is a programming error and will be punished by a Q_ASSERT(). + */ + void processingTerminated( ProcessingResult result ); + +private: + + // dbus Preprocessor interface: don't look :) + friend class ::PreprocessorAdaptor; + + /** + * Internal D-Bus handler. Called by the Akonadi server + * in order to trigger the processing of an item. Don't touch :) + */ + void beginProcessItem( qlonglong id ); + +Q_SIGNALS: + /** + * Internal D-Bus signal. Used to report item processing termination + * to the Akonadi server. Don't touch :) + */ + void itemProcessed( qlonglong id ); + +private: + + Q_DECLARE_PRIVATE( PreprocessorBase ) + +}; // class PreprocessorBase + +} // namespace Akonadi + +#ifndef AKONADI_PREPROCESSOR_MAIN +/** + * Convenience Macro for the most common main() function for Akonadi preprocessors. + */ +#define AKONADI_PREPROCESSOR_MAIN( preProcessorClass ) \ + int main( int argc, char **argv ) \ + { \ + return Akonadi::PreprocessorBase::init( argc, argv ); \ + } +#endif //!AKONADI_RESOURCE_MAIN + + +#endif //!_PREPROCESSORBASE_H_