diff --git a/TODO b/TODO
index bce54a7..c515bc3 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,4 @@
Features:
-* memo change theme
-* 1 MINUTES FROM NOW
* memo kicking
* user import
* Transparent background?
diff --git a/convo.pyc b/convo.pyc
index afd1769..9fdf065 100644
Binary files a/convo.pyc and b/convo.pyc differ
diff --git a/dataobjs.py b/dataobjs.py
index 4ff8fec..8be4b37 100644
--- a/dataobjs.py
+++ b/dataobjs.py
@@ -147,7 +147,11 @@ class PesterProfile(object):
initials = pcf+self.initials()
return "%s %s %s %s." % \
(syscolor.name(), self.colorhtml(), initials, timetext, verb, channel[1:].upper().replace("_", " "))
-
+ def memobanmsg(self, opchum, opgrammar, syscolor, timeGrammar):
+ initials = timeGrammar.pcf+self.initials()+timeGrammar.number
+ opinit = opgrammar.pcf+opchum.initials()+opgrammar.number
+ return "%s banned %s from responding to memo." % \
+ (opchum.colorhtml(), opinit, self.colorhtml(), initials)
def memojoinmsg(self, syscolor, td, timeGrammar, verb):
(temporal, pcf, when) = (timeGrammar.temporal, timeGrammar.pcf, timeGrammar.when)
timetext = timeDifference(td)
diff --git a/dataobjs.pyc b/dataobjs.pyc
index da4b76c..a378f29 100644
Binary files a/dataobjs.pyc and b/dataobjs.pyc differ
diff --git a/irc.py b/irc.py
index 6a54f53..f48289d 100644
--- a/irc.py
+++ b/irc.py
@@ -3,11 +3,12 @@ from oyoyo.client import IRCClient
from oyoyo.cmdhandler import DefaultCommandHandler
from oyoyo import helpers
import logging
+import random
from dataobjs import Mood, PesterProfile
from generic import PesterList
-logging.basicConfig(level=logging.INFO)
+logging.basicConfig(level=logging.DEBUG)
class PesterIRC(QtCore.QObject):
def __init__(self, window):
@@ -79,6 +80,11 @@ class PesterIRC(QtCore.QObject):
def leftChannel(self, channel):
c = unicode(channel)
helpers.part(self.cli, c)
+ @QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
+ def kickUser(self, handle, channel):
+ c = unicode(channel)
+ h = unicode(handle)
+ helpers.kick(self.cli, h, c)
def updateIRC(self):
self.conn.next()
@@ -155,7 +161,10 @@ class PesterHandler(DefaultCommandHandler):
def quit(self, nick, reason):
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, "", "quit")
- self.parent.moodUpdated.emit(handle, Mood("offline"))
+ self.parent.moodUpdated.emit(handle, Mood("offline"))
+ def kick(self, opnick, channel, handle, op):
+ self.parent.userPresentUpdate.emit(handle, channel, "kick:%s" % (op))
+ # ok i shouldnt be overloading that but am lazy
def part(self, nick, channel, reason="nanchos"):
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, channel, "left")
@@ -170,8 +179,7 @@ class PesterHandler(DefaultCommandHandler):
oldhandle = oldnick[0:oldnick.find("!")]
newchum = PesterProfile(newnick, chumdb=self.mainwindow.chumdb)
self.parent.moodUpdated.emit(oldhandle, Mood("offline"))
- self.parent.userPresentUpdate.emit(oldhandle, "", "oldnick")
- self.parent.userPresentUpdate.emit(newnick, "", "newnick")
+ self.parent.userPresentUpdate.emit("%s:%s" % (oldhandle, newnick), "", "nick")
if newnick in self.mainwindow.chumList.chums:
self.getMood(newchum)
def namreply(self, server, nick, op, channel, names):
diff --git a/irc.pyc b/irc.pyc
index bc6e9a6..34d021f 100644
Binary files a/irc.pyc and b/irc.pyc differ
diff --git a/memos.py b/memos.py
index 582a617..239947e 100644
--- a/memos.py
+++ b/memos.py
@@ -4,7 +4,7 @@ from PyQt4 import QtGui, QtCore
from datetime import time, timedelta, datetime
from dataobjs import PesterProfile, Mood
-from generic import PesterIcon
+from generic import PesterIcon, RightClickList
from convo import PesterConvo, PesterInput, PesterText, PesterTabWindow
from parsetools import convertTags, escapeBrackets, addTimeInitial, timeProtocol
@@ -282,8 +282,17 @@ class PesterMemo(PesterConvo):
self.textInput = MemoInput(self.mainwindow.theme, self)
self.textInput.setFocus()
- self.userlist = QtGui.QListWidget(self)
+ self.userlist = RightClickList(self)
self.userlist.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding))
+ self.userlist.optionsMenu = QtGui.QMenu(self)
+ self.addchumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
+ self.connect(self.addchumAction, QtCore.SIGNAL('triggered()'),
+ self, QtCore.SLOT('addChumSlot()'))
+ self.banuserAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/banuser"], self)
+ self.connect(self.banuserAction, QtCore.SIGNAL('triggered()'),
+ self, QtCore.SLOT('banSelectedUser()'))
+ self.userlist.optionsMenu.addAction(self.addchumAction)
+ # ban list added if we are op
self.timeslider = TimeSlider(QtCore.Qt.Horizontal, self)
self.timeinput = TimeInput(self.timeslider, self)
@@ -396,6 +405,8 @@ class PesterMemo(PesterConvo):
self.userlist.setStyleSheet(theme["memos/userlist/style"])
self.userlist.setFixedWidth(theme["memos/userlist/width"])
+ self.addchumAction.setText(theme["main/menus/rclickchumlist/addchum"])
+ self.banuserAction.setText(theme["main/menus/rclickchumlist/banuser"])
self.timeinput.setFixedWidth(theme["memos/time/text/width"])
self.timeinput.setStyleSheet(theme["memos/time/text/style"])
@@ -431,6 +442,7 @@ class PesterMemo(PesterConvo):
op = True
handle = handle[1:]
if handle == self.mainwindow.profile().handle:
+ self.userlist.optionsMenu.addAction(self.banuserAction)
self.op = True
item = QtGui.QListWidgetItem(handle)
if handle == self.mainwindow.profile().handle:
@@ -439,6 +451,8 @@ class PesterMemo(PesterConvo):
color = chumdb.getColor(handle, defaultcolor)
item.setTextColor(color)
self.userlist.addItem(item)
+ self.userlist
+
def timeUpdate(self, handle, cmd):
window = self.mainwindow
@@ -516,32 +530,103 @@ class PesterMemo(PesterConvo):
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
def userPresentChange(self, handle, channel, update):
- if (update in ["join","left"]) and channel != self.channel:
- return
- chums = self.userlist.findItems(handle, QtCore.Qt.MatchFlags(0))
h = unicode(handle)
c = unicode(channel)
+ update = unicode(update)
+ if update[0:4] == "kick": # yeah, i'm lazy.
+ l = update.split(":")
+ update = l[0]
+ op = l[1]
+ if update == "nick":
+ l = h.split(":")
+ oldnick = l[0]
+ newnick = l[1]
+ h = oldnick
+ if (update in ["join","left", "kick"]) and channel != self.channel:
+ return
+ chums = self.userlist.findItems(h, QtCore.Qt.MatchFlags(0))
systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
# print exit
- if update == "quit" or update == "left" or update == "oldnick":
+ if update == "quit" or update == "left" or update == "nick":
for c in chums:
chum = PesterProfile(h)
self.userlist.takeItem(self.userlist.row(c))
if not self.times.has_key(h):
- return
+ self.times[h] = TimeTracker(timedelta(0))
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())
+ if update == "nick":
+ self.addUser(newnick)
+ elif update == "kick":
+ print "KICKING"
+ if len(chums) == 0:
+ return
+ c = chums[0]
+ chum = PesterProfile(h)
+ if h == self.mainwindow.profile().handle:
+ chum = self.mainwindow.profile()
+ ttracker = self.time
+ curtime = self.time.getTime()
+ elif self.times.has_key(h):
+ ttracker = self.times[h]
+ else:
+ ttracker = TimeTracker(timedelta(0))
+ while ttracker.getTime() is not None:
+ grammar = ttracker.getGrammar()
+ opchum = PesterProfile(op)
+ if self.times.has_key(op):
+ opgrammar = self.times[op].getGrammar()
+ elif op == self.mainwindow.profile().handle:
+ opgrammar = self.time.getGrammar()
+ else:
+ opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW")
+ self.textArea.append(convertTags(chum.memobanmsg(opchum, opgrammar, systemColor, grammar)))
+ ttracker.removeTime(ttracker.getTime())
+
+ if chum is self.mainwindow.profile():
+ # are you next?
+ msgbox = QtGui.QMessageBox()
+ msgbox.setText(self.mainwindow.theme["convo/text/kickedmemo"])
+ msgbox.setInformativeText("press 0k to rec0nnect or cancel to absc0nd")
+ msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
+ ret = msgbox.exec_()
+ if ret == QtGui.QMessageBox.Ok:
+ self.userlist.clear()
+ self.time = TimeTracker(curtime)
+ self.resetSlider(curtime)
+ self.mainwindow.joinChannel.emit(self.channel)
+ me = self.mainwindow.profile()
+ self.textArea.append(convertTags(me.memoopenmsg(systemColor, self.time.getTime(), self.time.getGrammar(), self.mainwindow.theme["convo/text/openmemo"], self.channel)))
+ elif ret == QtGui.QMessageBox.Cancel:
+ if self.parent():
+ i = self.parent().tabIndices[self.channel]
+ self.parent().tabClose(i)
+ else:
+ self.close()
+ else:
+ # i warned you about those stairs bro
+ self.userlist.takeItem(self.userlist.row(c))
elif update == "join":
self.addUser(h)
time = self.time.getTime()
serverText = "PESTERCHUM:TIME>"+delta2txt(time, "server")
self.messageSent.emit(serverText, self.title())
- elif update == "newnick":
- self.addUser(h)
+ @QtCore.pyqtSlot()
+ def addChumSlot(self):
+ if not self.userlist.currentItem():
+ return
+ currentChum = PesterProfile(unicode(self.userlist.currentItem().text()))
+ self.mainwindow.addChum(currentChum)
+ @QtCore.pyqtSlot()
+ def banSelectedUser(self):
+ if not self.userlist.currentItem():
+ return
+ currentHandle = unicode(self.userlist.currentItem().text())
+ self.mainwindow.kickUser.emit(currentHandle, self.channel)
def resetSlider(self, time):
self.timeinput.setText(delta2txt(time))
self.timeinput.setSlider()
diff --git a/memos.pyc b/memos.pyc
index b04b9dc..8e6e6b4 100644
Binary files a/memos.pyc and b/memos.pyc differ
diff --git a/oyoyo/helpers.py b/oyoyo/helpers.py
index 081e94e..38841b1 100644
--- a/oyoyo/helpers.py
+++ b/oyoyo/helpers.py
@@ -38,6 +38,9 @@ def names(cli, *channels):
def channel_list(cli):
cli.send("LIST")
+def kick(cli, handle, channel):
+ cli.send("KICK %s %s" % (channel, handle))
+
def msgrandom(cli, choices, dest, user=None):
o = "%s: " % user if user else ""
o += random.choice(choices)
diff --git a/oyoyo/helpers.pyc b/oyoyo/helpers.pyc
index 16a01a9..6167088 100644
Binary files a/oyoyo/helpers.pyc and b/oyoyo/helpers.pyc differ
diff --git a/parsetools.py b/parsetools.py
index b6f7fff..5417607 100644
--- a/parsetools.py
+++ b/parsetools.py
@@ -121,9 +121,15 @@ def timeDifference(td):
if atd == timedelta(0):
timetext = "RIGHT NOW"
elif atd < timedelta(0,3600):
- timetext = "%d MINUTES %s" % (minutes, when)
+ if minutes == 1:
+ timetext = "%d MINUTE %s" % (minutes, when)
+ else:
+ timetext = "%d MINUTES %s" % (minutes, when)
elif atd < timedelta(0,3600*100):
- timetext = "%d:%02d HOURS %s" % (hours, leftoverminutes, when)
+ if hours == 1 and leftoverminutes == 0:
+ timetext = "%d:%02d HOUR %s" % (hours, leftoverminutes, when)
+ else:
+ timetext = "%d:%02d HOURS %s" % (hours, leftoverminutes, when)
else:
timetext = "%d HOURS %s" % (hours, when)
return timetext
diff --git a/parsetools.pyc b/parsetools.pyc
index fead7da..e63ad4e 100644
Binary files a/parsetools.pyc and b/parsetools.pyc differ
diff --git a/pesterchum.js b/pesterchum.js
index 9fb7056..2ab9987 100644
--- a/pesterchum.js
+++ b/pesterchum.js
@@ -1 +1 @@
-{"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
+{"tabs": false, "chums": ["aquaMarinist", "marineAquist", "unknownTraveler", "tentacleTherapist", "macruralAlchemist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium", "terminallyCapricious", "illuminatedWax", "illuminatedWax"], "defaultprofile": "testProfile", "block": []}
\ No newline at end of file
diff --git a/pesterchum.py b/pesterchum.py
index c26dbd9..d9997d9 100644
--- a/pesterchum.py
+++ b/pesterchum.py
@@ -1037,7 +1037,11 @@ class PesterWindow(MovingWindow):
def userPresentUpdate(self, handle, channel, update):
c = unicode(channel)
n = unicode(handle)
- if update == "quit" or update == "oldnick":
+ if update == "nick":
+ l = n.split(":")
+ oldnick = l[0]
+ newnick = l[1]
+ if update == "quit":
for c in self.namesdb.keys():
try:
i = self.namesdb[c].index(n)
@@ -1054,14 +1058,16 @@ class PesterWindow(MovingWindow):
pass
except KeyError:
self.namesdb[c] = []
- elif update == "newnick":
+ elif update == "nick":
for c in self.namesdb.keys():
try:
- i = self.namesdb[c].index(n)
+ i = self.namesdb[c].index(oldnick)
+ self.namesdb[c].pop(i)
+ self.namesdb[c].append(newnick)
except ValueError:
- self.namesdb[c].append(n)
+ pass
except KeyError:
- self.namesdb[c] = [n]
+ pass
elif update == "join":
try:
i = self.namesdb[c].index(n)
@@ -1406,6 +1412,7 @@ class PesterWindow(MovingWindow):
trayIconSignal = QtCore.pyqtSignal(int)
blockedChum = QtCore.pyqtSignal(QtCore.QString)
unblockedChum = QtCore.pyqtSignal(QtCore.QString)
+ kickUser = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
joinChannel = QtCore.pyqtSignal(QtCore.QString)
leftChannel = QtCore.pyqtSignal(QtCore.QString)
@@ -1511,7 +1518,10 @@ def main():
QtCore.SIGNAL('leftChannel(QString)'),
irc,
QtCore.SLOT('leftChannel(QString)'))
-
+ irc.connect(widget,
+ QtCore.SIGNAL('kickUser(QString, QString)'),
+ irc,
+ QtCore.SLOT('kickUser(QString, QString)'))
# IRC --> Main window
irc.connect(irc, QtCore.SIGNAL('connected()'),
diff --git a/themes/pesterchum/style.js b/themes/pesterchum/style.js
index 7a097e3..2bfe997 100644
--- a/themes/pesterchum/style.js
+++ b/themes/pesterchum/style.js
@@ -30,7 +30,8 @@
"removechum": "REMOVE CHUM",
"blockchum": "BLOCK",
"addchum": "ADD CHUM",
- "unblockchum": "UNBLOCK"
+ "unblockchum": "UNBLOCK",
+ "banuser": "BAN USER"
}
},
"chums": { "style": "border:2px solid yellow; background-color: black;color: white;font: bold;font-family: 'Courier';selection-background-color:#646464; ",
@@ -211,7 +212,8 @@
"unblocked": "unblocked",
"openmemo": "opened memo on board",
"joinmemo": "responded to memo",
- "closememo": "ceased responding to memo"
+ "closememo": "ceased responding to memo",
+ "kickedmemo": "You have been banned from this memo!"
},
"systemMsgColor": "#646464"
},
diff --git a/themes/trollian/style.js b/themes/trollian/style.js
index ed9af97..b2f397e 100644
--- a/themes/trollian/style.js
+++ b/themes/trollian/style.js
@@ -30,7 +30,8 @@
"removechum": "Trash",
"blockchum": "Block",
"addchum": "Add Chump",
- "unblockchum": "Mercy"}
+ "unblockchum": "Mercy",
+ "banuser": "BAN USER" }
},
"chums": { "style": "font-size: 12px; background: white; border:2px solid #c2c2c2; padding: 5px; font-family: 'Arial';selection-background-color:rgb(200,200,200); ",
"loc": [475, 89],
@@ -259,7 +260,8 @@
"unblocked": "mercifully forgave",
"openmemo": "opened memo on board",
"joinmemo": "responded to memo",
- "closememo": "ceased responding to memo"
+ "closememo": "ceased responding to memo",
+ "kickedmemo": "You have been banned from this memo!"
},
"systemMsgColor": "#646464"
},
@@ -293,8 +295,8 @@
"style": "color: black; font:bold; border:1px solid #c2c2c2; background: white; height: 19px;"
},
"slider": { "style": " border:1px solid #c2c2c2;",
- "groove": "border-image:url($path/timeslideraqua.png);",
- "handle": "image:url($path/aquaicon.png);"
+ "groove": "border-image:url($path/timeslider.png);",
+ "handle": "image:url($path/acceptant.png);"
},
"buttons": { "style": "border:1px solid #a68168; height: 17px; width: 50px; color: #cd8f9d; font-family: 'Arial'; background: rgb(190, 19, 4); margin-left: 2px;" },
"arrows": { "left": "$path/leftarrow.png",