From a69b72784afea7d2cc8c1492d65083c01e32f71d Mon Sep 17 00:00:00 2001 From: Stephen Dranger Date: Sat, 5 Feb 2011 11:17:33 -0600 Subject: [PATCH] memos in some semblance of working order --- TODO | 1 + convo.pyc | Bin 20233 -> 20233 bytes dataobjs.py | 43 +++- dataobjs.pyc | Bin 7588 -> 8965 bytes generic.py | 4 + generic.pyc | Bin 3235 -> 3575 bytes irc.py | 211 ++++++++++++++++++++ irc.pyc | Bin 0 -> 10883 bytes logs/chums.js | 2 +- memos.py | 389 ++++++++++++++++++++++++++++++++++--- memos.pyc | Bin 7759 -> 21607 bytes menus.py | 29 ++- menus.pyc | Bin 19532 -> 19758 bytes oyoyo/__init__.pyc | Bin 333 -> 333 bytes oyoyo/client.pyc | Bin 9728 -> 9728 bytes oyoyo/cmdhandler.pyc | Bin 8312 -> 8312 bytes oyoyo/helpers.pyc | Bin 4538 -> 4538 bytes oyoyo/ircevents.pyc | Bin 5693 -> 5693 bytes oyoyo/parse.pyc | Bin 2869 -> 2869 bytes parsetools.py | 21 ++ parsetools.pyc | Bin 3674 -> 4583 bytes pesterchum.js | 2 +- pesterchum.py | 290 +++++++-------------------- themes/pesterchum/style.js | 12 +- themes/trollian/style.js | 42 +++- 25 files changed, 773 insertions(+), 273 deletions(-) create mode 100644 irc.py create mode 100644 irc.pyc diff --git a/TODO b/TODO index eaf639e..2fbeac4 100644 --- a/TODO +++ b/TODO @@ -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? diff --git a/convo.pyc b/convo.pyc index 17043a1b51599b9afb58911908263d71f9e05063..afd17694ec63e09ecb894566a231efa98da39d73 100644 GIT binary patch delta 17 ZcmeC2$JjZKk?rCqUatEmHnK7M0{}ph2H^kz delta 17 ZcmeC2$JjZKk?rCqUaqCnHnK7M0{}ie26X@c diff --git a/dataobjs.py b/dataobjs.py index 4d19dbb..e12fbd2 100644 --- a/dataobjs.py +++ b/dataobjs.py @@ -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 "-- %s%s [%s%s] %s --" % (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 "-- %s%s [%s] %s --" % (syscolor.name(), handle, suffix, self.colorhtml(), initials, msg) def pestermsg(self, otherchum, syscolor, verb): return "-- %s [%s] %s %s [%s] at %s --" % (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 "%s%s%s %s." % (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 "%s %s [%s] %s %s." % \ + (syscolor.name(), self.colorhtml(), temporal, self.handle, + initials, timetext, verb) @staticmethod def checkLength(handle): diff --git a/dataobjs.pyc b/dataobjs.pyc index b6d0ace266487fca88a82fb0cb8714aa4b66d3bd..513d6e0a64a67d0095ac75e6f63c99dffa6a1932 100644 GIT binary patch delta 2018 zcmZ`)&u<%55T3W|U+W)@)1gSd_8Px+ z8iZX#6Qm-95L%GRfeV5^AmU#@NN@o4!U1tc;=+M50={{!O*x=w$MfFIn|be>Zzf-^ zytfg3_(v-KL}TkT`e6F0Pl?DO+7@J|$kE9rI##+Z=tQUO5bxU>orvJu=_hYMk3y&I zIN32e!NCOChEkGb$CZLOXUI;lj!@fEYMC4_(_~i5XTH90_NEwWNFK!(#vn24{)oBo>ewaEb61e)l;B{NT zPvh&)!NfmVSK|PK2>ChNTSR?N`90hr6_(6K45_AwE&p@+j4w?<%W{4D!E<`2Y=5jZuoqpVM)vPyJi)- ziea9Irk3UwYcD{kV@-r4s#zWB$Dp`v*LSU^3{KO_7tI~)08o-S2oi=^5>b&7Igu4< ztng_`EqE|{UmOPK&;2Zpf}AEA#@!e?ylhp#9rs)wSu5k3Lj zk&<1aY8fT4p&p@3wXEYh70I_O$zn;$i@{&n{O0cJ)3r4$i_*GXx50 ze!S`h#(s=1LxUx-9mB!lDsmBWwRWW>*G94=`R@@XmlYymx{B*eUTQK&)$9ETw05tx z=XA?_qY?cMpeY2Hz%O^LR?F&|U4Hz~Pr`=Bd$pz~8G{e89>0r$VK}$|>%3n8`EgsM zV~GbsYNTsm5?BCMpcHr$2FV~s{TM$EFwC+B)_@fGfkAzPn>#;Thzd`h2NTcu*b{w@DcDCgWP!7ed~lw| zb__!W`;!RF)G{VsH(t4AvPp6nI8W9*M*d3*Zjjq0 zIcb)XyzIVsH%w)&sM%n_$<>&-({S3VORPPqHf-xH$pdRh(y4iETlxn3f*!Wh^sP}R z`5fb4lJWd1GaViy6*Jbi%^vS|SxoYpci6<8Y5BIAjV-s`^Bt+$t>N{$(x0LtQPZjW z-l5YSo0)8C&^kvxIu0aVR@`Nh9(ZmW9Q_C`5=YUe3+U9Gh~sYtUq;O0%W7#1N?ptc z%lVJR7s2=WZz8Y5**p$DnO}))vwE8Y2kF9;_$nwCGGaP-uCQ=zhfS*0_gKSdB$MZ` z*w4W(6{|q`19MVKN#72_s-L0vhm+j@gHC5XVyu zLjwZ?-57`^wn)|;;yzZbA;nvg=3GrKs8~8rDwgewoOl}G7wl`y`XQ-#TitG>*B5m@ zvxM0>^&_59urxk!V5EiOe#`{Vx$_0m$adNC%)6B+DrbTp4y!ow;oBS z=6BW&PIBQChi|;ZgdMRIR>#WO0t=tGl?P$7{4>#|L5SfK_N=2BLb77X)n(68*;M*; z!K7`5*R+-9%>YLv=P_an@Gx87E>={{zoXVu@78GXWa zPc(y~DwF;aoSamD(j}^^<#{{IiVn=F*NbmxTP ze!o$Fu(sZIo#%2e$^flM$0$H4j2%K0__l&cFW$V1kLj diff --git a/generic.py b/generic.py index 173285e..ad9a8a8 100644 --- a/generic.py +++ b/generic.py @@ -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) diff --git a/generic.pyc b/generic.pyc index 6e857d84e6a0bbc598445ffc7a234d74eb57065a..69c7bc65b1e99a36a1eaecd90c53eeaed6250362 100644 GIT binary patch delta 601 zcmYLF&ubG=5T4mz&F-dcs+byLO`x#`#P(uARBT0|2r;D7gXm=|*_W~yi+10^AH7v6 z9>W|(5IlGhJQTe6PbeNd_#b%mBHo;N2wj-jdEfiKnQz|v#-C>M+wbY5^R;(p2>-u8 z{_7Iui%D}~a&_a3K`3GvA>=W<1ULY=cRztVfvs*jd3BM$_^Uln1R6J0I45ZzppcAk zfPgs&7X|IRY$GYnQ)_nfu8ORVEX{ail{4l+_1dW{D|QQ;W$sEzfL)(g{WeDYBwXh= zejF(r;pD^jkhCKo;zmd+;2(G^RH(vjZy#s*t+$fa%z}xgb(+8!_Ntfx*)}24*rF5HeCd9 za&YJ$aCC8S798B%LJH7g5EAn?Vx~mj{*LNmV zi1__VO>MYF|7sqy%A+k~RBSf=V_!C#_@>kh$s>W+Ilu*VEy{_8r|LNv_@$ODlX4db zgoO{Vh!+sWt`^HNAH)eFU_wGsAq5F=HN1p^&O5{?UTakxf-!j4)&VRm>s~3tQ>-AO zD>D?%FzvC<;gt^0x8^V^4>6zoN?EK#H#E8z#e+P0|^HKyc~`PeT$ C;8oE8 diff --git a/irc.py b/irc.py new file mode 100644 index 0000000..168c06c --- /dev/null +++ b/irc.py @@ -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) diff --git a/irc.pyc b/irc.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c6f50fd43e13232555c7a2f158781255ec17134 GIT binary patch literal 10883 zcmcgyyLTK{8NahHY4xT#ClFe~8tDTWN((H`9 zGqSC7q!5l1pa?Yu1q}@qB^8`QK|@Eu-;j!iiVl9i@0)#SrEr{0f~EO9bMKvdzxQkO z_kRr!l>U8vv1ZbL1Ni@ST=Aa)T>Ls_)0n_9Wyb^=Q_dKNqZzZAH9^jlbNZY$n|Tuy zOu3-XIkVYkf__u(*XO+1EShprb}X390TT?G@}LQZOnFFG^qI|J6O5Shh;h84@kfo@ zZ+LUWJT{Kw7LAuN{+L;Fj5}aHF&H)Pm5&;C(0BzI9cqn^8#ixOO2Z(*{}29^GPq0f z05_AX+kR4zyZNZ$l^o6#0j}Bk`M~$WM299Zbj4e%ZU@PHRIgV<_bpt3*U;%cOyBc@ zEw2$T>FzmV>Tn?Lr{Iq@qQW4Hpjt1T@N@Q_XFlJcFQ#vfRmjI zhGaJ1oE_db%M%ODsgZOFB60hggQFdT{msE69fQT@;MjqkRluO-=z*!h=3CCQll#Yo;aq>} zka6-Hg2>+E~I6Q0YN@)y=SEJ1| zuX$?X(*Ox9$}xV%?7{#Y`r$)AbfbrD1B$(1O{_DWz%o-Jh@Szta4)KR7u-fQT=yCm9!8DL3tM7nwR_w3 z3x1>a{ML>g#6p^2Of-yh#HkS#UOZF?*}x45Nua`FH!jf6(Pe-XkmhIUTYQWZ=rkTX zIg(i5EEg1v-)AcQ>EiZ?@PxBPzRp($lq=-IQbKg@MR5{~R|2ldPCbgk=e=#2+KL*9 zKX@Eiabf7!HicuWK~&rH!}Su$vJ^*$e@Q)(9pW%g*;0oi9K0v)N_M-|*!Gev=4*kU zjPif=Xcb-4ko8;D2ArR4Q;WioA|oce7r9#EEwcD>0ufo$x$34zuuDu`FwTq4sB=`s z)6}!8oIM6Ww&GV+%`u;0x!cw-(qg&HP6G(e>s~_dE2<=@iif3Q#62Kwsq0g?Vq#`8 z2aVy&A}Kqzv9l+!Z4ZcvQlzxTGaU$$C6pJhd5%8|043ke&`$TV)OIynsP`^@9lD%O zrt(c;sRyDOiT5b6jFZ?Jy4?#k)auv^-9;~stLq-Qu6COl za%xSI7`KI_GHyr`P#2OwTXftwU6jG5Nm&T*)IFmnDlzV{STf*Liw!()DW-znSXjBW zVCUbuy?F8R!qsa_F%yLO>49Ct)xNznm?Q0`^+D}*E!ElyDB z4{&0B;f<9ArDYcLU9^{YmKdH8*)v(B0SX~Rku7a?ppx+rUh|y!AwbJdJT_(zu}GAB z55#5Zz&Q)A4iiAy$_Hdh`#p(>vL!Y}U4+UIC_)wgwY}v+SmI!KygC?isqV=;y$FzY zr2D3M;&T{CWjN{-o$l!JTObO*w9HdHD+T z+Eu-7Gh@GUi^(Hmx#CzKRD*4=!<~Hx`}V*D`)$1UJzS}nN0nysm^u19XWj$oqWRH$ zbEFxquiU+0D0Z=Jl{CZ-essQxxDD|OOYWaG@3;&os_Oggn>r{#Rc)D=APhc0@Fq(( zy`8vA`R!SZcUSBt!B6mb&>+4({E^_NtmmE@s=qS+fwz{V_%H3lzo{<#U--{} z+Ubltb%ipsCji93hR7?wTFF6ot}YaXhsA@Y@lNSmJcI7NQlTBCm1w0>kKFA5k5WC_ zr?5Z^ST5b#xu2{AQDPYfB#pO{HJrkuA(Wa{Xu$^Zk4kqLSNt)6hsFq!rvn`}?W&>6=}H@| zoKHIipPQOg04N=ikHrU4{TtRat?0VW%$ck&t^*mz-fgH#VaH#969Gq;yZb9yv0cJZ4v zYZ+ua?9w0=%FFAY<3aXAZ(|NvbIUu%**VUP8OqDaf;okkSYqYPJK-slL&mo;V4`uf zVI2qSaInsXh*s~?sHG?3qbGtL&@sXA{V>x!sUIg54BGXqluV zL&hKG)LtJ^0d2eBvbHG)%|_NlCsEanush6SkB}^|bGI+e>Rxo@;P4ekXeQf+X0eP(ca_O5D+X3#7dK2j0eV%(svShMf{pK9l+*GVz(> z&~HxpXi$#{5Btr|IkS!`ZLer{`^}ZR<7RKb>=s29pxZG=@Bh>JsA%^3A&b*3Sxkv6 zAPD_k&vJo?BbhM%B=`CZTpSbxLE)4T0DK2UI^nSv?Z=ukP@-n?!SK2S=EFF|k4sK5 z7o$66&YwSjX}00j9?YJ;VXxg;T)8@XHlDqBHa;CwYddNSC|aa5=eXiL0Z);NUwkhbYVd8Aq1#>q zklHBTLYqzevwf2jR|(z%DABex@X|ZVX>_gHL0~7v@*wrnJM3L)gHDdBvt8)wsdV#N zj8xu#;jS=2%Q9&>w4Lk|`&Z%FR>OaQR?jL>h+hXV*)b>YOgYD#;mm}SMN?tK83UYv zE1h;`;8u^}dBT~?Je`}t$_bRLS?3&9ON#rP%e>=(G9#o$*8br?GRNvl$) zV}TB~JPPKaB=BqdMw<2p_r#Y~$KeNH3^3umx`Ol#@h7R18KE8Q(snj0?3iP~n+k7{RKAG5~)9BePq?nRN&$#`z2zm284i3=_6>?-8S!JtI&JM#H1H9XeKpGf&38Z%dc^Q_%H)QKu3lrlERis zFXLffES5rO4h>iGNVHrVuHYx)GDAl?fmQ_;A?iYP`IVvVeo3XeUwZ?$5D5TJy^n8~ zLSnSG7Wkp3{J4b~RZ}9PYP!HXBH7V=6raPr8(uYz!d@F!wvH`+gR8}t8AthE4Qu$q zA!g5`TRi#@4~Owc?YhMyJgVA}N4U#L)ST^N7?PY$hOx~H%~}ywbTW?!s_#4rzsT@ze)Y;KqVqeVL{~x6Yq4sdVr^sca8@BEDtl;b+9Y(GG>}M-5ZMWB z52-thG7UTWc>t^Xnbd6*Of;s-hm1^C$wvjzHlop~Z8R$eYH&1Y%@TkF2HwDv0BDk*dsJk{sf^}ZopT8?HWL~hK+L%ucPG7 z8>$}#BB4WBx&;=m%RD>vIrD0J4W4EgUu17Ja_ZQUl2ke!G@KNV!gz;fSqA?BO#E~&cv#nPKFH6-a1FGa#9GjZ4HNn0Kk{nu$NN{iTv9AX%V|4pG^+`AC&LjD97YDUbaK z00{%yCP6QBQx(DFXienxM?9r2U>FtrK-*jLgsYrA2e2+=S8y=sMcSet2ay^gh={^c z`w)Ix{eBT`+P2aF`7*YV5KDnc7LQ5-0;inQ?nh3dM zCp@GfwFqJ*)u1F=q+Z4Y`pwvVy*UvQnRT7AaAqOcsd`&m%KM zSy6mYBk`f?(Yp*>SMJ{6r+Ek!HmmI$L@kK%7$gSgx{)^#@}JHG99|Vmm`3VG;x6T# zm$B{rVe<~-9#jHaz;ENiFmh2^Sm~>LNjN6{R4gp5$!Gl!fOU5!pgJIu-vJ5jB3O!` z4h^ACZdE<&!S<>&$Aw3 zhVsRHu~6*Cg{NY^L_);N+}OF9yrjJXYKugyXa_&fr>zAVM8Y;mI$BSIf5T>*d&rE+ zgi%fSkI&WBXmumj1cM4FLRj}gui@9kuS-XHwHo_1d~9FywO4X&>CI(JCv54Pgq~iR dA$Yv1o%Ks3E@oS43h|3SLmAv<#xpaw{|oQ~bcg@| literal 0 HcmV?d00001 diff --git a/logs/chums.js b/logs/chums.js index 7c544c4..af455a4 100644 --- a/logs/chums.js +++ b/logs/chums.js @@ -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"}} \ No newline at end of file +{"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"}} \ No newline at end of file diff --git a/memos.py b/memos.py index cbb4984..2fd3aaa 100644 --- a/memos.py +++ b/memos.py @@ -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 = "%s" % (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 = "%s%s%s: %s" % (colorcmd, grammar.pcf, initials, grammar.number, qtext) + # account for TC's parsing error + serverText = "%s: %s " % (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)] diff --git a/memos.pyc b/memos.pyc index a2a04305e78760c007aec5175fa1944c7ee818b5..1f17bedbfd4515c52fa8a94b12cbad9e29ba7b39 100644 GIT binary patch literal 21607 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 MhuepL^lOFx2lr>c`Tzg` delta 3074 zcmZuzO>A4o5uSY%N%5Z)L+aQ1wQNeFqd1Y8D3#>OPAof+7-%KfwbDSQ_@1nn@JHZ# zLhRHok-9*y2^KvSz4Vj@JroI$TTm3a1n8m7q3NY43gnPeE&+1trSr|BWT7#Moi{r> zJAXSnv)_EE{Q_gql31 z_K}?;Cn?mv^eH({wnf{ejQMlVkIZQJ=jOA~-#-g${ayxpdv4S9_x4I5Pz=(Noc(nj?V6q33 zBPwadqA|<-bMoJ;>(i;}m~7u^A3NqhQ^ScAHueK#*oK$h6q$o3+ezhBPNh^09%CpT z*RYCx4;8IHv}pYXpWk)~OO+A>>iWl+=<=QWz92QT_TrL>&!*Mr885$@&6LNP_teV> zPxLu}QGhW3@f5=K44ll5GdjS-12a1rW*7J8KAQ32`PPQpbY8VxKiD?Oq$ehwaW*3B z=gnK?J6T~uoOKWp1f#5Hm~fHDscmwaPqR(T3ePg{lzI2k`2s{;#m;vbI7GXgstNP$ z=(PDZb-oj1?Jg%~lH3&1ms1yctdQfjWG|<=-Y&uM8d5FF1I|kHKVb1bk*mnH=pmm( zh#p&{_&|8F7a~3tAU%L?7zf3Y6?Q~G>hKKfQCW|Y+bhyyUFgP7kOaia)}*lZz*^qP zRP0ZapLrTRE5t0hIk+Zz`(#_7Hs6u;{15a#^FzICa)JCJx&7o0h>Sq>ps)^|kvc3w zM+AzUu$!%P&j~3jQbx(2C2DxN)0I7p#ejwD-{Wv#!+FR-c&EjH3j(JDwX9~E+>5a9 z#66w|mgdirn1v;FBfu;r=sB6+mH5~Z8hj-A0GTuNFhX2b2l43*KC$2vr$NMrldP4K zk2?#SAgzhCniFfwBxNAMIa)CvUY?6`cCxu4^Y_ckx3sKg?))@nALnlF}Z-(0V(ZAi7+-gte-hc{cduD0%*-@P!j zx!!i|jp~CIi^08ItGoA_H?BENpVbTJ4d(1Jz|VTXE7jQXy9=0AZF|G~s?W-Y22|cksx1Ee z9aAG#hOsQ~5t`~}uBghHFDLS5ez89RbyB&x9c?XMwca4}n?+qXZCY|1PZ*YBC`B$u z?9I~({!&DbF!AnL0@~63DPidnf^&RiSAFMNtKMpJqMVde=`0W$;&Bc1o92&87dk1< zE53$uIUjLBW36GSUVL>qk-6AOwgpWG;R{;LgCj?f{Z^|UbX}|+wOa>n-OCd_{Q_fh{)g43&5RdO{tLo&z)R9f5qJ*nCm+B3o>B?3uzY14(enTrPNU_`*Q@(Z zectmQ)Eys&9hyHa_nSW~@1(Qf;U~g;?eMtanas+6*C(0eqt|$je_LJ-H#w|YBF|LP z3t)it%&>zNngL!taQ3|8eb0COW8cv^^V;fWc?GOpS=ZhBj(yv;{X>m#>Z=S&BDLGt zK3}~Rd4-7$GGkZDY1|?ViT!1B=gM>QXCf;h0(THL^h5nJgA%r!X_X~umA_=7bY$Z6 z%&HoK07k@JWDfTb{42mhkKm8#PW3ClC zo^!^v3rK@OeZ&mE1`~7<->8%d^WDmtj|R?}?>DnKu_;K!9_HY3R<4wTyA{OA{Gzh; z+WQcJIi7OJh^IbsZe!u60Jv4b!|o0+dHuWsY{uLjE=FLL_VF5;E;EX!hgW34uc7B+ zRxHE=|7ffb3m0OgXUxC!vs!|{_psX9f6EK*11y$2yXQ2Wwp$BQ5RWSfk46e=2`Va= l#`98-13;rLvjHpS;!a<&kEdCcR7I=EXFq8bGsQ$P`ahUB3fTYv diff --git a/menus.py b/menus.py index e187afd..eb3611c 100644 --- a/menus.py +++ b/menus.py @@ -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()')) diff --git a/menus.pyc b/menus.pyc index 7229cd5ad49d3f120b793c2560f5cc6aabc80d7f..e7171d2d11bbc114abc074ba6c8729f88678ce50 100644 GIT binary patch delta 4718 zcmbVQYiwLc6`ompcfEe@+UvE~PU3gFPLq(tc{p#corm4TNj!EEk`TgX?@fG@^iMIvaRr9q=Ar3g_ZR0^UkVo4~XN|Q=ZQi|FNf%=CZMFNR`p@2ZpN}TUpdw1g+ zkZ8MKXXczaGjrygZ_f4G&&rpdlg;maSXI8YZ+JKU=7e;N7pe`?n2qRo1sLu-;gb^tcG~@-1!tjXE zSfdbnpLE(|9&(3MPB3Oon4>AnFf&eIraP3LoO1L%`Bzz?Z+o_Sp%&2ol2@sJr=&|( z>pzx^5cZa?@j<2<_1%We`thMsS(f{8=@u!=_20caWtkrEbyQSCV-cW6pY{#1wMKp0 zcbzQk@$Z!#`gwo2A_|2jK)HV1ACcWK>20QghFr9)$@?f4a&VDZ(;2pnL`p?4;v-1f z>EqT3$BX{BIbpi1wV;c|X~F?3ZP;hWEGK2EW__vZLs_pUtNVhyw-uzLRsw4Do$3T{ zaIt=<=Dnq>U;<{7_Eg$YUC^l@h?Ss)$xbQ3(Zef_sF;>L>w<06Jwm@M#)b6j`=J}U zG_=YWq^=6<&7qcV974ggY6o->#GvjP#B!5{m2^~4e<8GA9@Fumy? z967cMVdDR{yc)&aqLp6`H_J@!t#Geg!iU@sIS!evLd%>?C6Z<8ozvu2a|_46T^?;4Lu^Chb(p z%38Fw?K;%8*f-;!c-QCHKeuu(bnTZtJUa^$Q-BPB?|2-oGk^;O%(iY2PI0Q8csMLS z%3XZeBjq_g9jo_ooZI@jSiA2sW>xApVjVu-;d!3X(H)khy0^Qnvk<2+?S@$)POo9? zX^zebYTnG<>E2Tmoy(UrcNU^^Ig~-8MIPYoKc?*^-P0U#NfNUMoy4(J;+UB#3N>73 zQH0KSeGguR>wV^{PllvW+hOnXfI$LX+Ovk89nxxP|0ja+I;jM6zh8Q}gp=u?xp%bg>WI#`?YF*5^)DBx61aqDVp1}E=W(r^D z{RSx=)E}?wCyn(y}DiC519z6D_OH_$4qQGzbt4hJ#bhIQT- zX)vWr?~p1e%?kS(J@ z;i-{+>6I})Pa$)d6bnfMxA7H>j5--BeL}rN0}5wWIE(rb;3otw`^-b zf~Ok~)&TvoU(z3M{AfBLi~y!wq&g!aoCe_ph1DpmC`PV$c)UqC&1hInMS}~3Ln8}O zrxr99v04q|A~qEg25*UUV42HTTJB1zkeEMB2C9k-wD8mxVYLdU4f~Q<*EQJk9}HGQ zZ`NQt3hPU>Z;!A#X7<5m^8FSzi^V&|m1$Bg5f@8lmCM~V^Zm*>{kl2*`Z@i`oPN`s z{(^kJ3tPMrnK|J@*aP-y2r8p%^!Aqww?-r#EOXi!h`o-l7TwLG2Ps4O%+@TxpbJ^(T<4yY!-XhqqQXQeEB`Z_x+iYlC;8 z$C=HCt>$O&{diE`(tnDt)7RtPikqYoE0Uh<56M^c#s2q4=HWT^2h~_Z^tr%A{Rmp> zbu0t+E6^A}cggWYI&G%1>ibY|dFOWnb@HdVKM!=u{d`?aY|LbAKBmS z!$O6(VLo=7E_zGG@Hz7aJcMWxG9W{;Pxxe$Oybxj7^5E?o<%eu7x~Ne5)+0+Y3C-J z6q9~RRgbW%-HfHsrn%|afQFUb?q^NQ&#A561bl^{@U5fnvHwUU)N9Xb|4Vyw7B2uRRgt$t4 zT>?_Z4w;nEK*q3_KhW297}G{6xPZKUl)2HWX3tmQNhB_$KQFjabmTLn1q>3^FvikIJndBj4s&$0hQ2`p*Ih%9bli2>{~I`x_SMUEKZ$FS;E_ej3V*u32 s3e}`~2Jjl-UH!q%J&W-7h={E8L?r#|iPl7GqseG@^l-E-x<9)6-+G!ddjJ3c delta 4510 zcmbVPdu&@*8NbJgojA4==jFt4(j-mV+I^>K)22zO^XMaO+9f9?g_f>$eQ%PxI<{-y zq>boSq#&k3*Hk^ zOd^thIp=)me2;U!-*?V^_6hO&S48OcyS|Ft)zKqyZRxL!{zvJT?fzm&UUq7R(98;L zN@%)E`?RJlYTCz7cr?9?1zr}E=LJ4Zce9|91r>Qgm8N@&1m3*Buj#%bL1kW0t?5xpa>KfF0t}j$TVhI9MJy+MGUMZ{Ixte-eDAF8W;S*srWdooQz~->RLMy#+ z-kM0HEV<5hAV_0@+<1ADvle2WlQpa(DLs~ub?PBs(8YeVsIU7PL{L5Ndsoz|rz@j= z_HhfXky`;ib*D1Mjz-k|Rkt^7gEl8YJT;fJWC!NB3Bo04aTul4I(@S1lw7NxEA4f* zQuh<;3IFe0m6%ea=BryH91L{HHb6T;80%~e(4W@LxFsvqkE>y`%Jyuh$6184olEK%`!I%Y2Q<>B(8_dG9 z`a@kvoX-qvD9l1$sn<`cq(ibfvg?jL#NUIn@jc{qu8X=G^gECTS+8i=3gI@JVCZxR@R` zV~N!Cg8Ej&`pwJI4@WDJgE9;l14zIm;Iy5J5o(8X{f)nNhz-ggY84yR*3kW}n=plw zxG32$)&l5K*FvMBP2CN(pX|oKM*w>PwSXM}w%mi(PCyjU2j~Y300sd=1mOy_cms;; zsrlx$)oV$@8)C_Qn6#fVVUM_~{@gs~DGJz*<_yjFT<%IspR;)bHM7XT`B=i#W0ogA3dO)-*KNTT@6-0ZI9MhI}j>9P0KA1rM##4!enKe^MIjlz3tamMKrj?ZN>M$#Hd z>c&Os!SY%4R(Q4R5}Fn2Zn(q6{$E(qr_MyGM2SjA+B*ve4BLgOYG?Gr82h|^^5>|1 zBX=iq-%=h&H_|{B8Jsa5FydA?66TUh1DY&k_hxkK0ELa?s29|CH%2aVHgghiou(t? z)6bu-T$cSSr9u?im!&(`!{zCYdBcED0rnH98>PF2UwwAd;D4w3BP6fNHEn*Vgo(RK zz0mbo_x}#ezEhw)1VCK!kh-+(=)ekobLzx&eIRZjb(RIn8^b{{n}?LAJ6OL`KsH^w zau>S&Vl5o75PLEqR#5cckQ$$CcCT{0_}I zr{3OqMLe!%c5P~0LwyS~GpP#&ujG`vw(GF-+ccie{cG2x7-s{VNo?h-B#~U?4xn`q z&;ekVsA2mR#$MR$Vg)1Ut_AP~sNU#vdgC*(1nv;3M#k4e@^V2!VMO$bln z2g#sAGnI->h9i09dtGMLjiR?TC)%56^qA>G)h++b!>L5#BffPW=!FPD<-#RAb9yp zkbD`i63tPNQ<(=+X40;03F_M%H7?8=vniYTQ7nH7P`Ks$(Cr6sAt+qtIBGkIag~-8 z-P^8*DFd@n)icQC2n6)sInc^$ZS^gAyeg;DyPHgr1eox(t*dNqUO}It1h-xm;q<(Z@K)j^>eW1aA z6{-q1u%A2-%avGYJcXQ zGcMs?=XSVD+-2@E)jZPajgZvPv=c;khq~3$+C)q*p)qDU{L3@_x=N4e}^P z&4DnrG`O5F9PKsr=ArGxd=fKR_)JNS{ZvV$VmcK=n+XFLMIedT0%^5VedylcIE-bu zI%cuNn3$mtyqzR2Iv^h<^PbDElI3g-Ni-1>m2|KTjv7ams1<$@hg0|=KcG8%f`Ez} zMXpo84lPwl#fi3vIy5ucOQp#!msFQ%xKuNp_!>qrA!p4p%`De+mZ9s`^wP`k+d3FJ z%3)2>qtwv3xqo}tX!o%B$C3})Ph4G0rkPkaW?31DOtc^SZ=v-o0N-y2M!pHS4WJDv zFXrp0g$L{V&+9kXA1p@lRyy3YFGuZ9#zGFS^#1!TQgxHOMGJok707>=@Or}mYB1f$ z7RIgZb{?=_$JOxY)?Pc&ak8=rfX{LJO^CdfX8?FlO1!ZoZaSueyhZlzYsU9|KzJPi W5pV>nf;GW-FcLf&Y!6Nb2mS-9FD2vv diff --git a/oyoyo/__init__.pyc b/oyoyo/__init__.pyc index be26c04278418a75756d2cf8046f30e23a4107ba..28e3e80c476d1ac01bd4cfb463eeb187f0612c7e 100644 GIT binary patch delta 15 WcmX@hbe4(j;wN6NbFmxQ+!+BfRRyU4 delta 15 XcmX@hbe4(j;wN6Nd*3&*xibO)HMa&+ diff --git a/oyoyo/client.pyc b/oyoyo/client.pyc index 5ba5325557d363f0374c9e0ca7739ef737554db4..9115adc5cacf5adb23fb132f67c3c301bbd75af2 100644 GIT binary patch delta 15 WcmZqhY4BmY_=%V6#+Hq2zf=J<<_6mU delta 15 WcmZqhY4BmY_=%TGaLz`yU#b8v#0C5S diff --git a/oyoyo/cmdhandler.pyc b/oyoyo/cmdhandler.pyc index e9def19d77978e0983f9458c1605a5ac084df2c3..d97b3d1ff2c4eb42e44ae39815380e44fd3c0833 100644 GIT binary patch delta 15 Wcmez2@WX-a;wN6NbFmxQiWC4n$_B*% delta 15 Xcmez2@WX-a;wN6Nd*3&*6)6A!K`aMv diff --git a/oyoyo/helpers.pyc b/oyoyo/helpers.pyc index c05a1cdee96fff9af6990b89e30bec06ae64454a..16a01a9dfbd508f7afb86d25c3b04726acbe3a7d 100644 GIT binary patch delta 16 Xcmdm`yi1w=;wN4%&MfbZ?3)DvHM#}X delta 16 Xcmdm`yi1w=;wN6NzyhC*?3)DvH`@j! diff --git a/oyoyo/ircevents.pyc b/oyoyo/ircevents.pyc index 1f1ccd60b234136833f75055fd8d2e431da22511..c83999f5508b0e331f132f84e784455707b3e147 100644 GIT binary patch delta 15 Wcmdn1vsZ`h;wN6NbFmxQ%*6mS&IRHC delta 15 Xcmdn1vsZ`h;wN6Nd*3&*nTr7cI4}l` diff --git a/oyoyo/parse.pyc b/oyoyo/parse.pyc index e67f2eacb08e566bee9472177a2c6889c2828d09..9095b24ca7fdd4567a86d7cbbd0c9a4cc710c079 100644 GIT binary patch delta 15 WcmdlgwpEPn;wN6NbFmxQ^tk~smj#mm delta 15 XcmdlgwpEPn;wN6Nd*3&*>2m`BH2DTS diff --git a/parsetools.py b/parsetools.py index 5e9236b..fe3aca5 100644 --- a/parsetools.py +++ b/parsetools.py @@ -1,4 +1,5 @@ import re +from datetime import timedelta from PyQt4 import QtGui _ctag_begin = re.compile(r'') @@ -87,3 +88,23 @@ def escapeBrackets(string): for i in range(0, btlen-etlen): retval += "" 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 diff --git a/parsetools.pyc b/parsetools.pyc index 82e6ea5e3dd2e183c3d67c20c744cf7193e73cae..64d926f928596007e1af186b851d715f9a0a57f3 100644 GIT binary patch delta 1354 zcmXw2U2hvz5S`f%J6?YzO--zl5+`*_wzMHs@~5?z_S)DR zL8UlGO5WfF?i)fv`~r~rPT?o?wa-YrAXW4az?ti0?L9j)ckaiWGxyo~ziabPUlhG( z`*-dHbn>|PZr~jre?MOxheV-GU)a=fXvZOrh+>yQhmM$bGIZj)#?79(8RJe-n5A%v zj**$8Fh|EkJ069eG4d4VjZvVGY1=Pg%lJP$n?A!#a{_U;8--CPZT|8tv-S8p{)ySq zm+dNB`nJ8uwr<<^nDrC;IT!S=&U3_ncCR7+)SbKHUsH`j|Fo^n{W)PVz)U1rl zW@`S2(hdDV#^aj4pIKihNqQd82-0S&u^YAGB(>oW_jlET{w-6zG%wT6OI`*LB_R@3 z6{e5(bX9%m)wQ3U=G^1!**9%o*8h5MmC`9>G#YUdr;Wy{e&Su_%laShru!=5uj_jL z?aXVi)D;uF3iF!&BVXfJ^k4aPUers4ch-b0wJfjzNJX)TC+xvYL|Frtl>C zsuK@WRn|Wie&-eaaq;tUAlwK^GW{mr;UVAvIzV(54M*0gYZ=$316%r`P1JvxSR9Ai z4)u$0EDBw5dM+HIZ2{y;Qidu^2TUj4vUu4=$MV2+S3dCUm zGXiG>WW*OSQaSow4C=+}2YW_}WWT!`4SX3hJecZRgJ!qe9Gq&^+lwKBXLRfBK{@?R zer=qJ?9DK|7k8uE5GQVSK1F1RJR+XPZ<$>VWPj0I`ooa+Ck!c->D-8og+fL+pE)cT z07n=E9(m%sdUpIQcL(K)1O7Lgj9u>CP^Yy z(49yY#sgJ`Z&vzxT5X6ey_iCQaH5GUB<|Lrm-d2QCxAbk0}y-oy~H-xxx{C<#zlO6 zv*(sfl3Nxw(@18U1DK_^9^FmrO6oI>5%jwKxD%;G1eDBB7X&T|yiYVmYE#S)aTVXy Z*Gsc=a=!{Z!!wpN#I#kom|M+d{|DLX>#6_% delta 541 zcmX|7OG_L<5boNZ$GS5^cJ-vYI=)sWzC|xSBT8;b&`!ufO*ZS!AOq_vyCdR71icAD zD9A|=|9}_oMsMCk@Z>omM_YR3)Nz(|D$?L4dK%=#U5pv!cU4lAr_Lt2l3IXBg62K#)so` z064vXLjZ|ir3--DvK10|BtL<`dwB;I{?hJ9ztM+g68sW}U~!{b{*tdP4)CcYDIVV` zgCH^qs=<1>SPDE~HAClfsuw(Lvu5=?CG=rvO&PB# zQr)rGL*XDkSRIhVMtcHW{A|A&vp9hbRWm`P6I6?pmB6cKt(}406j#TetOT3ouokHX zyt2=r7Z03olW}t+ZbmhTE#|i7qY*{?xu&$Xx*nDT<&vPdQ>u-jli@8rZU%p5>eDt+ N8`6naKr>-?J^@E9YL5T_ diff --git a/pesterchum.js b/pesterchum.js index 129b3f8..9fb7056 100644 --- a/pesterchum.js +++ b/pesterchum.js @@ -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": []} \ No newline at end of file +{"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": []} \ No newline at end of file diff --git a/pesterchum.py b/pesterchum.py index ba2b613..35b392b 100644 --- a/pesterchum.py +++ b/pesterchum.py @@ -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() diff --git a/themes/pesterchum/style.js b/themes/pesterchum/style.js index 466a065..1522af3 100644 --- a/themes/pesterchum/style.js +++ b/themes/pesterchum/style.js @@ -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" } diff --git a/themes/trollian/style.js b/themes/trollian/style.js index bf0d2d8..5eab3b7 100644 --- a/themes/trollian/style.js +++ b/themes/trollian/style.js @@ -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" + } } \ No newline at end of file