diff --git a/TODO b/TODO index 2fbeac4..c49187e 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,6 @@ Features: -* Chat rooms/browser +* What if someone switches nick in memo? +* memo change theme * PESTERLOG: in convo window * help button on quirks menu? * tab recombining gives wrong window icon diff --git a/dataobjs.py b/dataobjs.py index e12fbd2..37419d9 100644 --- a/dataobjs.py +++ b/dataobjs.py @@ -3,6 +3,7 @@ from datetime import * import re from generic import PesterIcon +from parsetools import timeDifference class Mood(object): moods = ["chummy", "rancorous", "offline", "pleasant", "distraught", @@ -140,20 +141,16 @@ class PesterProfile(object): 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 memoopenmsg(self, syscolor, td, timeGrammar, verb, channel): + (temporal, pcf, when) = (timeGrammar.temporal, timeGrammar.pcf, timeGrammar.when) + timetext = timeDifference(td) + initials = pcf+self.initials() + return "%s %s %s %s." % \ + (syscolor.name(), self.colorhtml(), initials, timetext, verb, channel[1:].upper().replace("_", " ")) + 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) + timetext = timeDifference(td) initials = pcf+self.initials()+timeGrammar.number return "%s %s [%s] %s %s." % \ (syscolor.name(), self.colorhtml(), temporal, self.handle, diff --git a/dataobjs.pyc b/dataobjs.pyc index 513d6e0..ae8de03 100644 Binary files a/dataobjs.pyc and b/dataobjs.pyc differ diff --git a/irc.pyc b/irc.pyc index 2c6f50f..76d19a6 100644 Binary files a/irc.pyc and b/irc.pyc differ diff --git a/memos.py b/memos.py index 2fd3aaa..a9062b9 100644 --- a/memos.py +++ b/memos.py @@ -13,7 +13,7 @@ def delta2txt(d, format="pc"): sign = "+" if d >= timedelta(0) else "-" else: if d == timedelta(0): - return "" + return "i" sign = "F" if d >= timedelta(0) else "P" d = abs(d) totalminutes = (d.days*86400 + d.seconds) // 60 @@ -86,10 +86,20 @@ class TimeTracker(list): try: i = self.index(timed) self.current = i + return True except ValueError: self.current = len(self) self.append(timed) self.addRecord(timed) + 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): @@ -111,8 +121,9 @@ class TimeTracker(list): try: self.pop(self.index(timed)) self.current = len(self)-1 + return True except ValueError: - pass + return None def getTime(self): if self.current >= 0: return self[self.current] @@ -120,6 +131,8 @@ class TimeTracker(list): return None def getGrammar(self): timed = self.getTime() + return self.getGrammarTime(timed) + def getGrammarTime(self, timed): mytime = timedelta(0) (temporal, pcf, when) = pcfGrammar(timed - mytime) if timed == mytime: @@ -165,6 +178,8 @@ class TimeSlider(QtGui.QSlider): time = timelist[abs(self.value())] sign = "+" if self.value() >= 0 else "-" return sign+time + def mouseDoubleClickEvent(self, event): + self.setValue(0) class MemoTabWindow(PesterTabWindow): def __init__(self, mainwindow, parent=None): @@ -231,7 +246,7 @@ class MemoText(PesterText): else: start = 13 space = msg.find(" ") - msg = chum.memsg(systemColor, msg[start:space], msg[space:], timegrammar=time.getGrammar()) + msg = chum.memsg(systemColor, msg[start:space], msg[space:], time=time.getGrammar()) window.chatlog.log(parent.channel, convertTags(msg, "bbcode")) self.append(convertTags(msg)) else: @@ -274,6 +289,18 @@ class PesterMemo(PesterConvo): self.timeinput.setText(timestr) self.timeinput.setSlider() self.timetravel = QtGui.QPushButton("GO", self) + 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 = {} @@ -298,7 +325,9 @@ class PesterMemo(PesterConvo): layout_2.addWidget(self.timeslider) layout_2.addWidget(self.timeinput) layout_2.addWidget(self.timetravel) - + layout_2.addWidget(self.timeclose) + layout_2.addWidget(self.timeswitchl) + layout_2.addWidget(self.timeswitchr) self.layout = QtGui.QVBoxLayout() self.layout.addWidget(self.channelLabel) @@ -314,6 +343,11 @@ class PesterMemo(PesterConvo): if parent: parent.addChat(self) + p = self.mainwindow.profile() + timeGrammar = self.time.getGrammar() + systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"]) + self.textArea.append(convertTags(p.memoopenmsg(systemColor, self.time.getTime(), timeGrammar, self.mainwindow.theme["convo/text/openmemo"], self.channel))) + self.newmessage = False def title(self): @@ -366,6 +400,19 @@ class PesterMemo(PesterConvo): 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) + 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"]) + + def changeTheme(self, theme): self.initTheme(theme) self.textArea.changeTheme(theme) @@ -399,7 +446,7 @@ class PesterMemo(PesterConvo): secs = int(cmd) time = datetime.fromtimestamp(secs) timed = time - datetime.now() - s = (timed // 60)*60 + s = (timed.seconds // 60)*60 timed = timedelta(timed.days, s) except ValueError: if cmd == "i": @@ -483,6 +530,50 @@ class PesterMemo(PesterConvo): self.times[h].removeTime(t.getTime()) elif update == "join": self.addUser(h) + time = self.time.getTime() + serverText = "PESTERCHUM:TIME>"+delta2txt(time, "server") + self.messageSent.emit(serverText, self.title()) + + def resetSlider(self, time): + self.timeinput.setText(delta2txt(time)) + self.timeinput.setSlider() + self.sendtime() + + @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) + if not present: + self.textArea.append(convertTags(me.memojoinmsg(systemColor, time, self.time.getGrammar(), self.mainwindow.theme["convo/text/joinmemo"]))) + + 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"]) + self.textArea.append(convertTags(me.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"]))) + + newtime = self.time.getTime() + if newtime is None: + newtime = timedelta(0) + self.resetSlider(newtime) + @QtCore.pyqtSlot() + def prevtime(self): + time = self.time.prevTime() + self.time.setCurrent(time) + self.resetSlider(time) + @QtCore.pyqtSlot() + def nexttime(self): + time = self.time.nextTime() + self.time.setCurrent(time) + self.resetSlider(time) def closeEvent(self, event): self.mainwindow.waitingMessages.messageAnswered(self.channel) diff --git a/memos.pyc b/memos.pyc index 1f17bed..9e525be 100644 Binary files a/memos.pyc and b/memos.pyc differ diff --git a/parsetools.py b/parsetools.py index fe3aca5..b6f7fff 100644 --- a/parsetools.py +++ b/parsetools.py @@ -108,3 +108,22 @@ def timeProtocol(cmd): if dir == "P": timed = timed*-1 return timed + +def timeDifference(td): + if td < timedelta(0): + when = "AGO" + else: + when = "FROM NOW" + atd = abs(td) + minutes = (atd.days*86400 + atd.seconds) // 60 + hours = minutes // 60 + leftoverminutes = minutes % 60 + if atd == timedelta(0): + timetext = "RIGHT NOW" + 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) + return timetext diff --git a/parsetools.pyc b/parsetools.pyc index 64d926f..fead7da 100644 Binary files a/parsetools.pyc and b/parsetools.pyc differ diff --git a/pesterchum.py b/pesterchum.py index 35b392b..eebf8a4 100644 --- a/pesterchum.py +++ b/pesterchum.py @@ -1136,7 +1136,7 @@ class PesterWindow(MovingWindow): selectedmemo = self.memochooser.selectedmemo() time = unicode(self.memochooser.timeinput.text()) if newmemo: - channel = "#"+unicode(newmemo) + channel = "#"+unicode(newmemo).replace(" ", "_") self.newMemo(channel, time) elif selectedmemo: channel = "#"+unicode(selectedmemo.text()) diff --git a/profiles/testProfile.js b/profiles/testProfile.js index e63a331..223100d 100644 --- a/profiles/testProfile.js +++ b/profiles/testProfile.js @@ -1 +1 @@ -{"color": "#aa00ff", "theme": "pesterchum", "quirks": [], "handle": "testProfile"} \ No newline at end of file +{"color": "#aa00ff", "theme": "trollian", "quirks": [], "handle": "testProfile"} \ No newline at end of file diff --git a/themes/pesterchum/leftarrow.png b/themes/pesterchum/leftarrow.png new file mode 100644 index 0000000..8d2117a Binary files /dev/null and b/themes/pesterchum/leftarrow.png differ diff --git a/themes/pesterchum/rightarrow.png b/themes/pesterchum/rightarrow.png new file mode 100644 index 0000000..4eaf3b4 Binary files /dev/null and b/themes/pesterchum/rightarrow.png differ diff --git a/themes/pesterchum/style.js b/themes/pesterchum/style.js index 1522af3..c78287d 100644 --- a/themes/pesterchum/style.js +++ b/themes/pesterchum/style.js @@ -237,10 +237,17 @@ "userlist": { "width": 150, "style": "border:2px solid yellow; background: white;font: bold;font-family: 'Courier';selection-background-color:#646464; " }, - "time": { "text": { "width": 75, "style": "" }, + "time": { "text": { "width": 75, + "style": "" + }, "slider": { "style": "", "groove": "", - "handle": "" + "handle": "" + }, + "buttons": { "style": "color:white;font:bold;" }, + "arrows": { "left": "$path/leftarrow.png", + "right": "$path/rightarrow.png", + "style": "" } }, "systemMsgColor": "#646464" diff --git a/themes/trollian/leftarrow.png b/themes/trollian/leftarrow.png new file mode 100644 index 0000000..8d2117a Binary files /dev/null and b/themes/trollian/leftarrow.png differ diff --git a/themes/trollian/rightarrow.png b/themes/trollian/rightarrow.png new file mode 100644 index 0000000..4eaf3b4 Binary files /dev/null and b/themes/trollian/rightarrow.png differ diff --git a/themes/trollian/style.js b/themes/trollian/style.js index 5eab3b7..a0f9b24 100644 --- a/themes/trollian/style.js +++ b/themes/trollian/style.js @@ -289,10 +289,17 @@ "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": "" }, + "time": { "text": { "width": 75, + "style": "color:white;font:bold" + }, "slider": { "style": "", - "groove": "", - "handle": "" + "groove": "border-image:url($path/timeslider.png);", + "handle": "image:url($path/acceptant.png);" + }, + "buttons": { "style": "color:white;font:bold;" }, + "arrows": { "left": "$path/leftarrow.png", + "right": "$path/rightarrow.png", + "style": "" } }, "systemMsgColor": "#646464" diff --git a/themes/trollian/timeslider.png b/themes/trollian/timeslider.png new file mode 100644 index 0000000..14041bd Binary files /dev/null and b/themes/trollian/timeslider.png differ