the great parser change!

This commit is contained in:
Stephen Dranger 2011-02-13 03:27:12 -06:00
parent aca11bb00e
commit c7987a37aa
23 changed files with 384 additions and 180 deletions

12
TODO
View file

@ -1,17 +1,17 @@
Features: Features:
* Tray doesn't disappear on windows after close * More complex quirks: spelling, by-sound
* memo sending from unknown color breaks -- over IRC * random quirk string enter must clear text box and focus input on add
* smilies processed before quirks * IRC message limit!!!
* More complex quirks: random, spelling, by-sound * on ban, redirect to memo chooser
* ? time option??? * ? time option???
* convert hex tags (<GFFFFFF> or <GFF0000>)
* help menu -- about and forum * help menu -- about and forum
* Tray doesn't disappear on windows after close
* memo sending from unknown color breaks -- over IRC??
-- release alpha -- release alpha
* shared buddy lists - changes to the buddy list should refresh it? * shared buddy lists - changes to the buddy list should refresh it?
multiple clients share buddy list??? multiple clients share buddy list???
* chumList not scaling -- QListView + delegate? * chumList not scaling -- QListView + delegate?
* spell check? * spell check?
* convo backgrounds -- make them more like http://www.mspaintadventures.com/storyfiles/hs2/02546_2.gif
* help button on quirks menu? * help button on quirks menu?
-- release beta -- release beta
* flashing?? * flashing??

121
convo.py
View file

@ -1,11 +1,12 @@
from string import Template from string import Template
import re import re
from copy import copy
from datetime import datetime, timedelta from datetime import datetime, timedelta
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from dataobjs import PesterProfile, Mood, PesterHistory from dataobjs import PesterProfile, Mood, PesterHistory
from generic import PesterIcon, RightClickList from generic import PesterIcon, RightClickList
from parsetools import convertTags from parsetools import convertTags, lexMessage, mecmd, colorBegin, colorEnd
class PesterTabWindow(QtGui.QFrame): class PesterTabWindow(QtGui.QFrame):
def __init__(self, mainwindow, parent=None, convo="convo"): def __init__(self, mainwindow, parent=None, convo="convo"):
@ -203,74 +204,72 @@ class PesterText(QtGui.QTextEdit):
self.setStyleSheet("QTextEdit { %s } QScrollBar:vertical { %s } QScrollBar::handle:vertical { %s } QScrollBar::add-line:vertical { %s } QScrollBar::sub-line:vertical { %s } QScrollBar:up-arrow:vertical { %s } QScrollBar:down-arrow:vertical { %s }" % (theme["convo/textarea/style"], theme["convo/scrollbar/style"], theme["convo/scrollbar/handle"], theme["convo/scrollbar/downarrow"], theme["convo/scrollbar/uparrow"], theme["convo/scrollbar/uarrowstyle"], theme["convo/scrollbar/darrowstyle"] )) self.setStyleSheet("QTextEdit { %s } QScrollBar:vertical { %s } QScrollBar::handle:vertical { %s } QScrollBar::add-line:vertical { %s } QScrollBar::sub-line:vertical { %s } QScrollBar:up-arrow:vertical { %s } QScrollBar:down-arrow:vertical { %s }" % (theme["convo/textarea/style"], theme["convo/scrollbar/style"], theme["convo/scrollbar/handle"], theme["convo/scrollbar/downarrow"], theme["convo/scrollbar/uparrow"], theme["convo/scrollbar/uarrowstyle"], theme["convo/scrollbar/darrowstyle"] ))
else: else:
self.setStyleSheet("QTextEdit { %s }" % (theme["convo/textarea/style"])) self.setStyleSheet("QTextEdit { %s }" % (theme["convo/textarea/style"]))
def addMessage(self, text, chum): def addMessage(self, lexmsg, chum):
color = chum.colorhtml() if len(lexmsg) == 0:
return
color = chum.colorcmd()
systemColor = QtGui.QColor(self.parent().mainwindow.theme["convo/systemMsgColor"]) systemColor = QtGui.QColor(self.parent().mainwindow.theme["convo/systemMsgColor"])
initials = chum.initials() initials = chum.initials()
msg = unicode(text)
parent = self.parent() parent = self.parent()
window = parent.mainwindow window = parent.mainwindow
me = window.profile() me = window.profile()
quirks = window.userprofile.quirks if parent.applyquirks else None if lexmsg[0] == "PESTERCHUM:BEGIN":
if msg == "PESTERCHUM:BEGIN":
parent.setChumOpen(True) parent.setChumOpen(True)
msg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"]) pmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(msg)) self.append(convertTags(pmsg))
elif msg == "PESTERCHUM:CEASE": elif lexmsg[0] == "PESTERCHUM:CEASE":
parent.setChumOpen(False) parent.setChumOpen(False)
msg = chum.pestermsg(me, systemColor, window.theme["convo/text/ceasepester"]) pmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/ceasepester"])
window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(msg)) self.append(convertTags(pmsg))
elif msg == "PESTERCHUM:BLOCK": elif lexmsg[0] == "PESTERCHUM:BLOCK":
msg = chum.pestermsg(me, systemColor, window.theme['convo/text/blocked']) pmsg = chum.pestermsg(me, systemColor, window.theme['convo/text/blocked'])
window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(msg)) self.append(convertTags(pmsg))
elif msg == "PESTERCHUM:UNBLOCK": elif lexmsg[0] == "PESTERCHUM:UNBLOCK":
msg = chum.pestermsg(me, systemColor, window.theme['convo/text/unblocked']) pmsg = chum.pestermsg(me, systemColor, window.theme['convo/text/unblocked'])
window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(msg)) self.append(convertTags(pmsg))
elif msg == "PESTERCHUM:BLOCKED": elif lexmsg[0] == "PESTERCHUM:BLOCKED":
msg = chum.pestermsg(me, systemColor, window.theme['convo/text/blockedmsg']) pmsg = chum.pestermsg(me, systemColor, window.theme['convo/text/blockedmsg'])
window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(msg)) self.append(convertTags(pmsg))
elif msg == "PESTERCHUM:IDLE": elif lexmsg[0] == "PESTERCHUM:IDLE":
msg = chum.idlemsg(systemColor, window.theme['convo/text/idle']) imsg = chum.idlemsg(systemColor, window.theme['convo/text/idle'])
window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) window.chatlog.log(chum.handle, imsg)
self.append(convertTags(msg)) self.append(convertTags(imsg))
elif msg[0:3] == "/me" or msg[0:13] == "PESTERCHUM:ME": elif type(lexmsg[0]) is mecmd:
if quirks: memsg = chum.memsg(systemColor, lexmsg)
msg = quirks.apply(msg)
if msg[0:3] == "/me":
start = 3
else:
start = 13
space = msg.find(" ")
msg = chum.memsg(systemColor, msg[start:space], msg[space:])
if chum is me: if chum is me:
window.chatlog.log(parent.chum.handle, convertTags(msg, "bbcode")) window.chatlog.log(parent.chum.handle, memsg)
else: else:
window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) window.chatlog.log(chum.handle, memsg)
self.append(convertTags(msg)) self.append(convertTags(memsg))
else: else:
if not parent.chumopen and chum is not me: if not parent.chumopen and chum is not me:
beginmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"]) beginmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
parent.setChumOpen(True) parent.setChumOpen(True)
window.chatlog.log(chum.handle, convertTags(beginmsg, "bbcode")) window.chatlog.log(chum.handle, beginmsg)
self.append(convertTags(beginmsg)) self.append(convertTags(beginmsg))
msg = "<c=%s>%s: %s</c>" % (color, initials, msg) lexmsg[0:0] = [colorBegin("<c=%s>" % (color), color),
self.append(convertTags(msg, quirkobj=quirks)) "%s: " % (initials)]
lexmsg.append(colorEnd("</c>"))
self.append(convertTags(lexmsg))
if chum is me: if chum is me:
window.chatlog.log(parent.chum.handle, convertTags(msg, "bbcode", quirkobj=quirks)) window.chatlog.log(parent.chum.handle, lexmsg)
else: else:
if window.idle: if window.idleaction.isChecked():
idlethreshhold = 60 idlethreshhold = 60
if (not hasattr(self, 'lastmsg')) or \ if (not hasattr(self, 'lastmsg')) or \
datetime.now() - self.lastmsg > timedelta(0,60): datetime.now() - self.lastmsg > timedelta(0,idlethreshhold):
idlemsg = me.idlemsg(systemColor, verb)
self.textArea.append(convertTags(idlemsg))
window.chatlog.log(self.title(), idlemsg)
parent.messageSent.emit("PESTERCHUM:IDLE", parent.title()) parent.messageSent.emit("PESTERCHUM:IDLE", parent.title())
self.lastmsg = datetime.now() self.lastmsg = datetime.now()
window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) window.chatlog.log(chum.handle, lexmsg)
def changeTheme(self, theme): def changeTheme(self, theme):
self.initTheme(theme) self.initTheme(theme)
sb = self.verticalScrollBar() sb = self.verticalScrollBar()
@ -303,6 +302,7 @@ class PesterInput(QtGui.QLineEdit):
self.setStyleSheet(theme["convo/input/style"]) self.setStyleSheet(theme["convo/input/style"])
def focusInEvent(self, event): def focusInEvent(self, event):
self.parent().clearNewMessage() self.parent().clearNewMessage()
self.parent().textArea.textCursor().clearSelection()
QtGui.QLineEdit.focusInEvent(self, event) QtGui.QLineEdit.focusInEvent(self, event)
def keyPressEvent(self, event): def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Up: if event.key() == QtCore.Qt.Key_Up:
@ -388,7 +388,7 @@ class PesterConvo(QtGui.QFrame):
msg = self.mainwindow.profile().pestermsg(self.chum, QtGui.QColor(self.mainwindow.theme["convo/systemMsgColor"]), self.mainwindow.theme["convo/text/beganpester"]) msg = self.mainwindow.profile().pestermsg(self.chum, QtGui.QColor(self.mainwindow.theme["convo/systemMsgColor"]), self.mainwindow.theme["convo/text/beganpester"])
self.setChumOpen(True) self.setChumOpen(True)
self.textArea.append(convertTags(msg)) self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.title(), convertTags(msg, "bbcode")) self.mainwindow.chatlog.log(self.title(), msg)
self.newmessage = False self.newmessage = False
self.history = PesterHistory() self.history = PesterHistory()
@ -403,12 +403,12 @@ class PesterConvo(QtGui.QFrame):
self.mainwindow.ceasesound.play() self.mainwindow.ceasesound.play()
msg = self.chum.pestermsg(self.mainwindow.profile(), syscolor, self.mainwindow.theme["convo/text/ceasepester"]) msg = self.chum.pestermsg(self.mainwindow.profile(), syscolor, self.mainwindow.theme["convo/text/ceasepester"])
self.textArea.append(convertTags(msg)) self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.title(), convertTags(msg, "bbcode")) self.mainwindow.chatlog.log(self.title(), msg)
self.chumopen = False self.chumopen = False
elif old and old.name() != mood.name(): elif old and old.name() != mood.name():
msg = self.chum.moodmsg(mood, syscolor, self.mainwindow.theme) msg = self.chum.moodmsg(mood, syscolor, self.mainwindow.theme)
self.textArea.append(convertTags(msg)) self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.title(), convertTags(msg, "bbcode")) self.mainwindow.chatlog.log(self.title(), msg)
if self.parent(): if self.parent():
self.parent().updateMood(self.title(), mood, unblocked) self.parent().updateMood(self.title(), mood, unblocked)
else: else:
@ -431,13 +431,17 @@ class PesterConvo(QtGui.QFrame):
def updateColor(self, color): def updateColor(self, color):
self.chum.color = color self.chum.color = color
def addMessage(self, text, me=True): def addMessage(self, msg, me=True):
if type(msg) in [str, unicode]:
lexmsg = lexMessage(msg)
else:
lexmsg = msg
if me: if me:
chum = self.mainwindow.profile() chum = self.mainwindow.profile()
else: else:
chum = self.chum chum = self.chum
self.notifyNewMessage() self.notifyNewMessage()
self.textArea.addMessage(text, chum) self.textArea.addMessage(lexmsg, chum)
def notifyNewMessage(self): def notifyNewMessage(self):
# first see if this conversation HASS the focus # first see if this conversation HASS the focus
@ -516,13 +520,16 @@ class PesterConvo(QtGui.QFrame):
if text == "" or text[0:11] == "PESTERCHUM:": if text == "" or text[0:11] == "PESTERCHUM:":
return return
self.history.add(text) self.history.add(text)
self.addMessage(text, True) quirks = self.mainwindow.userprofile.quirks
lexmsg = lexMessage(text)
if type(lexmsg[0]) is not mecmd and self.applyquirks:
lexmsg = quirks.apply(lexmsg)
serverMsg = copy(lexmsg)
self.addMessage(lexmsg, True)
# if ceased, rebegin # if ceased, rebegin
if hasattr(self, 'chumopen') and not self.chumopen: if hasattr(self, 'chumopen') and not self.chumopen:
self.mainwindow.newConvoStarted.emit(QtCore.QString(self.title()), True) self.mainwindow.newConvoStarted.emit(QtCore.QString(self.title()), True)
# convert color tags text = convertTags(serverMsg, "ctag")
quirkobj = self.mainwindow.userprofile.quirks if self.applyquirks else None
text = convertTags(text, "ctag", quirkobj)
self.messageSent.emit(text, self.title()) self.messageSent.emit(text, self.title())
self.textInput.setText("") self.textInput.setText("")

BIN
convo.pyc

Binary file not shown.

View file

@ -1,9 +1,10 @@
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from datetime import * from datetime import *
import re import re
import random
from generic import PesterIcon from generic import PesterIcon
from parsetools import timeDifference from parsetools import timeDifference, convertTags
class Mood(object): class Mood(object):
moods = ["chummy", "rancorous", "offline", "pleasant", "distraught", moods = ["chummy", "rancorous", "offline", "pleasant", "distraught",
@ -37,15 +38,31 @@ class pesterQuirk(object):
raise ValueError("Quirks must be given a dictionary") raise ValueError("Quirks must be given a dictionary")
self.quirk = quirk self.quirk = quirk
self.type = self.quirk["type"] self.type = self.quirk["type"]
def apply(self, string): def apply(self, string, first=False, last=False):
if self.type == "prefix": if self.type == "prefix":
return self.quirk["value"] + string return self.quirk["value"] + string
if self.type == "suffix": elif self.type == "suffix":
return string + self.quirk["value"] return string + self.quirk["value"]
if self.type == "replace": elif self.type == "replace":
return string.replace(self.quirk["from"], self.quirk["to"]) return string.replace(self.quirk["from"], self.quirk["to"])
if self.type == "regexp": elif self.type == "regexp":
return re.sub(self.quirk["from"], self.quirk["to"], string) fr = self.quirk["from"]
if not first and len(fr) > 0 and fr[0] == "^":
return string
if not last and len(fr) > 0 and fr[len(fr)-1] == "$":
return string
return re.sub(fr, self.quirk["to"], string)
elif self.type == "random":
fr = self.quirk["from"]
if not first and len(fr) > 0 and fr[0] == "^":
return string
if not last and len(fr) > 0 and fr[len(fr)-1] == "$":
return string
def randomrep(mo):
choice = random.choice(self.quirk["randomlist"])
return mo.expand(choice)
return re.sub(self.quirk["from"], randomrep, string)
def __str__(self): def __str__(self):
if self.type == "prefix": if self.type == "prefix":
return "BEGIN WITH: %s" % (self.quirk["value"]) return "BEGIN WITH: %s" % (self.quirk["value"])
@ -55,6 +72,8 @@ class pesterQuirk(object):
return "REPLACE %s WITH %s" % (self.quirk["from"], self.quirk["to"]) return "REPLACE %s WITH %s" % (self.quirk["from"], self.quirk["to"])
elif self.type == "regexp": elif self.type == "regexp":
return "REGEXP: %s REPLACED WITH %s" % (self.quirk["from"], self.quirk["to"]) return "REGEXP: %s REPLACED WITH %s" % (self.quirk["from"], self.quirk["to"])
elif self.type == "random":
return "REGEXP: %s RANDOMLY REPLACED WITH %s" % (self.quirk["from"], [str(r) for r in self.quirk["randomlist"]])
class pesterQuirks(object): class pesterQuirks(object):
def __init__(self, quirklist): def __init__(self, quirklist):
@ -66,25 +85,35 @@ class pesterQuirks(object):
self.quirklist.append(q) self.quirklist.append(q)
def plainList(self): def plainList(self):
return [q.quirk for q in self.quirklist] return [q.quirk for q in self.quirklist]
def apply(self, string): def apply(self, lexed, first=False, last=False):
# don't quirk /me commands prefix = [q for q in self.quirklist if q.type=='prefix']
if string[0:3] == "/me": suffix = [q for q in self.quirklist if q.type=='suffix']
space = string.find(" ")
cmd = string[0:space]
string = string[space:]
else:
cmd = ""
presuffix = [q for q in self.quirklist if
q.type=='prefix' or q.type=='suffix']
replace = [q for q in self.quirklist if replace = [q for q in self.quirklist if
q.type=='replace' or q.type=='regexp'] q.type=='replace' or q.type=='regexp']
for r in replace: random = [q for q in self.quirklist if q.type=='random']
string = r.apply(string)
if not cmd: firstStr = True
for ps in presuffix: newlist = []
string = ps.apply(string) for (i, o) in enumerate(lexed):
string = cmd+string if type(o) not in [str, unicode]:
return string newlist.append(o)
continue
lastStr = (i == len(lexed)-1)
string = o
for r in random:
string = r.apply(string, first=firstStr, last=lastStr)
for r in replace:
string = r.apply(string, first=firstStr, last=lastStr)
if firstStr:
for p in prefix:
string = p.apply(string)
if lastStr:
for s in suffix:
string = s.apply(string)
newlist.append(string)
firstStr = False
return newlist
def __iter__(self): def __iter__(self):
for q in self.quirklist: for q in self.quirklist:
@ -127,7 +156,9 @@ class PesterProfile(object):
def blocked(self, config): def blocked(self, config):
return self.handle in config.getBlocklist() return self.handle in config.getBlocklist()
def memsg(self, syscolor, suffix, msg, time=None): def memsg(self, syscolor, lexmsg, time=None):
suffix = lexmsg[0].suffix
msg = convertTags(lexmsg[1:], "text")
uppersuffix = suffix.upper() uppersuffix = suffix.upper()
if time is not None: if time is not None:
handle = "%s %s" % (time.temporal, self.handle) handle = "%s %s" % (time.temporal, self.handle)

Binary file not shown.

Binary file not shown.

BIN
irc.pyc

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -1,12 +1,14 @@
from string import Template from string import Template
import re import re
from copy import copy
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from datetime import time, timedelta, datetime from datetime import time, timedelta, datetime
from dataobjs import PesterProfile, Mood, PesterHistory from dataobjs import PesterProfile, Mood, PesterHistory
from generic import PesterIcon, RightClickList from generic import PesterIcon, RightClickList
from convo import PesterConvo, PesterInput, PesterText, PesterTabWindow from convo import PesterConvo, PesterInput, PesterText, PesterTabWindow
from parsetools import convertTags, addTimeInitial, timeProtocol from parsetools import convertTags, addTimeInitial, timeProtocol, \
lexMessage, colorBegin, colorEnd, mecmd
def delta2txt(d, format="pc"): def delta2txt(d, format="pc"):
if format == "pc": if format == "pc":
@ -223,18 +225,20 @@ class MemoText(PesterText):
else: else:
self.setStyleSheet("QTextEdit { %s }" % theme["memos/textarea/style"]) self.setStyleSheet("QTextEdit { %s }" % theme["memos/textarea/style"])
def addMessage(self, text, chum): def addMessage(self, msg, chum):
if type(msg) in [str, unicode]:
lexmsg = lexMessage(msg)
else:
lexmsg = msg
parent = self.parent() parent = self.parent()
window = parent.mainwindow window = parent.mainwindow
me = window.profile() me = window.profile()
quirks = window.userprofile.quirks if parent.applyquirks else None
msg = unicode(text)
chumdb = window.chumdb chumdb = window.chumdb
if chum is not me: # SO MUCH WH1T3SP4C3 >:] if chum is not me: # SO MUCH WH1T3SP4C3 >:]
mobj = _ctag_begin.match(text) # get color from tag if type(lexmsg[0]) is colorBegin: # get color tag
if mobj: colortag = lexmsg[0]
try: try:
color = QtGui.QColor(*[int(c) for c in mobj.group(1).split(",")]) color = QtGui.QColor(*[int(c) for c in colortag.color.split(",")])
except ValueError: except ValueError:
color = QtGui.QColor("black") color = QtGui.QColor("black")
else: else:
@ -257,7 +261,7 @@ class MemoText(PesterText):
# new chum! time current # new chum! time current
newtime = timedelta(0) newtime = timedelta(0)
time = TimeTracker(newtime) time = TimeTracker(newtime)
parent.times[chum.handle] = time parent.times[handle] = time
else: else:
time = parent.time time = parent.time
@ -265,26 +269,16 @@ class MemoText(PesterText):
grammar = time.getGrammar() grammar = time.getGrammar()
joinmsg = chum.memojoinmsg(systemColor, time.getTime(), grammar, window.theme["convo/text/joinmemo"]) joinmsg = chum.memojoinmsg(systemColor, time.getTime(), grammar, window.theme["convo/text/joinmemo"])
self.append(convertTags(joinmsg)) self.append(convertTags(joinmsg))
parent.mainwindow.chatlog.log(parent.channel, convertTags(msg, "bbcode")) parent.mainwindow.chatlog.log(parent.channel, joinmsg)
time.openCurrentTime() time.openCurrentTime()
if msg[0:3] == "/me" or msg[0:13] == "PESTERCHUM:ME": if type(lexmsg[0]) is mecmd:
if quirks: memsg = chum.memsg(systemColor, lexmsg, time=time.getGrammar())
msg = quirks.apply(msg) window.chatlog.log(parent.channel, memsg)
if msg[0:3] == "/me":
start = 3
else:
start = 13
space = msg.find(" ")
memsg = chum.memsg(systemColor, msg[start:space], msg[space:], time=time.getGrammar())
window.chatlog.log(parent.channel, convertTags(msg, "bbcode"))
self.append(convertTags(memsg)) self.append(convertTags(memsg))
else: else:
if chum is not me: self.append(convertTags(lexmsg))
msg = addTimeInitial(msg, parent.times[chum.handle].getGrammar()) window.chatlog.log(parent.channel, lexmsg)
self.append(convertTags(msg, quirksobj=quirks))
window.chatlog.log(parent.channel, convertTags(msg, "bbcode", quirks))
def changeTheme(self, theme): def changeTheme(self, theme):
self.initTheme(theme) self.initTheme(theme)
@ -398,7 +392,7 @@ class PesterMemo(PesterConvo):
msg = p.memoopenmsg(systemColor, self.time.getTime(), timeGrammar, self.mainwindow.theme["convo/text/openmemo"], self.channel) msg = p.memoopenmsg(systemColor, self.time.getTime(), timeGrammar, self.mainwindow.theme["convo/text/openmemo"], self.channel)
self.time.openCurrentTime() self.time.openCurrentTime()
self.textArea.append(convertTags(msg)) self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) self.mainwindow.chatlog.log(self.channel, msg)
self.op = False self.op = False
self.newmessage = False self.newmessage = False
@ -537,7 +531,7 @@ class PesterMemo(PesterConvo):
self.times[handle].removeTime(close) self.times[handle].removeTime(close)
msg = chum.memoclosemsg(systemColor, grammar, window.theme["convo/text/closememo"]) msg = chum.memoclosemsg(systemColor, grammar, window.theme["convo/text/closememo"])
self.textArea.append(convertTags(msg)) self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) self.mainwindow.chatlog.log(self.channel, msg)
elif timed not in self.times[handle]: elif timed not in self.times[handle]:
self.times[handle].addTime(timed) self.times[handle].addTime(timed)
else: else:
@ -556,20 +550,26 @@ class PesterMemo(PesterConvo):
if self.time.getTime() == None: if self.time.getTime() == None:
self.sendtime() self.sendtime()
grammar = self.time.getGrammar() grammar = self.time.getGrammar()
if text[0:3] != "/me": quirks = self.mainwindow.userprofile.quirks
lexmsg = lexMessage(text)
if type(lexmsg[0]) is not mecmd:
if self.applyquirks:
lexmsg = quirks.apply(lexmsg)
initials = self.mainwindow.profile().initials() initials = self.mainwindow.profile().initials()
colorcmd = self.mainwindow.profile().colorcmd() colorcmd = self.mainwindow.profile().colorcmd()
clientText = "<c=%s>%s%s%s: %s</c>" % (colorcmd, grammar.pcf, initials, grammar.number, text) clientMsg = [colorBegin("<c=%s>" % (colorcmd), colorcmd),
"%s%s%s: " % (grammar.pcf, initials, grammar.number)] + lexmsg + [colorEnd("</c>")]
# account for TC's parsing error # account for TC's parsing error
serverText = "<c=%s>%s: %s</c> " % (colorcmd, initials, text) serverMsg = [colorBegin("<c=%s>" % (colorcmd), colorcmd),
"%s: " % (initials)] + lexmsg + [colorEnd("</c>"), " "]
else: else:
clientText = text clientMsg = copy(lexmsg)
serverText = clientText serverMsg = copy(lexmsg)
self.addMessage(clientText, True)
# convert color tags self.addMessage(clientMsg, True)
quirks = self.mainwindow.userprofile.quirks if self.applyquirks else None serverText = convertTags(serverMsg, "ctag")
serverText = convertTags(unicode(serverText), "ctag", quirks)
self.messageSent.emit(serverText, self.title()) self.messageSent.emit(serverText, self.title())
self.textInput.setText("") self.textInput.setText("")
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def namesUpdated(self): def namesUpdated(self):
@ -611,7 +611,7 @@ class PesterMemo(PesterConvo):
grammar = t.getGrammar() grammar = t.getGrammar()
msg = chum.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"]) msg = chum.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"])
self.textArea.append(convertTags(msg)) self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) self.mainwindow.chatlog.log(self.channel, msg)
self.times[h].removeTime(t.getTime()) self.times[h].removeTime(t.getTime())
if update == "nick": if update == "nick":
self.addUser(newnick) self.addUser(newnick)
@ -639,7 +639,7 @@ class PesterMemo(PesterConvo):
opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW") opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW")
msg = chum.memobanmsg(opchum, opgrammar, systemColor, grammar) msg = chum.memobanmsg(opchum, opgrammar, systemColor, grammar)
self.textArea.append(convertTags(msg)) self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) self.mainwindow.chatlog.log(self.channel, msg)
ttracker.removeTime(ttracker.getTime()) ttracker.removeTime(ttracker.getTime())
if chum is self.mainwindow.profile(): if chum is self.mainwindow.profile():
@ -658,7 +658,7 @@ class PesterMemo(PesterConvo):
self.time.openCurrentTime() self.time.openCurrentTime()
msg = me.memoopenmsg(systemColor, self.time.getTime(), self.time.getGrammar(), self.mainwindow.theme["convo/text/openmemo"], self.channel) msg = me.memoopenmsg(systemColor, self.time.getTime(), self.time.getGrammar(), self.mainwindow.theme["convo/text/openmemo"], self.channel)
self.textArea.append(convertTags(msg)) self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) self.mainwindow.chatlog.log(self.channel, msg)
elif ret == QtGui.QMessageBox.Cancel: elif ret == QtGui.QMessageBox.Cancel:
if self.parent(): if self.parent():
i = self.parent().tabIndices[self.channel] i = self.parent().tabIndices[self.channel]
@ -725,7 +725,7 @@ class PesterMemo(PesterConvo):
systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"]) systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
msg = me.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"]) msg = me.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"])
self.textArea.append(convertTags(msg)) self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) self.mainwindow.chatlog.log(self.channel, msg)
newtime = self.time.getTime() newtime = self.time.getTime()
if newtime is None: if newtime is None:
@ -738,12 +738,13 @@ class PesterMemo(PesterConvo):
time = self.time.prevTime() time = self.time.prevTime()
self.time.setCurrent(time) self.time.setCurrent(time)
self.resetSlider(time) self.resetSlider(time)
self.textInput.setFocus()
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def nexttime(self): def nexttime(self):
time = self.time.nextTime() time = self.time.nextTime()
self.time.setCurrent(time) self.time.setCurrent(time)
self.resetSlider(time) self.resetSlider(time)
self.textInput.setFocus()
def closeEvent(self, event): def closeEvent(self, event):
self.mainwindow.waitingMessages.messageAnswered(self.channel) self.mainwindow.waitingMessages.messageAnswered(self.channel)
self.windowClosed.emit(self.title()) self.windowClosed.emit(self.title())

BIN
memos.pyc

Binary file not shown.

107
menus.py
View file

@ -30,7 +30,7 @@ class PesterQuirkList(QtGui.QListWidget):
for q in mainwindow.userprofile.quirks: for q in mainwindow.userprofile.quirks:
item = PesterQuirkItem(q, self) item = PesterQuirkItem(q, self)
self.addItem(item) self.addItem(item)
self.sortItems() #self.sortItems()
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def removeCurrent(self): def removeCurrent(self):
@ -38,6 +38,77 @@ class PesterQuirkList(QtGui.QListWidget):
if i >= 0: if i >= 0:
self.takeItem(i) self.takeItem(i)
class RandomQuirkDialog(MultiTextDialog):
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
self.setWindowTitle("RANDOM QUIRK")
self.inputs = {}
layout_1 = QtGui.QHBoxLayout()
regexpl = QtGui.QLabel("REGEXP:", self)
self.regexp = QtGui.QLineEdit(self)
layout_1.addWidget(regexpl)
layout_1.addWidget(self.regexp)
replacewithl = QtGui.QLabel("REPLACE WITH:", self)
layout_2 = QtGui.QVBoxLayout()
layout_3 = QtGui.QHBoxLayout()
self.replacelist = QtGui.QListWidget(self)
self.replaceinput = QtGui.QLineEdit(self)
addbutton = QtGui.QPushButton("ADD", self)
self.connect(addbutton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('addRandomString()'))
removebutton = QtGui.QPushButton("REMOVE", self)
self.connect(removebutton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('removeRandomString()'))
layout_3.addWidget(addbutton)
layout_3.addWidget(removebutton)
layout_2.addWidget(self.replacelist)
layout_2.addWidget(self.replaceinput)
layout_2.addLayout(layout_3)
layout_1.addLayout(layout_2)
self.ok = QtGui.QPushButton("OK", self)
self.ok.setDefault(True)
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('accept()'))
self.cancel = QtGui.QPushButton("CANCEL", self)
self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('reject()'))
layout_ok = QtGui.QHBoxLayout()
layout_ok.addWidget(self.cancel)
layout_ok.addWidget(self.ok)
layout_0 = QtGui.QVBoxLayout()
layout_0.addLayout(layout_1)
layout_0.addLayout(layout_ok)
self.setLayout(layout_0)
def getText(self):
r = self.exec_()
if r == QtGui.QDialog.Accepted:
randomlist = [unicode(self.replacelist.item(i).text())
for i in range(0,self.replacelist.count())]
retval = {"from": unicode(self.regexp.text()),
"randomlist": randomlist }
return retval
else:
return None
@QtCore.pyqtSlot()
def addRandomString(self):
text = unicode(self.replaceinput.text())
item = QtGui.QListWidgetItem(text, self.replacelist)
self.replaceinput.setText("")
@QtCore.pyqtSlot()
def removeRandomString(self):
if not self.replacelist.currentItem():
return
else:
self.replacelist.takeItem(self.currentRow())
self.replaceinput.setFocus()
class PesterChooseQuirks(QtGui.QDialog): class PesterChooseQuirks(QtGui.QDialog):
def __init__(self, config, theme, parent): def __init__(self, config, theme, parent):
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, parent)
@ -62,11 +133,17 @@ class PesterChooseQuirks(QtGui.QDialog):
self.addRegexpReplaceButton = QtGui.QPushButton("REGEXP REPLACE", self) self.addRegexpReplaceButton = QtGui.QPushButton("REGEXP REPLACE", self)
self.connect(self.addRegexpReplaceButton, QtCore.SIGNAL('clicked()'), self.connect(self.addRegexpReplaceButton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('addRegexpDialog()')) self, QtCore.SLOT('addRegexpDialog()'))
self.addRandomReplaceButton = QtGui.QPushButton("RANDOM REPLACE", self)
self.connect(self.addRandomReplaceButton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('addRandomDialog()'))
layout_1 = QtGui.QHBoxLayout() layout_1 = QtGui.QHBoxLayout()
layout_1.addWidget(self.addPrefixButton) layout_1.addWidget(self.addPrefixButton)
layout_1.addWidget(self.addSuffixButton) layout_1.addWidget(self.addSuffixButton)
layout_1.addWidget(self.addSimpleReplaceButton) layout_1.addWidget(self.addSimpleReplaceButton)
layout_1.addWidget(self.addRegexpReplaceButton) layout_2 = QtGui.QHBoxLayout()
layout_2.addWidget(self.addRegexpReplaceButton)
layout_2.addWidget(self.addRandomReplaceButton)
self.removeSelectedButton = QtGui.QPushButton("REMOVE", self) self.removeSelectedButton = QtGui.QPushButton("REMOVE", self)
self.connect(self.removeSelectedButton, QtCore.SIGNAL('clicked()'), self.connect(self.removeSelectedButton, QtCore.SIGNAL('clicked()'),
@ -86,6 +163,7 @@ class PesterChooseQuirks(QtGui.QDialog):
layout_0 = QtGui.QVBoxLayout() layout_0 = QtGui.QVBoxLayout()
layout_0.addWidget(self.quirkList) layout_0.addWidget(self.quirkList)
layout_0.addLayout(layout_1) layout_0.addLayout(layout_1)
layout_0.addLayout(layout_2)
layout_0.addWidget(self.removeSelectedButton) layout_0.addWidget(self.removeSelectedButton)
layout_0.addLayout(layout_ok) layout_0.addLayout(layout_ok)
self.setLayout(layout_0) self.setLayout(layout_0)
@ -94,7 +172,6 @@ class PesterChooseQuirks(QtGui.QDialog):
return [self.quirkList.item(i).quirk for i in return [self.quirkList.item(i).quirk for i in
range(0,self.quirkList.count())] range(0,self.quirkList.count())]
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def addPrefixDialog(self): def addPrefixDialog(self):
pdict = MultiTextDialog("ENTER PREFIX", self, {"label": "Value:", "inputname": "value"}).getText() pdict = MultiTextDialog("ENTER PREFIX", self, {"label": "Value:", "inputname": "value"}).getText()
@ -102,7 +179,7 @@ class PesterChooseQuirks(QtGui.QDialog):
prefix = pesterQuirk(pdict) prefix = pesterQuirk(pdict)
pitem = PesterQuirkItem(prefix, self.quirkList) pitem = PesterQuirkItem(prefix, self.quirkList)
self.quirkList.addItem(pitem) self.quirkList.addItem(pitem)
self.quirkList.sortItems() #self.quirkList.sortItems()
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def addSuffixDialog(self): def addSuffixDialog(self):
vdict = MultiTextDialog("ENTER SUFFIX", self, {"label": "Value:", "inputname": "value"}).getText() vdict = MultiTextDialog("ENTER SUFFIX", self, {"label": "Value:", "inputname": "value"}).getText()
@ -110,7 +187,7 @@ class PesterChooseQuirks(QtGui.QDialog):
quirk = pesterQuirk(vdict) quirk = pesterQuirk(vdict)
item = PesterQuirkItem(quirk, self.quirkList) item = PesterQuirkItem(quirk, self.quirkList)
self.quirkList.addItem(item) self.quirkList.addItem(item)
self.quirkList.sortItems() #self.quirkList.sortItems()
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def addSimpleReplaceDialog(self): def addSimpleReplaceDialog(self):
vdict = MultiTextDialog("REPLACE", self, {"label": "Replace:", "inputname": "from"}, {"label": "With:", "inputname": "to"}).getText() vdict = MultiTextDialog("REPLACE", self, {"label": "Replace:", "inputname": "from"}, {"label": "With:", "inputname": "to"}).getText()
@ -118,7 +195,7 @@ class PesterChooseQuirks(QtGui.QDialog):
quirk = pesterQuirk(vdict) quirk = pesterQuirk(vdict)
item = PesterQuirkItem(quirk, self.quirkList) item = PesterQuirkItem(quirk, self.quirkList)
self.quirkList.addItem(item) self.quirkList.addItem(item)
self.quirkList.sortItems() #self.quirkList.sortItems()
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def addRegexpDialog(self): def addRegexpDialog(self):
vdict = MultiTextDialog("REGEXP REPLACE", self, {"label": "Regexp:", "inputname": "from"}, {"label": "Replace With:", "inputname": "to"}).getText() vdict = MultiTextDialog("REGEXP REPLACE", self, {"label": "Regexp:", "inputname": "from"}, {"label": "Replace With:", "inputname": "to"}).getText()
@ -135,7 +212,23 @@ class PesterChooseQuirks(QtGui.QDialog):
quirk = pesterQuirk(vdict) quirk = pesterQuirk(vdict)
item = PesterQuirkItem(quirk, self.quirkList) item = PesterQuirkItem(quirk, self.quirkList)
self.quirkList.addItem(item) self.quirkList.addItem(item)
self.quirkList.sortItems() #self.quirkList.sortItems()
@QtCore.pyqtSlot()
def addRandomDialog(self):
vdict = RandomQuirkDialog(self).getText()
vdict["type"] = "random"
try:
re.compile(vdict["from"])
except re.error, e:
quirkWarning = QtGui.QMessageBox(self)
quirkWarning.setText("Not a valid regular expression!")
quirkWarning.setInformativeText("H3R3S WHY DUMP4SS: %s" % (e))
quirkWarning.exec_()
return
quirk = pesterQuirk(vdict)
item = PesterQuirkItem(quirk, self.quirkList)
self.quirkList.addItem(item)
#self.quirkList.sortItems()
class PesterChooseTheme(QtGui.QDialog): class PesterChooseTheme(QtGui.QDialog):
def __init__(self, config, theme, parent): def __init__(self, config, theme, parent):

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

@ -4,10 +4,13 @@ from datetime import timedelta
from PyQt4 import QtGui from PyQt4 import QtGui
_ctag_begin = re.compile(r'(?i)<c=(.*?)>') _ctag_begin = re.compile(r'(?i)<c=(.*?)>')
_gtag_begin = re.compile(r'(?i)<g[a-f]>')
_ctag_end = re.compile(r'(?i)</c>') _ctag_end = re.compile(r'(?i)</c>')
_ctag_rgb = re.compile(r'\d+,\d+,\d+') _ctag_rgb = re.compile(r'\d+,\d+,\d+')
_urlre = re.compile(r"(?i)http://[^\s]+") _urlre = re.compile(r"(?i)http://[^\s]+")
_memore = re.compile(r" (#[A-Za-z0-9_]+)") _memore = re.compile(r"(\s|^)(#[A-Za-z0-9_]+)")
_imgre = re.compile(r"""(?i)<img src=['"](\S+)['"]\s*/>""")
_mecmdre = re.compile(r"^/me(\S*)")
def lexer(string, objlist): def lexer(string, objlist):
"""objlist is a list: [(objecttype, re),...] list is in order of preference""" """objlist is a list: [(objecttype, re),...] list is in order of preference"""
@ -38,6 +41,8 @@ class colorBegin(object):
self.color = color self.color = color
def convert(self, format): def convert(self, format):
color = self.color color = self.color
if format == "text":
return ""
if _ctag_rgb.match(color) is not None: if _ctag_rgb.match(color) is not None:
if format=='ctag': if format=='ctag':
return "<c=%s>" % (color) return "<c=%s>" % (color)
@ -64,6 +69,8 @@ class colorEnd(object):
return "</span>" return "</span>"
elif format == "bbcode": elif format == "bbcode":
return "[/color]" return "[/color]"
elif format == "text":
return ""
else: else:
return self.string return self.string
class hyperlink(object): class hyperlink(object):
@ -76,6 +83,30 @@ class hyperlink(object):
return "[url]%s[/url]" % (self.string) return "[url]%s[/url]" % (self.string)
else: else:
return self.string return self.string
class imagelink(object):
def __init__(self, string, img):
self.string = string
self.img = img
def convert(self, format):
if format == "html":
return self.string
elif format == "bbcode":
if self.img[0:7] == "http://":
return "[img]%s[/img]" % (img)
else:
return ""
else:
return ""
class memolex(object):
def __init__(self, string, space, channel):
self.string = string
self.space = space
self.channel = channel
def convert(self, format):
if format == "html":
return "%s<a href='%s'>%s</a>" % (self.space, self.channel, self.channel)
else:
return self.string
class smiley(object): class smiley(object):
def __init__(self, string): def __init__(self, string):
self.string = string self.string = string
@ -84,15 +115,22 @@ class smiley(object):
return "<img src='smilies/%s' />" % (smiledict[self.string]) return "<img src='smilies/%s' />" % (smiledict[self.string])
else: else:
return self.string return self.string
class mecmd(object):
def __init__(self, string, suffix):
self.string = string
self.suffix = suffix
def convert(self, format):
return self.string
def convertTags(string, format="html", quirkobj=None): def lexMessage(string):
if format not in ["html", "bbcode", "ctag"]: lexlist = [(mecmd, _mecmdre),
raise ValueError("Color format not recognized") (colorBegin, _ctag_begin), (colorBegin, _gtag_begin),
lexlist = [(colorBegin, _ctag_begin), (colorEnd, _ctag_end), (colorEnd, _ctag_end), (imagelink, _imgre),
(hyperlink, _urlre), (hyperlink, _memore), (hyperlink, _urlre), (memolex, _memore),
(smiley, _smilere)] (smiley, _smilere)]
lexed = lexer(string, lexlist) lexed = lexer(unicode(string), lexlist)
balanced = [] balanced = []
beginc = 0 beginc = 0
endc = 0 endc = 0
@ -111,25 +149,35 @@ def convertTags(string, format="html", quirkobj=None):
if beginc > endc: if beginc > endc:
for i in range(0, beginc-endc): for i in range(0, beginc-endc):
balanced.append(colorEnd("</c>")) balanced.append(colorEnd("</c>"))
if type(balanced[len(balanced)-1]) not in [str, unicode]:
balanced.append("")
return balanced
def convertTags(lexed, format="html"):
if format not in ["html", "bbcode", "ctag", "text"]:
raise ValueError("Color format not recognized")
if type(lexed) in [str, unicode]:
lexed = lexMessage(lexed)
escaped = "" escaped = ""
for o in balanced: firststr = True
for (i, o) in enumerate(lexed):
if type(o) in [str, unicode]: if type(o) in [str, unicode]:
if quirkobj:
o = quirkobj.apply(o)
if format == "html": if format == "html":
escaped += o.replace("&", "&amp;").replace(">", "&gt;").replace("<","&lt;") escaped += o.replace("&", "&amp;").replace(">", "&gt;").replace("<","&lt;")
else: else:
escaped += o escaped += o
else: else:
escaped += o.convert(format) escaped += o.convert(format)
return escaped return escaped
def addTimeInitial(string, grammar): def addTimeInitial(string, grammar):
endofi = string.find(":") endofi = string.find(":")
endoftag = string.find(">") endoftag = string.find(">")
if endoftag < 0 or endoftag > 16 or endofi > 17: # support Doc Scratch mode
if (endoftag < 0 or endoftag > 16) or (endofi < 0 or endofi > 17):
return string return string
return string[0:endoftag+1]+grammar.pcf+string[endoftag+1:endofi]+grammar.number+string[endofi:] return string[0:endoftag+1]+grammar.pcf+string[endoftag+1:endofi]+grammar.number+string[endofi:]

Binary file not shown.

View file

@ -1 +1 @@
{"tabs": false, "soundon": true, "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", "maxiumumFatness", "elegantDiversion", "moirailBunp", "uroborosUnbound", "androidTechnician", "midnightSparrow", "apocalypseArisen", "anguillaNuntia", "oilslickOrchid", "confusedTransient", "pretentiousFantasia", "aquaticMarinist", "lyricalKeraunoscopic", "counterRealist", "ectoBiologist"], "defaultprofile": "ghostDunk", "block": []} {"tabs": true, "soundon": true, "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"], "defaultprofile": "ghostDunk", "block": []}

View file

@ -19,8 +19,8 @@ from menus import PesterChooseQuirks, PesterChooseTheme, \
from dataobjs import PesterProfile, Mood, pesterQuirk, pesterQuirks from dataobjs import PesterProfile, Mood, pesterQuirk, pesterQuirks
from generic import PesterIcon, RightClickList, MultiTextDialog, PesterList 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 from parsetools import convertTags, addTimeInitial
from memos import PesterMemo, MemoTabWindow from memos import PesterMemo, MemoTabWindow, TimeTracker
from irc import PesterIRC from irc import PesterIRC
class waitingMessageHolder(object): class waitingMessageHolder(object):
@ -59,27 +59,35 @@ class PesterLog(object):
self.handle = handle self.handle = handle
self.convos = {} self.convos = {}
def log(self, handle, msg): def log(self, handle, msg):
bbcodemsg = convertTags(msg, "bbcode")
html = convertTags(msg, "html")
msg = convertTags(msg, "text")
modes = {"bbcode": bbcodemsg, "html": html, "text": msg}
if not self.convos.has_key(handle): if not self.convos.has_key(handle):
if not os.path.exists("logs/%s" % (self.handle)): time = datetime.now().strftime("%Y-%m-%d.%H.%M")
os.mkdir("logs/%s" % (self.handle)) self.convos[handle] = {}
time = datetime.now().strftime("%Y-%m-%d.%H.%M.txt") for (format, t) in modes.iteritems():
if not os.path.exists("logs/%s/%s" % (self.handle, handle)): if not os.path.exists("logs/%s/%s/%s" % (self.handle, handle, format)):
os.mkdir("logs/%s/%s" % (self.handle, handle)) os.makedirs("logs/%s/%s/%s" % (self.handle, handle, format))
fp = codecs.open("logs/%s/%s/%s.%s" % (self.handle, handle, handle, time), encoding='utf-8', mode='a') fp = codecs.open("logs/%s/%s/%s/%s.%s.txt" % (self.handle, handle, format, handle, time), encoding='utf-8', mode='a')
self.convos[handle] = fp self.convos[handle][format] = fp
if platform.system() == "Windows": for (format, t) in modes.iteritems():
self.convos[handle].write(msg+"\r\n") f = self.convos[handle][format]
else: if platform.system() == "Windows":
self.convos[handle].write(msg+"\n") f.write(t+"\r\n")
self.convos[handle].flush() else:
f.write(t+"\r\n")
f.flush()
def finish(self, handle): def finish(self, handle):
if not self.convos.has_key(handle): if not self.convos.has_key(handle):
return return
self.convos[handle].close() for f in self.convos[handle].values():
f.close()
del self.convos[handle] del self.convos[handle]
def close(self): def close(self):
for h in self.convos.keys(): for h in self.convos.keys():
self.convos[h].close() for f in self.convos[h].values():
f.close()
class PesterProfileDB(dict): class PesterProfileDB(dict):
def __init__(self): def __init__(self):
@ -668,6 +676,10 @@ class PesterWindow(MovingWindow):
self.importaction = QtGui.QAction(self.theme["main/menus/client/import"], self) self.importaction = QtGui.QAction(self.theme["main/menus/client/import"], self)
self.connect(self.importaction, QtCore.SIGNAL('triggered()'), self.connect(self.importaction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('importExternalConfig()')) self, QtCore.SLOT('importExternalConfig()'))
self.idleaction = QtGui.QAction(self.theme["main/menus/client/idle"], self)
self.idleaction.setCheckable(True)
self.connect(self.idleaction, QtCore.SIGNAL('toggled(bool)'),
self, QtCore.SLOT('toggleIdle(bool)'))
self.menu = QtGui.QMenuBar(self) self.menu = QtGui.QMenuBar(self)
@ -676,6 +688,7 @@ class PesterWindow(MovingWindow):
filemenu.addAction(opts) filemenu.addAction(opts)
filemenu.addAction(memoaction) filemenu.addAction(memoaction)
filemenu.addAction(userlistaction) filemenu.addAction(userlistaction)
filemenu.addAction(self.idleaction)
filemenu.addAction(self.importaction) filemenu.addAction(self.importaction)
filemenu.addAction(exitaction) filemenu.addAction(exitaction)
@ -769,7 +782,7 @@ class PesterWindow(MovingWindow):
self.waitingMessages = waitingMessageHolder(self) self.waitingMessages = waitingMessageHolder(self)
self.idle = False self.autoidle = False
self.idlethreshold = 600 self.idlethreshold = 600
self.idletimer = QtCore.QTimer(self) self.idletimer = QtCore.QTimer(self)
self.idleposition = QtGui.QCursor.pos() self.idleposition = QtGui.QCursor.pos()
@ -843,6 +856,14 @@ class PesterWindow(MovingWindow):
# silently ignore in case we forgot to /part # silently ignore in case we forgot to /part
return return
memo = self.memos[chan] memo = self.memos[chan]
msg = unicode(msg)
if not memo.times.has_key(handle):
# new chum! time current
newtime = timedelta(0)
time = TimeTracker(newtime)
memo.times[handle] = time
if msg[0:3] != "/me" and msg[0:13] != "PESTERCHUM:ME":
msg = addTimeInitial(msg, memo.times[handle].getGrammar())
memo.addMessage(msg, handle) memo.addMessage(msg, handle)
self.alarm.play() self.alarm.play()
@ -963,6 +984,7 @@ class PesterWindow(MovingWindow):
self.userlistaction.setText(theme["main/menus/client/userlist"]) self.userlistaction.setText(theme["main/menus/client/userlist"])
self.memoaction.setText(theme["main/menus/client/memos"]) self.memoaction.setText(theme["main/menus/client/memos"])
self.importaction.setText(theme["main/menus/client/import"]) self.importaction.setText(theme["main/menus/client/import"])
self.idleaction.setText(theme["main/menus/client/idle"])
self.filemenu.setTitle(theme["main/menus/client/_name"]) self.filemenu.setTitle(theme["main/menus/client/_name"])
self.changetheme.setText(theme["main/menus/profile/theme"]) self.changetheme.setText(theme["main/menus/profile/theme"])
self.changequirks.setText(theme["main/menus/profile/quirks"]) self.changequirks.setText(theme["main/menus/profile/quirks"])
@ -1116,7 +1138,7 @@ class PesterWindow(MovingWindow):
chum = self.convos[h].chum chum = self.convos[h].chum
chumopen = self.convos[h].chumopen chumopen = self.convos[h].chumopen
if 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.log(chum.handle, self.profile().pestermsg(chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/ceasepester"]))
self.convoClosed.emit(handle) self.convoClosed.emit(handle)
self.chatlog.finish(h) self.chatlog.finish(h)
del self.convos[h] del self.convos[h]
@ -1242,7 +1264,7 @@ class PesterWindow(MovingWindow):
convo = self.convos[h] convo = self.convos[h]
msg = self.profile().pestermsg(convo.chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/blocked"]) msg = self.profile().pestermsg(convo.chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/blocked"])
convo.textArea.append(convertTags(msg)) convo.textArea.append(convertTags(msg))
self.chatlog.log(convo.chum.handle, convertTags(msg, "bbcode")) self.chatlog.log(convo.chum.handle, msg)
convo.updateBlocked() convo.updateBlocked()
self.chumList.removeChum(h) self.chumList.removeChum(h)
if hasattr(self, 'trollslum') and self.trollslum: if hasattr(self, 'trollslum') and self.trollslum:
@ -1259,7 +1281,7 @@ class PesterWindow(MovingWindow):
convo = self.convos[h] convo = self.convos[h]
msg = self.profile().pestermsg(convo.chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/unblocked"]) msg = self.profile().pestermsg(convo.chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/unblocked"])
convo.textArea.append(convertTags(msg)) convo.textArea.append(convertTags(msg))
self.chatlog.log(convo.chum.handle, convertTags(msg, "bbcode")) self.chatlog.log(convo.chum.handle, msg)
convo.updateMood(convo.chum.mood, unblocked=True) convo.updateMood(convo.chum.mood, unblocked=True)
chum = PesterProfile(h, chumdb=self.chumdb) chum = PesterProfile(h, chumdb=self.chumdb)
if hasattr(self, 'trollslum') and self.trollslum: if hasattr(self, 'trollslum') and self.trollslum:
@ -1271,18 +1293,16 @@ class PesterWindow(MovingWindow):
@QtCore.pyqtSlot(bool) @QtCore.pyqtSlot(bool)
def toggleIdle(self, idle): def toggleIdle(self, idle):
if self.idle and not idle: if idle:
self.idle = False
elif idle and not self.idle:
self.idle = True
sysColor = QtGui.QColor(self.theme["convo/systemMsgColor"]) sysColor = QtGui.QColor(self.theme["convo/systemMsgColor"])
verb = self.theme["convo/text/idle"] verb = self.theme["convo/text/idle"]
for (h, convo) in self.convos.iteritems(): for (h, convo) in self.convos.iteritems():
msg = self.profile().idlemsg(sysColor, verb) msg = self.profile().idlemsg(sysColor, verb)
convo.textArea.append(convertTags(msg)) convo.textArea.append(convertTags(msg))
self.chatlog.log(h, convertTags(msg, "bbcode")) self.chatlog.log(h, msg)
self.sendMessage.emit("PESTERCHUM:IDLE", h) self.sendMessage.emit("PESTERCHUM:IDLE", h)
else:
self.idletime = 0
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def checkIdle(self): def checkIdle(self):
newpos = QtGui.QCursor.pos() newpos = QtGui.QCursor.pos()
@ -1291,9 +1311,14 @@ class PesterWindow(MovingWindow):
else: else:
self.idletime = 0 self.idletime = 0
if self.idletime >= self.idlethreshold: if self.idletime >= self.idlethreshold:
self.toggleIdle(True) if not self.idleaction.isChecked():
self.idleaction.toggle()
self.autoidle = True
else: else:
self.toggleIdle(False) if self.autoidle:
if self.idleaction.isChecked():
self.idleaction.toggle()
self.autoidle = False
self.idleposition = newpos self.idleposition = newpos
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def importExternalConfig(self): def importExternalConfig(self):
@ -1801,10 +1826,9 @@ class MainProgram(QtCore.QObject):
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()'))
self.widget.loadingscreen = None status = self.widget.loadingscreen.exec_()
#status = self.widget.loadingscreen.exec_() if status == QtGui.QDialog.Rejected:
#if status == QtGui.QDialog.Rejected: sys.exit(0)
# sys.exit(0)
os._exit(self.app.exec_()) os._exit(self.app.exec_())
pesterchum = MainProgram() pesterchum = MainProgram()

View file

@ -1 +1 @@
{"color": "#ff00ff", "theme": "pesterchum", "quirks": [{"to": "7", "from": "t", "type": "replace"}], "handle": "ghostDunk"} {"color": "#ff00ff", "theme": "pesterchum", "quirks": [], "handle": "ghostDunk"}