/* eventloopinteractor.h Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB This file is part of GPGME++. GPGME++ 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. GPGME++ 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 GPGME++; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // -*- c++ -*- #ifndef __GPGMEPP_EVENTLOOPINTERACTOR_H__ #define __GPGMEPP_EVENTLOOPINTERACTOR_H__ #include "gpgmepp_export.h" namespace GpgME { class Context; class Error; class TrustItem; class Key; /*! \file eventloopinteractor.h \brief Abstract base class for gpgme's external event loop support This class does most of the work involved with hooking GpgME++ up with external event loops, such as the GTK or Qt ones. It actually provides two interfaces: An interface to the gpgme IO Callback handling and one for gpgme events. The IO Callback interface consists of the three methods \c actOn(), \c registerWatcher() and \c unregisterWatcher(). The event interface consists of the three methods \c nextTrustItemEvent(), \c nextKeyEvent() and \c operationDoneEvent(). \sect General Usage \c EventLoopInteractor is designed to be used as a singleton. However, in order to make any use of it, you have to subclass it and reimplement it's pure virtual methods (see below). We suggest you keep the constructor protected and provide a static \c instance() method that returns the single instance. Alternatively, you can create an instance on the stack, e.g. in \c main(). If you want \c EventLoopInteractor to manage a particular \c Context, just call \c manage() on the \c Context. OTOH, if you want to disable IO callbacks for a \c Context, use \c unmanage(). \sect IO Callback Interface One part of this interface is represented by \c registerWatcher() and \c unregisterWatcher(), both of which are pure virtual. \c registerWatcher() should do anything necessary to hook up watching of file descriptor \c fd for reading (\c dir = \c Read) or writing (\c dir = Write) to the event loop you use and return a tag identifying that particular watching process uniquely. This could be the index into an array of objects you use for that purpose or the address of such an object. E.g. in Qt, you'd essentially just create a new \c QSocketNotifier: \verbatim void * registerWatcher( int fd, Direction dir ) { return new QSocketNotifier( fd, dir == Read ? QSocketNotifier::Read : QSocketNotifier::Write ); // misses connecting to the activated() signal... } \endverbatim which uses the address of the created object as unique tag. The tag returned by \c registerWatcher is stored by \c EventLoopInteractor and passed as argument to \c unregisterWatcher(). So, in the picture above, you'd implement \c unregisterWatcher() like this: \verbatim void unregisterWatcher( void * tag ) { delete static_cast( tag ); } \endverbatim The other part of the IO callback interface is \c actOn(), which you should call if you receive notification from your event loop about activity on file descriptor \c fd in direction \c dir. In the picture above, you'd call this from the slot connected to the socket notifier's \c activated() signal. \note \c registerWatcher() as well as \c unregisterWatcher() may be called from within \c actOn(), so be careful with e.g. locking in threaded environments and keep in mind that the object you used to find the \c fd and \c dir fo the \c actOn() call might be deleted when \c actOn() returns! \sect Event Handler Interface */ class GPGMEPP_EXPORT EventLoopInteractor { protected: EventLoopInteractor(); public: virtual ~EventLoopInteractor(); static EventLoopInteractor *instance() { return mSelf; } void manage(Context *context); void unmanage(Context *context); enum Direction { Read, Write }; protected: // // IO Notification Interface // /** Call this if your event loop detected activity on file descriptor fd, with direction dir */ void actOn(int fd, Direction dir); virtual void *registerWatcher(int fd, Direction dir, bool &ok) = 0; virtual void unregisterWatcher(void *tag) = 0; // // Event Handler Interface // virtual void operationStartEvent(Context *context) = 0; virtual void nextTrustItemEvent(Context *context, const TrustItem &item) = 0; virtual void nextKeyEvent(Context *context, const Key &key) = 0; virtual void operationDoneEvent(Context *context, const Error &e) = 0; private: class Private; friend class Private; Private *const d; static EventLoopInteractor *mSelf; }; } #endif // __GPGMEPP_EVENTLOOPINTERACTOR_H__