diff --git a/TODO b/TODO index c68d534..9ea530e 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,4 @@ Features: -* More complex quirks: spelling, by-sound -* IRC message limit!!! -* on ban, redirect to memo chooser -* ? time option??? * help menu -- about and forum * Tray doesn't disappear on windows after close -- release alpha @@ -12,7 +8,9 @@ Features: * spell check? * help button on quirks menu? -- release beta -* flashing?? +* hide offline chums +* chum list groups +* More complex quirks: by-sound * change profile only once we have confirmation from server * log viewer * pick your own icon @@ -22,5 +20,3 @@ Features: * Spy mode * Animated * put code into separate files -* hide offline chums -* chum list groups \ No newline at end of file diff --git a/convo.py b/convo.py index 7a7431f..9924f47 100644 --- a/convo.py +++ b/convo.py @@ -117,13 +117,16 @@ class PesterTabWindow(QtGui.QFrame): return True else: return False - + def activateChat(self): + if platform.system() == "Windows": + self.activateWindow() def notifyNewMessage(self, handle): i = self.tabIndices[handle] self.tabs.setTabTextColor(i, QtGui.QColor(self.mainwindow.theme["%s/tabs/newmsgcolor" % (self.type)])) convo = self.convos[handle] def func(): convo.showChat() + self.activateChat() self.mainwindow.waitingMessages.addMessage(handle, func) # set system tray def clearNewMessage(self, handle): @@ -480,6 +483,11 @@ class PesterConvo(QtGui.QFrame): if self.parent(): self.parent().showChat(self.title()) self.raiseChat() + def activateChat(self): + if self.parent(): + self.parent().activateChat() + if platform.system() == "Windows": + self.activateWindow() def contextMenuEvent(self, event): if event.reason() == QtGui.QContextMenuEvent.Mouse: self.optionsMenu.popup(event.globalPos()) diff --git a/convo.pyc b/convo.pyc index 9651083..1578fea 100644 Binary files a/convo.pyc and b/convo.pyc differ diff --git a/dataobjs.py b/dataobjs.py index e0da239..fb0b62f 100644 --- a/dataobjs.py +++ b/dataobjs.py @@ -5,6 +5,9 @@ import random from generic import PesterIcon from parsetools import timeDifference, convertTags +from mispeller import mispeller + +_upperre = re.compile(r"upper\(([\w\\]+)\)") class Mood(object): moods = ["chummy", "rancorous", "offline", "pleasant", "distraught", @@ -32,6 +35,7 @@ class Mood(object): return PesterIcon(theme["main/chums/moods/chummy/icon"]) return PesterIcon(f) + class pesterQuirk(object): def __init__(self, quirk): if type(quirk) != dict: @@ -51,7 +55,13 @@ class pesterQuirk(object): return string if not last and len(fr) > 0 and fr[len(fr)-1] == "$": return string - return re.sub(fr, self.quirk["to"], string) + def regexprep(mo): + to = self.quirk["to"] + def upperrep(m): + return mo.expand(m.group(1)).upper() + to = _upperre.sub(upperrep, to) + return mo.expand(to) + return re.sub(fr, regexprep, string) elif self.type == "random": fr = self.quirk["from"] if not first and len(fr) > 0 and fr[0] == "^": @@ -62,6 +72,17 @@ class pesterQuirk(object): choice = random.choice(self.quirk["randomlist"]) return mo.expand(choice) return re.sub(self.quirk["from"], randomrep, string) + elif self.type == "spelling": + percentage = self.quirk["percentage"]/100.0 + words = string.split(" ") + newl = [] + for w in words: + p = random.random() + if p < percentage: + newl.append(mispeller(w)) + else: + newl.append(w) + return " ".join(newl) def __str__(self): if self.type == "prefix": @@ -74,6 +95,8 @@ class pesterQuirk(object): 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"]]) + elif self.type == "spelling": + return "MISPELLER: %d%%" % (self.quirk["percentage"]) class pesterQuirks(object): def __init__(self, quirklist): @@ -91,6 +114,7 @@ class pesterQuirks(object): replace = [q for q in self.quirklist if q.type=='replace' or q.type=='regexp'] random = [q for q in self.quirklist if q.type=='random'] + spelling = [q for q in self.quirklist if q.type=='spelling'] newlist = [] for (i, o) in enumerate(lexed): @@ -104,6 +128,8 @@ class pesterQuirks(object): continue lastStr = (i == len(lexed)-1) string = o + for s in spelling: + string = s.apply(string) for r in random: string = r.apply(string, first=(i==0), last=lastStr) for r in replace: diff --git a/dataobjs.pyc b/dataobjs.pyc index 670a7cc..c548bdb 100644 Binary files a/dataobjs.pyc and b/dataobjs.pyc differ diff --git a/generic.py b/generic.py index ad9a8a8..fd77ad6 100644 --- a/generic.py +++ b/generic.py @@ -1,4 +1,13 @@ from PyQt4 import QtGui, QtCore +from datetime import timedelta + +class mysteryTime(timedelta): + def __sub__(self, other): + return self + def __eq__(self, other): + return (type(other) is mysteryTime) + def __neq__(self, other): + return (type(other) is not mysteryTime) class PesterList(list): def __init__(self, l): diff --git a/generic.pyc b/generic.pyc index 3b026d6..2fe98c5 100644 Binary files a/generic.pyc and b/generic.pyc differ diff --git a/irc.py b/irc.py index 93f7a49..7c49931 100644 --- a/irc.py +++ b/irc.py @@ -32,8 +32,24 @@ class PesterIRC(QtCore.QObject): @QtCore.pyqtSlot(QtCore.QString, QtCore.QString) def sendMessage(self, text, handle): h = unicode(handle) + textl = [unicode(text)] + def splittext(l): + if len(l[0]) > 400: + space = l[0].rfind(" ", 0,400) + if space == -1: + space = 400 + a = l[0][0:space] + b = l[0][space:] + if len(b) > 0: + return [a] + splittext([b]) + else: + return [a] + else: + return l + textl = splittext(textl) try: - helpers.msg(self.cli, h, text) + for t in textl: + helpers.msg(self.cli, h, t) except socket.error: self.setConnectionBroken() @QtCore.pyqtSlot(QtCore.QString, bool) diff --git a/irc.pyc b/irc.pyc index e4a65a5..4fd91eb 100644 Binary files a/irc.pyc and b/irc.pyc differ diff --git a/logs/chums.js b/logs/chums.js index e55192a..74ba284 100644 --- a/logs/chums.js +++ b/logs/chums.js @@ -1 +1 @@ -{"macruralAlchemist": {"color": "#700000", "handle": "macruralAlchemist", "mood": "offline"}, "lyricalKeraunoscopic": {"color": "#00c000", "handle": "lyricalKeraunoscopic", "mood": "offline"}, "fireSwallow": {"color": "#80bb9a", "handle": "fireSwallow", "mood": "offline"}, "aquaMarinist": {"color": "#00caca", "handle": "aquaMarinist", "mood": "offline"}, "centaursTesticle": {"color": "#000056", "handle": "centaursTesticle", "mood": "offline"}, "mechanicalSpectacle": {"color": "#0000ff", "handle": "mechanicalSpectacle", "mood": "offline"}, "carcinoGeneticist": {"color": "#999999", "handle": "carcinoGeneticist", "mood": "offline"}, "greyscalePacifist": {"color": "#7f7f7f", "handle": "greyscalePacifist", "mood": "offline"}, "aquaticMarinist": {"color": "#00caca", "handle": "aquaticMarinist", "mood": "offline"}, "iw": {"color": "#ff0000", "handle": "iw", "mood": "offline"}, "insipidTranscient": {"color": "#145064", "handle": "insipidTranscient", "mood": "offline"}, "caffeinatedAnalyst": {"color": "#aa0000", "handle": "caffeinatedAnalyst", "mood": "offline"}, "pesterClient394": {"color": "#ff3737", "handle": "pesterClient394", "mood": "offline"}, "absoluteTranquility": {"color": "#000033", "handle": "absoluteTranquility", "mood": "offline"}, "nitroZealist": {"color": "#ff3737", "handle": "nitroZealist", "mood": "offline"}, "quintessentialArbalest": {"color": "#999999", "handle": "quintessentialArbalest", "mood": "offline"}, "noSense": {"color": "#1d0059", "handle": "noSense", "mood": "offline"}, "agogPorphyry": {"color": "#522d80", "handle": "agogPorphyry", "mood": "offline"}, "grimAuxiliatrix": {"color": "#008141", "handle": "grimAuxiliatrix", "mood": "offline"}, "terminallyCapricious": {"color": "#2b0057", "handle": "terminallyCapricious", "mood": "offline"}, "androidTechnician": {"color": "#0000ff", "handle": "androidTechnician", "mood": "offline"}, "ardentAbettor": {"color": "#c8b670", "handle": "ardentAbettor", "mood": "offline"}, "aceIsm": {"color": "#ffcc66", "handle": "aceIsm", "mood": "offline"}, "apocalypseArisen": {"color": "#a10000", "handle": "apocalypseArisen", "mood": "offline"}, "radicalApologist": {"color": "#ffaa00", "handle": "radicalApologist", "mood": "offline"}, "microMachines": {"color": "#aa00ff", "handle": "microMachines", "mood": "offline"}, "uroborosUnbound": {"color": "#00416a", "handle": "uroborosUnbound", "mood": "offline"}, "arachnidsGrip": {"color": "#005682", "handle": "arachnidsGrip", "mood": "offline"}, "caligulasAquarium": {"color": "#6a006a", "handle": "caligulasAquarium", "mood": "offline"}, "percipientPedestrian": {"color": "#00ffff", "handle": "percipientPedestrian", "mood": "offline"}, "tentacleTherapist": {"color": "#cc66ff", "handle": "tentacleTherapist", "mood": "offline"}, "sucroseSaboteur": {"color": "#00e700", "handle": "sucroseSaboteur", "mood": "offline"}, "illuminatedWax": {"color": "#000000", "handle": "illuminatedWax", "mood": "offline"}, "moirailBunp": {"color": "#6a3d0f", "handle": "moirailBunp", "mood": "offline"}, "madLurker": {"color": "#000000", "handle": "madLurker", "mood": "offline"}, "testOut": {"color": "#c760cc", "handle": "testOut", "mood": "offline"}, "pesterClient3022": {"color": "#336600", "handle": "pesterClient3022", "mood": "offline"}, "hellerificJefferson": {"color": "#3300ff", "handle": "hellerificJefferson", "mood": "offline"}, "DocScratch": {"color": "#ffffff", "handle": "DocScratch", "mood": "offline"}, "recalcitrantDisaster": {"color": "#8b0068", "handle": "recalcitrantDisaster", "mood": "offline"}, "superGhost": {"color": "#800564", "handle": "superGhost", "mood": "offline"}, "arsenicCatnip": {"color": "#006400", "handle": "arsenicCatnip", "mood": "offline"}, "kaleidoscopicMind": {"color": "#ff6666", "handle": "kaleidoscopicMind", "mood": "offline"}, "zealousScarecrow": {"color": "#00c882", "handle": "zealousScarecrow", "mood": "offline"}, "captainCaveman": {"color": "#7c414e", "handle": "captainCaveman", "mood": "offline"}, "gamblingGenocider": {"color": "#00ff00", "handle": "gamblingGenocider", "mood": "offline"}, "cuttlefishCuller": {"color": "#77003c", "handle": "cuttlefishCuller", "mood": "offline"}, "wovenWay": {"color": "#000000", "handle": "wovenWay", "mood": "offline"}, "masterG": {"color": "#77003c", "handle": "masterG", "mood": "offline"}, "elegantDiversion": {"color": "#14b40a", "handle": "elegantDiversion", "mood": "offline"}, "plasmaModerator": {"color": "#5685cc", "handle": "plasmaModerator", "mood": "offline"}, "carcinoGenetecist": {"color": "#7f7f7f", "handle": "carcinoGenetecist", "mood": "offline"}, "marineAquist": {"color": "#00caca", "handle": "marineAquist", "mood": "offline"}, "remoteBloodbath": {"color": "#c70000", "handle": "remoteBloodbath", "mood": "offline"}, "oilslickOrchid": {"color": "#743f7e", "handle": "oilslickOrchid", "mood": "offline"}, "acapellaWaterfall": {"color": "#000099", "handle": "acapellaWaterfall", "mood": "offline"}, "gallowsCalibrator": {"color": "#008282", "handle": "gallowsCalibrator", "mood": "offline"}, "rageInducer": {"color": "#00ffff", "handle": "rageInducer", "mood": "offline"}, "anguillaNuntia": {"color": "#ff007f", "handle": "anguillaNuntia", "mood": "offline"}, "greenZephyr": {"color": "#00ca40", "handle": "greenZephyr", "mood": "offline"}, "lawdEngrish": {"color": "#00ff00", "handle": "lawdEngrish", "mood": "offline"}, "pretentiousFantasia": {"color": "#ff66cf", "handle": "pretentiousFantasia", "mood": "offline"}, "counterRealist": {"color": "#10d985", "handle": "counterRealist", "mood": "offline"}, "maxiumumFatness": {"color": "#3366ff", "handle": "maxiumumFatness", "mood": "offline"}, "schlagzeugGator": {"color": "#61821f", "handle": "schlagzeugGator", "mood": "offline"}, "metaliAggressive": {"color": "#9289d5", "handle": "metaliAggressive", "mood": "offline"}, "midnightSparrow": {"color": "#ff55ff", "handle": "midnightSparrow", "mood": "offline"}, "magmaExploiter": {"color": "#d90000", "handle": "magmaExploiter", "mood": "offline"}, "gardenGnostic": {"color": "#00ff00", "handle": "gardenGnostic", "mood": "offline"}, "unknownTraveler": {"color": "#006666", "handle": "unknownTraveler", "mood": "offline"}, "utilitarianTurnabout": {"color": "#dd0000", "handle": "utilitarianTurnabout", "mood": "offline"}, "adiosToreador": {"color": "#aa5500", "handle": "adiosToreador", "mood": "offline"}} \ No newline at end of file +{"macruralAlchemist": {"color": "#700000", "handle": "macruralAlchemist", "mood": "offline"}, "lyricalKeraunoscopic": {"color": "#00aa00", "handle": "lyricalKeraunoscopic", "mood": "offline"}, "fireSwallow": {"color": "#80bb9a", "handle": "fireSwallow", "mood": "offline"}, "aquaMarinist": {"color": "#00caca", "handle": "aquaMarinist", "mood": "offline"}, "centaursTesticle": {"color": "#000056", "handle": "centaursTesticle", "mood": "offline"}, "mechanicalSpectacle": {"color": "#0000ff", "handle": "mechanicalSpectacle", "mood": "offline"}, "depthPerception": {"color": "#6f3886", "handle": "depthPerception", "mood": "offline"}, "carcinoGeneticist": {"color": "#999999", "handle": "carcinoGeneticist", "mood": "offline"}, "greyscalePacifist": {"color": "#7f7f7f", "handle": "greyscalePacifist", "mood": "offline"}, "aquaticMarinist": {"color": "#00caca", "handle": "aquaticMarinist", "mood": "offline"}, "iw": {"color": "#000000", "handle": "iw", "mood": "offline"}, "insipidTranscient": {"color": "#145064", "handle": "insipidTranscient", "mood": "offline"}, "caffeinatedAnalyst": {"color": "#aa0000", "handle": "caffeinatedAnalyst", "mood": "offline"}, "midnightSparrow": {"color": "#ff55ff", "handle": "midnightSparrow", "mood": "offline"}, "absoluteTranquility": {"color": "#000033", "handle": "absoluteTranquility", "mood": "offline"}, "nitroZealist": {"color": "#ff3737", "handle": "nitroZealist", "mood": "offline"}, "quintessentialArbalest": {"color": "#999999", "handle": "quintessentialArbalest", "mood": "offline"}, "noSense": {"color": "#1d0059", "handle": "noSense", "mood": "offline"}, "agogPorphyry": {"color": "#522d80", "handle": "agogPorphyry", "mood": "offline"}, "grimAuxiliatrix": {"color": "#008141", "handle": "grimAuxiliatrix", "mood": "offline"}, "terminallyCapricious": {"color": "#2b0057", "handle": "terminallyCapricious", "mood": "offline"}, "androidTechnician": {"color": "#0000ff", "handle": "androidTechnician", "mood": "offline"}, "ardentAbettor": {"color": "#c8b670", "handle": "ardentAbettor", "mood": "offline"}, "aceIsm": {"color": "#ffcc66", "handle": "aceIsm", "mood": "offline"}, "apocalypseArisen": {"color": "#a10000", "handle": "apocalypseArisen", "mood": "offline"}, "radicalApologist": {"color": "#ffaa00", "handle": "radicalApologist", "mood": "offline"}, "microMachines": {"color": "#aa00ff", "handle": "microMachines", "mood": "offline"}, "uroborosUnbound": {"color": "#00416a", "handle": "uroborosUnbound", "mood": "offline"}, "arachnidsGrip": {"color": "#005682", "handle": "arachnidsGrip", "mood": "offline"}, "caligulasAquarium": {"color": "#6a006a", "handle": "caligulasAquarium", "mood": "offline"}, "percipientPedestrian": {"color": "#00ffff", "handle": "percipientPedestrian", "mood": "offline"}, "tentacleTherapist": {"color": "#cc66ff", "handle": "tentacleTherapist", "mood": "offline"}, "sucroseSaboteur": {"color": "#00e700", "handle": "sucroseSaboteur", "mood": "offline"}, "illuminatedWax": {"color": "#000000", "handle": "illuminatedWax", "mood": "offline"}, "moirailBunp": {"color": "#6a3d0f", "handle": "moirailBunp", "mood": "offline"}, "madLurker": {"color": "#000000", "handle": "madLurker", "mood": "offline"}, "testOut": {"color": "#c760cc", "handle": "testOut", "mood": "offline"}, "pesterClient3022": {"color": "#336600", "handle": "pesterClient3022", "mood": "offline"}, "hellerificJefferson": {"color": "#3300ff", "handle": "hellerificJefferson", "mood": "offline"}, "DocScratch": {"color": "#ffffff", "handle": "DocScratch", "mood": "offline"}, "recalcitrantDisaster": {"color": "#8b0068", "handle": "recalcitrantDisaster", "mood": "offline"}, "superGhost": {"color": "#800564", "handle": "superGhost", "mood": "offline"}, "arsenicCatnip": {"color": "#006400", "handle": "arsenicCatnip", "mood": "offline"}, "kaleidoscopicMind": {"color": "#ff6666", "handle": "kaleidoscopicMind", "mood": "offline"}, "zealousScarecrow": {"color": "#00c882", "handle": "zealousScarecrow", "mood": "offline"}, "captainCaveman": {"color": "#7c414e", "handle": "captainCaveman", "mood": "offline"}, "gamblingGenocider": {"color": "#00ff00", "handle": "gamblingGenocider", "mood": "offline"}, "cuttlefishCuller": {"color": "#77003c", "handle": "cuttlefishCuller", "mood": "offline"}, "wovenWay": {"color": "#000000", "handle": "wovenWay", "mood": "offline"}, "masterG": {"color": "#77003c", "handle": "masterG", "mood": "offline"}, "elegantDiversion": {"color": "#14b40a", "handle": "elegantDiversion", "mood": "offline"}, "plasmaModerator": {"color": "#5685cc", "handle": "plasmaModerator", "mood": "offline"}, "carcinoGenetecist": {"color": "#7f7f7f", "handle": "carcinoGenetecist", "mood": "offline"}, "marineAquist": {"color": "#00caca", "handle": "marineAquist", "mood": "offline"}, "remoteBloodbath": {"color": "#c70000", "handle": "remoteBloodbath", "mood": "offline"}, "oilslickOrchid": {"color": "#743f7e", "handle": "oilslickOrchid", "mood": "offline"}, "acapellaWaterfall": {"color": "#000099", "handle": "acapellaWaterfall", "mood": "offline"}, "gallowsCalibrator": {"color": "#008282", "handle": "gallowsCalibrator", "mood": "offline"}, "rageInducer": {"color": "#00ffff", "handle": "rageInducer", "mood": "offline"}, "anguillaNuntia": {"color": "#ff007f", "handle": "anguillaNuntia", "mood": "offline"}, "doctectiveMiracles": {"color": "#999900", "handle": "doctectiveMiracles", "mood": "offline"}, "obliviousCrafter": {"color": "#fd36b1", "handle": "obliviousCrafter", "mood": "offline"}, "greenZephyr": {"color": "#00ca40", "handle": "greenZephyr", "mood": "offline"}, "lawdEngrish": {"color": "#00ff00", "handle": "lawdEngrish", "mood": "offline"}, "pretentiousFantasia": {"color": "#ff66cf", "handle": "pretentiousFantasia", "mood": "offline"}, "counterRealist": {"color": "#10d985", "handle": "counterRealist", "mood": "offline"}, "maxiumumFatness": {"color": "#3366ff", "handle": "maxiumumFatness", "mood": "offline"}, "schlagzeugGator": {"color": "#61821f", "handle": "schlagzeugGator", "mood": "offline"}, "metaliAggressive": {"color": "#9289d5", "handle": "metaliAggressive", "mood": "offline"}, "pesterClient394": {"color": "#ff3737", "handle": "pesterClient394", "mood": "offline"}, "magmaExploiter": {"color": "#d90000", "handle": "magmaExploiter", "mood": "offline"}, "gardenGnostic": {"color": "#00ff00", "handle": "gardenGnostic", "mood": "offline"}, "unknownTraveler": {"color": "#006666", "handle": "unknownTraveler", "mood": "offline"}, "utilitarianTurnabout": {"color": "#dd0000", "handle": "utilitarianTurnabout", "mood": "offline"}, "adiosToreador": {"color": "#aa5500", "handle": "adiosToreador", "mood": "offline"}} \ No newline at end of file diff --git a/memos.py b/memos.py index ec8bb6b..6562550 100644 --- a/memos.py +++ b/memos.py @@ -5,12 +5,15 @@ from PyQt4 import QtGui, QtCore from datetime import time, timedelta, datetime from dataobjs import PesterProfile, Mood, PesterHistory -from generic import PesterIcon, RightClickList +from generic import PesterIcon, RightClickList, mysteryTime from convo import PesterConvo, PesterInput, PesterText, PesterTabWindow from parsetools import convertTags, addTimeInitial, timeProtocol, \ lexMessage, colorBegin, colorEnd, mecmd + def delta2txt(d, format="pc"): + if type(d) is mysteryTime: + return "?" if format == "pc": sign = "+" if d >= timedelta(0) else "-" else: @@ -34,6 +37,8 @@ def delta2txt(d, format="pc"): def txt2delta(txt): sign = 1 + if txt[0] == '?': + return mysteryTime() if txt[0] == '+': txt = txt[1:] elif txt[0] == '-': @@ -51,7 +56,11 @@ def txt2delta(txt): return sign*timed def pcfGrammar(td): - if td > timedelta(0): + if type(td) is mysteryTime: + when = "???" + temporal = "???" + pcf = "?" + elif td > timedelta(0): when = "FROM NOW" temporal = "FUTURE" pcf = "F" @@ -109,14 +118,14 @@ class TimeTracker(list): self.current = self.index(timed) def addRecord(self, timed): (temporal, pcf, when) = pcfGrammar(timed - timedelta(0)) - if pcf == "C": + if pcf == "C" or pcf == "?": 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": + if pcf == "C" or pcf == "?": return 0 if len(self.timerecord[pcf]) > 1: return self.timerecord[pcf].index(timed)+1 @@ -170,6 +179,10 @@ class TimeInput(QtGui.QLineEdit): def setSlider(self): value = unicode(self.text()) timed = txt2delta(value) + if type(timed) is mysteryTime: + self.timeslider.setValue(0) + self.setText("?") + return sign = 1 if timed >= timedelta(0) else -1 abstimed = abs(txt2delta(value)) index = 50 @@ -254,7 +267,7 @@ class MemoText(PesterText): if chum is not me: if parent.times.has_key(chum.handle): time = parent.times[chum.handle] - if not time.getTime(): + if time.getTime() is None: # MY WAY OR THE HIGHWAY time.addTime(timedelta(0)) else: diff --git a/memos.pyc b/memos.pyc index 3061b67..e3f1eb4 100644 Binary files a/memos.pyc and b/memos.pyc differ diff --git a/menus.py b/menus.py index f7ff4e6..7e221a8 100644 --- a/menus.py +++ b/menus.py @@ -38,6 +38,45 @@ class PesterQuirkList(QtGui.QListWidget): if i >= 0: self.takeItem(i) +class MispellQuirkDialog(QtGui.QDialog): + def __init__(self, parent): + QtGui.QDialog.__init__(self, parent) + self.setWindowTitle("MISPELLER") + layout_1 = QtGui.QHBoxLayout() + zero = QtGui.QLabel("1%", self) + hund = QtGui.QLabel("100%", self) + self.slider = QtGui.QSlider(QtCore.Qt.Horizontal, self) + self.slider.setMinimum(1) + self.slider.setMaximum(100) + self.slider.setValue(50) + layout_1.addWidget(zero) + layout_1.addWidget(self.slider) + layout_1.addWidget(hund) + + 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 getPercentage(self): + r = self.exec_() + if r == QtGui.QDialog.Accepted: + retval = {"percentage": self.slider.value()} + return retval + else: + return None + class RandomQuirkDialog(MultiTextDialog): def __init__(self, parent): QtGui.QDialog.__init__(self, parent) @@ -138,6 +177,10 @@ class PesterChooseQuirks(QtGui.QDialog): self.connect(self.addRandomReplaceButton, QtCore.SIGNAL('clicked()'), self, QtCore.SLOT('addRandomDialog()')) + self.addMispellingButton = QtGui.QPushButton("MISPELLER", self) + self.connect(self.addMispellingButton, QtCore.SIGNAL('clicked()'), + self, QtCore.SLOT('addSpellDialog()')) + layout_1 = QtGui.QHBoxLayout() layout_1.addWidget(self.addPrefixButton) layout_1.addWidget(self.addSuffixButton) @@ -145,6 +188,7 @@ class PesterChooseQuirks(QtGui.QDialog): layout_2 = QtGui.QHBoxLayout() layout_2.addWidget(self.addRegexpReplaceButton) layout_2.addWidget(self.addRandomReplaceButton) + layout_2.addWidget(self.addMispellingButton) self.removeSelectedButton = QtGui.QPushButton("REMOVE", self) self.connect(self.removeSelectedButton, QtCore.SIGNAL('clicked()'), @@ -240,6 +284,16 @@ class PesterChooseQuirks(QtGui.QDialog): item = PesterQuirkItem(quirk, self.quirkList) self.quirkList.addItem(item) #self.quirkList.sortItems() + @QtCore.pyqtSlot() + def addSpellDialog(self): + vdict = MispellQuirkDialog(self).getPercentage() + if vdict is None: + return + vdict["type"] = "spelling" + quirk = pesterQuirk(vdict) + item = PesterQuirkItem(quirk, self.quirkList) + self.quirkList.addItem(item) + #self.quirkList.sortItems() class PesterChooseTheme(QtGui.QDialog): def __init__(self, config, theme, parent): diff --git a/menus.pyc b/menus.pyc index 271db3a..78b4664 100644 Binary files a/menus.pyc and b/menus.pyc differ diff --git a/mispeller.py b/mispeller.py new file mode 100644 index 0000000..b8240e3 --- /dev/null +++ b/mispeller.py @@ -0,0 +1,60 @@ +import random + +kbloc = [[x for x in "1234567890-="], + [x for x in "qwertyuiop[]"], + [x for x in "asdfghjkl:;'"], + [x for x in "zxcvbnm,.>/?"]] +kbdict = {} +for (i, l) in enumerate(kbloc): + for (j, k) in enumerate(l): + kbdict[k] = (i, j) + +sounddict = {"a": "e", "b": "d", "c": "k", "d": "g", "e": "eh", + "f": "ph", "g": "j", "h": "h", "i": "ai", "j": "ge", + "k": "c", "l": "ll", "m": "n", "n": "m", "o": "oa", + "p": "b", "q": "kw", "r": "ar", "s": "ss", "t": "d", + "u": "you", "v": "w", "w": "wn", "x": "cks", "y": "uy", "z": "s"} + + +def mispeller(word): + if len(word) <= 6: + num = 1 + else: + num = random.choice([1,2]) + wordseq = range(0, len(word)) + random.shuffle(wordseq) + letters = wordseq[0:num] + def mistype(string, i): + l = string[i] + if not kbdict.has_key(l): + return string + lpos = kbdict[l] + newpos = lpos + while newpos == lpos: + newpos = ((lpos[0] + random.choice([-1, 0, 1])) % len(kbloc), + (lpos[1] + random.choice([-1,0,1])) % len(kbloc[0])) + string = string[0:i]+kbloc[newpos[0]][newpos[1]]+string[i+1:] + return string + def transpose(string, i): + j = (i + random.choice([-1,1])) % len(string) + l = [c for c in string] + l[i], l[j] = l[j], l[i] + return "".join(l) + def randomletter(string, i): + string = string[0:i+1]+random.choice("abcdefghijklmnopqrstuvwxyz")+string[i+1:] + return string + def randomreplace(string, i): + string = string[0:i]+random.choice("abcdefghijklmnopqrstuvwxyz")+string[i+1:] + return string + def soundalike(string, i): + try: + c = sounddict[string[i]] + except: + return string + string = string[0:i]+c+string[i+1:] + return string + func = random.choice([mistype, transpose, randomletter, randomreplace, + soundalike]) + for i in letters: + word = func(word, i) + return word diff --git a/mispeller.pyc b/mispeller.pyc new file mode 100644 index 0000000..c5eb90b Binary files /dev/null and b/mispeller.pyc differ diff --git a/parsetools.py b/parsetools.py index cc9f8b9..474034a 100644 --- a/parsetools.py +++ b/parsetools.py @@ -3,6 +3,8 @@ from copy import copy from datetime import timedelta from PyQt4 import QtGui +from generic import mysteryTime + _ctag_begin = re.compile(r'(?i)<c=(.*?)>') _gtag_begin = re.compile(r'(?i)<g[a-f]>') _ctag_end = re.compile(r'(?i)</c>') @@ -183,6 +185,8 @@ def addTimeInitial(string, grammar): def timeProtocol(cmd): dir = cmd[0] + if dir == "?": + return mysteryTime(0) cmd = cmd[1:] cmd = re.sub("[^0-9:]", "", cmd) try: @@ -195,6 +199,8 @@ def timeProtocol(cmd): return timed def timeDifference(td): + if type(td) is mysteryTime: + return "??:?? FROM ????" if td < timedelta(0): when = "AGO" else: diff --git a/parsetools.pyc b/parsetools.pyc index 35887e8..b589134 100644 Binary files a/parsetools.pyc and b/parsetools.pyc differ diff --git a/pesterchum.js b/pesterchum.js index ff954a3..e8e728a 100644 --- a/pesterchum.js +++ b/pesterchum.js @@ -1 +1 @@ -{"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": []} \ No newline at end of file +{"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", "doctectiveMiracles", "noSense"], "defaultprofile": "ghostDunk", "block": []} \ No newline at end of file diff --git a/pesterchum.py b/pesterchum.py index b5edad3..91fa78e 100644 --- a/pesterchum.py +++ b/pesterchum.py @@ -825,6 +825,7 @@ class PesterWindow(MovingWindow): self.closeConversations() if hasattr(self, 'trollslum') and self.trollslum: self.trollslum.close() + self.closeSignal.emit() event.accept() def newMessage(self, handle, msg): if handle in self.config.getBlocklist(): @@ -1625,6 +1626,7 @@ class PesterWindow(MovingWindow): joinChannel = QtCore.pyqtSignal(QtCore.QString) leftChannel = QtCore.pyqtSignal(QtCore.QString) setChannelMode = QtCore.pyqtSignal(QtCore.QString, QtCore.QString, QtCore.QString) + closeSignal = QtCore.pyqtSignal() class IRCThread(QtCore.QThread): def __init__(self, ircobj): @@ -1652,6 +1654,9 @@ class PesterTray(QtGui.QSystemTrayIcon): self.setIcon(PesterIcon(self.mainwindow.theme["main/icon"])) else: self.setIcon(PesterIcon(self.mainwindow.theme["main/newmsgicon"])) + @QtCore.pyqtSlot() + def mainWindowClosed(self): + self.hide() class MainProgram(QtCore.QObject): def __init__(self): @@ -1698,6 +1703,10 @@ class MainProgram(QtCore.QObject): QtCore.SIGNAL('closeToTraySignal()'), self.trayicon, QtCore.SLOT('show()')) + self.trayicon.connect(self.widget, + QtCore.SIGNAL('closeSignal()'), + self.trayicon, + QtCore.SLOT('mainWindowClosed()')) self.irc = PesterIRC(self.widget) self.connectWidgets(self.irc, self.widget) @@ -1829,7 +1838,7 @@ class MainProgram(QtCore.QObject): status = self.widget.loadingscreen.exec_() if status == QtGui.QDialog.Rejected: sys.exit(0) - os._exit(self.app.exec_()) + sys.exit(self.app.exec_()) pesterchum = MainProgram() pesterchum.run()