memos in some semblance of working order

This commit is contained in:
Stephen Dranger 2011-02-05 11:17:33 -06:00
parent 3bafa1e48a
commit a69b72784a
25 changed files with 773 additions and 273 deletions

1
TODO
View file

@ -6,6 +6,7 @@ Features:
* help menu -- about and forum
* profile switch should say current profile
* Transparent background?
* X closes to tray
-- release alpha
* User commands/stop user from sending commands accidentally
* shared buddy lists - changes to the buddy list should refresh it?

BIN
convo.pyc

Binary file not shown.

View file

@ -100,12 +100,21 @@ class PesterProfile(object):
color = QtGui.QColor("black")
self.color = color
self.mood = mood
def initials(self):
def initials(self, time=None):
handle = self.handle
caps = [l for l in handle if l.isupper()]
if not caps:
caps = [""]
return (handle[0]+caps[0]).upper()
initials = (handle[0]+caps[0]).upper()
if hasattr(self, 'time') and time:
if self.time > time:
return "F"+initials
elif self.time < time:
return "P"+initials
else:
return "C"+initials
else:
return (handle[0]+caps[0]).upper()
def colorhtml(self):
return self.color.name()
def colorcmd(self):
@ -118,11 +127,37 @@ class PesterProfile(object):
def blocked(self, config):
return self.handle in config.getBlocklist()
def memsg(self, syscolor, suffix, msg):
def memsg(self, syscolor, suffix, msg, time=None):
uppersuffix = suffix.upper()
return "<c=%s>-- %s%s <c=%s>[%s%s]</c> %s --</c>" % (syscolor.name(), self.handle, suffix, self.colorhtml(), self.initials(), uppersuffix, msg)
if time is not None:
handle = "%s %s" % (time.temporal, self.handle)
initials = time.pcf+self.initials()+uppersuffix
else:
handle = self.handle
initials = self.initials()+uppersuffix
return "<c=%s>-- %s%s <c=%s>[%s]</c> %s --</c>" % (syscolor.name(), handle, suffix, self.colorhtml(), initials, msg)
def pestermsg(self, otherchum, syscolor, verb):
return "<c=%s>-- %s <c=%s>[%s]</c> %s %s <c=%s>[%s]</c> at %s --</c>" % (syscolor.name(), self.handle, self.colorhtml(), self.initials(), verb, otherchum.handle, otherchum.colorhtml(), otherchum.initials(), datetime.now().strftime("%H:%M"))
def memoclosemsg(self, syscolor, timeGrammar, verb):
return "<c=%s><c=%s>%s%s%s</c> %s.</c>" % (syscolor.name(), self.colorhtml(), timeGrammar.pcf, self.initials(), timeGrammar.number, verb)
def memojoinmsg(self, syscolor, td, timeGrammar, verb):
(temporal, pcf, when) = (timeGrammar.temporal, timeGrammar.pcf, timeGrammar.when)
atd = abs(td)
minutes = (atd.days*86400 + atd.seconds) // 60
hours = minutes // 60
leftoverminutes = minutes % 60
if atd == timedelta(0):
timetext = when
elif atd < timedelta(0,3600):
timetext = "%d MINUTES %s" % (minutes, when)
elif atd < timedelta(0,3600*100):
timetext = "%d:%02d HOURS %s" % (hours, leftoverminutes, when)
else:
timetext = "%d HOURS %s" % (hours, when)
initials = pcf+self.initials()+timeGrammar.number
return "<c=%s><c=%s>%s %s [%s]</c> %s %s." % \
(syscolor.name(), self.colorhtml(), temporal, self.handle,
initials, timetext, verb)
@staticmethod
def checkLength(handle):

Binary file not shown.

View file

@ -1,5 +1,9 @@
from PyQt4 import QtGui, QtCore
class PesterList(list):
def __init__(self, l):
self.extend(l)
class PesterIcon(QtGui.QIcon):
def __init__(self, *x, **y):
QtGui.QIcon.__init__(self, *x, **y)

Binary file not shown.

211
irc.py Normal file
View file

@ -0,0 +1,211 @@
from PyQt4 import QtGui, QtCore
from oyoyo.client import IRCClient
from oyoyo.cmdhandler import DefaultCommandHandler
from oyoyo import helpers
import logging
from dataobjs import Mood, PesterProfile
from generic import PesterList
logging.basicConfig(level=logging.INFO)
class PesterIRC(QtCore.QObject):
def __init__(self, window):
QtCore.QObject.__init__(self)
self.mainwindow = window
def IRCConnect(self):
self.cli = IRCClient(PesterHandler, host="irc.tymoon.eu", port=6667, nick=self.mainwindow.profile().handle, blocking=True)
self.cli.command_handler.parent = self
self.cli.command_handler.mainwindow = self.mainwindow
self.conn = self.cli.connect()
@QtCore.pyqtSlot(PesterProfile)
def getMood(self, *chums):
self.cli.command_handler.getMood(*chums)
@QtCore.pyqtSlot(PesterList)
def getMoods(self, chums):
self.cli.command_handler.getMood(*chums)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
def sendMessage(self, text, handle):
h = unicode(handle)
helpers.msg(self.cli, h, text)
@QtCore.pyqtSlot(QtCore.QString, bool)
def startConvo(self, handle, initiated):
h = unicode(handle)
if initiated:
helpers.msg(self.cli, h, "PESTERCHUM:BEGIN")
helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
@QtCore.pyqtSlot(QtCore.QString)
def endConvo(self, handle):
h = unicode(handle)
helpers.msg(self.cli, h, "PESTERCHUM:CEASE")
@QtCore.pyqtSlot()
def updateProfile(self):
me = self.mainwindow.profile()
handle = me.handle
helpers.nick(self.cli, handle)
self.updateMood()
@QtCore.pyqtSlot()
def updateMood(self):
me = self.mainwindow.profile()
helpers.msg(self.cli, "#pesterchum", "MOOD >%d" % (me.mood.value()))
@QtCore.pyqtSlot()
def updateColor(self):
me = self.mainwindow.profile()
for h in self.mainwindow.convos.keys():
helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
@QtCore.pyqtSlot(QtCore.QString)
def blockedChum(self, handle):
h = unicode(handle)
helpers.msg(self.cli, h, "PESTERCHUM:BLOCK")
@QtCore.pyqtSlot(QtCore.QString)
def unblockedChum(self, handle):
h = unicode(handle)
helpers.msg(self.cli, h, "PESTERCHUM:UNBLOCK")
@QtCore.pyqtSlot(QtCore.QString)
def requestNames(self, channel):
c = unicode(channel)
helpers.names(self.cli, c)
@QtCore.pyqtSlot()
def requestChannelList(self):
helpers.channel_list(self.cli)
@QtCore.pyqtSlot(QtCore.QString)
def joinChannel(self, channel):
c = unicode(channel)
helpers.join(self.cli, c)
@QtCore.pyqtSlot(QtCore.QString)
def leftChannel(self, channel):
c = unicode(channel)
helpers.part(self.cli, c)
def updateIRC(self):
self.conn.next()
moodUpdated = QtCore.pyqtSignal(QtCore.QString, Mood)
colorUpdated = QtCore.pyqtSignal(QtCore.QString, QtGui.QColor)
messageReceived = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
memoReceived = QtCore.pyqtSignal(QtCore.QString, QtCore.QString, QtCore.QString)
timeCommand = QtCore.pyqtSignal(QtCore.QString, QtCore.QString, QtCore.QString)
namesReceived = QtCore.pyqtSignal(QtCore.QString, PesterList)
channelListReceived = QtCore.pyqtSignal(PesterList)
nickCollision = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
connected = QtCore.pyqtSignal()
userPresentUpdate = QtCore.pyqtSignal(QtCore.QString, QtCore.QString,
QtCore.QString)
class PesterHandler(DefaultCommandHandler):
def privmsg(self, nick, chan, msg):
# display msg, do other stuff
# silently ignore CTCP
if msg[0] == '\x01':
return
handle = nick[0:nick.find("!")]
logging.info("---> recv \"PRIVMSG %s :%s\"" % (handle, msg))
if chan == "#pesterchum":
# follow instructions
if msg[0:6] == "MOOD >":
try:
mood = Mood(int(msg[6:]))
except ValueError:
mood = Mood(0)
self.parent.moodUpdated.emit(handle, mood)
elif msg[0:7] == "GETMOOD":
mychumhandle = self.mainwindow.profile().handle
mymood = self.mainwindow.profile().mood.value()
if msg.find(mychumhandle, 8) != -1:
helpers.msg(self.client, "#pesterchum",
"MOOD >%d" % (mymood))
elif chan[0] == '#':
if msg[0:16] == "PESTERCHUM:TIME>":
self.parent.timeCommand.emit(chan, handle, msg[16:])
else:
self.parent.memoReceived.emit(chan, handle, msg)
else:
# private message
# silently ignore messages to yourself.
if handle == self.mainwindow.profile().handle:
return
if msg[0:7] == "COLOR >":
colors = msg[7:].split(",")
try:
colors = [int(d) for d in colors]
except ValueError:
colors = [0,0,0]
color = QtGui.QColor(*colors)
self.parent.colorUpdated.emit(handle, color)
else:
self.parent.messageReceived.emit(handle, msg)
def welcome(self, server, nick, msg):
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))
helpers.nick(self.client, newnick)
self.parent.nickCollision.emit(nick, newnick)
def quit(self, nick, reason):
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, "", "quit")
self.parent.moodUpdated.emit(handle, Mood("offline"))
def part(self, nick, channel, reason="nanchos"):
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, channel, "left")
if channel == "#pesterchum":
self.parent.moodUpdated.emit(handle, Mood("offline"))
def join(self, nick, channel):
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, channel, "join")
if channel == "#pesterchum":
self.parent.moodUpdated.emit(handle, Mood("chummy"))
def nick(self, oldnick, newnick):
oldhandle = oldnick[0:oldnick.find("!")]
newchum = PesterProfile(newnick, chumdb=self.mainwindow.chumdb)
self.parent.moodUpdated.emit(oldhandle, Mood("offline"))
if newnick in self.mainwindow.chumList.chums:
self.getMood(newchum)
def namreply(self, server, nick, op, channel, names):
namelist = names.split(" ")
logging.info("---> recv \"NAMES %s: %d names\"" % (channel, len(namelist)))
if not hasattr(self, 'channelnames'):
self.channelnames = {}
if not self.channelnames.has_key(channel):
self.channelnames[channel] = []
self.channelnames[channel].extend(namelist)
def endofnames(self, server, nick, channel, msg):
namelist = self.channelnames[channel]
pl = PesterList(namelist)
del self.channelnames[channel]
self.parent.namesReceived.emit(channel, pl)
def liststart(self, server, handle, *info):
self.channel_list = []
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:
helpers.msg(self.client, "#pesterchum", chumglub)
chumglub = "GETMOOD "
chumglub += chandle
if chumglub != "GETMOOD ":
helpers.msg(self.client, "#pesterchum", chumglub)

BIN
irc.pyc Normal file

Binary file not shown.

View file

@ -1 +1 @@
{"macruralAlchemist": {"color": "#700000", "handle": "macruralAlchemist", "mood": "offline"}, "agogPorphyry": {"color": "#522d80", "handle": "agogPorphyry", "mood": "offline"}, "fireSwallow": {"color": "#80bb9a", "handle": "fireSwallow", "mood": "offline"}, "aquaMarinist": {"color": "#00caca", "handle": "aquaMarinist", "mood": "offline"}, "nitroZealist": {"color": "#ff3737", "handle": "nitroZealist", "mood": "offline"}, "superGhost": {"color": "#800564", "handle": "superGhost", "mood": "offline"}, "tentacleTherapist": {"color": "#cc66ff", "handle": "tentacleTherapist", "mood": "offline"}, "gardenGnostic": {"color": "#00ff00", "handle": "gardenGnostic", "mood": "offline"}, "aquaticMarinist": {"color": "#00caca", "handle": "aquaticMarinist", "mood": "offline"}, "captainCaveman": {"color": "#7c414e", "handle": "captainCaveman", "mood": "offline"}, "greenZephyr": {"color": "#00ca40", "handle": "greenZephyr", "mood": "offline"}, "pesterClient394": {"color": "#ff3737", "handle": "pesterClient394", "mood": "offline"}, "gamblingGenocider": {"color": "#00ff00", "handle": "gamblingGenocider", "mood": "offline"}, "mechanicalSpectacle": {"color": "#0000ff", "handle": "mechanicalSpectacle", "mood": "offline"}, "elegantDiversion": {"color": "#12b40d", "handle": "elegantDiversion", "mood": "offline"}, "absoluteTranquility": {"color": "#000033", "handle": "absoluteTranquility", "mood": "offline"}, "centaursTesticle": {"color": "#000056", "handle": "centaursTesticle", "mood": "offline"}, "schlagzeugGator": {"color": "#61821f", "handle": "schlagzeugGator", "mood": "offline"}, "unknownTraveler": {"color": "#006666", "handle": "unknownTraveler", "mood": "offline"}, "remoteBloodbath": {"color": "#c70000", "handle": "remoteBloodbath", "mood": "offline"}, "marineAquist": {"color": "#00caca", "handle": "marineAquist", "mood": "offline"}}
{"macruralAlchemist": {"color": "#700000", "handle": "macruralAlchemist", "mood": "offline"}, "fireSwallow": {"color": "#80bb9a", "handle": "fireSwallow", "mood": "offline"}, "aquaMarinist": {"color": "#00caca", "handle": "aquaMarinist", "mood": "offline"}, "nitroZealist": {"color": "#ff3737", "handle": "nitroZealist", "mood": "offline"}, "masterG": {"color": "#77003c", "handle": "masterG", "mood": "offline"}, "aquaticMarinist": {"color": "#00caca", "handle": "aquaticMarinist", "mood": "offline"}, "iw": {"color": "#ff0000", "handle": "iw", "mood": "offline"}, "pesterClient394": {"color": "#ff3737", "handle": "pesterClient394", "mood": "offline"}, "absoluteTranquility": {"color": "#000033", "handle": "absoluteTranquility", "mood": "offline"}, "centaursTesticle": {"color": "#000056", "handle": "centaursTesticle", "mood": "offline"}, "agogPorphyry": {"color": "#522d80", "handle": "agogPorphyry", "mood": "offline"}, "illuminatedWax": {"color": "#ffff00", "handle": "illuminatedWax", "mood": "offline"}, "gamblingGenocider": {"color": "#00ff00", "handle": "gamblingGenocider", "mood": "offline"}, "elegantDiversion": {"color": "#12b40d", "handle": "elegantDiversion", "mood": "offline"}, "testOut": {"color": "#c760cc", "handle": "testOut", "mood": "offline"}, "superGhost": {"color": "#800564", "handle": "superGhost", "mood": "offline"}, "tentacleTherapist": {"color": "#cc66ff", "handle": "tentacleTherapist", "mood": "offline"}, "captainCaveman": {"color": "#7c414e", "handle": "captainCaveman", "mood": "offline"}, "cuttlefishCuller": {"color": "#77003c", "handle": "cuttlefishCuller", "mood": "offline"}, "mechanicalSpectacle": {"color": "#0000ff", "handle": "mechanicalSpectacle", "mood": "offline"}, "remoteBloodbath": {"color": "#c70000", "handle": "remoteBloodbath", "mood": "offline"}, "rageInducer": {"color": "#00ffff", "handle": "rageInducer", "mood": "offline"}, "gallowsCalibrator": {"color": "#008282", "handle": "gallowsCalibrator", "mood": "offline"}, "greenZephyr": {"color": "#00ca40", "handle": "greenZephyr", "mood": "offline"}, "schlagzeugGator": {"color": "#61821f", "handle": "schlagzeugGator", "mood": "offline"}, "gardenGnostic": {"color": "#00ff00", "handle": "gardenGnostic", "mood": "offline"}, "unknownTraveler": {"color": "#006666", "handle": "unknownTraveler", "mood": "offline"}, "marineAquist": {"color": "#00caca", "handle": "marineAquist", "mood": "offline"}}

389
memos.py
View file

@ -1,10 +1,170 @@
from string import Template
import re
from PyQt4 import QtGui, QtCore
from datetime import time, timedelta, datetime
from dataobjs import PesterProfile, Mood
from generic import PesterIcon
from convo import PesterConvo, PesterInput, PesterText, PesterTabWindow
from parsetools import convertTags, escapeBrackets, addTimeInitial, timeProtocol
def delta2txt(d, format="pc"):
if format == "pc":
sign = "+" if d >= timedelta(0) else "-"
else:
if d == timedelta(0):
return ""
sign = "F" if d >= timedelta(0) else "P"
d = abs(d)
totalminutes = (d.days*86400 + d.seconds) // 60
hours = totalminutes // 60
leftovermins = totalminutes % 60
if hours < 100:
if format == "pc":
return "%s%d:%02d" % (sign, hours, leftovermins)
else:
return "%s%02d:%02d" % (sign, hours, leftovermins)
else:
if format == "pc":
return "%s%d" % (sign, hours)
else:
return "%s%02d:%02d" % (sign, hours, leftovermins)
def txt2delta(txt):
sign = 1
if txt[0] == '+':
txt = txt[1:]
elif txt[0] == '-':
sign = -1
txt = txt[1:]
l = txt.split(":")
try:
h = int(l[0])
m = 0
if len(l) > 1:
m = int(l[1])
timed = timedelta(0, h*3600+m*60)
except ValueError:
timed = timedelta(0)
return sign*timed
def pcfGrammar(td):
if td > timedelta(0):
when = "FROM NOW"
temporal = "FUTURE"
pcf = "F"
elif td < timedelta(0):
when = "AGO"
temporal = "PAST"
pcf = "P"
else:
when = "RIGHT NOW"
temporal = "CURRENT"
pcf = "C"
return (temporal, pcf, when)
class TimeGrammar(object):
def __init__(self, temporal, pcf, when, number="0"):
self.temporal = temporal
self.pcf = pcf
self.when = when
if number == "0" or number == 0:
self.number = ""
else:
self.number = str(number)
class TimeTracker(list):
def __init__(self, time=None):
self.timerecord = {"P": [], "F": []}
if time is not None:
self.append(time)
self.current=0
self.addRecord(time)
else:
self.current=-1
def addTime(self, timed):
try:
i = self.index(timed)
self.current = i
except ValueError:
self.current = len(self)
self.append(timed)
self.addRecord(timed)
def setCurrent(self, timed):
self.current = self.index(timed)
def addRecord(self, timed):
(temporal, pcf, when) = pcfGrammar(timed - timedelta(0))
if pcf == "C":
return
if timed in self.timerecord[pcf]:
return
self.timerecord[pcf].append(timed)
def getRecord(self, timed):
(temporal, pcf, when) = pcfGrammar(timed - timedelta(0))
if pcf == "C":
return 0
if len(self.timerecord[pcf]) > 1:
return self.timerecord[pcf].index(timed)+1
else:
return 0
def removeTime(self, timed):
try:
self.pop(self.index(timed))
self.current = len(self)-1
except ValueError:
pass
def getTime(self):
if self.current >= 0:
return self[self.current]
else:
return None
def getGrammar(self):
timed = self.getTime()
mytime = timedelta(0)
(temporal, pcf, when) = pcfGrammar(timed - mytime)
if timed == mytime:
return TimeGrammar(temporal, pcf, when, 0)
return TimeGrammar(temporal, pcf, when, self.getRecord(timed))
class TimeInput(QtGui.QLineEdit):
def __init__(self, timeslider, parent):
QtGui.QLineEdit.__init__(self, parent)
self.timeslider = timeslider
self.setText("+0:00")
self.connect(self.timeslider, QtCore.SIGNAL('valueChanged(int)'),
self, QtCore.SLOT('setTime(int)'))
self.connect(self, QtCore.SIGNAL('editingFinished()'),
self, QtCore.SLOT('setSlider()'))
@QtCore.pyqtSlot(int)
def setTime(self, sliderval):
self.setText(self.timeslider.getTime())
@QtCore.pyqtSlot()
def setSlider(self):
value = unicode(self.text())
timed = txt2delta(value)
sign = 1 if timed >= timedelta(0) else -1
abstimed = abs(txt2delta(value))
index = 50
for i, td in enumerate(timedlist):
if abstimed < td:
index = i-1
break
self.timeslider.setValue(sign*index)
text = delta2txt(timed)
self.setText(text)
class TimeSlider(QtGui.QSlider):
def __init__(self, orientation, parent):
QtGui.QSlider.__init__(self, orientation, parent)
self.setTracking(True)
self.setMinimum(-50)
self.setMaximum(50)
self.setValue(0)
self.setPageStep(1)
def getTime(self):
time = timelist[abs(self.value())]
sign = "+" if self.value() >= 0 else "-"
return sign+time
class MemoTabWindow(PesterTabWindow):
def __init__(self, mainwindow, parent=None):
@ -30,10 +190,57 @@ class MemoText(PesterText):
self.setReadOnly(True)
self.setMouseTracking(True)
def addMessage(self, text, chum):
# get chum color from c tag
mobj = _ctag_begin.match(text)
# tinychum sends straight /me with no color. go to chumdb!
systemColor = QtGui.QColor(self.parent().mainwindow.theme["memo/systemMsgColor"])
parent = self.parent()
window = parent.mainwindow
me = window.profile()
msg = unicode(text)
chumdb = window.chumdb
if chum is not me: # SO MUCH WH1T3SP4C3 >:]
mobj = _ctag_begin.match(text) # get color from tag
if mobj:
try:
color = QtGui.QColor(*[int(c) for c in mobj.group(1).split(",")])
except ValueError:
color = QtGui.QColor("black")
else:
chumdb.setColor(chum.handle, color)
parent.updateColor(chum.handle, color)
else:
color = chumdb.getColor(chum.handle)
else:
color = me.color
chum.color = color
systemColor = QtGui.QColor(window.theme["memos/systemMsgColor"])
if chum is not me:
if parent.times.has_key(chum.handle):
time = parent.times[chum.handle]
else:
# new chum! time current
newtime = timedelta(0)
time = TimeTracker(newtime)
parent.times[chum.handle] = time
timeGrammar = time.getGrammar()
self.append(convertTags(chum.memojoinmsg(systemColor, time.getTime(), timeGrammar, window.theme["convo/text/joinmemo"])))
else:
time = parent.time
if msg[0:3] == "/me" or msg[0:13] == "PESTERCHUM:ME":
if msg[0:3] == "/me":
start = 3
else:
start = 13
space = msg.find(" ")
msg = chum.memsg(systemColor, msg[start:space], msg[space:], timegrammar=time.getGrammar())
window.chatlog.log(parent.channel, convertTags(msg, "bbcode"))
self.append(convertTags(msg))
else:
if chum is not me:
msg = addTimeInitial(msg, parent.times[chum.handle].getGrammar())
msg = escapeBrackets(msg)
self.append(convertTags(msg))
window.chatlog.log(parent.channel, convertTags(msg, "bbcode"))
def changeTheme(self):
pass
@ -46,10 +253,11 @@ class MemoInput(PesterInput):
self.setStyleSheet(theme["memos/input/style"])
class PesterMemo(PesterConvo):
def __init__(self, channel, mainwindow, parent=None):
def __init__(self, channel, timestr, mainwindow, parent=None):
QtGui.QFrame.__init__(self, parent)
self.channel = channel
self.mainwindow = mainwindow
self.time = TimeTracker(txt2delta(timestr))
self.setWindowTitle(channel)
self.channelLabel = QtGui.QLabel(self)
self.channelLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding))
@ -61,8 +269,13 @@ class PesterMemo(PesterConvo):
self.userlist = QtGui.QListWidget(self)
self.userlist.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding))
self.timeslider = QtGui.QSlider(QtCore.Qt.Vertical, self)
self.timeinput = QtGui.QLineEdit(self)
self.timeslider = TimeSlider(QtCore.Qt.Horizontal, self)
self.timeinput = TimeInput(self.timeslider, self)
self.timeinput.setText(timestr)
self.timeinput.setSlider()
self.timetravel = QtGui.QPushButton("GO", self)
self.times = {}
self.initTheme(self.mainwindow.theme)
@ -71,27 +284,36 @@ class PesterMemo(PesterConvo):
self, QtCore.SLOT('sentMessage()'))
layout_0 = QtGui.QVBoxLayout()
layout_0.addWidget(self.channelLabel)
layout_0.addWidget(self.textArea)
layout_0.addWidget(self.textInput)
layout_1 = QtGui.QGridLayout()
layout_1.addWidget(self.timeslider, 0, 1, QtCore.Qt.AlignHCenter)
layout_1.addWidget(self.timeinput, 1, 0, 1, 3)
layout_1 = QtGui.QHBoxLayout()
layout_1.addLayout(layout_0)
layout_1.addWidget(self.userlist)
self.layout = QtGui.QHBoxLayout()
self.setLayout(self.layout)
# layout_1 = QtGui.QGridLayout()
# layout_1.addWidget(self.timeslider, 0, 1, QtCore.Qt.AlignHCenter)
# layout_1.addWidget(self.timeinput, 1, 0, 1, 3)
layout_2 = QtGui.QHBoxLayout()
layout_2.addWidget(self.timeslider)
layout_2.addWidget(self.timeinput)
layout_2.addWidget(self.timetravel)
self.layout.addLayout(layout_0)
self.layout.addWidget(self.userlist)
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.channelLabel)
self.layout.addLayout(layout_1)
self.layout.addLayout(layout_2)
self.layout.setSpacing(0)
margins = self.mainwindow.theme["memos/margins"]
self.layout.setContentsMargins(margins["left"], margins["top"],
margins["right"], margins["bottom"])
self.setLayout(self.layout)
if parent:
parent.addChat(self)
self.newmessage = False
def title(self):
@ -99,17 +321,28 @@ class PesterMemo(PesterConvo):
def icon(self):
return PesterIcon(self.mainwindow.theme["memos/memoicon"])
def sendTimeInfo(self, newChum=False):
if newChum:
self.messageSent.emit("PESTERCHUM:TIME>%s" % (delta2txt(self.time.getTime(), "server")+"i"),
self.title())
else:
self.messageSent.emit("PESTERCHUM:TIME>%s" % (delta2txt(self.time.getTime(), "server")),
self.title())
def updateMood(self):
pass
def updateBlocked(self):
pass
def updateColor(self):
pass
def updateColor(self, handle, color):
chums = self.userlist.findItems(handle, QtCore.Qt.MatchFlags(0))
for c in chums:
c.setTextColor(color)
def addMessage(self, text, handle):
if type(handle) is bool:
chum = self.mainwindow.profile()
else:
chum = PesterProfile(handle)
self.notifyNewMessage()
self.textArea.addMessage(text, chum)
def initTheme(self, theme):
@ -125,7 +358,7 @@ class PesterMemo(PesterConvo):
self.channelLabel.setMaximumHeight(theme["memos/label/maxheight"])
self.channelLabel.setMinimumHeight(theme["memos/label/minheight"])
self.userlist.setStyleSheet(theme["main/chums/style"])
self.userlist.setStyleSheet(theme["memos/userlist/style"])
self.userlist.setFixedWidth(theme["memos/userlist/width"])
self.timeinput.setFixedWidth(theme["memos/time/text/width"])
@ -137,23 +370,127 @@ class PesterMemo(PesterConvo):
self.initTheme(theme)
self.textArea.changeTheme(theme)
self.textInput.changeTheme(theme)
margins = theme["memos/margins"]
self.layout.setContentsMargins(margins["left"], margins["top"],
margins["right"], margins["bottom"])
def addUser(self, handle):
chumdb = self.mainwindow.chumdb
defaultcolor = QtGui.QColor("black")
op = False
if handle[0] == '@':
op = True
handle = handle[1:]
item = QtGui.QListWidgetItem(handle)
if handle == self.mainwindow.profile().handle:
color = self.mainwindow.profile().color
else:
color = chumdb.getColor(handle, defaultcolor)
item.setTextColor(color)
self.userlist.addItem(item)
def timeUpdate(self, handle, cmd):
window = self.mainwindow
chum = PesterProfile(handle)
systemColor = QtGui.QColor(window.theme["memos/systemMsgColor"])
close = None
# old TC command?
try:
secs = int(cmd)
time = datetime.fromtimestamp(secs)
timed = time - datetime.now()
s = (timed // 60)*60
timed = timedelta(timed.days, s)
except ValueError:
if cmd == "i":
timed = timedelta(0)
else:
if cmd[len(cmd)-1] == 'c':
close = timeProtocol(cmd)
timed = None
else:
timed = timeProtocol(cmd)
if self.times.has_key(handle):
if close is not None:
if close in self.times[handle]:
self.times[handle].setCurrent(close)
grammar = self.times[handle].getGrammar()
self.times[handle].removeTime(close)
self.textArea.append(convertTags(chum.memoclosemsg(systemColor, grammar, window.theme["convo/text/closememo"])))
elif timed not in self.times[handle]:
self.times[handle].addTime(timed)
grammar = self.times[handle].getGrammar()
self.textArea.append(convertTags(chum.memojoinmsg(systemColor, timed, grammar, window.theme["convo/text/joinmemo"])))
else:
self.times[handle].setCurrent(timed)
else:
if timed is not None:
ttracker = TimeTracker(timed)
grammar = ttracker.getGrammar()
self.textArea.append(convertTags(chum.memojoinmsg(systemColor, timed, grammar, window.theme["convo/text/joinmemo"])))
self.times[handle] = ttracker
@QtCore.pyqtSlot()
def sentMessage(self):
text = self.textInput.text()
if text == "":
return
text = "<c=%s>%s</c>" % (self.mainwindow.profile().colorcmd(), text)
self.textInput.setText(text)
PesterConvo.sentMessage(self)
grammar = self.time.getGrammar()
# deal with quirks here
qtext = self.mainwindow.userprofile.quirks.apply(unicode(text))
if qtext[0:3] != "/me":
initials = self.mainwindow.profile().initials()
colorcmd = self.mainwindow.profile().colorcmd()
clientText = "<c=%s>%s%s%s: %s</c>" % (colorcmd, grammar.pcf, initials, grammar.number, qtext)
# account for TC's parsing error
serverText = "<c=%s>%s: %s</c> " % (colorcmd, initials, qtext)
else:
clientText = qtext
serverText = clientText
self.textInput.setText("")
self.addMessage(clientText, True)
# convert color tags
text = convertTags(unicode(serverText), "ctag")
self.messageSent.emit(serverText, self.title())
@QtCore.pyqtSlot()
def namesUpdated(self):
# get namesdb
namesdb = self.mainwindow.namesdb
# reload names
self.userlist.clear()
for n in self.mainwindow.namesdb[self.channel]:
self.addUser(n)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
def userPresentChange(self, handle, channel, update):
if channel != self.channel:
return
chums = self.userlist.findItems(handle, QtCore.Qt.MatchFlags(0))
h = unicode(handle)
c = unicode(channel)
systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
# print exit
if update == "quit" or update == "left":
for c in chums:
chum = PesterProfile(h)
self.userlist.takeItem(self.userlist.row(c))
while self.times[h].getTime() is not None:
t = self.times[h]
grammar = t.getGrammar()
self.textArea.append(convertTags(chum.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"])))
self.times[h].removeTime(t.getTime())
elif update == "join":
self.addUser(h)
def closeEvent(self, event):
self.mainwindow.waitingMessages.messageAnswered(self.channel)
# self.windowClosed.emit(self.chum.handle)
self.windowClosed.emit(self.title())
windowClosed = QtCore.pyqtSignal(QtCore.QString)
# messageSent - signal -> sendMessage -> sendMessage(Memo)
# windowClosed - signal -> closeMemo
timelist = ["0:00", "0:01", "0:02", "0:04", "0:06", "0:10", "0:14", "0:22", "0:30", "0:41", "1:00", "1:34", "2:16", "3:14", "4:13", "4:20", "5:25", "6:12", "7:30", "8:44", "10:25", "11:34", "14:13", "16:12", "17:44", "22:22", "25:10", "33:33", "42:00", "43:14", "50:00", "62:12", "75:00", "88:44", "100", "133", "143", "188", "200", "222", "250", "314", "333", "413", "420", "500", "600", "612", "888", "1000", "1025"]
# self.textInput
# self.textArea
timedlist = [timedelta(0), timedelta(0, 60), timedelta(0, 120), timedelta(0, 240), timedelta(0, 360), timedelta(0, 600), timedelta(0, 840), timedelta(0, 1320), timedelta(0, 1800), timedelta(0, 2460), timedelta(0, 3600), timedelta(0, 5640), timedelta(0, 8160), timedelta(0, 11640), timedelta(0, 15180), timedelta(0, 15600), timedelta(0, 19500), timedelta(0, 22320), timedelta(0, 27000), timedelta(0, 31440), timedelta(0, 37500), timedelta(0, 41640), timedelta(0, 51180), timedelta(0, 58320), timedelta(0, 63840), timedelta(0, 80520), timedelta(1, 4200), timedelta(1, 34380), timedelta(1, 64800), timedelta(1, 69240), timedelta(2, 7200), timedelta(2, 51120), timedelta(3, 10800), timedelta(3, 60240), timedelta(4, 14400), timedelta(5, 46800), timedelta(5, 82800), timedelta(7, 72000), timedelta(8, 28800), timedelta(9, 21600), timedelta(10, 36000), timedelta(13, 7200), timedelta(13, 75600), timedelta(17, 18000), timedelta(17, 43200), timedelta(20, 72000), timedelta(25), timedelta(25, 43200), timedelta(37), timedelta(41, 57600), timedelta(42, 61200)]

BIN
memos.pyc

Binary file not shown.

View file

@ -3,6 +3,7 @@ import re
from generic import RightClickList, MultiTextDialog
from dataobjs import pesterQuirk, PesterProfile
from memos import TimeSlider, TimeInput
class PesterQuirkItem(QtGui.QListWidgetItem):
def __init__(self, quirk, parent):
@ -407,13 +408,17 @@ class PesterMemoList(QtGui.QDialog):
self.orjoinlabel = QtGui.QLabel("OR MAKE A NEW MEMO:")
self.newmemo = QtGui.QLineEdit(self)
self.timelabel = QtGui.QLabel("TIMEFRAME:")
self.timeslider = TimeSlider(QtCore.Qt.Horizontal, self)
self.timeinput = TimeInput(self.timeslider, self)
self.cancel = QtGui.QPushButton("CANCEL", self)
self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('reject()'))
self.join = QtGui.QPushButton("JOIN", self)
self.join.setDefault(True)
self.connect(self.join, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('accept()'))
self, QtCore.SLOT('checkEmpty()'))
layout_ok = QtGui.QHBoxLayout()
layout_ok.addWidget(self.cancel)
layout_ok.addWidget(self.join)
@ -423,6 +428,9 @@ class PesterMemoList(QtGui.QDialog):
layout_0.addWidget(self.channelarea)
layout_0.addWidget(self.orjoinlabel)
layout_0.addWidget(self.newmemo)
layout_0.addWidget(self.timelabel)
layout_0.addWidget(self.timeslider)
layout_0.addWidget(self.timeinput)
layout_0.addLayout(layout_ok)
self.setLayout(layout_0)
@ -446,6 +454,12 @@ class PesterMemoList(QtGui.QDialog):
item.setTextColor(QtGui.QColor(theme["main/chums/userlistcolor"]))
item.setIcon(QtGui.QIcon(theme["memos/memoicon"]))
@QtCore.pyqtSlot()
def checkEmpty(self):
newmemo = self.newmemoname()
selectedmemo = self.selectedmemo()
if newmemo or selectedmemo:
self.accept()
@QtCore.pyqtSlot(QtGui.QListWidgetItem)
def joinActivatedMemo(self, item):
self.channelarea.setCurrentItem(item)
@ -460,16 +474,11 @@ class LoadingScreen(QtGui.QDialog):
self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
self.loadinglabel = QtGui.QLabel("LO4D1NG")
self.cancel = QtGui.QPushButton("QU1T >:?")
self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('reject()'))
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.loadinglabel)
self.layout.addWidget(self.cancel)
self.setLayout(self.layout)
QtCore.QTimer.singleShot(25000, self, QtCore.SLOT('connectTimeout()'))
@QtCore.pyqtSlot()
def connectTimeout(self):
if hasattr(self, 'failed'):
self.accept()
else:
self.failed = True
self.loadinglabel.setText("F41L3D")
QtCore.QTimer.singleShot(1000, self, QtCore.SLOT('connectTimeout()'))

BIN
menus.pyc

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +1,5 @@
import re
from datetime import timedelta
from PyQt4 import QtGui
_ctag_begin = re.compile(r'<c=(.*?)>')
@ -87,3 +88,23 @@ def escapeBrackets(string):
for i in range(0, btlen-etlen):
retval += "</c>"
return retval
def addTimeInitial(string, grammar):
endofi = string.find(":")
endoftag = string.find(">")
if endoftag < 0 or endoftag > 16 or endofi > 17:
return string
return string[0:endoftag+1]+grammar.pcf+string[endoftag+1:endofi]+grammar.number+string[endofi:]
def timeProtocol(cmd):
dir = cmd[0]
cmd = cmd[1:]
cmd = re.sub("[^0-9:]", "", cmd)
try:
l = [int(x) for x in cmd.split(":")]
except ValueError:
l = [0,0]
timed = timedelta(0, l[0]*3600+l[1]*60)
if dir == "P":
timed = timed*-1
return timed

Binary file not shown.

View file

@ -1 +1 @@
{"tabs": false, "chums": ["aquaMarinist", "marineAquist", "unknownTraveler", "tentacleTherapist", "macruralAlchemist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "fireSwallow", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador"], "defaultprofile": "testProfile", "block": []}
{"tabs": true, "chums": ["aquaMarinist", "marineAquist", "unknownTraveler", "tentacleTherapist", "macruralAlchemist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "fireSwallow", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium"], "defaultprofile": "testProfile", "block": []}

View file

@ -1,7 +1,4 @@
# pesterchum
from oyoyo.client import IRCClient
from oyoyo.cmdhandler import DefaultCommandHandler
from oyoyo import helpers
import logging
import os, sys
import os.path
@ -17,12 +14,11 @@ from menus import PesterChooseQuirks, PesterChooseTheme, \
PesterChooseProfile, PesterOptions, PesterUserlist, PesterMemoList, \
LoadingScreen
from dataobjs import PesterProfile, Mood, pesterQuirk, pesterQuirks
from generic import PesterIcon, RightClickList, MultiTextDialog
from generic import PesterIcon, RightClickList, MultiTextDialog, PesterList
from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo
from parsetools import convertTags
from memos import PesterMemo, MemoTabWindow
logging.basicConfig(level=logging.INFO)
from irc import PesterIRC
class waitingMessageHolder(object):
def __init__(self, mainwindow, **msgfuncs):
@ -110,10 +106,6 @@ class PesterProfileDB(dict):
dict.__setitem__(self, key, val)
self.save()
class PesterList(list):
def __init__(self, l):
self.extend(l)
class pesterTheme(dict):
def __init__(self, name):
self.path = "themes/%s" % (name)
@ -708,6 +700,8 @@ class PesterWindow(MovingWindow):
if not self.config.defaultprofile():
self.changeProfile()
self.loadingscreen = LoadingScreen(self)
self.connect(self.loadingscreen, QtCore.SIGNAL('rejected()'),
self, QtCore.SLOT('close()'))
def profile(self):
return self.userprofile.chat
@ -756,6 +750,7 @@ class PesterWindow(MovingWindow):
return
memo = self.memos[chan]
memo.addMessage(msg, handle)
self.alarm.play()
def changeColor(self, handle, color):
# pesterconvo and chumlist
@ -798,28 +793,34 @@ class PesterWindow(MovingWindow):
self.connect(self.tabmemo, QtCore.SIGNAL('windowClosed()'),
self, QtCore.SLOT('memoTabsClosed()'))
def newMemo(self, channel):
def newMemo(self, channel, timestr):
if channel == "#pesterchum":
return
if self.memos.has_key(channel):
# load memo
self.memos[channel].showChat()
return
# do slider dialog then set
if self.config.tabs():
if not self.tabmemo:
self.createMemoTabWindow()
memoWindow = PesterMemo(channel, self, self.tabmemo)
memoWindow = PesterMemo(channel, timestr, self, self.tabmemo)
self.tabmemo.show()
else:
memoWindow = PesterMemo(channel, self, None)
memoWindow = PesterMemo(channel, timestr, self, None)
# connect signals
self.connect(memoWindow, QtCore.SIGNAL('messageSent(QString, QString)'),
self, QtCore.SIGNAL('sendMessage(QString, QString)'))
# self.connect(memoWindow, QtCore.SIGNAL('windowClosed(QString)'),
# self, QtCore.SLOT('closeConvo(QString)'))
self.connect(memoWindow, QtCore.SIGNAL('windowClosed(QString)'),
self, QtCore.SLOT('closeMemo(QString)'))
self.connect(self, QtCore.SIGNAL('namesUpdated()'),
memoWindow, QtCore.SLOT('namesUpdated()'))
self.connect(self,
QtCore.SIGNAL('userPresentSignal(QString, QString, QString)'),
memoWindow, QtCore.SLOT('userPresentChange(QString, QString, QString)'))
# chat client send memo open
self.memos[channel] = memoWindow
self.joinChannel.emit(channel)
self.joinChannel.emit(channel) # race condition?
memoWindow.sendTimeInfo()
memoWindow.show()
def addChum(self, chum):
@ -859,6 +860,7 @@ class PesterWindow(MovingWindow):
self.opts.setText(theme["main/menus/client/options"])
self.exitaction.setText(theme["main/menus/client/exit"])
self.userlistaction.setText(theme["main/menus/client/userlist"])
self.memoaction.setText(theme["main/menus/client/memos"])
self.filemenu.setTitle(theme["main/menus/client/_name"])
self.changetheme.setText(theme["main/menus/profile/theme"])
self.changequirks.setText(theme["main/menus/profile/quirks"])
@ -949,7 +951,7 @@ class PesterWindow(MovingWindow):
@QtCore.pyqtSlot()
def connected(self):
if self.loadingscreen:
self.loadingscreen.close()
self.loadingscreen.accept()
self.loadingscreen = None
@QtCore.pyqtSlot()
def blockSelectedChum(self):
@ -977,9 +979,15 @@ class PesterWindow(MovingWindow):
chumopen = self.convos[h].chumopen
if chumopen:
self.chatlog.log(chum.handle, convertTags(self.profile().pestermsg(chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/ceasepester"]), "bbcode"))
self.chatlog.finish(h)
self.convoClosed.emit(handle)
self.chatlog.finish(h)
del self.convos[h]
@QtCore.pyqtSlot(QtCore.QString)
def closeMemo(self, channel):
c = unicode(channel)
self.chatlog.finish(c)
self.leftChannel.emit(channel)
del self.memos[c]
@QtCore.pyqtSlot()
def tabsClosed(self):
del self.tabconvo
@ -1008,6 +1016,11 @@ class PesterWindow(MovingWindow):
def deliverMemo(self, chan, handle, msg):
(c, h, m) = (unicode(chan), unicode(handle), unicode(msg))
self.newMemoMsg(c,h,m)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
def timeCommand(self, chan, handle, command):
(c, h, cmd) = (unicode(chan), unicode(handle), unicode(command))
if self.memos[c]:
self.memos[c].timeUpdate(h, cmd)
@QtCore.pyqtSlot(QtCore.QString, PesterList)
def updateNames(self, channel, names):
@ -1121,12 +1134,13 @@ class PesterWindow(MovingWindow):
def joinSelectedMemo(self):
newmemo = self.memochooser.newmemoname()
selectedmemo = self.memochooser.selectedmemo()
time = unicode(self.memochooser.timeinput.text())
if newmemo:
channel = "#"+unicode(newmemo)
self.newMemo(channel)
self.newMemo(channel, time)
elif selectedmemo:
channel = "#"+unicode(selectedmemo.text())
self.newMemo(channel)
self.newMemo(channel, time)
self.memochooser = None
@QtCore.pyqtSlot()
def memoChooserClose(self):
@ -1208,13 +1222,20 @@ class PesterWindow(MovingWindow):
tabsetting = self.optionmenu.tabcheck.isChecked()
if curtab and not tabsetting:
# split tabs into windows
windows = []
if self.tabconvo:
windows = list(self.tabconvo.convos.values())
for w in windows:
w.setParent(None)
w.show()
w.raiseChat()
if self.tabmemo:
windows += list(self.tabmemo.convos.values())
for w in windows:
w.setParent(None)
w.show()
w.raiseChat()
if self.tabconvo:
self.tabconvo.closeSoft()
if self.tabmemo:
self.tabmemo.closeSoft()
# save options
self.config.set("tabs", tabsetting)
elif tabsetting and not curtab:
@ -1227,6 +1248,14 @@ class PesterWindow(MovingWindow):
self.tabconvo.show()
newconvos[h] = c
self.convos = newconvos
newmemos = {}
self.createMemoTabWindow()
for (h,m) in self.memos.iteritems():
m.setParent(self.tabmemo)
self.tabmemo.addChat(m)
self.tabmemo.show()
newmemos[h] = m
self.memos = newmemos
# save options
self.config.set("tabs", tabsetting)
self.optionmenu = None
@ -1366,203 +1395,7 @@ class PesterWindow(MovingWindow):
blockedChum = QtCore.pyqtSignal(QtCore.QString)
unblockedChum = QtCore.pyqtSignal(QtCore.QString)
joinChannel = QtCore.pyqtSignal(QtCore.QString)
class PesterIRC(QtCore.QObject):
def __init__(self, window):
QtCore.QObject.__init__(self)
self.mainwindow = window
def IRCConnect(self):
self.cli = IRCClient(PesterHandler, host="irc.tymoon.eu", port=6667, nick=self.mainwindow.profile().handle, blocking=True)
self.cli.command_handler.parent = self
self.cli.command_handler.mainwindow = self.mainwindow
self.conn = self.cli.connect()
@QtCore.pyqtSlot(PesterProfile)
def getMood(self, *chums):
self.cli.command_handler.getMood(*chums)
@QtCore.pyqtSlot(PesterList)
def getMoods(self, chums):
self.cli.command_handler.getMood(*chums)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
def sendMessage(self, text, handle):
h = unicode(handle)
helpers.msg(self.cli, h, text)
@QtCore.pyqtSlot(QtCore.QString, bool)
def startConvo(self, handle, initiated):
h = unicode(handle)
if initiated:
helpers.msg(self.cli, h, "PESTERCHUM:BEGIN")
helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
@QtCore.pyqtSlot(QtCore.QString)
def endConvo(self, handle):
h = unicode(handle)
helpers.msg(self.cli, h, "PESTERCHUM:CEASE")
@QtCore.pyqtSlot()
def updateProfile(self):
me = self.mainwindow.profile()
handle = me.handle
helpers.nick(self.cli, handle)
self.updateMood()
@QtCore.pyqtSlot()
def updateMood(self):
me = self.mainwindow.profile()
helpers.msg(self.cli, "#pesterchum", "MOOD >%d" % (me.mood.value()))
@QtCore.pyqtSlot()
def updateColor(self):
me = self.mainwindow.profile()
for h in self.mainwindow.convos.keys():
helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
@QtCore.pyqtSlot(QtCore.QString)
def blockedChum(self, handle):
h = unicode(handle)
helpers.msg(self.cli, h, "PESTERCHUM:BLOCK")
@QtCore.pyqtSlot(QtCore.QString)
def unblockedChum(self, handle):
h = unicode(handle)
helpers.msg(self.cli, h, "PESTERCHUM:UNBLOCK")
@QtCore.pyqtSlot(QtCore.QString)
def requestNames(self, channel):
c = unicode(channel)
helpers.names(self.cli, c)
@QtCore.pyqtSlot()
def requestChannelList(self):
helpers.channel_list(self.cli)
@QtCore.pyqtSlot(QtCore.QString)
def joinChannel(self, channel):
c = unicode(channel)
helpers.join(self.cli, c)
def updateIRC(self):
self.conn.next()
moodUpdated = QtCore.pyqtSignal(QtCore.QString, Mood)
colorUpdated = QtCore.pyqtSignal(QtCore.QString, QtGui.QColor)
messageReceived = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
memoReceived = QtCore.pyqtSignal(QtCore.QString, QtCore.QString, QtCore.QString)
namesReceived = QtCore.pyqtSignal(QtCore.QString, PesterList)
channelListReceived = QtCore.pyqtSignal(PesterList)
nickCollision = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
connected = QtCore.pyqtSignal()
userPresentUpdate = QtCore.pyqtSignal(QtCore.QString, QtCore.QString,
QtCore.QString)
class PesterHandler(DefaultCommandHandler):
def privmsg(self, nick, chan, msg):
# display msg, do other stuff
# silently ignore CTCP
if msg[0] == '\x01':
return
handle = nick[0:nick.find("!")]
logging.info("---> recv \"PRIVMSG %s :%s\"" % (handle, msg))
if chan == "#pesterchum":
# follow instructions
if msg[0:6] == "MOOD >":
try:
mood = Mood(int(msg[6:]))
except ValueError:
mood = Mood(0)
self.parent.moodUpdated.emit(handle, mood)
elif msg[0:7] == "GETMOOD":
mychumhandle = self.mainwindow.profile().handle
mymood = self.mainwindow.profile().mood.value()
if msg.find(mychumhandle, 8) != -1:
helpers.msg(self.client, "#pesterchum",
"MOOD >%d" % (mymood))
elif chan[0] == '#':
if msg[0:16] == "PESTERCHUM:TIME>":
# send time msg
pass
else:
self.parent.memoReceived.emit(chan, handle, msg)
else:
# private message
# silently ignore messages to yourself.
if handle == self.mainwindow.profile().handle:
return
if msg[0:7] == "COLOR >":
colors = msg[7:].split(",")
try:
colors = [int(d) for d in colors]
except ValueError:
colors = [0,0,0]
color = QtGui.QColor(*colors)
self.parent.colorUpdated.emit(handle, color)
else:
self.parent.messageReceived.emit(handle, msg)
def welcome(self, server, nick, msg):
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))
helpers.nick(self.client, newnick)
self.parent.nickCollision.emit(nick, newnick)
def quit(self, nick, reason):
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, "", "quit")
self.parent.moodUpdated.emit(handle, Mood("offline"))
def part(self, nick, channel, reason="nanchos"):
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, channel, "left")
if channel == "#pesterchum":
self.parent.moodUpdated.emit(handle, Mood("offline"))
def join(self, nick, channel):
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, channel, "join")
if channel == "#pesterchum":
self.parent.moodUpdated.emit(handle, Mood("chummy"))
def nick(self, oldnick, newnick):
oldhandle = oldnick[0:oldnick.find("!")]
newchum = PesterProfile(newnick, chumdb=self.mainwindow.chumdb)
self.parent.moodUpdated.emit(oldhandle, Mood("offline"))
if newnick in self.mainwindow.chumList.chums:
self.getMood(newchum)
def namreply(self, server, nick, op, channel, names):
namelist = names.split(" ")
logging.info("---> recv \"NAMES %s: %d names\"" % (channel, len(namelist)))
if not hasattr(self, 'channelnames'):
self.channelnames = {}
if not self.channelnames.has_key(channel):
self.channelnames[channel] = []
self.channelnames[channel].extend(namelist)
def endofnames(self, server, nick, channel, msg):
namelist = self.channelnames[channel]
pl = PesterList(namelist)
del self.channelnames[channel]
self.parent.namesReceived.emit(channel, pl)
def liststart(self, server, handle, *info):
self.channel_list = []
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:
helpers.msg(self.client, "#pesterchum", chumglub)
chumglub = "GETMOOD "
chumglub += chandle
if chumglub != "GETMOOD ":
helpers.msg(self.client, "#pesterchum", chumglub)
leftChannel = QtCore.pyqtSignal(QtCore.QString)
class IRCThread(QtCore.QThread):
def __init__(self, ircobj):
@ -1662,6 +1495,11 @@ def main():
QtCore.SIGNAL('joinChannel(QString)'),
irc,
QtCore.SLOT('joinChannel(QString)'))
irc.connect(widget,
QtCore.SIGNAL('leftChannel(QString)'),
irc,
QtCore.SLOT('leftChannel(QString)'))
# IRC --> Main window
irc.connect(irc, QtCore.SIGNAL('connected()'),
@ -1698,10 +1536,16 @@ def main():
QtCore.SIGNAL('channelListReceived(PyQt_PyObject)'),
widget,
QtCore.SLOT('updateChannelList(PyQt_PyObject)'))
irc.connect(irc,
QtCore.SIGNAL('timeCommand(QString, QString, QString)'),
widget,
QtCore.SLOT('timeCommand(QString, QString, QString)'))
ircapp = IRCThread(irc)
ircapp.start()
widget.loadingscreen.exec_()
status = widget.loadingscreen.exec_()
if status == QtGui.QDialog.Rejected:
sys.exit(0)
sys.exit(app.exec_())
main()

View file

@ -208,7 +208,10 @@
"beganpester": "began pestering",
"ceasepester": "ceased pestering",
"blocked": "blocked",
"unblocked": "unblocked"
"unblocked": "unblocked",
"openmemo": "opened memo on board",
"joinmemo": "responded to memo",
"closememo": "ceased responding to memo"
},
"systemMsgColor": "#646464"
},
@ -231,11 +234,14 @@
"input": { "style": "background: white; border:2px solid #c48a00;margin-top:5px;" },
"textarea": { "style": "background: white; font:bold; border:2px solid #c48a00;text-align:center;" },
"margins": {"top": 0, "bottom": 0, "left": 0, "right": 0 },
"userlist": { "width": 150 },
"userlist": { "width": 150,
"style": "border:2px solid yellow; background: white;font: bold;font-family: 'Courier';selection-background-color:#646464; "
},
"time": { "text": { "width": 75, "style": "" },
"slider": { "style": "",
"groove": "",
"handle": "" }
"handle": ""
}
},
"systemMsgColor": "#646464"
}

View file

@ -256,13 +256,45 @@
"beganpester": "began trolling",
"ceasepester": "gave up trolling",
"blocked": "blocked",
"unblocked": "mercifully forgave"
"unblocked": "mercifully forgave",
"openmemo": "opened memo on board",
"joinmemo": "responded to memo",
"closememo": "ceased responding to memo"
},
"systemMsgColor": "#646464"
},
"memos":
{"memoicon": "$path/memo.png"
}
{"memoicon": "$path/memo.png",
"style": "background: rgb(190, 19, 4); font-family: 'Arial';",
"size": [600,300],
"tabs": {
"style": "",
"selectedstyle": "",
"newmsgcolor": "red",
"tabstyle": 0
},
"label": { "text": "$channel",
"style": "background: rgb(255, 38, 18); color: white; padding: 2px; border:1px solid #c2c2c2;",
"align": { "h": "center", "v": "center" },
"minheight": 30,
"maxheight": 50
},
"textarea": {
"style": "background: white; border:2px solid #c2c2c2; font-size: 12px; margin-top: 4px;"
},
"input": {
"style": "background: white;margin-top:5px; border:1px solid #c2c2c2; margin-right: 54px; font-size: 12px;"
},
"margins": {"top": 0, "bottom": 0, "left": 0, "right": 0 },
"userlist": { "width": 150,
"style": "font-size: 12px; background: white; border:2px solid #c2c2c2; padding: 5px; font-family: 'Arial';selection-background-color:rgb(200,200,200);"
},
"time": { "text": { "width": 75, "style": "" },
"slider": { "style": "",
"groove": "",
"handle": ""
}
},
"systemMsgColor": "#646464"
}
}