forked from alessandrod/twisted
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revert "Merge remove-qtreactor-2130"
This reverts parts of commit 5e1c1a6. Reintegrating the Qt Reactor
- Loading branch information
Showing
4 changed files
with
280 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Copyright (c) 2001-2004 Twisted Matrix Laboratories. | ||
# See LICENSE for details. | ||
|
||
|
||
"""Qt demo. | ||
Fetch a URL's contents. | ||
""" | ||
|
||
import sys, urlparse | ||
from qt import * | ||
|
||
from twisted.internet import qtreactor, protocol | ||
app = QApplication([]) | ||
qtreactor.install(app) | ||
|
||
from twisted.web import http | ||
|
||
|
||
class TwistzillaClient(http.HTTPClient): | ||
def __init__(self, edit, urls): | ||
self.urls = urls | ||
self.edit = edit | ||
|
||
def connectionMade(self): | ||
print 'Connected.' | ||
|
||
self.sendCommand('GET', self.urls[2]) | ||
self.sendHeader('Host', '%s:%d' % (self.urls[0], self.urls[1]) ) | ||
self.sendHeader('User-Agent', 'Twistzilla') | ||
self.endHeaders() | ||
|
||
def handleResponse(self, data): | ||
print 'Got response.' | ||
self.edit.setText(data) | ||
|
||
|
||
|
||
class TwistzillaWindow(QMainWindow): | ||
def __init__(self, *args): | ||
QMainWindow.__init__(self, *args) | ||
|
||
self.setCaption("Twistzilla") | ||
|
||
vbox = QVBox(self) | ||
vbox.setMargin(2) | ||
vbox.setSpacing(3) | ||
|
||
hbox = QHBox(vbox) | ||
label = QLabel("Address: ", hbox) | ||
|
||
self.line = QLineEdit("http://www.twistedmatrix.com/", hbox) | ||
self.connect(self.line, SIGNAL('returnPressed()'), self.fetchURL) | ||
|
||
self.edit = QMultiLineEdit(vbox) | ||
self.edit.setEdited(0) | ||
|
||
self.setCentralWidget(vbox) | ||
|
||
def fetchURL(self): | ||
u = urlparse.urlparse(str(self.line.text())) | ||
|
||
pos = u[1].find(':') | ||
|
||
if pos == -1: | ||
host, port = u[1], 80 | ||
else: | ||
host, port = u[1][:pos], int(u[1][pos+1:]) | ||
|
||
if u[2] == '': | ||
file = '/' | ||
else: | ||
file = u[2] | ||
|
||
print 'Connecting to.' | ||
from twisted.internet import reactor | ||
protocol.ClientCreator(reactor, TwistzillaClient, self.edit, (host, port, file)).connectTCP(host, port) | ||
|
||
|
||
def main(): | ||
"""Run application.""" | ||
# hook up Qt application to Twisted | ||
from twisted.internet import reactor | ||
|
||
win = TwistzillaWindow() | ||
win.show() | ||
|
||
# make sure stopping twisted event also shuts down QT | ||
reactor.addSystemEventTrigger('after', 'shutdown', app.quit ) | ||
|
||
# shutdown twisted when window is closed | ||
app.connect(app, SIGNAL("lastWindowClosed()"), reactor.stop) | ||
|
||
reactor.run() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,184 @@ | ||
# -*- test-case-name: twisted.internet.test.test_qtreactor -*- | ||
# Copyright (c) 2001-2009 Twisted Matrix Laboratories. | ||
# Copyright (c) 2001-2004 Twisted Matrix Laboratories. | ||
# See LICENSE for details. | ||
|
||
try: | ||
# 'import qtreactor' would have imported this file instead of the | ||
# top-level qtreactor. __import__ does the right thing | ||
# (kids, don't repeat this at home) | ||
install = __import__('qtreactor').install | ||
except ImportError: | ||
from twisted.plugins.twisted_qtstub import errorMessage | ||
raise ImportError(errorMessage) | ||
else: | ||
import warnings | ||
warnings.warn("Please use qtreactor instead of twisted.internet.qtreactor", | ||
category=DeprecationWarning) | ||
|
||
""" | ||
This module provides support for Twisted to interact with the PyQt mainloop. | ||
In order to use this support, simply do the following:: | ||
| from twisted.internet import qtreactor | ||
| qtreactor.install() | ||
Then use twisted.internet APIs as usual. The other methods here are not | ||
intended to be called directly. | ||
API Stability: stable | ||
Maintainer: U{Itamar Shtull-Trauring<mailto:twisted@itamarst.org>} | ||
""" | ||
|
||
__all__ = ['install'] | ||
|
||
# System Imports | ||
from qt import QSocketNotifier, QObject, SIGNAL, QTimer, QApplication | ||
import sys | ||
|
||
# Twisted Imports | ||
from twisted.python import log, failure | ||
from twisted.internet import posixbase | ||
|
||
reads = {} | ||
writes = {} | ||
hasReader = reads.has_key | ||
hasWriter = writes.has_key | ||
|
||
|
||
class TwistedSocketNotifier(QSocketNotifier): | ||
'''Connection between an fd event and reader/writer callbacks''' | ||
|
||
def __init__(self, reactor, watcher, type): | ||
QSocketNotifier.__init__(self, watcher.fileno(), type) | ||
self.reactor = reactor | ||
self.watcher = watcher | ||
self.fn = None | ||
if type == QSocketNotifier.Read: | ||
self.fn = self.read | ||
elif type == QSocketNotifier.Write: | ||
self.fn = self.write | ||
QObject.connect(self, SIGNAL("activated(int)"), self.fn) | ||
|
||
def shutdown(self): | ||
QObject.disconnect(self, SIGNAL("activated(int)"), self.fn) | ||
self.setEnabled(0) | ||
self.fn = self.watcher = None | ||
|
||
def read(self, sock): | ||
why = None | ||
w = self.watcher | ||
try: | ||
why = w.doRead() | ||
except: | ||
why = sys.exc_info()[1] | ||
log.msg('Error in %s.doRead()' % w) | ||
log.deferr() | ||
if why: | ||
self.reactor._disconnectSelectable(w, why, True) | ||
self.reactor.simulate() | ||
|
||
def write(self, sock): | ||
why = None | ||
w = self.watcher | ||
self.setEnabled(0) | ||
try: | ||
why = w.doWrite() | ||
except: | ||
why = sys.exc_value | ||
log.msg('Error in %s.doWrite()' % w) | ||
log.deferr() | ||
if why: | ||
self.reactor.removeReader(w) | ||
self.reactor.removeWriter(w) | ||
try: | ||
w.connectionLost(failure.Failure(why)) | ||
except: | ||
log.deferr() | ||
elif self.watcher: | ||
self.setEnabled(1) | ||
self.reactor.simulate() | ||
|
||
|
||
class QTReactor(posixbase.PosixReactorBase): | ||
"""Qt based reactor.""" | ||
|
||
# Reference to a DelayedCall for self.crash() when the reactor is | ||
# entered through .iterate() | ||
_crashCall = None | ||
|
||
_timer = None | ||
|
||
def __init__(self, app=None): | ||
self.running = 0 | ||
posixbase.PosixReactorBase.__init__(self) | ||
if app is None: | ||
app = QApplication([]) | ||
self.qApp = app | ||
self.addSystemEventTrigger('after', 'shutdown', self.cleanup) | ||
|
||
def addReader(self, reader): | ||
if not hasReader(reader): | ||
reads[reader] = TwistedSocketNotifier(self, reader, QSocketNotifier.Read) | ||
|
||
def addWriter(self, writer): | ||
if not hasWriter(writer): | ||
writes[writer] = TwistedSocketNotifier(self, writer, QSocketNotifier.Write) | ||
|
||
def removeReader(self, reader): | ||
if hasReader(reader): | ||
reads[reader].shutdown() | ||
del reads[reader] | ||
|
||
def removeWriter(self, writer): | ||
if hasWriter(writer): | ||
writes[writer].shutdown() | ||
del writes[writer] | ||
|
||
def removeAll(self): | ||
return self._removeAll(reads, writes) | ||
|
||
def simulate(self): | ||
if self._timer is not None: | ||
self._timer.stop() | ||
self._timer = None | ||
|
||
if not self.running: | ||
self.running = 1 | ||
self.qApp.exit_loop() | ||
return | ||
self.runUntilCurrent() | ||
|
||
if self._crashCall is not None: | ||
self._crashCall.reset(0) | ||
|
||
# gah | ||
timeout = self.timeout() | ||
if timeout is None: | ||
timeout = 1.0 | ||
timeout = min(timeout, 0.1) * 1010 | ||
|
||
if self._timer is None: | ||
self._timer = QTimer() | ||
QObject.connect(self._timer, SIGNAL("timeout()"), self.simulate) | ||
self._timer.start(timeout, 1) | ||
|
||
def cleanup(self): | ||
if self._timer is not None: | ||
self._timer.stop() | ||
self._timer = None | ||
|
||
def iterate(self, delay=0.0): | ||
log.msg(channel='system', event='iteration', reactor=self) | ||
self._crashCall = self.callLater(delay, self.crash) | ||
self.run() | ||
|
||
def run(self, installSignalHandlers=1): | ||
self.running = 1 | ||
self.startRunning(installSignalHandlers=installSignalHandlers) | ||
self.simulate() | ||
self.qApp.enter_loop() | ||
|
||
def crash(self): | ||
if self._crashCall is not None: | ||
if self._crashCall.active(): | ||
self._crashCall.cancel() | ||
self._crashCall = None | ||
self.running = 0 | ||
|
||
|
||
def install(app=None): | ||
"""Configure the twisted mainloop to be run inside the qt mainloop. | ||
""" | ||
from twisted.internet import main | ||
|
||
reactor = QTReactor(app=app) | ||
main.installReactor(reactor) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters