failed twisted integration....just stick w/oyoyo for now
This commit is contained in:
parent
666c2b88c0
commit
5de02c65b5
33 changed files with 984 additions and 181 deletions
1
TODO
1
TODO
|
@ -1,4 +1,5 @@
|
||||||
Bugs:
|
Bugs:
|
||||||
|
* memos need to test for max time
|
||||||
* color swatch text doesnt disappear
|
* color swatch text doesnt disappear
|
||||||
* X and _ buttons move around all crazy like
|
* X and _ buttons move around all crazy like
|
||||||
|
|
||||||
|
|
BIN
convo.pyc
BIN
convo.pyc
Binary file not shown.
BIN
dataobjs.pyc
BIN
dataobjs.pyc
Binary file not shown.
BIN
generic.pyc
BIN
generic.pyc
Binary file not shown.
295
irc.py
295
irc.py
|
@ -1,10 +1,9 @@
|
||||||
from PyQt4 import QtGui, QtCore
|
from PyQt4 import QtGui, QtCore
|
||||||
from oyoyo.client import IRCClient
|
from twisted.internet.protocol import ClientFactory
|
||||||
from oyoyo.cmdhandler import DefaultCommandHandler
|
from twisted.words.protocols.irc import IRCClient
|
||||||
from oyoyo import helpers
|
from twisted.internet import reactor
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
import socket
|
|
||||||
|
|
||||||
from dataobjs import Mood, PesterProfile
|
from dataobjs import Mood, PesterProfile
|
||||||
from generic import PesterList
|
from generic import PesterList
|
||||||
|
@ -18,31 +17,32 @@ class PesterIRC(QtCore.QObject):
|
||||||
self.config = config
|
self.config = config
|
||||||
def IRCConnect(self):
|
def IRCConnect(self):
|
||||||
server = self.config.server()
|
server = self.config.server()
|
||||||
port = self.config.port()
|
port = int(self.config.port())
|
||||||
self.cli = IRCClient(PesterHandler, host=server, port=int(port), nick=self.mainwindow.profile().handle, real_name='pcc30', blocking=True)
|
nick = self.mainwindow.profile()
|
||||||
self.cli.command_handler.parent = self
|
self.cli = PesterIRCFactory(nick, self)
|
||||||
self.cli.command_handler.mainwindow = self.mainwindow
|
logging.info("---> Logging on...")
|
||||||
self.conn = self.cli.connect()
|
reactor.connectTCP(server, port, self.cli)
|
||||||
self.brokenConnection = False
|
reactor.run()
|
||||||
def closeConnection(self):
|
def closeConnection(self):
|
||||||
self.cli.close()
|
#logging.info("---> Logging on...")
|
||||||
def setConnectionBroken(self, broken=True):
|
# self.cli.close()
|
||||||
self.brokenConnection = True
|
pass
|
||||||
@QtCore.pyqtSlot(PesterProfile)
|
@QtCore.pyqtSlot(PesterProfile)
|
||||||
def getMood(self, *chums):
|
def getMood(self, *chums):
|
||||||
self.cli.command_handler.getMood(*chums)
|
self.cli.getMood(*chums)
|
||||||
@QtCore.pyqtSlot(PesterList)
|
@QtCore.pyqtSlot(PesterList)
|
||||||
def getMoods(self, chums):
|
def getMoods(self, chums):
|
||||||
self.cli.command_handler.getMood(*chums)
|
self.cli.getMood(*chums)
|
||||||
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
|
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
|
||||||
def sendMessage(self, text, handle):
|
def sendMessage(self, text, handle):
|
||||||
h = unicode(handle)
|
h = unicode(handle)
|
||||||
textl = [unicode(text)]
|
textl = [unicode(text)]
|
||||||
|
CMD_LENGTH = 450
|
||||||
def splittext(l):
|
def splittext(l):
|
||||||
if len(l[0]) > 400:
|
if len(l[0]) > CMD_LENGTH:
|
||||||
space = l[0].rfind(" ", 0,400)
|
space = l[0].rfind(" ", 0,CMD_LENGTH)
|
||||||
if space == -1:
|
if space == -1:
|
||||||
space = 400
|
space = CMD_LENGTH
|
||||||
a = l[0][0:space]
|
a = l[0][0:space]
|
||||||
b = l[0][space:]
|
b = l[0][space:]
|
||||||
if len(b) > 0:
|
if len(b) > 0:
|
||||||
|
@ -52,117 +52,72 @@ class PesterIRC(QtCore.QObject):
|
||||||
else:
|
else:
|
||||||
return l
|
return l
|
||||||
textl = splittext(textl)
|
textl = splittext(textl)
|
||||||
try:
|
for t in textl:
|
||||||
for t in textl:
|
self.cli.msg(h, t)
|
||||||
helpers.msg(self.cli, h, t)
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot(QtCore.QString, bool)
|
@QtCore.pyqtSlot(QtCore.QString, bool)
|
||||||
def startConvo(self, handle, initiated):
|
def startConvo(self, handle, initiated):
|
||||||
h = unicode(handle)
|
h = unicode(handle)
|
||||||
try:
|
if initiated:
|
||||||
if initiated:
|
self.cli.msg(h, "PESTERCHUM:BEGIN")
|
||||||
helpers.msg(self.cli, h, "PESTERCHUM:BEGIN")
|
self.cli.msg(h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
|
||||||
helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot(QtCore.QString)
|
@QtCore.pyqtSlot(QtCore.QString)
|
||||||
def endConvo(self, handle):
|
def endConvo(self, handle):
|
||||||
h = unicode(handle)
|
h = unicode(handle)
|
||||||
try:
|
self.cli.msg(h, "PESTERCHUM:CEASE")
|
||||||
helpers.msg(self.cli, h, "PESTERCHUM:CEASE")
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def updateProfile(self):
|
def updateProfile(self):
|
||||||
me = self.mainwindow.profile()
|
me = self.mainwindow.profile()
|
||||||
handle = me.handle
|
handle = me.handle
|
||||||
try:
|
self.cli.setNick(handle)
|
||||||
helpers.nick(self.cli, handle)
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
self.updateMood()
|
self.updateMood()
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def updateMood(self):
|
def updateMood(self):
|
||||||
me = self.mainwindow.profile()
|
me = self.mainwindow.profile()
|
||||||
try:
|
self.cli.msg("#pesterchum", "MOOD >%d" % (me.mood.value()))
|
||||||
helpers.msg(self.cli, "#pesterchum", "MOOD >%d" % (me.mood.value()))
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def updateColor(self):
|
def updateColor(self):
|
||||||
me = self.mainwindow.profile()
|
me = self.mainwindow.profile()
|
||||||
for h in self.mainwindow.convos.keys():
|
for h in self.mainwindow.convos.keys():
|
||||||
try:
|
self.cli.msg(h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
|
||||||
helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot(QtCore.QString)
|
@QtCore.pyqtSlot(QtCore.QString)
|
||||||
def blockedChum(self, handle):
|
def blockedChum(self, handle):
|
||||||
h = unicode(handle)
|
h = unicode(handle)
|
||||||
try:
|
self.cli.msg(h, "PESTERCHUM:BLOCK")
|
||||||
helpers.msg(self.cli, h, "PESTERCHUM:BLOCK")
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot(QtCore.QString)
|
@QtCore.pyqtSlot(QtCore.QString)
|
||||||
def unblockedChum(self, handle):
|
def unblockedChum(self, handle):
|
||||||
h = unicode(handle)
|
h = unicode(handle)
|
||||||
try:
|
self.cli.msg(h, "PESTERCHUM:UNBLOCK")
|
||||||
helpers.msg(self.cli, h, "PESTERCHUM:UNBLOCK")
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot(QtCore.QString)
|
@QtCore.pyqtSlot(QtCore.QString)
|
||||||
def requestNames(self, channel):
|
def requestNames(self, channel):
|
||||||
c = unicode(channel)
|
c = unicode(channel)
|
||||||
try:
|
self.cli.sendMessage("NAMES", c)
|
||||||
helpers.names(self.cli, c)
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def requestChannelList(self):
|
def requestChannelList(self):
|
||||||
try:
|
self.cli.sendMessage("LIST")
|
||||||
helpers.channel_list(self.cli)
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot(QtCore.QString)
|
@QtCore.pyqtSlot(QtCore.QString)
|
||||||
def joinChannel(self, channel):
|
def joinChannel(self, channel):
|
||||||
c = unicode(channel)
|
c = unicode(channel)
|
||||||
try:
|
self.cli.join(c)
|
||||||
helpers.join(self.cli, c)
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot(QtCore.QString)
|
@QtCore.pyqtSlot(QtCore.QString)
|
||||||
def leftChannel(self, channel):
|
def leftChannel(self, channel):
|
||||||
c = unicode(channel)
|
c = unicode(channel)
|
||||||
try:
|
self.cli.leave(c)
|
||||||
helpers.part(self.cli, c)
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
|
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
|
||||||
def kickUser(self, handle, channel):
|
def kickUser(self, handle, channel):
|
||||||
c = unicode(channel)
|
c = unicode(channel)
|
||||||
h = unicode(handle)
|
h = unicode(handle)
|
||||||
try:
|
self.cli.kick(h, c)
|
||||||
helpers.kick(self.cli, h, c)
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
|
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
|
||||||
def setChannelMode(self, channel, mode, command):
|
def setChannelMode(self, channel, mode, command):
|
||||||
c = unicode(channel)
|
c = unicode(channel)
|
||||||
m = unicode(mode)
|
m = unicode(mode).replace("+", "")
|
||||||
cmd = unicode(command)
|
cmd = unicode(command)
|
||||||
if cmd == "":
|
if cmd == "":
|
||||||
cmd = None
|
cmd = None
|
||||||
try:
|
self.cli.mode(c, True, m, cmd)
|
||||||
helpers.mode(self.cli, c, m, cmd)
|
|
||||||
except socket.error:
|
|
||||||
self.setConnectionBroken()
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def reconnectIRC(self):
|
def reconnectIRC(self):
|
||||||
self.setConnectionBroken()
|
pass
|
||||||
|
|
||||||
def updateIRC(self):
|
|
||||||
self.conn.next()
|
|
||||||
|
|
||||||
moodUpdated = QtCore.pyqtSignal(QtCore.QString, Mood)
|
moodUpdated = QtCore.pyqtSignal(QtCore.QString, Mood)
|
||||||
colorUpdated = QtCore.pyqtSignal(QtCore.QString, QtGui.QColor)
|
colorUpdated = QtCore.pyqtSignal(QtCore.QString, QtGui.QColor)
|
||||||
|
@ -174,10 +129,48 @@ class PesterIRC(QtCore.QObject):
|
||||||
nickCollision = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
|
nickCollision = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
|
||||||
connected = QtCore.pyqtSignal()
|
connected = QtCore.pyqtSignal()
|
||||||
userPresentUpdate = QtCore.pyqtSignal(QtCore.QString, QtCore.QString,
|
userPresentUpdate = QtCore.pyqtSignal(QtCore.QString, QtCore.QString,
|
||||||
QtCore.QString)
|
QtCore.QString)
|
||||||
|
|
||||||
|
|
||||||
|
class PesterIRCClient(IRCClient):
|
||||||
|
realname = "pcc30"
|
||||||
|
username = "pcc30"
|
||||||
|
|
||||||
|
def __init__(self, nick, qobj):
|
||||||
|
self.nickname = nick
|
||||||
|
self.parent = qobj
|
||||||
|
self.mainwindow = qobj.mainwindow
|
||||||
|
qobj.irc = self
|
||||||
|
|
||||||
|
def msg(self, user, message):
|
||||||
|
logging.info("---> send PRIVMSG %s %s" % (user, message))
|
||||||
|
IRCClient.msg(self, user, message)
|
||||||
|
|
||||||
|
def signedOn(self):
|
||||||
|
logging.info("---> recv WELCOME")
|
||||||
|
self.parent.connected.emit()
|
||||||
|
self.join("#pesterchum")
|
||||||
|
mychumhandle = self.mainwindow.profile().handle
|
||||||
|
mymood = self.mainwindow.profile().mood.value()
|
||||||
|
self.msg("#pesterchum", "MOOD >%d" % (mymood))
|
||||||
|
|
||||||
|
chums = self.mainwindow.chumList.chums
|
||||||
|
self.getMood(*chums)
|
||||||
|
|
||||||
|
def getMood(self, *chums):
|
||||||
|
chumglub = "GETMOOD "
|
||||||
|
for c in chums:
|
||||||
|
chandle = c.handle
|
||||||
|
if len(chumglub+chandle) >= 350:
|
||||||
|
self.msg("#pesterchum", chumglub)
|
||||||
|
chumglub = "GETMOOD "
|
||||||
|
chumglub += chandle
|
||||||
|
if chumglub != "GETMOOD ":
|
||||||
|
self.msg("#pesterchum", chumglub)
|
||||||
|
|
||||||
class PesterHandler(DefaultCommandHandler):
|
|
||||||
def privmsg(self, nick, chan, msg):
|
def privmsg(self, nick, chan, msg):
|
||||||
|
# do we still need this?
|
||||||
|
#msg = msg.decode("utf-8")
|
||||||
# display msg, do other stuff
|
# display msg, do other stuff
|
||||||
if len(msg) == 0:
|
if len(msg) == 0:
|
||||||
return
|
return
|
||||||
|
@ -185,7 +178,7 @@ class PesterHandler(DefaultCommandHandler):
|
||||||
if msg[0] == '\x01':
|
if msg[0] == '\x01':
|
||||||
return
|
return
|
||||||
handle = nick[0:nick.find("!")]
|
handle = nick[0:nick.find("!")]
|
||||||
logging.info("---> recv \"PRIVMSG %s :%s\"" % (handle, msg))
|
logging.info("---> recv PRIVMSG %s :%s" % (handle, msg))
|
||||||
if chan == "#pesterchum":
|
if chan == "#pesterchum":
|
||||||
# follow instructions
|
# follow instructions
|
||||||
if msg[0:6] == "MOOD >":
|
if msg[0:6] == "MOOD >":
|
||||||
|
@ -198,8 +191,7 @@ class PesterHandler(DefaultCommandHandler):
|
||||||
mychumhandle = self.mainwindow.profile().handle
|
mychumhandle = self.mainwindow.profile().handle
|
||||||
mymood = self.mainwindow.profile().mood.value()
|
mymood = self.mainwindow.profile().mood.value()
|
||||||
if msg.find(mychumhandle, 8) != -1:
|
if msg.find(mychumhandle, 8) != -1:
|
||||||
helpers.msg(self.client, "#pesterchum",
|
self.msg("#pesterchum", "MOOD >%d" % (mymood))
|
||||||
"MOOD >%d" % (mymood))
|
|
||||||
elif chan[0] == '#':
|
elif chan[0] == '#':
|
||||||
if msg[0:16] == "PESTERCHUM:TIME>":
|
if msg[0:16] == "PESTERCHUM:TIME>":
|
||||||
self.parent.timeCommand.emit(chan, handle, msg[16:])
|
self.parent.timeCommand.emit(chan, handle, msg[16:])
|
||||||
|
@ -221,88 +213,87 @@ class PesterHandler(DefaultCommandHandler):
|
||||||
else:
|
else:
|
||||||
self.parent.messageReceived.emit(handle, msg)
|
self.parent.messageReceived.emit(handle, msg)
|
||||||
|
|
||||||
|
def irc_ERR_NICKNAMEINUSE(self, prefix, params):
|
||||||
def welcome(self, server, nick, msg):
|
logging.info("---> recv NICKINUSE %s %s" % (prefix, params))
|
||||||
self.parent.connected.emit()
|
|
||||||
helpers.join(self.client, "#pesterchum")
|
|
||||||
mychumhandle = self.mainwindow.profile().handle
|
|
||||||
mymood = self.mainwindow.profile().mood.value()
|
|
||||||
helpers.msg(self.client, "#pesterchum", "MOOD >%d" % (mymood))
|
|
||||||
|
|
||||||
chums = self.mainwindow.chumList.chums
|
|
||||||
self.getMood(*chums)
|
|
||||||
|
|
||||||
def nicknameinuse(self, server, cmd, nick, msg):
|
|
||||||
newnick = "pesterClient%d" % (random.randint(100,999))
|
newnick = "pesterClient%d" % (random.randint(100,999))
|
||||||
helpers.nick(self.client, newnick)
|
self.setNick(newnick)
|
||||||
self.parent.nickCollision.emit(nick, newnick)
|
self.parent.nickCollision.emit(nick, newnick)
|
||||||
def quit(self, nick, reason):
|
def userQuit(self, nick, reason):
|
||||||
|
logging.info("---> recv QUIT %s %s" % (nick, reason))
|
||||||
handle = nick[0:nick.find("!")]
|
handle = nick[0:nick.find("!")]
|
||||||
self.parent.userPresentUpdate.emit(handle, "", "quit")
|
self.parent.userPresentUpdate.emit(handle, "", "quit")
|
||||||
self.parent.moodUpdated.emit(handle, Mood("offline"))
|
self.parent.moodUpdated.emit(handle, Mood("offline"))
|
||||||
def kick(self, opnick, channel, handle, op):
|
def userKicked(self, kickee, channel, kicker, msg):
|
||||||
self.parent.userPresentUpdate.emit(handle, channel, "kick:%s" % (op))
|
logging.info("---> recv KICK %s %s %s %s" % (kickee, channel, kicker, msg))
|
||||||
|
self.parent.userPresentUpdate.emit(kickee, channel, "kick:%s" % (op))
|
||||||
# ok i shouldnt be overloading that but am lazy
|
# ok i shouldnt be overloading that but am lazy
|
||||||
def part(self, nick, channel, reason="nanchos"):
|
def userLeft(self, nick, channel, reason="nanchos"):
|
||||||
|
logging.info("---> recv LEFT %s %s" % (nick, channel))
|
||||||
handle = nick[0:nick.find("!")]
|
handle = nick[0:nick.find("!")]
|
||||||
self.parent.userPresentUpdate.emit(handle, channel, "left")
|
self.parent.userPresentUpdate.emit(handle, channel, "left")
|
||||||
if channel == "#pesterchum":
|
if channel == "#pesterchum":
|
||||||
self.parent.moodUpdated.emit(handle, Mood("offline"))
|
self.parent.moodUpdated.emit(handle, Mood("offline"))
|
||||||
def join(self, nick, channel):
|
def userJoined(self, nick, channel):
|
||||||
|
logging.info("---> recv JOIN %s %s" % (nick, channel))
|
||||||
handle = nick[0:nick.find("!")]
|
handle = nick[0:nick.find("!")]
|
||||||
self.parent.userPresentUpdate.emit(handle, channel, "join")
|
self.parent.userPresentUpdate.emit(handle, channel, "join")
|
||||||
if channel == "#pesterchum":
|
if channel == "#pesterchum":
|
||||||
self.parent.moodUpdated.emit(handle, Mood("chummy"))
|
self.parent.moodUpdated.emit(handle, Mood("chummy"))
|
||||||
def mode(self, op, channel, mode, handle=""):
|
def modeChannel(self, op, channel, set, modes, args):
|
||||||
|
logging.info("---> recv MODE %s %s %s %s %s" % (op, channel, set, modes, args))
|
||||||
|
if set:
|
||||||
|
modes += "+"
|
||||||
|
else:
|
||||||
|
modes += "-"
|
||||||
|
handle = ""
|
||||||
|
print args
|
||||||
self.parent.userPresentUpdate.emit(handle, channel, mode)
|
self.parent.userPresentUpdate.emit(handle, channel, mode)
|
||||||
def nick(self, oldnick, newnick):
|
def userRenamed(self, oldnick, newnick):
|
||||||
oldhandle = oldnick[0:oldnick.find("!")]
|
logging.info("---> recv RENAME %s %s" % (oldnick, newnick))
|
||||||
newchum = PesterProfile(newnick, chumdb=self.mainwindow.chumdb)
|
newchum = PesterProfile(newnick, chumdb=self.mainwindow.chumdb)
|
||||||
self.parent.moodUpdated.emit(oldhandle, Mood("offline"))
|
self.parent.moodUpdated.emit(oldnick, Mood("offline"))
|
||||||
self.parent.userPresentUpdate.emit("%s:%s" % (oldhandle, newnick), "", "nick")
|
self.parent.userPresentUpdate.emit("%s:%s" % (oldnick, newnick), "", "nick")
|
||||||
if newnick in self.mainwindow.chumList.chums:
|
if newnick in self.mainwindow.chumList.chums:
|
||||||
self.getMood(newchum)
|
self.getMood(newchum)
|
||||||
def namreply(self, server, nick, op, channel, names):
|
def irc_RPL_NAMREPLY(self, prefix, params):
|
||||||
namelist = names.split(" ")
|
logging.info("---> recv NAMREPLY %s %s" % (prefix, params))
|
||||||
logging.info("---> recv \"NAMES %s: %d names\"" % (channel, len(namelist)))
|
# namelist = names.split(" ")
|
||||||
if not hasattr(self, 'channelnames'):
|
# logging.info("---> recv \"NAMES %s: %d names\"" % (channel, len(namelist)))
|
||||||
self.channelnames = {}
|
# if not hasattr(self, 'channelnames'):
|
||||||
if not self.channelnames.has_key(channel):
|
# self.channelnames = {}
|
||||||
self.channelnames[channel] = []
|
# if not self.channelnames.has_key(channel):
|
||||||
self.channelnames[channel].extend(namelist)
|
# self.channelnames[channel] = []
|
||||||
def endofnames(self, server, nick, channel, msg):
|
# self.channelnames[channel].extend(namelist)
|
||||||
namelist = self.channelnames[channel]
|
def irc_RPL_ENDOFNAMES(self, prefix, params):
|
||||||
pl = PesterList(namelist)
|
logging.info("---> recv ENDOFNAMES %s %s" % (prefix, params))
|
||||||
del self.channelnames[channel]
|
# namelist = self.channelnames[channel]
|
||||||
self.parent.namesReceived.emit(channel, pl)
|
# pl = PesterList(namelist)
|
||||||
|
# del self.channelnames[channel]
|
||||||
|
# self.parent.namesReceived.emit(channel, pl)
|
||||||
|
def irc_RPL_LISTSTART(self, prefix, params):
|
||||||
|
logging.info("---> recv LISTSTART %s %s" % (prefix, params))
|
||||||
|
# self.channel_list = []
|
||||||
|
# info = list(info)
|
||||||
|
# self.channel_field = info.index("Channel") # dunno if this is protocol
|
||||||
|
def irc_RPL_LIST(self, prefix, params):
|
||||||
|
logging.info("---> recv LIST %s %s" % (prefix, params))
|
||||||
|
# channel = info[self.channel_field]
|
||||||
|
# if channel not in self.channel_list and channel != "#pesterchum":
|
||||||
|
# self.channel_list.append(channel)
|
||||||
|
def irc_RPL_LISTEND(self, prefix, params):
|
||||||
|
logging.info("---> recv LISTEND %s %s" % (prefix, params))
|
||||||
|
# pl = PesterList(self.channel_list)
|
||||||
|
# self.parent.channelListReceived.emit(pl)
|
||||||
|
# self.channel_list = []
|
||||||
|
|
||||||
def liststart(self, server, handle, *info):
|
class PesterIRCFactory(ClientFactory):
|
||||||
self.channel_list = []
|
protocol = PesterIRCClient
|
||||||
info = list(info)
|
|
||||||
self.channel_field = info.index("Channel") # dunno if this is protocol
|
|
||||||
def list(self, server, handle, *info):
|
|
||||||
channel = info[self.channel_field]
|
|
||||||
if channel not in self.channel_list and channel != "#pesterchum":
|
|
||||||
self.channel_list.append(channel)
|
|
||||||
def listend(self, server, handle, msg):
|
|
||||||
pl = PesterList(self.channel_list)
|
|
||||||
self.parent.channelListReceived.emit(pl)
|
|
||||||
self.channel_list = []
|
|
||||||
|
|
||||||
def getMood(self, *chums):
|
|
||||||
chumglub = "GETMOOD "
|
|
||||||
for c in chums:
|
|
||||||
chandle = c.handle
|
|
||||||
if len(chumglub+chandle) >= 350:
|
|
||||||
try:
|
|
||||||
helpers.msg(self.client, "#pesterchum", chumglub)
|
|
||||||
except socket.error:
|
|
||||||
self.parent.setConnectionBroken()
|
|
||||||
chumglub = "GETMOOD "
|
|
||||||
chumglub += chandle
|
|
||||||
if chumglub != "GETMOOD ":
|
|
||||||
try:
|
|
||||||
helpers.msg(self.client, "#pesterchum", chumglub)
|
|
||||||
except socket.error:
|
|
||||||
self.parent.setConnectionBroken()
|
|
||||||
|
|
||||||
|
def __init__(self, nick, qobj):
|
||||||
|
self.irc = self.protocol(nick, qobj)
|
||||||
|
def buildProtocol(self, addr=None):
|
||||||
|
return self.irc
|
||||||
|
def clientConnectionLost(self, conn, reason):
|
||||||
|
conn.connect()
|
||||||
|
def clientConnectionFailed(self, conn, reason):
|
||||||
|
conn.connect()
|
||||||
|
|
BIN
irc.pyc
BIN
irc.pyc
Binary file not shown.
BIN
memos.pyc
BIN
memos.pyc
Binary file not shown.
2
menus.py
2
menus.py
|
@ -649,6 +649,6 @@ class LoadingScreen(QtGui.QDialog):
|
||||||
class AboutPesterchum(QtGui.QMessageBox):
|
class AboutPesterchum(QtGui.QMessageBox):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QtGui.QMessageBox.__init__(self, parent)
|
QtGui.QMessageBox.__init__(self, parent)
|
||||||
self.setText("P3ST3RCHUM V. 0.1.2")
|
self.setText("P3ST3RCHUM V. 3.14 alpha 4")
|
||||||
self.setInformativeText("Programming by illuminatedwax (ghostDunk), art by Grimlive (aquaMarinist)")
|
self.setInformativeText("Programming by illuminatedwax (ghostDunk), art by Grimlive (aquaMarinist)")
|
||||||
self.mainwindow = parent
|
self.mainwindow = parent
|
||||||
|
|
BIN
menus.pyc
BIN
menus.pyc
Binary file not shown.
BIN
mispeller.pyc
BIN
mispeller.pyc
Binary file not shown.
Binary file not shown.
|
@ -29,6 +29,8 @@ from oyoyo.parse import *
|
||||||
from oyoyo import helpers
|
from oyoyo import helpers
|
||||||
from oyoyo.cmdhandler import CommandError
|
from oyoyo.cmdhandler import CommandError
|
||||||
|
|
||||||
|
from datetime import *
|
||||||
|
|
||||||
# Python < 3 compatibility
|
# Python < 3 compatibility
|
||||||
if sys.version_info < (3,):
|
if sys.version_info < (3,):
|
||||||
class bytes(object):
|
class bytes(object):
|
||||||
|
|
BIN
oyoyo/client.pyc
BIN
oyoyo/client.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
oyoyo/parse.pyc
BIN
oyoyo/parse.pyc
Binary file not shown.
BIN
parsetools.pyc
BIN
parsetools.pyc
Binary file not shown.
|
@ -1 +1 @@
|
||||||
{"tabs": true, "soundon": true, "server": "irc.tymoon.eu", "chums": ["unknownTraveler", "tentacleTherapist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium", "terminallyCapricious", "illuminatedWax", "aquaMarinist", "elegantDiversion", "moirailBunp", "uroborosUnbound", "androidTechnician", "midnightSparrow", "apocalypseArisen", "anguillaNuntia", "oilslickOrchid", "confusedTransient", "pretentiousFantasia", "aquaticMarinist", "lyricalKeraunoscopic", "counterRealist", "ectoBiologist", "percipientPedestrian", "asceticClinician", "doctectiveMiracles", "noSense", "obliviousCrafter", "ircMonster"], "defaultprofile": "ghostDunk", "block": []}
|
{"tabs": true, "soundon": true, "server": "irc.tymoon.eu", "chums": ["unknownTraveler", "tentacleTherapist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium", "terminallyCapricious", "illuminatedWax", "aquaMarinist", "elegantDiversion", "moirailBunp", "uroborosUnbound", "androidTechnician", "midnightSparrow", "apocalypseArisen", "anguillaNuntia", "oilslickOrchid", "confusedTransient", "pretentiousFantasia", "aquaticMarinist", "lyricalKeraunoscopic", "counterRealist", "ectoBiologist", "percipientPedestrian", "asceticClinician", "doctectiveMiracles", "noSense", "obliviousCrafter", "ircMonster"], "defaultprofile": "testProfile", "block": []}
|
|
@ -21,7 +21,6 @@ from generic import PesterIcon, RightClickList, MultiTextDialog, PesterList
|
||||||
from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo
|
from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo
|
||||||
from parsetools import convertTags, addTimeInitial
|
from parsetools import convertTags, addTimeInitial
|
||||||
from memos import PesterMemo, MemoTabWindow, TimeTracker
|
from memos import PesterMemo, MemoTabWindow, TimeTracker
|
||||||
from irc import PesterIRC
|
|
||||||
|
|
||||||
class waitingMessageHolder(object):
|
class waitingMessageHolder(object):
|
||||||
def __init__(self, mainwindow, **msgfuncs):
|
def __init__(self, mainwindow, **msgfuncs):
|
||||||
|
@ -1657,26 +1656,6 @@ class PesterWindow(MovingWindow):
|
||||||
closeSignal = QtCore.pyqtSignal()
|
closeSignal = QtCore.pyqtSignal()
|
||||||
reconnectIRC = QtCore.pyqtSignal()
|
reconnectIRC = QtCore.pyqtSignal()
|
||||||
|
|
||||||
class IRCThread(QtCore.QThread):
|
|
||||||
def __init__(self, ircobj):
|
|
||||||
QtCore.QThread.__init__(self)
|
|
||||||
self.irc = ircobj
|
|
||||||
def run(self):
|
|
||||||
irc = self.irc
|
|
||||||
irc.IRCConnect()
|
|
||||||
while 1:
|
|
||||||
if irc.brokenConnection:
|
|
||||||
irc.brokenConnection = False
|
|
||||||
self.restartIRC.emit()
|
|
||||||
irc.closeConnection()
|
|
||||||
irc.IRCConnect()
|
|
||||||
try:
|
|
||||||
irc.updateIRC()
|
|
||||||
except socket.error:
|
|
||||||
irc.setConnectionBroken()
|
|
||||||
|
|
||||||
restartIRC = QtCore.pyqtSignal()
|
|
||||||
|
|
||||||
class PesterTray(QtGui.QSystemTrayIcon):
|
class PesterTray(QtGui.QSystemTrayIcon):
|
||||||
def __init__(self, icon, mainwindow, parent):
|
def __init__(self, icon, mainwindow, parent):
|
||||||
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
|
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
|
||||||
|
@ -1696,6 +1675,9 @@ class MainProgram(QtCore.QObject):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QtCore.QObject.__init__(self)
|
QtCore.QObject.__init__(self)
|
||||||
self.app = QtGui.QApplication(sys.argv)
|
self.app = QtGui.QApplication(sys.argv)
|
||||||
|
from qt4reactor import qt4reactor
|
||||||
|
qt4reactor.install()
|
||||||
|
from irc import PesterIRC
|
||||||
if pygame.mixer:
|
if pygame.mixer:
|
||||||
# we could set the frequency higher but i love how cheesy it sounds
|
# we could set the frequency higher but i love how cheesy it sounds
|
||||||
try:
|
try:
|
||||||
|
@ -1744,9 +1726,7 @@ class MainProgram(QtCore.QObject):
|
||||||
|
|
||||||
self.irc = PesterIRC(self.widget.config, self.widget)
|
self.irc = PesterIRC(self.widget.config, self.widget)
|
||||||
self.connectWidgets(self.irc, self.widget)
|
self.connectWidgets(self.irc, self.widget)
|
||||||
self.ircapp = IRCThread(self.irc)
|
self.irc.IRCConnect()
|
||||||
self.connect(self.ircapp, QtCore.SIGNAL('restartIRC()'),
|
|
||||||
self, QtCore.SLOT('restartIRC()'))
|
|
||||||
|
|
||||||
def connectWidgets(self, irc, widget):
|
def connectWidgets(self, irc, widget):
|
||||||
irc.connect(widget, QtCore.SIGNAL('sendMessage(QString, QString)'),
|
irc.connect(widget, QtCore.SIGNAL('sendMessage(QString, QString)'),
|
||||||
|
@ -1866,7 +1846,6 @@ class MainProgram(QtCore.QObject):
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.ircapp.start()
|
|
||||||
self.widget.loadingscreen = LoadingScreen(self.widget)
|
self.widget.loadingscreen = LoadingScreen(self.widget)
|
||||||
self.connect(self.widget.loadingscreen, QtCore.SIGNAL('rejected()'),
|
self.connect(self.widget.loadingscreen, QtCore.SIGNAL('rejected()'),
|
||||||
self.widget, QtCore.SLOT('close()'))
|
self.widget, QtCore.SLOT('close()'))
|
||||||
|
|
9
qt4reactor/.gitignore
vendored
Normal file
9
qt4reactor/.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
*.[oa]
|
||||||
|
*~
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.class
|
||||||
|
.project
|
||||||
|
.pydevproject
|
||||||
|
*.cache
|
||||||
|
_trial_temp
|
57
qt4reactor/LICENSE
Normal file
57
qt4reactor/LICENSE
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
Copyright (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.
|
55
qt4reactor/README
Normal file
55
qt4reactor/README
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
Unpack 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
|
0
qt4reactor/__init__.py
Normal file
0
qt4reactor/__init__.py
Normal file
24
qt4reactor/bin/gtrial
Executable file
24
qt4reactor/bin/gtrial
Executable file
|
@ -0,0 +1,24 @@
|
||||||
|
#!/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()
|
57
qt4reactor/ghtTests/buttonStress.py
Executable file
57
qt4reactor/ghtTests/buttonStress.py
Executable file
|
@ -0,0 +1,57 @@
|
||||||
|
import 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?...')
|
||||||
|
|
||||||
|
|
51
qt4reactor/ghtTests/fakeAppButtonStress.py
Executable file
51
qt4reactor/ghtTests/fakeAppButtonStress.py
Executable file
|
@ -0,0 +1,51 @@
|
||||||
|
import 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?...'
|
||||||
|
|
||||||
|
|
106
qt4reactor/ghtTests/ircClient.py
Normal file
106
qt4reactor/ghtTests/ircClient.py
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
from 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_())
|
37
qt4reactor/ghtTests/testIterate.py
Executable file
37
qt4reactor/ghtTests/testIterate.py
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
import 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?...')
|
||||||
|
|
||||||
|
|
25
qt4reactor/ghtTests/trivialscript.py
Executable file
25
qt4reactor/ghtTests/trivialscript.py
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
import 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_())
|
||||||
|
|
41
qt4reactor/gtrial.py
Executable file
41
qt4reactor/gtrial.py
Executable file
|
@ -0,0 +1,41 @@
|
||||||
|
import 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?...'
|
||||||
|
|
||||||
|
|
359
qt4reactor/qt4reactor.py
Normal file
359
qt4reactor/qt4reactor.py
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
# 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<mailto:glenn@tarbox.org>}
|
||||||
|
|
||||||
|
Previous maintainer: U{Itamar Shtull-Trauring<mailto:twisted@itamarst.org>}
|
||||||
|
Original port to QT4: U{Gabe Rudy<mailto:rudy@goldenhelix.com>}
|
||||||
|
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.startingUp():
|
||||||
|
# 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"]
|
||||||
|
|
9
qt4reactor/twisted/plugins/qt4.py
Normal file
9
qt4reactor/twisted/plugins/qt4.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# 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')
|
||||||
|
|
Loading…
Reference in a new issue