Mercurial > code > home > repos > light9
comparison lib/qt4reactor.py @ 463:60b49f6c2027
start porting lightsim to qt
author | drewp@bigasterisk.com |
---|---|
date | Mon, 01 Sep 2008 00:41:29 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
462:cd4d7b878550 | 463:60b49f6c2027 |
---|---|
1 # http://twistedmatrix.com/trac/browser/sandbox/therve/qt4reactor.py | |
2 # with some fixes by drewp | |
3 | |
4 # Copyright (c) 2001-2008 Twisted Matrix Laboratories. | |
5 # See LICENSE for details. | |
6 | |
7 | |
8 """ | |
9 This module provides support for Twisted to interact with the PyQt mainloop. | |
10 | |
11 In order to use this support, simply do the following:: | |
12 | |
13 | import qt4reactor | |
14 | qt4reactor.install() | |
15 | |
16 Then use twisted.internet APIs as usual. The other methods here are not | |
17 intended to be called directly. | |
18 | |
19 API Stability: stable | |
20 | |
21 Maintainer: U{Itamar Shtull-Trauring<mailto:twisted@itamarst.org>} | |
22 Port to QT4: U{Gabe Rudy<mailto:rudy@goldenhelix.com>} | |
23 """ | |
24 | |
25 __all__ = ['install'] | |
26 | |
27 | |
28 import sys | |
29 | |
30 from zope.interface import implements | |
31 | |
32 from PyQt4.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer | |
33 from PyQt4.QtGui import QApplication | |
34 | |
35 from twisted.internet.interfaces import IReactorFDSet | |
36 from twisted.python import log | |
37 from twisted.internet.posixbase import PosixReactorBase | |
38 | |
39 | |
40 | |
41 class TwistedSocketNotifier(QSocketNotifier): | |
42 """ | |
43 Connection between an fd event and reader/writer callbacks. | |
44 """ | |
45 | |
46 def __init__(self, reactor, watcher, type): | |
47 QSocketNotifier.__init__(self, watcher.fileno(), type) | |
48 self.reactor = reactor | |
49 self.watcher = watcher | |
50 self.fn = None | |
51 if type == QSocketNotifier.Read: | |
52 self.fn = self.read | |
53 elif type == QSocketNotifier.Write: | |
54 self.fn = self.write | |
55 QObject.connect(self, SIGNAL("activated(int)"), self.fn) | |
56 | |
57 | |
58 def shutdown(self): | |
59 QObject.disconnect(self, SIGNAL("activated(int)"), self.fn) | |
60 self.setEnabled(0) | |
61 self.fn = self.watcher = None | |
62 | |
63 | |
64 def read(self, sock): | |
65 w = self.watcher | |
66 def _read(): | |
67 why = None | |
68 try: | |
69 why = w.doRead() | |
70 except: | |
71 log.err() | |
72 why = sys.exc_info()[1] | |
73 if why: | |
74 self.reactor._disconnectSelectable(w, why, True) | |
75 log.callWithLogger(w, _read) | |
76 self.reactor.simulate() | |
77 | |
78 | |
79 def write(self, sock): | |
80 w = self.watcher | |
81 def _write(): | |
82 why = None | |
83 self.setEnabled(0) | |
84 try: | |
85 why = w.doWrite() | |
86 except: | |
87 log.err() | |
88 why = sys.exc_info()[1] | |
89 if why: | |
90 self.reactor._disconnectSelectable(w, why, False) | |
91 elif self.watcher: | |
92 self.setEnabled(1) | |
93 log.callWithLogger(w, _write) | |
94 self.reactor.simulate() | |
95 | |
96 | |
97 | |
98 class QTReactor(PosixReactorBase): | |
99 """ | |
100 Qt based reactor. | |
101 """ | |
102 implements(IReactorFDSet) | |
103 | |
104 # Reference to a DelayedCall for self.crash() when the reactor is | |
105 # entered through .iterate() | |
106 _crashCall = None | |
107 | |
108 _timer = None | |
109 | |
110 def __init__(self, app=None): | |
111 self._reads = {} | |
112 self._writes = {} | |
113 if app is None: | |
114 app = QApplication([]) | |
115 self.qApp = app | |
116 PosixReactorBase.__init__(self) | |
117 self.addSystemEventTrigger('after', 'shutdown', self.cleanup) | |
118 | |
119 | |
120 | |
121 def addReader(self, reader): | |
122 if not reader in self._reads: | |
123 self._reads[reader] = TwistedSocketNotifier(self, reader, | |
124 QSocketNotifier.Read) | |
125 | |
126 | |
127 def addWriter(self, writer): | |
128 if not writer in self._writes: | |
129 self._writes[writer] = TwistedSocketNotifier(self, writer, | |
130 QSocketNotifier.Write) | |
131 | |
132 | |
133 def removeReader(self, reader): | |
134 if reader in self._reads: | |
135 self._reads[reader].shutdown() | |
136 del self._reads[reader] | |
137 | |
138 | |
139 def removeWriter(self, writer): | |
140 if writer in self._writes: | |
141 self._writes[writer].shutdown() | |
142 del self._writes[writer] | |
143 | |
144 | |
145 def removeAll(self): | |
146 return self._removeAll(self._reads, self._writes) | |
147 | |
148 | |
149 def getReaders(self): | |
150 return self._reads.keys() | |
151 | |
152 | |
153 def getWriters(self): | |
154 return self._writes.keys() | |
155 | |
156 | |
157 def simulate(self): | |
158 self._lastTimer = self._timer # put off the __del__ | |
159 if self._timer is not None: | |
160 self._timer.stop() | |
161 self._timer = None | |
162 | |
163 if not self.running: | |
164 self.qApp.exit() | |
165 return | |
166 self.runUntilCurrent() | |
167 | |
168 if self._crashCall is not None: | |
169 self._crashCall.reset(0) | |
170 | |
171 timeout = self.timeout() | |
172 if timeout is None: | |
173 timeout = 1.0 | |
174 timeout = min(timeout, 0.01) * 1010 | |
175 | |
176 if self._timer is None: | |
177 self._timer = QTimer() | |
178 self._timer.setObjectName("simulateTimer") | |
179 QObject.connect(self._timer, SIGNAL("timeout()"), self.simulate) | |
180 self._timer.start(timeout) | |
181 | |
182 def cleanup(self): | |
183 if self._timer is not None: | |
184 self._timer.stop() | |
185 self._timer = None | |
186 | |
187 | |
188 def iterate(self, delay=0.0): | |
189 self._crashCall = self.callLater(delay, self._crash) | |
190 self.run() | |
191 | |
192 | |
193 def mainLoop(self): | |
194 self.simulate() | |
195 self.qApp.exec_() | |
196 | |
197 | |
198 def _crash(self): | |
199 if self._crashCall is not None: | |
200 if self._crashCall.active(): | |
201 self._crashCall.cancel() | |
202 self._crashCall = None | |
203 self.running = False | |
204 | |
205 | |
206 | |
207 def install(app=None): | |
208 """ | |
209 Configure the twisted mainloop to be run inside the qt mainloop. | |
210 """ | |
211 from twisted.internet import main | |
212 reactor = QTReactor(app=app) | |
213 main.installReactor(reactor) |