Ticket #3977: qtreactor-3977.patch
| File qtreactor-3977.patch, 14.3 KB (added by michaelnt, 2 years ago) |
|---|
-
(a) /dev/null vs. (b) doc/core/examples/qtdemo.py
diff --git doc/core/examples/qtdemo.py doc/core/examples/qtdemo.py new file mode 100644 index 0000000..b16709f
a b 1 # Copyright (c) 2001-20011 Twisted Matrix Laboratories. 2 # See LICENSE for details. 3 4 5 """ 6 Qt demo. 7 8 Fetch a URL's contents and display it in a Webkit window. 9 """ 10 11 import sys, urlparse 12 13 from PySide import QtGui, QtCore 14 from PySide.QtWebKit import QWebView 15 16 from twisted.internet import protocol 17 18 app = QtGui.QApplication(sys.argv) 19 from twisted.internet import qtreactor 20 qtreactor.install() 21 22 # The reactor must be installed before this import 23 from twisted.web import http 24 25 26 class TwistzillaClient(http.HTTPClient): 27 def __init__(self, web, urls): 28 self.urls = urls 29 self.web = web 30 31 def connectionMade(self): 32 self.sendCommand('GET', self.urls[2]) 33 self.sendHeader('Host', '%s:%d' % (self.urls[0], self.urls[1]) ) 34 self.sendHeader('User-Agent', 'Twistzilla') 35 self.endHeaders() 36 37 def handleResponse(self, data): 38 self.web.setHtml(data) 39 40 41 class TwistzillaWindow(QtGui.QMainWindow): 42 def __init__(self, *args): 43 QtGui.QMainWindow.__init__(self, *args) 44 45 self.centralwidget = QtGui.QWidget(self) 46 47 vbox = QtGui.QVBoxLayout(self.centralwidget) 48 49 hbox = QtGui.QHBoxLayout() 50 label = QtGui.QLabel("Address: ") 51 self.line = QtGui.QLineEdit("http://www.twistedmatrix.com/") 52 self.connect(self.line, QtCore.SIGNAL('returnPressed()'), self.fetchURL) 53 hbox.addWidget(label) 54 hbox.addWidget(self.line) 55 56 self.web = QWebView() 57 58 vbox.addLayout(hbox) 59 vbox.addWidget(self.web) 60 vbox.setMargin(2) 61 vbox.setSpacing(3) 62 63 self.setCentralWidget(self.centralwidget) 64 self.fetchURL() 65 66 def fetchURL(self): 67 u = urlparse.urlparse(str(self.line.text())) 68 69 pos = u[1].find(':') 70 71 if pos == -1: 72 host, port = u[1], 80 73 else: 74 host, port = u[1][:pos], int(u[1][pos+1:]) 75 76 if u[2] == '': 77 file = '/' 78 else: 79 file = u[2] 80 81 from twisted.internet import reactor 82 protocol.ClientCreator(reactor, TwistzillaClient, self.web, (host, port, file)).connectTCP(host, port) 83 84 def closeEvent(self, event=None): 85 from twisted.internet import reactor 86 reactor.stop() 87 88 89 def main(): 90 win = TwistzillaWindow() 91 win.show() 92 93 from twisted.internet import reactor 94 sys.exit(reactor.run()) 95 96 if __name__ == '__main__': 97 main() -
twisted/internet/qtreactor.py
diff --git twisted/internet/qtreactor.py twisted/internet/qtreactor.py index abbd3ba..a235b1f 100644
1 # -*- test-case-name: twisted.internet.test.test_qtreactor -*- 2 # Copyright (c) 2001-2009 Twisted Matrix Laboratories. 1 # Copyright (c) 2001-2011 Twisted Matrix Laboratories. 3 2 # See LICENSE for details. 4 3 4 5 """ 6 This module provides support for Twisted to be driven by the Qt mainloop. 7 8 In order to use this support, simply do the following:: 9 | app = QApplication(sys.argv) # your code to init Qt 10 | import qt4reactor 11 | qt4reactor.install() 12 13 alternatively: 14 15 | from twisted.application import reactors 16 | reactors.installReactor('qt4') 17 18 Then use twisted.internet APIs as usual. The other methods here are not 19 intended to be called directly. 20 21 If you don't instantiate a QApplication or QCoreApplication prior to 22 installing the reactor, a QCoreApplication will be constructed 23 by the reactor. QCoreApplication does not require a GUI so trial testing 24 can occur normally. 25 26 Twisted can be initialized after QApplication.exec_() with a call to 27 reactor.runReturn(). calling reactor.stop() will unhook twisted but 28 leave your Qt application running 29 """ 30 31 import sys 32 from zope.interface import implements 33 from twisted.internet.interfaces import IReactorFDSet 34 from twisted.python import log 35 from twisted.internet import posixbase 36 5 37 try: 6 # 'import qtreactor' would have imported this file instead of the 7 # top-level qtreactor. __import__ does the right thing 8 # (kids, don't repeat this at home) 9 install = __import__('qtreactor').install 38 from PySide.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication 39 from PySide.QtCore import QEventLoop 10 40 except ImportError: 11 from twisted.plugins.twisted_qtstub import errorMessage 12 raise ImportError(errorMessage) 13 else: 14 import warnings 15 warnings.warn("Please use qtreactor instead of twisted.internet.qtreactor", 16 category=DeprecationWarning) 17 18 __all__ = ['install'] 41 from PyQt4.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication 42 from PyQt4.QtCore import QEventLoop 43 44 45 46 class TwistedSocketNotifier(QObject): 47 """ 48 Connection between an fd event and reader/writer callbacks. 49 """ 50 51 def __init__(self, parent, reactor, watcher, socketType): 52 QObject.__init__(self, parent) 53 self.reactor = reactor 54 self.watcher = watcher 55 fd = watcher.fileno() 56 self.notifier = QSocketNotifier(fd, socketType, parent) 57 self.notifier.setEnabled(True) 58 if socketType == QSocketNotifier.Read: 59 self.fn = self.read 60 else: 61 self.fn = self.write 62 QObject.connect(self.notifier, SIGNAL("activated(int)"), self.fn) 63 64 65 def shutdown(self): 66 self.notifier.setEnabled(False) 67 self.disconnect(self.notifier, SIGNAL("activated(int)"), self.fn) 68 self.fn = self.watcher = None 69 self.notifier.deleteLater() 70 self.deleteLater() 71 72 73 def read(self, fd): 74 if not self.watcher: 75 return 76 w = self.watcher 77 # doRead can cause self.shutdown to be called so keep a reference to self.watcher 78 def _read(): 79 #Don't call me again, until the data has been read 80 self.notifier.setEnabled(False) 81 why = None 82 try: 83 why = w.doRead() 84 inRead = True 85 except: 86 inRead = False 87 log.err() 88 why = sys.exc_info()[1] 89 if why: 90 self.reactor._disconnectSelectable(w, why, inRead) 91 elif self.watcher: 92 self.notifier.setEnabled(True) # Re enable notification following sucessfull read 93 self.reactor._iterate(fromqt=True) 94 log.callWithLogger(w, _read) 95 96 97 def write(self, sock): 98 if not self.watcher: 99 return 100 w = self.watcher 101 def _write(): 102 why = None 103 self.notifier.setEnabled(False) 104 105 try: 106 why = w.doWrite() 107 except: 108 log.err() 109 why = sys.exc_info()[1] 110 if why: 111 self.reactor._disconnectSelectable(w, why, False) 112 elif self.watcher: 113 self.notifier.setEnabled(True) 114 self.reactor._iterate(fromqt=True) 115 log.callWithLogger(w, _write) 116 117 118 119 class QtReactor(posixbase.PosixReactorBase): 120 implements(IReactorFDSet) 121 122 123 def __init__(self): 124 self._reads = {} 125 self._writes = {} 126 self._notifiers = {} 127 self._timer = QTimer() 128 self._timer.setSingleShot(True) 129 QObject.connect(self._timer, SIGNAL("timeout()"), self.iterate) 130 131 if QCoreApplication.startingUp(): 132 # Application Object has not been started yet 133 self.qApp=QCoreApplication([]) 134 self._ownApp=True 135 else: 136 self.qApp = QCoreApplication.instance() 137 self._ownApp=False 138 self._blockApp = None 139 posixbase.PosixReactorBase.__init__(self) 140 141 142 def _add(self, xer, primary, type): 143 """ 144 Private method for adding a descriptor from the event loop. 145 146 It takes care of adding it if new or modifying it if already added 147 for another state (read -> read/write for example). 148 """ 149 if xer not in primary: 150 primary[xer] = TwistedSocketNotifier(None, self, xer, type) 151 152 153 def addReader(self, reader): 154 """ 155 Add a FileDescriptor for notification of data available to read. 156 """ 157 self._add(reader, self._reads, QSocketNotifier.Read) 158 159 160 def addWriter(self, writer): 161 """ 162 Add a FileDescriptor for notification of data available to write. 163 """ 164 self._add(writer, self._writes, QSocketNotifier.Write) 165 166 167 def _remove(self, xer, primary): 168 """ 169 Private method for removing a descriptor from the event loop. 170 171 It does the inverse job of _add, and also add a check in case of the fd 172 has gone away. 173 """ 174 if xer in primary: 175 notifier = primary.pop(xer) 176 notifier.shutdown() 177 178 179 def removeReader(self, reader): 180 """ 181 Remove a Selectable for notification of data available to read. 182 """ 183 self._remove(reader, self._reads) 184 185 186 def removeWriter(self, writer): 187 """ 188 Remove a Selectable for notification of data available to write. 189 """ 190 self._remove(writer, self._writes) 191 192 193 def removeAll(self): 194 """ 195 Remove all selectables, and return a list of them. 196 """ 197 rv = self._removeAll(self._reads, self._writes) 198 return rv 199 200 201 def getReaders(self): 202 return self._reads.keys() 203 204 205 def getWriters(self): 206 return self._writes.keys() 207 208 209 def callLater(self,howlong, *args, **kargs): 210 rval = super(QtReactor,self).callLater(howlong, *args, **kargs) 211 self.reactorInvocation() 212 return rval 213 214 215 def reactorInvocation(self): 216 self._timer.stop() 217 self._timer.setInterval(0) 218 self._timer.start() 219 220 221 def _iterate(self, delay=None, fromqt=False): 222 """ 223 See twisted.internet.interfaces.IReactorCore.iterate. 224 """ 225 self.runUntilCurrent() 226 self.doIteration(delay, fromqt) 227 228 229 iterate = _iterate 230 231 232 def doIteration(self, delay=None, fromqt=False): 233 """ 234 This method is called by a Qt timer or by network activity on 235 a file descriptor. 236 237 If called becuase of network activiy then control should not 238 be handed back to Qt as this would cause recursion. 239 """ 240 241 if not self.running and self._blockApp: 242 self._blockApp.quit() 243 244 self._timer.stop() 245 delay = max(delay, 1) 246 if not fromqt: 247 self.qApp.processEvents(QEventLoop.AllEvents, delay * 1000) 248 if self.timeout() is None: 249 timeout = 0.1 250 elif self.timeout() == 0: 251 timeout = 0 252 else: 253 timeout = self.timeout() 254 self._timer.setInterval(timeout * 1000) 255 self._timer.start() 256 257 258 def runReturn(self, installSignalHandlers=True): 259 self.startRunning(installSignalHandlers=installSignalHandlers) 260 self.reactorInvocation() 261 262 263 def stop(self): 264 super(QtReactor, self).stop() 265 self.iterate(0) 266 267 268 def run(self, installSignalHandlers=True): 269 if self._ownApp: 270 self._blockApp = self.qApp 271 else: 272 self._blockApp = QEventLoop() 273 self.runReturn() 274 self._blockApp.exec_() 275 276 277 278 def install(): 279 """ 280 Install the Qt reactor. 281 """ 282 p = QtReactor() 283 from twisted.internet.main import installReactor 284 installReactor(p) 285 286 __all__ = ["install"] 19 287 -
twisted/internet/test/reactormixins.py
diff --git twisted/internet/test/reactormixins.py twisted/internet/test/reactormixins.py index 1ba5dbc..0fa10cd 100644
51 51 "twisted.internet.kqreactor.KQueueReactor", 52 52 "twisted.internet.win32eventreactor.Win32Reactor", 53 53 "twisted.internet.iocpreactor.reactor.IOCPReactor", 54 "twisted.internet.cfreactor.CFReactor"] 54 "twisted.internet.cfreactor.CFReactor", 55 "twisted.internet.qtreactor.QtReactor"] 55 56 56 57 reactorFactory = None 57 58 originalHandler = None -
(a) twisted/plugins/twisted_qtstub.py vs. (b) /dev/null
diff --git twisted/plugins/twisted_qtstub.py twisted/plugins/twisted_qtstub.py deleted file mode 100644 index 1b9b08a..0000000
a b 1 # Copyright (c) 2006 Twisted Matrix Laboratories.2 # See LICENSE for details.3 4 """5 Backwards-compatibility plugin for the Qt reactor.6 7 This provides a Qt reactor plugin named C{qt} which emits a deprecation8 warning and a pointer to the separately distributed Qt reactor plugins.9 """10 11 import warnings12 13 from twisted.application.reactors import Reactor, NoSuchReactor14 15 wikiURL = 'http://twistedmatrix.com/trac/wiki/QTReactor'16 errorMessage = ('qtreactor is no longer a part of Twisted due to licensing '17 'issues. Please see %s for details.' % (wikiURL,))18 19 class QTStub(Reactor):20 """21 Reactor plugin which emits a deprecation warning on the successful22 installation of its reactor or a pointer to further information if an23 ImportError occurs while attempting to install it.24 """25 def __init__(self):26 super(QTStub, self).__init__(27 'qt', 'qtreactor', 'QT integration reactor')28 29 30 def install(self):31 """32 Install the Qt reactor with a deprecation warning or try to point33 the user to further information if it cannot be installed.34 """35 try:36 super(QTStub, self).install()37 except (ValueError, ImportError):38 raise NoSuchReactor(errorMessage)39 else:40 warnings.warn(41 "Please use -r qt3 to import qtreactor",42 category=DeprecationWarning)43 44 45 qt = QTStub() -
twisted/plugins/twisted_reactors.py
diff --git twisted/plugins/twisted_reactors.py twisted/plugins/twisted_reactors.py index 428e96c..8b58c80 100644
36 36 iocp = Reactor( 37 37 'iocp', 'twisted.internet.iocpreactor', 38 38 'Win32 IO Completion Ports-based reactor.') 39 qt = Reactor( 40 'qt', 'twisted.internet.qtreactor', 41 'Qt based reactor using PySide or PyQt')
