qt4reactor-1.0/0000755000175000017500000000000011657021400014574 5ustar nessitanessita00000000000000qt4reactor-1.0/twisted/0000755000175000017500000000000011657021400016257 5ustar nessitanessita00000000000000qt4reactor-1.0/twisted/plugins/0000755000175000017500000000000011657021400017740 5ustar nessitanessita00000000000000qt4reactor-1.0/twisted/plugins/qt4.py0000644000175000017500000000040711657016240021031 0ustar nessitanessita00000000000000# Copyright (c) 2001-2010 Twisted Matrix Laboratories. # see LICENSE for details from twisted.application.reactors import Reactor qt4 = Reactor('qt4', 'qt4reactor', 'Qt4 integration reactor') qt4bad = Reactor('qt4bad', 'qt4reactor_bad', 'Qt4 broken reactor') qt4reactor-1.0/gtrial.py0000755000175000017500000000172511657016240016446 0ustar nessitanessita00000000000000import sys from PyQt4 import QtGui, QtScript from PyQt4.QtCore import QTimer, SIGNAL, QEventLoop import qt4reactor app = QtGui.QApplication(sys.argv) qt4reactor.install() from twisted.internet import reactor, task class doNothing(object): def __init__(self): self.count = 0 self.running=False def buttonClick(self): if not self.running: from twisted.scripts import trial trial.run() def run(): t=doNothing() engine = QtScript.QScriptEngine() button = QtGui.QPushButton() scriptButton = engine.newQObject(button) engine.globalObject().setProperty("button", scriptButton) app.connect(button, SIGNAL("clicked()"), t.buttonClick) engine.evaluate("button.text = 'Do Twisted Gui Trial'") engine.evaluate("button.styleSheet = 'font-style: italic'") engine.evaluate("button.show()") app.exec_() print 'fell off the bottom?...' qt4reactor-1.0/qt4reactor.py0000644000175000017500000002430411657016240017247 0ustar nessitanessita00000000000000# Copyright (c) 2001-2011 Twisted Matrix Laboratories. # See LICENSE for details. """ This module provides support for Twisted to be driven by the Qt mainloop. In order to use this support, simply do the following:: | app = QApplication(sys.argv) # your code to init Qt | import qt4reactor | qt4reactor.install() alternatively: | from twisted.application import reactors | reactors.installReactor('qt4') Then use twisted.internet APIs as usual. The other methods here are not intended to be called directly. If you don't instantiate a QApplication or QCoreApplication prior to installing the reactor, a QCoreApplication will be constructed by the reactor. QCoreApplication does not require a GUI so trial testing can occur normally. Twisted can be initialized after QApplication.exec_() with a call to reactor.runReturn(). calling reactor.stop() will unhook twisted but leave your Qt application running API Stability: stable Maintainer: U{Glenn H Tarbox, PhD} Previous maintainer: U{Itamar Shtull-Trauring} Original port to QT4: U{Gabe Rudy} Subsequent port by therve """ import sys import time from zope.interface import implements from twisted.internet.interfaces import IReactorFDSet from twisted.python import log, runtime from twisted.internet import posixbase from twisted.python.runtime import platformType, platform try: from PyQt4.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication from PyQt4.QtCore import QEventLoop except ImportError: from PySide.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication from PySide.QtCore import QEventLoop class TwistedSocketNotifier(QObject): """ Connection between an fd event and reader/writer callbacks. """ def __init__(self, parent, reactor, watcher, socketType): QObject.__init__(self, parent) self.reactor = reactor self.watcher = watcher fd = watcher.fileno() self.notifier = QSocketNotifier(fd, socketType, parent) self.notifier.setEnabled(True) if socketType == QSocketNotifier.Read: self.fn = self.read else: self.fn = self.write QObject.connect(self.notifier, SIGNAL("activated(int)"), self.fn) def shutdown(self): self.notifier.setEnabled(False) self.disconnect(self.notifier, SIGNAL("activated(int)"), self.fn) self.fn = self.watcher = None self.notifier.deleteLater() self.deleteLater() def read(self, fd): if not self.watcher: return w = self.watcher # doRead can cause self.shutdown to be called so keep a reference to self.watcher def _read(): #Don't call me again, until the data has been read self.notifier.setEnabled(False) why = None try: why = w.doRead() inRead = True except: inRead = False log.err() why = sys.exc_info()[1] if why: self.reactor._disconnectSelectable(w, why, inRead) elif self.watcher: self.notifier.setEnabled(True) # Re enable notification following sucessfull read self.reactor._iterate(fromqt=True) log.callWithLogger(w, _read) def write(self, sock): if not self.watcher: return w = self.watcher def _write(): why = None self.notifier.setEnabled(False) try: why = w.doWrite() except: log.err() why = sys.exc_info()[1] if why: self.reactor._disconnectSelectable(w, why, False) elif self.watcher: self.notifier.setEnabled(True) self.reactor._iterate(fromqt=True) log.callWithLogger(w, _write) class QtReactor(posixbase.PosixReactorBase): implements(IReactorFDSet) def __init__(self): self._reads = {} self._writes = {} self._notifiers = {} self._timer = QTimer() self._timer.setSingleShot(True) QObject.connect(self._timer, SIGNAL("timeout()"), self.iterate) if QCoreApplication.instance() is None: # Application Object has not been started yet self.qApp=QCoreApplication([]) self._ownApp=True else: self.qApp = QCoreApplication.instance() self._ownApp=False self._blockApp = None posixbase.PosixReactorBase.__init__(self) def _add(self, xer, primary, type): """ Private method for adding a descriptor from the event loop. It takes care of adding it if new or modifying it if already added for another state (read -> read/write for example). """ if xer not in primary: primary[xer] = TwistedSocketNotifier(None, self, xer, type) def addReader(self, reader): """ Add a FileDescriptor for notification of data available to read. """ self._add(reader, self._reads, QSocketNotifier.Read) def addWriter(self, writer): """ Add a FileDescriptor for notification of data available to write. """ self._add(writer, self._writes, QSocketNotifier.Write) def _remove(self, xer, primary): """ Private method for removing a descriptor from the event loop. It does the inverse job of _add, and also add a check in case of the fd has gone away. """ if xer in primary: notifier = primary.pop(xer) notifier.shutdown() def removeReader(self, reader): """ Remove a Selectable for notification of data available to read. """ self._remove(reader, self._reads) def removeWriter(self, writer): """ Remove a Selectable for notification of data available to write. """ self._remove(writer, self._writes) def removeAll(self): """ Remove all selectables, and return a list of them. """ rv = self._removeAll(self._reads, self._writes) return rv def getReaders(self): return self._reads.keys() def getWriters(self): return self._writes.keys() def callLater(self,howlong, *args, **kargs): rval = super(QtReactor,self).callLater(howlong, *args, **kargs) self.reactorInvocation() return rval def reactorInvocation(self): self._timer.stop() self._timer.setInterval(0) self._timer.start() def _iterate(self, delay=None, fromqt=False): """See twisted.internet.interfaces.IReactorCore.iterate. """ self.runUntilCurrent() self.doIteration(delay, fromqt) iterate = _iterate def doIteration(self, delay=None, fromqt=False): 'This method is called by a Qt timer or by network activity on a file descriptor' if not self.running and self._blockApp: self._blockApp.quit() self._timer.stop() delay = max(delay, 1) if not fromqt: self.qApp.processEvents(QEventLoop.AllEvents, delay * 1000) if self.timeout() is None: timeout = 0.1 elif self.timeout() == 0: timeout = 0 else: timeout = self.timeout() self._timer.setInterval(timeout * 1000) self._timer.start() def runReturn(self, installSignalHandlers=True): self.startRunning(installSignalHandlers=installSignalHandlers) self.reactorInvocation() def run(self, installSignalHandlers=True): if self._ownApp: self._blockApp = self.qApp else: self._blockApp = QEventLoop() self.runReturn() self._blockApp.exec_() class QtEventReactor(QtReactor): def __init__(self, *args, **kwargs): self._events = {} super(QtEventReactor, self).__init__() def addEvent(self, event, fd, action): """ Add a new win32 event to the event loop. """ self._events[event] = (fd, action) def removeEvent(self, event): """ Remove an event. """ if event in self._events: del self._events[event] def doEvents(self): handles = self._events.keys() if len(handles) > 0: val = None while val != WAIT_TIMEOUT: val = MsgWaitForMultipleObjects(handles, 0, 0, QS_ALLINPUT | QS_ALLEVENTS) if val >= WAIT_OBJECT_0 and val < WAIT_OBJECT_0 + len(handles): event_id = handles[val - WAIT_OBJECT_0] if event_id in self._events: fd, action = self._events[event_id] log.callWithLogger(fd, self._runAction, action, fd) elif val == WAIT_TIMEOUT: pass else: #print 'Got an unexpected return of %r' % val return def _runAction(self, action, fd): try: closed = getattr(fd, action)() except: closed = sys.exc_info()[1] log.deferr() if closed: self._disconnectSelectable(fd, closed, action == 'doRead') def timeout(self): t = super(QtEventReactor, self).timeout() return min(t, 0.01) def iterate(self, delay=None): """See twisted.internet.interfaces.IReactorCore.iterate. """ self.runUntilCurrent() self.doEvents() self.doIteration(delay) def posixinstall(): """ Install the Qt reactor. """ p = QtReactor() from twisted.internet.main import installReactor installReactor(p) def win32install(): """ Install the Qt reactor. """ p = QtEventReactor() from twisted.internet.main import installReactor installReactor(p) if runtime.platform.getType() == 'win32': from win32event import CreateEvent, MsgWaitForMultipleObjects from win32event import WAIT_OBJECT_0, WAIT_TIMEOUT, QS_ALLINPUT, QS_ALLEVENTS install = win32install else: install = posixinstall __all__ = ["install"] qt4reactor-1.0/setup.py0000755000175000017500000000117411657020760016324 0ustar nessitanessita00000000000000#!/usr/bin/env python # # See LICENSE file for copyright and license details. """Setup.py: build, distribute, clean.""" import os import sys from distutils import log from distutils.core import setup from glob import glob setup( name='qt4reactor', version='1.0', license='MIT', author='Glenn H. Tarbox', author_email='glenn@tarbox.org', description='Twisted Qt4 Integration', long_description='Provides support for Twisted to be driven by the ' \ 'Qt mainloop.', url='https://github.com/ghtdak/qtreactor', scripts=glob("./bin/*"), py_modules=['qt4reactor', 'gtrial'], ) qt4reactor-1.0/README0000644000175000017500000000336511657016240015471 0ustar nessitanessita00000000000000Unpack this directory into your PYTHONPATH. test with: trial --reactor=qt4 twisted (or twisted.test or twisted.test.test_internet) = Contributors = Many thanks to Darren Dale who provided the patch to fix the reactor for Qt4.4 = Using the Qt4Reactor = In your own code, BEFORE you import the reactor... app = QApplication(sys.argv) import qt4reactor qt4reactor.install() = Gui = There is a way to run trial using a gui... in bin, there is a routine gtrial. Put that in the same directory as trial and it pops up a trivial gui... hit the buton and it all runs the same... don't use the --reactor option when calling gtrial... but all the other options appear to work. This was just to make sure there wasn't anything strange with guis which there doesn't appear to be If you're writing a conventional Qt application and just want twisted as an addon, you can get that by calling reactor.runReturn() instead of run(). This call needs to occur after your installation of of the reactor and after QApplication.exec_() (or QCoreApplication.exec_() whichever you are using. reactor.run() will also work as expected in a typical twisted application more docs in qt4reactor.py Note that if a QApplication or QCoreApplication instance isn't constructed prior to calling reactor run, an internally owned QCoreApplication is created and destroyed. This won't work if you call runReturn instead of run unless you take responsibility for wacking QCoreApplication yourself... However, most users want this reactor to do gui stuff so this shouldn't be an issue. Performance impact of Qt has been reduced by minimizing use of signaling which is expensive. 186s for qt4reactor vs 180s for select for entire twisted trial suite. -glenn -- Glenn H. Tarbox, PhD glenn@tarbox.org qt4reactor-1.0/bin/0000755000175000017500000000000011657021400015344 5ustar nessitanessita00000000000000qt4reactor-1.0/bin/gtrial0000755000175000017500000000130011657016240016554 0ustar nessitanessita00000000000000#!/usr/bin/python # Twisted, the Framework of Your Internet # Copyright (c) 2001-2004 Twisted Matrix Laboratories. # See LICENSE for details. ### Twisted Preamble # This makes sure that users don't have to set up their environment # specially in order to run these programs from bin/. import sys, os, string if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) if hasattr(os, "getuid") and os.getuid() != 0: sys.path.insert(0, os.curdir) ### end of preamble # begin chdir armor sys.path[:] = map(os.path.abspath, sys.path) # end chdir armor from gtrial import run run() qt4reactor-1.0/PKG-INFO0000644000175000017500000000044511657021400015674 0ustar nessitanessita00000000000000Metadata-Version: 1.0 Name: qt4reactor Version: 1.0 Summary: Twisted Qt4 Integration Home-page: https://github.com/ghtdak/qtreactor Author: Glenn H. Tarbox Author-email: glenn@tarbox.org License: MIT Description: Provides support for Twisted to be driven by the Qt mainloop. Platform: UNKNOWN qt4reactor-1.0/LICENSE0000644000175000017500000000317011657016240015610 0ustar nessitanessita00000000000000Copyright (c) 2001-2010 Allen Short Andy Gayton Andrew Bennetts Antoine Pitrou Apple Computer, Inc. Benjamin Bruheim Bob Ippolito Canonical Limited Christopher Armstrong David Reid Donovan Preston Eric Mangold Eyal Lotem Itamar Shtull-Trauring James Knight Jason A. Mobarak Jean-Paul Calderone Jessica McKellar Jonathan Jacobs Jonathan Lange Jonathan D. Simms Jürgen Hermann Kevin Horn Kevin Turner Mary Gardiner Matthew Lefkowitz Massachusetts Institute of Technology Moshe Zadka Paul Swartz Pavel Pergamenshchik Ralph Meijer Sean Riley Software Freedom Conservancy Travis B. Hartwell Thijs Triemstra Thomas Herve Timothy Allen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. qt4reactor-1.0/ghtTests/0000755000175000017500000000000011657021400016401 5ustar nessitanessita00000000000000qt4reactor-1.0/ghtTests/ircClient.py0000644000175000017500000000734311657016240020704 0ustar nessitanessita00000000000000from PySide.QtCore import * from PySide.QtGui import * import sys, qt4reactor app = QApplication(sys.argv) qt4reactor.install() from twisted.words.protocols import irc from twisted.internet import reactor, protocol from twisted.python import log import time, sys class IRCCore(irc.IRCClient): nickname = 'dosdsdssd' def connectionMade(self): self.nickname = self.factory.window.nickName.text().encode('ascii') self.factory.window.protocol = self irc.IRCClient.connectionMade(self) self.log('connected!!') def connectionLost(self, reason): self.log('disconnected... :( %s'%reason) def signedOn(self): chanName = self.factory.window.channelName.text().encode('ascii') self.join(chanName) def joined(self, channel): self.log('joined %s'%channel) def privmsg(self, user, channel, msg): self.log('%s %s %s'%(user, channel, msg)) def action(self, user, channel, msg): self.log('action: %s %s %s'%(user, channel, msg)) def log(self, str): self.factory.window.view.addItem(str) class IRCCoreFactory(protocol.ClientFactory): protocol = IRCCore def __init__(self, window): self.window = window def clientConnectionLost(self, connector, reason): # reconnect to server if lose connection connector.connect() def clientConnectionFailed(self, connector, reason): print('connection failed! :(', reason) reactor.stop() class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() connectLayout = QHBoxLayout() connectLayout.addWidget(QLabel('Server:')) self.serverName = QLineEdit('irc.freenode.org') connectLayout.addWidget(self.serverName) connectLayout.addWidget(QLabel('Channel:')) self.channelName = QLineEdit('#pangaea') connectLayout.addWidget(self.channelName) connectLayout.addWidget(QLabel('Nick:')) self.nickName = QLineEdit('ceruleanwave9832') connectLayout.addWidget(self.nickName) self.connectButton = QPushButton('Connect!') connectLayout.addWidget(self.connectButton) self.connectButton.clicked.connect(self.connectIRC) self.view = QListWidget() self.entry = QLineEdit() self.entry.returnPressed.connect(self.sendMessage) irc = QWidget(self) vbox = QVBoxLayout() vbox.addLayout(connectLayout) vbox.addWidget(self.view) vbox.addWidget(self.entry) irc.setLayout(vbox) self.setCentralWidget(irc) self.setWindowTitle('IRC') self.setUnifiedTitleAndToolBarOnMac(True) self.showMaximized() self.protocol = None def connectIRC(self): self.connectButton.setDisabled(True) self.channelName.setDisabled(True) self.nickName.setDisabled(True) self.serverName.setDisabled(True) ircCoreFactory = IRCCoreFactory(self) serverName = self.serverName.text().encode('ascii') reactor.connectTCP(serverName, 6667, ircCoreFactory) #reactor.runReturn() #app.exit() #app.exit() reactor.run() def sendMessage(self): if self.protocol: chanName = self.channelName.text().encode('ascii') message = self.entry.text().encode('ascii') self.protocol.msg(chanName, message) self.view.addItem('%s <%s> %s'%(chanName, self.protocol.nickname, message)) else: self.view.addItem('Not connected.') self.entry.setText('') def closeEvent(self, event): print('Attempting to close the main window!') reactor.stop() event.accept() if __name__ == '__main__': mainWin = MainWindow() sys.exit(app.exec_()) qt4reactor-1.0/ghtTests/buttonStress.py0000755000175000017500000000264511657016240021512 0ustar nessitanessita00000000000000import sys from PySide import QtGui, QtScript from PySide.QtCore import QTimer, SIGNAL, QObject import qt4reactor app = QtGui.QApplication(sys.argv) qt4reactor.install() from twisted.internet import reactor, task from twisted.python import log log.startLogging(sys.stdout) class doNothing(QObject): def __init__(self): self.count = 0 self.looping=False task.LoopingCall(self.printStat).start(1.0) QObject.__init__(self) def doSomething(self): if not self.looping: return self.count += 1 reactor.callLater(0.003,self.doSomething) def buttonClick(self): if self.looping: self.looping=False log.msg('looping stopped....') else: self.looping=True self.doSomething() log.msg('looping started....') def printStat(self): log.msg(' c: ' + str(self.count) + ' st: ' + str(reactor._doSomethingCount)) t=doNothing() engine = QtScript.QScriptEngine() button = QtGui.QPushButton() scriptButton = engine.newQObject(button) engine.globalObject().setProperty("button", scriptButton) app.connect(button, SIGNAL("clicked()"), t.buttonClick) engine.evaluate("button.text = 'Hello World!'") engine.evaluate("button.styleSheet = 'font-style: italic'") engine.evaluate("button.show()") reactor.runReturn() app.exec_() log.msg('fell off the bottom?...') qt4reactor-1.0/ghtTests/fakeAppButtonStress.py0000755000175000017500000000231711657016240022736 0ustar nessitanessita00000000000000import sys from PySide import QtGui, QtScript from PySide.QtCore import QTimer, SIGNAL, QEventLoop import qt4reactor app = QtGui.QApplication(sys.argv) qt4reactor.install() from twisted.internet import reactor, task class doNothing(object): def __init__(self): self.count = 0 self.running=False task.LoopingCall(self.printStat).start(1.0) def buttonClick(self): if self.running: self.running=False print 'CLICK: calling reactor stop...' reactor.stop() print 'reactor stop called....' else: self.running=True print 'CLICK: entering run' reactor.run() print 'reactor run returned...' def printStat(self): print 'tick...' t=doNothing() engine = QtScript.QScriptEngine() button = QtGui.QPushButton() scriptButton = engine.newQObject(button) engine.globalObject().setProperty("button", scriptButton) app.connect(button, SIGNAL("clicked()"), t.buttonClick) engine.evaluate("button.text = 'Hello World!'") engine.evaluate("button.styleSheet = 'font-style: italic'") engine.evaluate("button.show()") app.exec_() print 'fell off the bottom?...' qt4reactor-1.0/ghtTests/testIterate.py0000755000175000017500000000152711657016240021266 0ustar nessitanessita00000000000000import sys from PySide import QtGui, QtScript from PySide.QtCore import QTimer, SIGNAL import qt4reactor app = QtGui.QApplication(sys.argv) qt4reactor.install() from twisted.internet import reactor, task from twisted.python import log log.startLogging(sys.stdout) def testReactor(): print 'tick...' def buttonClick(): print 'click...' reactor.iterate(5.0) print 'click return' engine = QtScript.QScriptEngine() button = QtGui.QPushButton() scriptButton = engine.newQObject(button) engine.globalObject().setProperty("button", scriptButton) app.connect(button, SIGNAL("clicked()"), buttonClick) engine.evaluate("button.text = 'Hello World!'") engine.evaluate("button.styleSheet = 'font-style: italic'") engine.evaluate("button.show()") task.LoopingCall(testReactor).start(1.0) reactor.run() log.msg('fell off the bottom?...') qt4reactor-1.0/ghtTests/trivialscript.py0000755000175000017500000000077611657016240021675 0ustar nessitanessita00000000000000import sys from twisted.application import reactors import qt4reactor qt4reactor.install() #reactors.installReactor('qt4') from twisted.internet import reactor, task from twisted.python import log log.startLogging(sys.stdout) def testReactor(): print 'tick...' def doit(): task.LoopingCall(testReactor).start(1.0) reactor.callLater(15.0,reactor.stop) reactor.callWhenRunning(doit) log.msg('calling reactor.run()') reactor.run() log.msg('fell off the bottom?...') #sys.exit(app.exec_())