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