pesterchum/memos.py

942 lines
40 KiB
Python
Raw Normal View History

2011-02-04 16:17:27 -05:00
from string import Template
import re
2011-02-13 04:27:12 -05:00
from copy import copy
2011-02-04 16:17:27 -05:00
from PyQt4 import QtGui, QtCore
from datetime import time, timedelta, datetime
2011-02-04 16:17:27 -05:00
2011-02-11 04:07:07 -05:00
from dataobjs import PesterProfile, Mood, PesterHistory
2011-02-13 20:32:02 -05:00
from generic import PesterIcon, RightClickList, mysteryTime
2011-02-04 19:50:56 -05:00
from convo import PesterConvo, PesterInput, PesterText, PesterTabWindow
2011-02-13 04:27:12 -05:00
from parsetools import convertTags, addTimeInitial, timeProtocol, \
2011-05-03 19:41:40 -04:00
lexMessage, colorBegin, colorEnd, mecmd, smiledict
from logviewer import PesterLogViewer
2011-02-13 20:32:02 -05:00
def delta2txt(d, format="pc"):
2011-02-13 20:32:02 -05:00
if type(d) is mysteryTime:
return "?"
if format == "pc":
sign = "+" if d >= timedelta(0) else "-"
else:
if d == timedelta(0):
2011-02-05 13:56:25 -05:00
return "i"
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
2011-02-13 20:32:02 -05:00
if txt[0] == '?':
return mysteryTime()
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)
2011-02-18 03:31:04 -05:00
except OverflowError:
if sign < 0:
return timedelta(min)
else:
return timedelta(max)
return sign*timed
def pcfGrammar(td):
2011-02-13 20:32:02 -05:00
if type(td) is mysteryTime:
when = "???"
temporal = "???"
pcf = "?"
elif 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": []}
2011-02-07 13:40:05 -05:00
self.open = {}
if time is not None:
self.append(time)
self.current=0
self.addRecord(time)
2011-02-07 13:40:05 -05:00
self.open[time] = False
else:
self.current=-1
def addTime(self, timed):
try:
i = self.index(timed)
self.current = i
2011-02-05 13:56:25 -05:00
return True
except ValueError:
self.current = len(self)
self.append(timed)
2011-02-07 13:40:05 -05:00
self.open[timed] = False
self.addRecord(timed)
2011-02-05 13:56:25 -05:00
return False
def prevTime(self):
i = self.current
i = (i - 1) % len(self)
return self[i]
def nextTime(self):
i = self.current
i = (i + 1) % len(self)
return self[i]
def setCurrent(self, timed):
self.current = self.index(timed)
def addRecord(self, timed):
(temporal, pcf, when) = pcfGrammar(timed - timedelta(0))
2011-02-13 20:32:02 -05:00
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))
2011-02-13 20:32:02 -05:00
if pcf == "C" or pcf == "?":
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
2011-02-07 13:40:05 -05:00
del self.open[timed]
2011-02-05 13:56:25 -05:00
return True
except ValueError:
2011-02-05 13:56:25 -05:00
return None
2011-02-07 13:40:05 -05:00
def openTime(self, time):
if self.open.has_key(time):
self.open[time] = True
def openCurrentTime(self):
timed = self.getTime()
self.openTime(timed)
def isFirstTime(self):
timed = self.getTime()
return not self.open[timed]
def getTime(self):
if self.current >= 0:
return self[self.current]
else:
return None
def getGrammar(self):
timed = self.getTime()
2011-02-05 13:56:25 -05:00
return self.getGrammarTime(timed)
def getGrammarTime(self, timed):
if not timed:
timed = timedelta(0)
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)
2011-02-13 20:32:02 -05:00
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
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
2011-02-05 13:56:25 -05:00
def mouseDoubleClickEvent(self, event):
self.setValue(0)
2011-02-04 19:50:56 -05:00
class MemoTabWindow(PesterTabWindow):
def __init__(self, mainwindow, parent=None):
PesterTabWindow.__init__(self, mainwindow, parent, "memos")
def addChat(self, convo):
2011-04-14 05:50:55 -04:00
self.convos[convo.channel] = convo
2011-02-04 19:50:56 -05:00
# either addTab or setCurrentIndex will trigger changed()
2011-04-14 05:50:55 -04:00
newindex = self.tabs.addTab(convo.channel)
self.tabIndices[convo.channel] = newindex
2011-02-04 19:50:56 -05:00
self.tabs.setCurrentIndex(newindex)
self.tabs.setTabIcon(newindex, PesterIcon(self.mainwindow.theme["memos/memoicon"]))
def updateBlocked(self):
pass
def updateMood(self):
pass
_ctag_begin = re.compile(r'<c=(.*?)>')
2011-02-04 16:17:27 -05:00
class MemoText(PesterText):
def __init__(self, theme, parent=None):
QtGui.QTextEdit.__init__(self, parent)
2011-02-11 04:07:07 -05:00
self.initTheme(theme)
2011-02-04 16:17:27 -05:00
self.setReadOnly(True)
self.setMouseTracking(True)
2011-02-23 06:27:37 -05:00
self.textSelected = False
self.connect(self, QtCore.SIGNAL('copyAvailable(bool)'),
self, QtCore.SLOT('textReady(bool)'))
2011-05-03 19:41:40 -04:00
self.urls = {}
for k in smiledict:
self.addAnimation(QtCore.QUrl("smilies/%s" % (smiledict[k])), "smilies/%s" % (smiledict[k]));
2011-02-23 06:27:37 -05:00
2011-02-11 04:07:07 -05:00
def initTheme(self, theme):
if theme.has_key("memos/scrollbar"):
self.setStyleSheet("QTextEdit { %s } QScrollBar:vertical { %s } QScrollBar::handle:vertical { %s } QScrollBar::add-line:vertical { %s } QScrollBar::sub-line:vertical { %s } QScrollBar:up-arrow:vertical { %s } QScrollBar:down-arrow:vertical { %s }" % (theme["memos/textarea/style"], theme["memos/scrollbar/style"], theme["memos/scrollbar/handle"], theme["memos/scrollbar/downarrow"], theme["memos/scrollbar/uparrow"], theme["memos/scrollbar/uarrowstyle"], theme["memos/scrollbar/darrowstyle"] ))
else:
self.setStyleSheet("QTextEdit { %s }" % theme["memos/textarea/style"])
2011-02-13 04:27:12 -05:00
def addMessage(self, msg, chum):
if type(msg) in [str, unicode]:
lexmsg = lexMessage(msg)
else:
lexmsg = msg
parent = self.parent()
window = parent.mainwindow
me = window.profile()
chumdb = window.chumdb
if chum is not me: # SO MUCH WH1T3SP4C3 >:]
2011-02-13 04:27:12 -05:00
if type(lexmsg[0]) is colorBegin: # get color tag
colortag = lexmsg[0]
try:
2011-02-13 04:27:12 -05:00
color = QtGui.QColor(*[int(c) for c in colortag.color.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]
2011-02-13 20:32:02 -05:00
if time.getTime() is None:
2011-02-08 02:56:30 -05:00
# MY WAY OR THE HIGHWAY
time.addTime(timedelta(0))
else:
# new chum! time current
newtime = timedelta(0)
time = TimeTracker(newtime)
2011-02-13 04:27:12 -05:00
parent.times[handle] = time
else:
time = parent.time
2011-02-07 13:40:05 -05:00
if time.isFirstTime():
grammar = time.getGrammar()
joinmsg = chum.memojoinmsg(systemColor, time.getTime(), grammar, window.theme["convo/text/joinmemo"])
self.append(convertTags(joinmsg))
2011-04-14 05:50:55 -04:00
parent.mainwindow.chatlog.log(parent.channel, joinmsg)
2011-02-07 13:40:05 -05:00
time.openCurrentTime()
2011-02-13 04:27:12 -05:00
if type(lexmsg[0]) is mecmd:
memsg = chum.memsg(systemColor, lexmsg, time=time.getGrammar())
2011-04-14 05:50:55 -04:00
window.chatlog.log(parent.channel, memsg)
2011-02-07 13:40:05 -05:00
self.append(convertTags(memsg))
else:
2011-02-13 04:27:12 -05:00
self.append(convertTags(lexmsg))
2011-04-14 05:50:55 -04:00
window.chatlog.log(parent.channel, lexmsg)
2011-02-05 22:24:10 -05:00
def changeTheme(self, theme):
2011-02-11 04:07:07 -05:00
self.initTheme(theme)
2011-02-23 06:06:00 -05:00
def submitLogTitle(self):
return "[%s]" % (self.parent().title())
2011-02-04 16:17:27 -05:00
class MemoInput(PesterInput):
def __init__(self, theme, parent=None):
QtGui.QLineEdit.__init__(self, parent)
self.setStyleSheet(theme["memos/input/style"])
def changeTheme(self, theme):
self.setStyleSheet(theme["memos/input/style"])
class PesterMemo(PesterConvo):
def __init__(self, channel, timestr, mainwindow, parent=None):
2011-02-04 16:17:27 -05:00
QtGui.QFrame.__init__(self, parent)
2011-03-02 18:36:10 -05:00
self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
2011-02-04 16:17:27 -05:00
self.channel = channel
2011-03-03 04:03:41 -05:00
self.setObjectName(self.channel)
2011-02-04 16:17:27 -05:00
self.mainwindow = mainwindow
self.time = TimeTracker(txt2delta(timestr))
2011-02-04 16:17:27 -05:00
self.setWindowTitle(channel)
self.channelLabel = QtGui.QLabel(self)
self.channelLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding))
self.textArea = MemoText(self.mainwindow.theme, self)
self.textInput = MemoInput(self.mainwindow.theme, self)
self.textInput.setFocus()
2011-02-06 01:02:39 -05:00
self.userlist = RightClickList(self)
2011-02-04 16:17:27 -05:00
self.userlist.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding))
2011-02-06 01:02:39 -05:00
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()'))
2011-02-08 02:56:30 -05:00
self.opAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/opuser"], self)
self.connect(self.opAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('opSelectedUser()'))
2011-05-09 21:59:36 -04:00
self.voiceAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/voiceuser"], self)
self.connect(self.voiceAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('voiceSelectedUser()'))
2011-02-06 01:02:39 -05:00
self.userlist.optionsMenu.addAction(self.addchumAction)
2011-02-08 02:56:30 -05:00
# ban & op list added if we are op
2011-02-04 16:17:27 -05:00
2011-02-08 17:47:07 -05:00
self.optionsMenu = QtGui.QMenu(self)
self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
self.quirksOff.setCheckable(True)
self.connect(self.quirksOff, QtCore.SIGNAL('toggled(bool)'),
self, QtCore.SLOT('toggleQuirks(bool)'))
self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
self.connect(self.logchum, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('openChumLogs()'))
2011-02-08 17:47:07 -05:00
self.optionsMenu.addAction(self.quirksOff)
self.optionsMenu.addAction(self.logchum)
2011-02-08 17:47:07 -05:00
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)
2011-02-05 13:56:25 -05:00
self.timeclose = QtGui.QPushButton("CLOSE", self)
self.timeswitchl = QtGui.QPushButton(self)
self.timeswitchr = QtGui.QPushButton(self)
self.connect(self.timetravel, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('sendtime()'))
self.connect(self.timeclose, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('smashclock()'))
self.connect(self.timeswitchl, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('prevtime()'))
self.connect(self.timeswitchr, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('nexttime()'))
self.times = {}
2011-02-04 16:17:27 -05:00
self.initTheme(self.mainwindow.theme)
# connect
2011-02-04 19:50:56 -05:00
self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
self, QtCore.SLOT('sentMessage()'))
2011-02-04 16:17:27 -05:00
layout_0 = QtGui.QVBoxLayout()
layout_0.addWidget(self.textArea)
layout_0.addWidget(self.textInput)
layout_1 = QtGui.QHBoxLayout()
layout_1.addLayout(layout_0)
layout_1.addWidget(self.userlist)
2011-02-04 16:17:27 -05:00
# 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)
2011-02-05 13:56:25 -05:00
layout_2.addWidget(self.timeclose)
layout_2.addWidget(self.timeswitchl)
layout_2.addWidget(self.timeswitchr)
self.layout = QtGui.QVBoxLayout()
2011-02-04 16:17:27 -05:00
self.layout.addWidget(self.channelLabel)
2011-02-04 16:17:27 -05:00
self.layout.addLayout(layout_1)
self.layout.addLayout(layout_2)
2011-02-04 16:17:27 -05:00
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)
2011-02-04 19:50:56 -05:00
if parent:
parent.addChat(self)
2011-02-05 13:56:25 -05:00
p = self.mainwindow.profile()
timeGrammar = self.time.getGrammar()
systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
2011-02-06 19:50:21 -05:00
msg = p.memoopenmsg(systemColor, self.time.getTime(), timeGrammar, self.mainwindow.theme["convo/text/openmemo"], self.channel)
2011-02-07 13:40:05 -05:00
self.time.openCurrentTime()
2011-02-06 19:50:21 -05:00
self.textArea.append(convertTags(msg))
2011-04-14 05:50:55 -04:00
self.mainwindow.chatlog.log(self.channel, msg)
2011-02-05 13:56:25 -05:00
2011-02-05 22:24:10 -05:00
self.op = False
2011-02-04 16:17:27 -05:00
self.newmessage = False
2011-02-11 04:07:07 -05:00
self.history = PesterHistory()
2011-02-08 17:47:07 -05:00
self.applyquirks = True
2011-02-04 16:17:27 -05:00
2011-02-04 19:50:56 -05:00
def title(self):
2011-04-14 05:50:55 -04:00
return self.channel
2011-02-04 19:50:56 -05:00
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())
2011-02-04 16:17:27 -05:00
def updateMood(self):
pass
def updateBlocked(self):
pass
def updateColor(self, handle, color):
chums = self.userlist.findItems(handle, QtCore.Qt.MatchFlags(0))
for c in chums:
c.setTextColor(color)
2011-02-04 19:50:56 -05:00
def addMessage(self, text, handle):
if type(handle) is bool:
chum = self.mainwindow.profile()
else:
chum = PesterProfile(handle)
self.notifyNewMessage()
2011-02-04 19:50:56 -05:00
self.textArea.addMessage(text, chum)
2011-02-04 16:17:27 -05:00
def initTheme(self, theme):
2011-02-16 06:11:09 -05:00
self.resize(*theme["memos/size"])
2011-03-03 04:03:41 -05:00
self.setStyleSheet("QFrame#%s { %s }" % (self.channel, theme["memos/style"]))
2011-02-04 16:17:27 -05:00
self.setWindowIcon(PesterIcon(theme["memos/memoicon"]))
t = Template(theme["memos/label/text"])
self.channelLabel.setText(t.safe_substitute(channel=self.channel))
self.channelLabel.setStyleSheet(theme["memos/label/style"])
self.channelLabel.setAlignment(self.aligndict["h"][theme["memos/label/align/h"]] | self.aligndict["v"][theme["memos/label/align/v"]])
self.channelLabel.setMaximumHeight(theme["memos/label/maxheight"])
self.channelLabel.setMinimumHeight(theme["memos/label/minheight"])
2011-02-08 02:56:30 -05:00
self.userlist.optionsMenu.setStyleSheet(theme["main/defaultwindow/style"])
2011-05-03 21:25:05 -04:00
if theme.has_key("main/chums/scrollbar"):
self.setStyleSheet("QListWidget { %s } QScrollBar { %s } QScrollBar::handle { %s } QScrollBar::add-line { %s } QScrollBar::sub-line { %s } QScrollBar:up-arrow { %s } QScrollBar:down-arrow { %s }" % (theme["memos/userlist/style"], theme["main/chums/scrollbar/style"], theme["main/chums/scrollbar/handle"], theme["main/chums/scrollbar/downarrow"], theme["main/chums/scrollbar/uparrow"], theme["main/chums/scrollbar/uarrowstyle"], theme["main/chums/scrollbar/darrowstyle"] ))
else:
self.userlist.setStyleSheet(theme["memos/userlist/style"])
2011-02-04 16:17:27 -05:00
self.userlist.setFixedWidth(theme["memos/userlist/width"])
2011-02-06 01:02:39 -05:00
self.addchumAction.setText(theme["main/menus/rclickchumlist/addchum"])
self.banuserAction.setText(theme["main/menus/rclickchumlist/banuser"])
2011-02-08 02:56:30 -05:00
self.opAction.setText(theme["main/menus/rclickchumlist/opuser"])
2011-05-09 21:59:36 -04:00
self.voiceAction.setText(theme["main/menus/rclickchumlist/voiceuser"])
self.quirksOff.setText(theme["main/menus/rclickchumlist/quirksoff"])
self.logchum.setText(theme["main/menus/rclickchumlist/viewlog"])
2011-02-04 16:17:27 -05:00
self.timeinput.setFixedWidth(theme["memos/time/text/width"])
self.timeinput.setStyleSheet(theme["memos/time/text/style"])
slidercss = "QSlider { %s } QSlider::groove { %s } QSlider::handle { %s }" % (theme["memos/time/slider/style"], theme["memos/time/slider/groove"], theme["memos/time/slider/handle"])
self.timeslider.setStyleSheet(slidercss)
2011-02-04 16:17:27 -05:00
2011-02-05 13:56:25 -05:00
larrow = PesterIcon(self.mainwindow.theme["memos/time/arrows/left"])
self.timeswitchl.setIcon(larrow)
self.timeswitchl.setIconSize(larrow.realsize())
self.timeswitchl.setStyleSheet(self.mainwindow.theme["memos/time/arrows/style"])
self.timetravel.setStyleSheet(self.mainwindow.theme["memos/time/buttons/style"])
self.timeclose.setStyleSheet(self.mainwindow.theme["memos/time/buttons/style"])
rarrow = PesterIcon(self.mainwindow.theme["memos/time/arrows/right"])
self.timeswitchr.setIcon(rarrow)
self.timeswitchr.setIconSize(rarrow.realsize())
self.timeswitchr.setStyleSheet(self.mainwindow.theme["memos/time/arrows/style"])
2011-02-04 16:17:27 -05:00
def changeTheme(self, theme):
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"])
2011-02-11 04:07:07 -05:00
for item in [self.userlist.item(i) for i in range(0,self.userlist.count())]:
2011-02-08 02:56:30 -05:00
if item.op:
icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
item.setIcon(icon)
2011-05-09 21:59:36 -04:00
elif item.voice:
icon = PesterIcon(self.mainwindow.theme["memos/voice/icon"])
item.setIcon(icon)
def addUser(self, handle):
chumdb = self.mainwindow.chumdb
defaultcolor = QtGui.QColor("black")
op = False
2011-05-09 21:59:36 -04:00
voice = False
if handle[0] == '@':
op = True
handle = handle[1:]
2011-02-05 22:24:10 -05:00
if handle == self.mainwindow.profile().handle:
2011-02-08 02:56:30 -05:00
self.userlist.optionsMenu.addAction(self.opAction)
2011-02-06 01:02:39 -05:00
self.userlist.optionsMenu.addAction(self.banuserAction)
2011-02-05 22:24:10 -05:00
self.op = True
2011-05-09 21:59:36 -04:00
elif handle[0] == '+':
voice = 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)
2011-02-08 02:56:30 -05:00
item.op = op
2011-05-09 21:59:36 -04:00
item.voice = voice
2011-02-08 02:56:30 -05:00
if op:
icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
item.setIcon(icon)
2011-05-09 21:59:36 -04:00
elif voice:
icon = PesterIcon(self.mainwindow.theme["memos/voice/icon"])
item.setIcon(icon)
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()
2011-02-05 13:56:25 -05:00
s = (timed.seconds // 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)
2011-02-06 19:50:21 -05:00
msg = chum.memoclosemsg(systemColor, grammar, window.theme["convo/text/closememo"])
self.textArea.append(convertTags(msg))
2011-04-14 05:50:55 -04:00
self.mainwindow.chatlog.log(self.channel, msg)
elif timed not in self.times[handle]:
self.times[handle].addTime(timed)
else:
self.times[handle].setCurrent(timed)
else:
if timed is not None:
ttracker = TimeTracker(timed)
self.times[handle] = ttracker
2011-02-04 16:17:27 -05:00
2011-02-04 19:50:56 -05:00
@QtCore.pyqtSlot()
2011-02-04 16:17:27 -05:00
def sentMessage(self):
2011-02-08 17:47:07 -05:00
text = unicode(self.textInput.text())
2011-02-10 13:00:06 -05:00
if text == "" or text[0:11] == "PESTERCHUM:":
2011-02-04 19:50:56 -05:00
return
2011-02-09 01:26:23 -05:00
self.history.add(text)
2011-02-07 13:40:05 -05:00
if self.time.getTime() == None:
self.sendtime()
grammar = self.time.getGrammar()
2011-02-13 04:27:12 -05:00
quirks = self.mainwindow.userprofile.quirks
lexmsg = lexMessage(text)
if type(lexmsg[0]) is not mecmd:
if self.applyquirks:
lexmsg = quirks.apply(lexmsg)
initials = self.mainwindow.profile().initials()
colorcmd = self.mainwindow.profile().colorcmd()
2011-02-13 04:27:12 -05:00
clientMsg = [colorBegin("<c=%s>" % (colorcmd), colorcmd),
"%s%s%s: " % (grammar.pcf, initials, grammar.number)] + lexmsg + [colorEnd("</c>")]
# account for TC's parsing error
2011-02-13 04:27:12 -05:00
serverMsg = [colorBegin("<c=%s>" % (colorcmd), colorcmd),
"%s: " % (initials)] + lexmsg + [colorEnd("</c>"), " "]
else:
2011-02-13 04:27:12 -05:00
clientMsg = copy(lexmsg)
serverMsg = copy(lexmsg)
self.addMessage(clientMsg, True)
serverText = convertTags(serverMsg, "ctag")
self.messageSent.emit(serverText, self.title())
2011-02-13 04:27:12 -05:00
2011-02-08 17:47:07 -05:00
self.textInput.setText("")
@QtCore.pyqtSlot()
def namesUpdated(self):
# get namesdb
namesdb = self.mainwindow.namesdb
# reload names
self.userlist.clear()
2011-04-14 05:50:55 -04:00
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):
h = unicode(handle)
c = unicode(channel)
2011-02-06 01:02:39 -05:00
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[0:2] in ["+o", "-o", "+v", "-v"]:
l = update.split(":")
update = l[0]
op = l[1]
2011-05-09 21:59:36 -04:00
if (update in ["join","left", "kick", "+o", "-o", "+v", "-v"]) \
2011-02-08 02:56:30 -05:00
and channel != self.channel:
2011-02-06 01:02:39 -05:00
return
chums = self.userlist.findItems(h, QtCore.Qt.MatchFlags(0))
systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
# print exit
2011-02-06 01:02:39 -05:00
if update == "quit" or update == "left" or update == "nick":
for c in chums:
chum = PesterProfile(h)
self.userlist.takeItem(self.userlist.row(c))
2011-02-05 22:24:10 -05:00
if not self.times.has_key(h):
2011-02-06 01:02:39 -05:00
self.times[h] = TimeTracker(timedelta(0))
while self.times[h].getTime() is not None:
t = self.times[h]
grammar = t.getGrammar()
2011-02-06 19:50:21 -05:00
msg = chum.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"])
self.textArea.append(convertTags(msg))
2011-04-14 05:50:55 -04:00
self.mainwindow.chatlog.log(self.channel, msg)
self.times[h].removeTime(t.getTime())
2011-02-06 01:02:39 -05:00
if update == "nick":
self.addUser(newnick)
elif update == "kick":
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")
2011-02-06 19:50:21 -05:00
msg = chum.memobanmsg(opchum, opgrammar, systemColor, grammar)
self.textArea.append(convertTags(msg))
2011-04-14 05:50:55 -04:00
self.mainwindow.chatlog.log(self.channel, msg)
2011-02-06 01:02:39 -05:00
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()
2011-02-07 13:40:05 -05:00
self.time.openCurrentTime()
2011-02-06 19:50:21 -05:00
msg = me.memoopenmsg(systemColor, self.time.getTime(), self.time.getGrammar(), self.mainwindow.theme["convo/text/openmemo"], self.channel)
self.textArea.append(convertTags(msg))
2011-04-14 05:50:55 -04:00
self.mainwindow.chatlog.log(self.channel, msg)
2011-02-06 01:02:39 -05:00
elif ret == QtGui.QMessageBox.Cancel:
if self.parent():
2011-04-14 05:50:55 -04:00
i = self.parent().tabIndices[self.channel]
2011-02-06 01:02:39 -05:00
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)
2011-02-05 13:56:25 -05:00
time = self.time.getTime()
serverText = "PESTERCHUM:TIME>"+delta2txt(time, "server")
self.messageSent.emit(serverText, self.title())
2011-02-08 02:56:30 -05:00
elif update == "+o":
if self.mainwindow.config.opvoiceMessages():
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))
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")
msg = chum.memoopmsg(opchum, opgrammar, systemColor)
self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, msg)
2011-02-08 02:56:30 -05:00
for c in chums:
2011-05-09 21:59:36 -04:00
c.op = True
2011-02-08 02:56:30 -05:00
icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
c.setIcon(icon)
if unicode(c.text()) == self.mainwindow.profile().handle:
self.userlist.optionsMenu.addAction(self.opAction)
2011-05-09 21:59:36 -04:00
self.userlist.optionsMenu.addAction(self.voiceAction)
2011-02-08 02:56:30 -05:00
self.userlist.optionsMenu.addAction(self.banuserAction)
2011-05-09 20:51:34 -04:00
elif update == "-o":
self.mainwindow.channelNames.emit(self.channel)
if self.mainwindow.config.opvoiceMessages():
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))
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")
msg = chum.memodeopmsg(opchum, opgrammar, systemColor)
self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, msg)
2011-05-09 20:51:34 -04:00
for c in chums:
2011-05-09 21:59:36 -04:00
c.op = False
if c.voice:
icon = PesterIcon(self.mainwindow.theme["memos/voice/icon"])
c.setIcon(icon)
else:
icon = QtGui.QIcon()
c.setIcon(icon)
2011-05-09 20:51:34 -04:00
if unicode(c.text()) == self.mainwindow.profile().handle:
self.userlist.optionsMenu.removeAction(self.opAction)
2011-05-09 21:59:36 -04:00
self.userlist.optionsMenu.removeAction(self.voiceAction)
2011-05-09 20:51:34 -04:00
self.userlist.optionsMenu.removeAction(self.banuserAction)
2011-05-09 21:59:36 -04:00
elif update == "+v":
if self.mainwindow.config.opvoiceMessages():
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))
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")
msg = chum.memovoicemsg(opchum, opgrammar, systemColor)
self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, msg)
2011-05-09 21:59:36 -04:00
for c in chums:
c.voice = True
if not c.op:
icon = PesterIcon(self.mainwindow.theme["memos/voice/icon"])
c.setIcon(icon)
elif update == "-v":
if self.mainwindow.config.opvoiceMessages():
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))
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")
msg = chum.memodevoicemsg(opchum, opgrammar, systemColor)
self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.channel, msg)
2011-05-09 21:59:36 -04:00
for c in chums:
c.voice = False
if c.op:
icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
c.setIcon(icon)
else:
icon = QtGui.QIcon()
c.setIcon(icon)
2011-02-05 13:56:25 -05:00
2011-02-06 01:02:39 -05:00
@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)
2011-02-08 02:56:30 -05:00
@QtCore.pyqtSlot()
def opSelectedUser(self):
if not self.userlist.currentItem():
return
currentHandle = unicode(self.userlist.currentItem().text())
self.mainwindow.setChannelMode.emit(self.channel, "+o", currentHandle)
2011-05-09 21:59:36 -04:00
@QtCore.pyqtSlot()
def voiceSelectedUser(self):
if not self.userlist.currentItem():
return
currentHandle = unicode(self.userlist.currentItem().text())
self.mainwindow.setChannelMode.emit(self.channel, "+v", currentHandle)
2011-02-07 13:40:05 -05:00
def resetSlider(self, time, send=True):
2011-02-05 13:56:25 -05:00
self.timeinput.setText(delta2txt(time))
self.timeinput.setSlider()
2011-02-07 13:40:05 -05:00
if send:
self.sendtime()
2011-02-05 13:56:25 -05:00
@QtCore.pyqtSlot()
def openChumLogs(self):
currentChum = self.channel
self.mainwindow.chumList.pesterlogviewer = PesterLogViewer(currentChum, self.mainwindow.config, self.mainwindow.theme, self.mainwindow)
self.connect(self.mainwindow.chumList.pesterlogviewer, QtCore.SIGNAL('rejected()'),
self.mainwindow.chumList, QtCore.SLOT('closeActiveLog()'))
self.mainwindow.chumList.pesterlogviewer.show()
self.mainwindow.chumList.pesterlogviewer.raise_()
self.mainwindow.chumList.pesterlogviewer.activateWindow()
2011-02-05 13:56:25 -05:00
@QtCore.pyqtSlot()
def sendtime(self):
me = self.mainwindow.profile()
systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
time = txt2delta(self.timeinput.text())
present = self.time.addTime(time)
serverText = "PESTERCHUM:TIME>"+delta2txt(time, "server")
self.messageSent.emit(serverText, self.title())
@QtCore.pyqtSlot()
def smashclock(self):
me = self.mainwindow.profile()
time = txt2delta(self.timeinput.text())
removed = self.time.removeTime(time)
if removed:
grammar = self.time.getGrammarTime(time)
systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
2011-02-06 19:50:21 -05:00
msg = me.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"])
self.textArea.append(convertTags(msg))
2011-04-14 05:50:55 -04:00
self.mainwindow.chatlog.log(self.channel, msg)
2011-02-05 13:56:25 -05:00
newtime = self.time.getTime()
if newtime is None:
newtime = timedelta(0)
2011-02-07 13:40:05 -05:00
self.resetSlider(newtime, send=False)
else:
self.resetSlider(newtime)
2011-02-05 13:56:25 -05:00
@QtCore.pyqtSlot()
def prevtime(self):
time = self.time.prevTime()
self.time.setCurrent(time)
self.resetSlider(time)
2011-02-13 04:27:12 -05:00
self.textInput.setFocus()
2011-02-05 13:56:25 -05:00
@QtCore.pyqtSlot()
def nexttime(self):
time = self.time.nextTime()
self.time.setCurrent(time)
self.resetSlider(time)
2011-02-13 04:27:12 -05:00
self.textInput.setFocus()
2011-02-04 16:17:27 -05:00
def closeEvent(self, event):
self.mainwindow.waitingMessages.messageAnswered(self.channel)
self.windowClosed.emit(self.title())
windowClosed = QtCore.pyqtSignal(QtCore.QString)
2011-02-04 16:17:27 -05:00
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"]
2011-02-04 16:17:27 -05:00
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)]