1/*
2 eventloopinteractor.h
3 Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
4
5 This file is part of GPGME++.
6
7 GPGME++ is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 GPGME++ is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with GPGME++; see the file COPYING.LIB. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21*/
22
23// -*- c++ -*-
24#ifndef __GPGMEPP_EVENTLOOPINTERACTOR_H__
25#define __GPGMEPP_EVENTLOOPINTERACTOR_H__
26
27#include <gpgme++/gpgme++_export.h>
28
29namespace GpgME {
30
31 class Context;
32 class Error;
33 class TrustItem;
34 class Key;
35
36 /*! \file eventloopinteractor.h
37 \brief Abstract base class for gpgme's external event loop support
38
39 This class does most of the work involved with hooking GpgME++
40 up with external event loops, such as the GTK or Qt ones.
41
42 It actually provides two interfaces: An interface to the gpgme
43 IO Callback handling and one for gpgme events. The IO Callback
44 interface consists of the three methods \c actOn(), \c
45 registerWatcher() and \c unregisterWatcher(). The event
46 interface consists of the three methods \c nextTrustItemEvent(),
47 \c nextKeyEvent() and \c operationDoneEvent().
48
49 \sect General Usage
50
51 \c EventLoopInteractor is designed to be used as a
52 singleton. However, in order to make any use of it, you have to
53 subclass it and reimplement it's pure virtual methods (see
54 below). We suggest you keep the constructor protected and
55 provide a static \c instance() method that returns the single
56 instance. Alternatively, you can create an instance on the
57 stack, e.g. in \c main().
58
59 If you want \c EventLoopInteractor to manage a particular \c
60 Context, just call \c manage() on the \c Context. OTOH, if you
61 want to disable IO callbacks for a \c Context, use \c unmanage().
62
63 \sect IO Callback Interface
64
65 One part of this interface is represented by \c
66 registerWatcher() and \c unregisterWatcher(), both of which are
67 pure virtual. \c registerWatcher() should do anything necessary
68 to hook up watching of file descriptor \c fd for reading (\c dir
69 = \c Read) or writing (\c dir = Write) to the event loop you use
70 and return a tag identifying that particular watching process
71 uniquely. This could be the index into an array of objects you
72 use for that purpose or the address of such an object. E.g. in
73 Qt, you'd essentially just create a new \c QSocketNotifier:
74
75 \verbatim
76 void * registerWatcher( int fd, Direction dir ) {
77 return new QSocketNotifier( fd, dir == Read ? QSocketNotifier::Read : QSocketNotifier::Write );
78 // misses connecting to the activated() signal...
79 }
80 \endverbatim
81
82 which uses the address of the created object as unique tag. The
83 tag returned by \c registerWatcher is stored by \c
84 EventLoopInteractor and passed as argument to \c
85 unregisterWatcher(). So, in the picture above, you'd implement \c
86 unregisterWatcher() like this:
87
88 \verbatim
89 void unregisterWatcher( void * tag ) {
90 delete static_cast<QSocketNotifier*>( tag );
91 }
92 \endverbatim
93
94 The other part of the IO callback interface is \c actOn(), which
95 you should call if you receive notification from your event loop
96 about activity on file descriptor \c fd in direction \c dir. In
97 the picture above, you'd call this from the slot connected to
98 the socket notifier's \c activated() signal.
99
100 \note \c registerWatcher() as well as \c unregisterWatcher() may
101 be called from within \c actOn(), so be careful with
102 e.g. locking in threaded environments and keep in mind that the
103 object you used to find the \c fd and \c dir fo the \c actOn()
104 call might be deleted when \c actOn() returns!
105
106 \sect Event Handler Interface
107
108
109 */
110 class GPGMEPP_EXPORT EventLoopInteractor {
111 protected:
112 EventLoopInteractor();
113 public:
114 virtual ~EventLoopInteractor();
115
116 static EventLoopInteractor * instance() {
117 return mSelf;
118 }
119
120 void manage( Context * context );
121 void unmanage( Context * context );
122
123 enum Direction { Read, Write };
124 protected:
125 //
126 // IO Notification Interface
127 //
128
129 /** Call this if your event loop detected activity on file
130 descriptor fd, with direction dir */
131 void actOn( int fd, Direction dir );
132
133 virtual void * registerWatcher( int fd, Direction dir, bool & ok ) = 0;
134 virtual void unregisterWatcher( void * tag ) = 0;
135
136 //
137 // Event Handler Interface
138 //
139
140 virtual void operationStartEvent( Context * context ) = 0;
141 virtual void nextTrustItemEvent( Context * context, const TrustItem & item ) = 0;
142 virtual void nextKeyEvent( Context * context, const Key & key ) = 0;
143 virtual void operationDoneEvent( Context * context, const Error & e ) = 0;
144
145 private:
146 class Private;
147 friend class Private;
148 Private * const d;
149 static EventLoopInteractor * mSelf;
150 };
151
152}
153
154#endif // __GPGMEPP_EVENTLOOPINTERACTOR_H__
155