This commit is contained in:
illuminatedwax 2011-04-06 11:41:14 -05:00
commit 764018fe2f
16 changed files with 1299 additions and 477 deletions

18
CHANGELOG.mkdn Normal file
View file

@ -0,0 +1,18 @@
Pesterchum 3.14
===============
Visit http://nova.xzibition.com/~illuminatedwax/help.html for tutorial.
Visit https://github.com/illuminatedwax/pesterchum for git access and source code.
CHANGELOG
---------
### 3.14b (idk on version number scheme)
* Pesterchum 3.14 - illuminatedwax [ghostDunk]
* Art - Grimlive [aquaMarinist]
* Quirks lower() function - Kiooeht [evacipatedBox]
* Quirks scrabble() function - Kiooeht [evacipatedBox]
* Timestamps - Kiooeht [evacipatedBox]
* Logviewer - Kiooeht [evacipatedBox]
* Chum list groups - Kiooeht [evacipatedBox]
* Chum list bug fixes - Kiooeht [evacipatedBox]

7
TODO
View file

@ -1,5 +1,9 @@
Bugs: Bugs:
* multiline msgs breaks shit * multiline msgs breaks shit
* REGEXP: \b(\S)(\S*)(\S)\b REPLACE WITH: upper(\1)\2upper(\3) <--
this regexp, when used as a quirk and then typed in breaks
* import modified.tar
* channels aren't case sensitive! get the real name of a channel
* Windows doesn't show style sheet sometimes?? Maybe related to themes. * Windows doesn't show style sheet sometimes?? Maybe related to themes.
* Issues with connecting? Client not closing connection right? People keep getting "nick taken" messages * Issues with connecting? Client not closing connection right? People keep getting "nick taken" messages
* Windows XP SP2: sometimes mouse clicks dont register? must be some kinda crash * Windows XP SP2: sometimes mouse clicks dont register? must be some kinda crash
@ -20,10 +24,7 @@ Features:
* # of users in each memo * # of users in each memo
* copy quirks between profiles? * copy quirks between profiles?
* help button on quirks menu? * help button on quirks menu?
* chum list groups
* More complex quirks: by-sound * More complex quirks: by-sound
* log viewer
* time codes
* Theme checking * Theme checking
* Spy mode * Spy mode
* Animated * Animated

View file

@ -2,6 +2,7 @@ from string import Template
import re import re
import platform import platform
import httplib, urllib import httplib, urllib
from time import strftime
from copy import copy from copy import copy
from datetime import datetime, timedelta from datetime import datetime, timedelta
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
@ -221,6 +222,17 @@ class PesterText(QtGui.QTextEdit):
parent = self.parent() parent = self.parent()
window = parent.mainwindow window = parent.mainwindow
me = window.profile() me = window.profile()
if self.parent().mainwindow.config.showTimeStamps():
if self.parent().mainwindow.config.time12Format():
time = strftime("[%I:%M")
else:
time = strftime("[%H:%M")
if self.parent().mainwindow.config.showSeconds():
time += strftime(":%S] ")
else:
time += "] "
else:
time = ""
if lexmsg[0] == "PESTERCHUM:BEGIN": if lexmsg[0] == "PESTERCHUM:BEGIN":
parent.setChumOpen(True) parent.setChumOpen(True)
pmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"]) pmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
@ -253,7 +265,7 @@ class PesterText(QtGui.QTextEdit):
window.chatlog.log(parent.chum.handle, memsg) window.chatlog.log(parent.chum.handle, memsg)
else: else:
window.chatlog.log(chum.handle, memsg) window.chatlog.log(chum.handle, memsg)
self.append(convertTags(memsg)) self.append(time + convertTags(memsg))
else: else:
if not parent.chumopen and chum is not me: if not parent.chumopen and chum is not me:
beginmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"]) beginmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
@ -264,7 +276,7 @@ class PesterText(QtGui.QTextEdit):
lexmsg[0:0] = [colorBegin("<c=%s>" % (color), color), lexmsg[0:0] = [colorBegin("<c=%s>" % (color), color),
"%s: " % (initials)] "%s: " % (initials)]
lexmsg.append(colorEnd("</c>")) lexmsg.append(colorEnd("</c>"))
self.append(convertTags(lexmsg)) self.append(time + convertTags(lexmsg))
if chum is me: if chum is me:
window.chatlog.log(parent.chum.handle, lexmsg) window.chatlog.log(parent.chum.handle, lexmsg)
else: else:

View file

@ -8,6 +8,8 @@ from parsetools import timeDifference, convertTags, lexMessage
from mispeller import mispeller from mispeller import mispeller
_upperre = re.compile(r"upper\(([\w\\]+)\)") _upperre = re.compile(r"upper\(([\w\\]+)\)")
_lowerre = re.compile(r"lower\(([\w\\]+)\)")
_scramblere = re.compile(r"scramble\(([\w\\]+)\)")
class Mood(object): class Mood(object):
moods = ["chummy", "rancorous", "offline", "pleasant", "distraught", moods = ["chummy", "rancorous", "offline", "pleasant", "distraught",
@ -62,7 +64,13 @@ class pesterQuirk(object):
to = self.quirk["to"] to = self.quirk["to"]
def upperrep(m): def upperrep(m):
return mo.expand(m.group(1)).upper() return mo.expand(m.group(1)).upper()
def lowerrep(m):
return mo.expand(m.group(1)).lower()
def scramblerep(m):
return "".join(random.sample(mo.expand(m.group(1)), len(mo.expand(m.group(1)))))
to = _upperre.sub(upperrep, to) to = _upperre.sub(upperrep, to)
to = _lowerre.sub(lowerrep, to)
to = _scramblere.sub(scramblerep, to)
return mo.expand(to) return mo.expand(to)
return re.sub(fr, regexprep, string) return re.sub(fr, regexprep, string)
elif self.type == "random": elif self.type == "random":
@ -77,6 +85,12 @@ class pesterQuirk(object):
choice = random.choice(self.quirk["randomlist"]) choice = random.choice(self.quirk["randomlist"])
def upperrep(m): def upperrep(m):
return mo.expand(m.group(1)).upper() return mo.expand(m.group(1)).upper()
def lowerrep(m):
return mo.expand(m.group(1)).lower()
def scramblerep(m):
return "".join(random.sample(mo.expand(m.group(1)), len(mo.expand(m.group(1)))))
choice = _upperre.sub(upperrep, choice)
choice = _lowerre.sub(lowerrep, choice)
choice = _upperre.sub(upperrep, choice) choice = _upperre.sub(upperrep, choice)
return mo.expand(choice) return mo.expand(choice)
return re.sub(self.quirk["from"], randomrep, string) return re.sub(self.quirk["from"], randomrep, string)
@ -167,7 +181,7 @@ class pesterQuirks(object):
yield q yield q
class PesterProfile(object): class PesterProfile(object):
def __init__(self, handle, color=None, mood=Mood("offline"), chumdb=None): def __init__(self, handle, color=None, mood=Mood("offline"), group=None, chumdb=None):
self.handle = handle self.handle = handle
if color is None: if color is None:
if chumdb: if chumdb:
@ -176,6 +190,12 @@ class PesterProfile(object):
color = QtGui.QColor("black") color = QtGui.QColor("black")
self.color = color self.color = color
self.mood = mood self.mood = mood
if group is None:
if chumdb:
group = chumdb.getGroup(handle, "Chums")
else:
group = "Chums"
self.group = group
def initials(self, time=None): def initials(self, time=None):
handle = self.handle handle = self.handle
caps = [l for l in handle if l.isupper()] caps = [l for l in handle if l.isupper()]
@ -205,7 +225,8 @@ class PesterProfile(object):
def plaindict(self): def plaindict(self):
return (self.handle, {"handle": self.handle, return (self.handle, {"handle": self.handle,
"mood": self.mood.name(), "mood": self.mood.name(),
"color": unicode(self.color.name())}) "color": unicode(self.color.name()),
"group": unicode(self.group)})
def blocked(self, config): def blocked(self, config):
return self.handle in config.getBlocklist() return self.handle in config.getBlocklist()

View file

@ -37,6 +37,13 @@ class RightClickList(QtGui.QListWidget):
self.setCurrentItem(listing) self.setCurrentItem(listing)
self.optionsMenu.popup(event.globalPos()) self.optionsMenu.popup(event.globalPos())
class RightClickTree(QtGui.QTreeWidget):
def contextMenuEvent(self, event):
if event.reason() == QtGui.QContextMenuEvent.Mouse:
listing = self.itemAt(event.pos())
self.setCurrentItem(listing)
self.optionsMenu.popup(event.globalPos())
class MultiTextDialog(QtGui.QDialog): class MultiTextDialog(QtGui.QDialog):
def __init__(self, title, parent, *queries): def __init__(self, title, parent, *queries):
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, parent)

6
irc.py
View file

@ -335,12 +335,16 @@ class PesterHandler(DefaultCommandHandler):
self.channel_list = [] self.channel_list = []
info = list(info) info = list(info)
self.channel_field = info.index("Channel") # dunno if this is protocol self.channel_field = info.index("Channel") # dunno if this is protocol
logging.info("---> recv \"CHANNELS: %s " % (self.channel_field))
def list(self, server, handle, *info): def list(self, server, handle, *info):
channel = info[self.channel_field] channel = info[self.channel_field]
usercount = info[1]
if channel not in self.channel_list and channel != "#pesterchum": if channel not in self.channel_list and channel != "#pesterchum":
self.channel_list.append(channel) self.channel_list.append((channel, usercount))
logging.info("---> recv \"CHANNELS: %s " % (channel))
def listend(self, server, handle, msg): def listend(self, server, handle, msg):
pl = PesterList(self.channel_list) pl = PesterList(self.channel_list)
logging.info("---> recv \"CHANNELS END\"")
self.parent.channelListReceived.emit(pl) self.parent.channelListReceived.emit(pl)
self.channel_list = [] self.channel_list = []

233
logviewer.py Normal file
View file

@ -0,0 +1,233 @@
import os, sys
import codecs
import re
from time import strftime, strptime
from PyQt4 import QtGui, QtCore
from generic import RightClickList, RightClickTree
from parsetools import convertTags
from convo import PesterText
class PesterLogUserSelect(QtGui.QDialog):
def __init__(self, config, theme, parent):
QtGui.QDialog.__init__(self, parent)
self.setModal(False)
self.config = config
self.theme = theme
self.parent = parent
self.handle = parent.profile().handle
if sys.platform != "darwin":
self.logpath = "logs"
else:
self.logpath = _datadir+"logs"
self.setStyleSheet(self.theme["main/defaultwindow/style"])
self.setWindowTitle("Pesterlogs")
instructions = QtGui.QLabel("Pick a memo or chumhandle:")
if os.path.exists("%s/%s" % (self.logpath, self.handle)):
chumMemoList = os.listdir("%s/%s/" % (self.logpath, self.handle))
else:
chumMemoList = []
chumslist = config.chums()
for c in chumslist:
if not c in chumMemoList:
chumMemoList.append(c)
chumMemoList.sort()
self.chumsBox = RightClickList(self)
self.chumsBox.setStyleSheet(self.theme["main/chums/style"])
self.chumsBox.optionsMenu = QtGui.QMenu(self)
for (i, t) in enumerate(chumMemoList):
item = QtGui.QListWidgetItem(t)
item.setTextColor(QtGui.QColor(self.theme["main/chums/userlistcolor"]))
self.chumsBox.addItem(item)
self.cancel = QtGui.QPushButton("CANCEL", self)
self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('reject()'))
self.ok = QtGui.QPushButton("OK", self)
self.ok.setDefault(True)
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('viewActivatedLog()'))
layout_ok = QtGui.QHBoxLayout()
layout_ok.addWidget(self.cancel)
layout_ok.addWidget(self.ok)
layout_0 = QtGui.QVBoxLayout()
layout_0.addWidget(instructions)
layout_0.addWidget(self.chumsBox)
layout_0.addLayout(layout_ok)
self.setLayout(layout_0)
def selectedchum(self):
return self.chumsBox.currentItem()
@QtCore.pyqtSlot()
def viewActivatedLog(self):
selectedchum = self.selectedchum().text()
if not hasattr(self, 'pesterlogviewer'):
self.pesterlogviewer = None
if not self.pesterlogviewer:
self.pesterlogviewer = PesterLogViewer(selectedchum, self.config, self.theme, self.parent)
self.connect(self.pesterlogviewer, QtCore.SIGNAL('rejected()'),
self, QtCore.SLOT('closeActiveLog()'))
self.pesterlogviewer.show()
self.pesterlogviewer.raise_()
self.pesterlogviewer.activateWindow()
self.accept()
@QtCore.pyqtSlot()
def closeActiveLog(self):
self.pesterlogviewer.close()
self.pesterlogviewer = None
class PesterLogViewer(QtGui.QDialog):
def __init__(self, chum, config, theme, parent):
QtGui.QDialog.__init__(self, parent)
self.setModal(False)
self.config = config
self.theme = theme
self.parent = parent
global _datadir
self.handle = parent.profile().handle
self.chum = chum
self.convos = {}
if sys.platform != "darwin":
self.logpath = "logs"
else:
self.logpath = _datadir+"logs"
self.setStyleSheet(self.theme["main/defaultwindow/style"])
self.setWindowTitle("Pesterlogs with " + self.chum)
self.format = "bbcode"
if os.path.exists("%s/%s/%s/%s" % (self.logpath, self.handle, chum, self.format)):
self.logList = os.listdir("%s/%s/%s/%s/" % (self.logpath, self.handle, self.chum, self.format))
else:
self.logList = []
if not os.path.exists("%s/%s/%s/%s" % (self.logpath, self.handle, chum, self.format)) or len(self.logList) == 0:
instructions = QtGui.QLabel("No Pesterlogs were found")
self.ok = QtGui.QPushButton("CLOSE", self)
self.ok.setDefault(True)
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('reject()'))
layout_ok = QtGui.QHBoxLayout()
layout_ok.addWidget(self.ok)
layout_0 = QtGui.QVBoxLayout()
layout_0.addWidget(instructions)
layout_0.addLayout(layout_ok)
self.setLayout(layout_0)
else:
self.instructions = QtGui.QLabel("Pesterlog with " +self.chum+ " on")
self.textArea = PesterLogText(theme, self.parent)
self.textArea.setReadOnly(True)
self.textArea.setFixedWidth(600)
if theme.has_key("convo/scrollbar"):
self.textArea.setStyleSheet("QTextEdit { width:500px; %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["convo/textarea/style"], theme["convo/scrollbar/style"], theme["convo/scrollbar/handle"], theme["convo/scrollbar/downarrow"], theme["convo/scrollbar/uparrow"], theme["convo/scrollbar/uarrowstyle"], theme["convo/scrollbar/darrowstyle"] ))
else:
self.textArea.setStyleSheet("QTextEdit { width:500px; %s }" % (theme["convo/textarea/style"]))
self.logList.sort()
self.logList.reverse()
self.tree = RightClickTree()
self.tree.optionsMenu = QtGui.QMenu(self)
self.tree.setFixedSize(260, 300)
self.tree.header().hide()
if theme.has_key("convo/scrollbar"):
self.tree.setStyleSheet("QTreeWidget { %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["convo/textarea/style"], theme["convo/scrollbar/style"], theme["convo/scrollbar/handle"], theme["convo/scrollbar/downarrow"], theme["convo/scrollbar/uparrow"], theme["convo/scrollbar/uarrowstyle"], theme["convo/scrollbar/darrowstyle"] ))
else:
self.tree.setStyleSheet("%s" % (theme["convo/textarea/style"]))
self.connect(self.tree, QtCore.SIGNAL('itemSelectionChanged()'),
self, QtCore.SLOT('loadSelectedLog()'))
self.tree.setSortingEnabled(False)
child_1 = None
last = ["",""]
for (i,l) in enumerate(self.logList):
my = self.fileToMonthYear(l)
if my[0] != last[0]:
child_1 = QtGui.QTreeWidgetItem(["%s %s" % (my[0], my[1])])
self.tree.addTopLevelItem(child_1)
if i == 0:
child_1.setExpanded(True)
child_1.addChild(QtGui.QTreeWidgetItem([self.fileToTime(l)]))
last = self.fileToMonthYear(l)
if len(self.logList) > 0: self.loadLog(self.logList[0])
self.ok = QtGui.QPushButton("CLOSE", self)
self.ok.setDefault(True)
self.ok.setFixedWidth(80)
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('reject()'))
layout_ok = QtGui.QHBoxLayout()
layout_ok.addWidget(self.ok)
layout_ok.setAlignment(self.ok, QtCore.Qt.AlignRight)
layout_logs = QtGui.QHBoxLayout()
layout_logs.addWidget(self.tree)
layout_logs.addWidget(self.textArea)
layout_0 = QtGui.QVBoxLayout()
layout_0.addWidget(self.instructions)
layout_0.addLayout(layout_logs)
layout_0.addLayout(layout_ok)
self.setLayout(layout_0)
@QtCore.pyqtSlot()
def loadSelectedLog(self):
if len(self.tree.currentItem().text(0)) > len("September 2011"):
self.loadLog(self.timeToFile(self.tree.currentItem().text(0)))
def loadLog(self, fname):
fp = codecs.open("%s/%s/%s/%s/%s" % (self.logpath, self.handle, self.chum, self.format, fname), encoding='utf-8', mode='r')
self.textArea.clear()
for line in fp:
cline = line.replace("\r\n", "").replace("[/color]","</c>").replace("[url]","").replace("[/url]","")
cline = re.sub("\[color=(#.{6})]", r"<c=\1>", cline)
self.textArea.append(convertTags(cline))
textCur = self.textArea.textCursor()
textCur.movePosition(1)
self.textArea.setTextCursor(textCur)
self.instructions.setText("Pesterlog with " +self.chum+ " on " + self.fileToTime(str(fname)))
def fileToMonthYear(self, fname):
time = strptime(fname[(fname.index(".")+1):fname.index(".txt")], "%Y-%m-%d.%H.%M")
return [strftime("%B", time), strftime("%Y", time)]
def fileToTime(self, fname):
timestr = fname[(fname.index(".")+1):fname.index(".txt")]
return strftime("%a %d %b %Y %H %M", strptime(timestr, "%Y-%m-%d.%H.%M"))
def timeToFile(self, time):
return self.chum + strftime(".%Y-%m-%d.%H.%M.txt", strptime(str(time), "%a %d %b %Y %H %M"))
class PesterLogText(PesterText):
def __init__(self, theme, parent=None):
PesterText.__init__(self, theme, parent)
def focusInEvent(self, event):
QtGui.QTextEdit.focusInEvent(self, event)
def mousePressEvent(self, event):
url = self.anchorAt(event.pos())
if url != "":
if url[0] != "#":
QtGui.QDesktopServices.openUrl(QtCore.QUrl(url, QtCore.QUrl.TolerantMode))
QtGui.QTextEdit.mousePressEvent(self, event)
def mouseMoveEvent(self, event):
QtGui.QTextEdit.mouseMoveEvent(self, event)
if self.anchorAt(event.pos()):
if self.viewport().cursor().shape != QtCore.Qt.PointingHandCursor:
url = self.anchorAt(event.pos())
if url != "" and url[0] != "#":
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
else:
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))

View file

@ -14,6 +14,7 @@ class PesterQuirkItem(QtGui.QListWidgetItem):
self.quirk = quirk self.quirk = quirk
self.setText(unicode(quirk)) self.setText(unicode(quirk))
def __lt__(self, quirkitem): def __lt__(self, quirkitem):
"""Sets the order of quirks if auto-sorted by Qt. Obsolete now."""
if self.quirk.type == "prefix": if self.quirk.type == "prefix":
return True return True
elif (self.quirk.type == "replace" or self.quirk.type == "regexp") and \ elif (self.quirk.type == "replace" or self.quirk.type == "regexp") and \
@ -21,11 +22,11 @@ class PesterQuirkItem(QtGui.QListWidgetItem):
return True return True
else: else:
return False return False
class PesterQuirkList(QtGui.QListWidget): class PesterQuirkList(QtGui.QListWidget):
def __init__(self, mainwindow, parent): def __init__(self, mainwindow, parent):
QtGui.QListWidget.__init__(self, parent) QtGui.QListWidget.__init__(self, parent)
self.resize(400, 200) self.resize(400, 200)
# make sure we have access to mainwindow info like profiles
self.mainwindow = mainwindow self.mainwindow = mainwindow
self.setStyleSheet("background:black; color:white;") self.setStyleSheet("background:black; color:white;")
@ -37,6 +38,20 @@ class PesterQuirkList(QtGui.QListWidget):
def currentQuirk(self): def currentQuirk(self):
return self.item(self.currentRow()) return self.item(self.currentRow())
def upShiftQuirk(self):
i = self.currentRow()
if i > 0:
shifted_item = self.takeItem(i)
self.insertItem(i-1,shifted_item)
self.setCurrentRow(i-1)
def downShiftQuirk(self):
i = self.currentRow()
if i < self.count() - 1 and i >= 0:
shifted_item = self.takeItem(i)
self.insertItem(i+1,shifted_item)
self.setCurrentRow(i+1)
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def removeCurrent(self): def removeCurrent(self):
i = self.currentRow() i = self.currentRow()
@ -187,6 +202,19 @@ class PesterChooseQuirks(QtGui.QDialog):
self.addMispellingButton = QtGui.QPushButton("MISPELLER", self) self.addMispellingButton = QtGui.QPushButton("MISPELLER", self)
self.connect(self.addMispellingButton, QtCore.SIGNAL('clicked()'), self.connect(self.addMispellingButton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('addSpellDialog()')) self, QtCore.SLOT('addSpellDialog()'))
self.upShiftButton = QtGui.QPushButton("^", self)
self.downShiftButton = QtGui.QPushButton("v", self)
self.connect(self.upShiftButton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('upShiftQuirk()'))
self.connect(self.downShiftButton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('downShiftQuirk()'))
layout_quirklist = QtGui.QHBoxLayout() #the nude layout quirklist
layout_shiftbuttons = QtGui.QVBoxLayout() #the shift button layout
layout_shiftbuttons.addWidget(self.upShiftButton)
layout_shiftbuttons.addWidget(self.downShiftButton)
layout_quirklist.addWidget(self.quirkList)
layout_quirklist.addLayout(layout_shiftbuttons)
layout_1 = QtGui.QHBoxLayout() layout_1 = QtGui.QHBoxLayout()
layout_1.addWidget(self.addPrefixButton) layout_1.addWidget(self.addPrefixButton)
@ -219,7 +247,7 @@ class PesterChooseQuirks(QtGui.QDialog):
layout_ok.addWidget(self.ok) layout_ok.addWidget(self.ok)
layout_0 = QtGui.QVBoxLayout() layout_0 = QtGui.QVBoxLayout()
layout_0.addWidget(self.quirkList) layout_0.addLayout(layout_quirklist)
layout_0.addLayout(layout_1) layout_0.addLayout(layout_1)
layout_0.addLayout(layout_2) layout_0.addLayout(layout_2)
layout_0.addLayout(layout_3) layout_0.addLayout(layout_3)
@ -230,6 +258,15 @@ class PesterChooseQuirks(QtGui.QDialog):
return [self.quirkList.item(i).quirk for i in return [self.quirkList.item(i).quirk for i in
range(0,self.quirkList.count())] range(0,self.quirkList.count())]
# could probably do away with these and just connect to the relevant methods on the quirk list widget
@QtCore.pyqtSlot()
def upShiftQuirk(self):
self.quirkList.upShiftQuirk()
@QtCore.pyqtSlot()
def downShiftQuirk(self):
self.quirkList.downShiftQuirk()
#!!!
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def editSelected(self): def editSelected(self):
q = self.quirkList.currentQuirk() q = self.quirkList.currentQuirk()
@ -507,6 +544,10 @@ class PesterOptions(QtGui.QDialog):
self.theme = theme self.theme = theme
self.setStyleSheet(self.theme["main/defaultwindow/style"]) self.setStyleSheet(self.theme["main/defaultwindow/style"])
hr = QtGui.QFrame()
hr.setFrameShape(QtGui.QFrame.HLine)
hr.setFrameShadow(QtGui.QFrame.Sunken)
self.tabcheck = QtGui.QCheckBox("Tabbed Conversations", self) self.tabcheck = QtGui.QCheckBox("Tabbed Conversations", self)
if self.config.tabs(): if self.config.tabs():
self.tabcheck.setChecked(True) self.tabcheck.setChecked(True)
@ -517,6 +558,28 @@ class PesterOptions(QtGui.QDialog):
self.soundcheck = QtGui.QCheckBox("Sounds On", self) self.soundcheck = QtGui.QCheckBox("Sounds On", self)
if self.config.soundOn(): if self.config.soundOn():
self.soundcheck.setChecked(True) self.soundcheck.setChecked(True)
self.timestampcheck = QtGui.QCheckBox("Time Stamps", self)
if self.config.showTimeStamps():
self.timestampcheck.setChecked(True)
self.timestampBox = QtGui.QComboBox(self)
self.timestampBox.addItem("12 hour")
self.timestampBox.addItem("24 hour")
if self.config.time12Format():
self.timestampBox.setCurrentIndex(0)
else:
self.timestampBox.setCurrentIndex(1)
self.secondscheck = QtGui.QCheckBox("Show Seconds", self)
if self.config.showSeconds():
self.secondscheck.setChecked(True)
# Will add ability to turn off groups later
#self.groupscheck = QtGui.QCheckBox("Use Groups", self)
#self.groupscheck.setChecked(self.config.useGroups())
self.showemptycheck = QtGui.QCheckBox("Show Empty Groups", self)
self.showemptycheck.setChecked(self.config.showEmptyGroups())
self.ok = QtGui.QPushButton("OK", self) self.ok = QtGui.QPushButton("OK", self)
self.ok.setDefault(True) self.ok.setDefault(True)
self.connect(self.ok, QtCore.SIGNAL('clicked()'), self.connect(self.ok, QtCore.SIGNAL('clicked()'),
@ -532,6 +595,12 @@ class PesterOptions(QtGui.QDialog):
layout_0.addWidget(self.tabcheck) layout_0.addWidget(self.tabcheck)
layout_0.addWidget(self.soundcheck) layout_0.addWidget(self.soundcheck)
layout_0.addWidget(self.hideOffline) layout_0.addWidget(self.hideOffline)
#layout_0.addWidget(self.groupscheck)
layout_0.addWidget(self.showemptycheck)
layout_0.addWidget(hr)
layout_0.addWidget(self.timestampcheck)
layout_0.addWidget(self.timestampBox)
layout_0.addWidget(self.secondscheck)
layout_0.addLayout(layout_2) layout_0.addLayout(layout_2)
self.setLayout(layout_0) self.setLayout(layout_0)
@ -622,6 +691,13 @@ class PesterUserlist(QtGui.QDialog):
addChum = QtCore.pyqtSignal(QtCore.QString) addChum = QtCore.pyqtSignal(QtCore.QString)
class MemoListItem(QtGui.QListWidgetItem):
def __init__(self, channel, usercount):
QtGui.QListWidgetItem.__init__(self, None)
self.target = channel
self.setText(channel + " (" + str(usercount) + ")")
class PesterMemoList(QtGui.QDialog): class PesterMemoList(QtGui.QDialog):
def __init__(self, parent, channel=""): def __init__(self, parent, channel=""):
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, parent)
@ -678,7 +754,7 @@ class PesterMemoList(QtGui.QDialog):
def updateChannels(self, channels): def updateChannels(self, channels):
for c in channels: for c in channels:
item = QtGui.QListWidgetItem(c[1:]) item = MemoListItem(c[0][1:],c[1])
item.setTextColor(QtGui.QColor(self.theme["main/chums/userlistcolor"])) item.setTextColor(QtGui.QColor(self.theme["main/chums/userlistcolor"]))
item.setIcon(QtGui.QIcon(self.theme["memos/memoicon"])) item.setIcon(QtGui.QIcon(self.theme["memos/memoicon"]))
self.channelarea.addItem(item) self.channelarea.addItem(item)
@ -704,8 +780,8 @@ class PesterMemoList(QtGui.QDialog):
class LoadingScreen(QtGui.QDialog): class LoadingScreen(QtGui.QDialog):
def __init__(self, parent=None): def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent, flags=(QtCore.Qt.CustomizeWindowHint | QtGui.QDialog.__init__(self, parent, (QtCore.Qt.CustomizeWindowHint |
QtCore.Qt.FramelessWindowHint)) QtCore.Qt.FramelessWindowHint))
self.mainwindow = parent self.mainwindow = parent
self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"]) self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])

View file

@ -12,16 +12,18 @@ import socket
import platform import platform
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
import pygame import pygame
from time import strftime
from menus import PesterChooseQuirks, PesterChooseTheme, \ from menus import PesterChooseQuirks, PesterChooseTheme, \
PesterChooseProfile, PesterOptions, PesterUserlist, PesterMemoList, \ PesterChooseProfile, PesterOptions, PesterUserlist, PesterMemoList, \
LoadingScreen, AboutPesterchum LoadingScreen, AboutPesterchum
from dataobjs import PesterProfile, Mood, pesterQuirk, pesterQuirks from dataobjs import PesterProfile, Mood, pesterQuirk, pesterQuirks
from generic import PesterIcon, RightClickList, MultiTextDialog, PesterList from generic import PesterIcon, RightClickList, RightClickTree, MultiTextDialog, PesterList
from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo
from parsetools import convertTags, addTimeInitial from parsetools import convertTags, addTimeInitial
from memos import PesterMemo, MemoTabWindow, TimeTracker from memos import PesterMemo, MemoTabWindow, TimeTracker
from irc import PesterIRC from irc import PesterIRC
from logviewer import PesterLogUserSelect, PesterLogViewer
_datadir = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.DataLocation)+"Pesterchum/" _datadir = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.DataLocation)+"Pesterchum/"
@ -76,9 +78,10 @@ class PesterLog(object):
self.logpath = _datadir+"logs" self.logpath = _datadir+"logs"
def log(self, handle, msg): def log(self, handle, msg):
bbcodemsg = convertTags(msg, "bbcode") time = strftime("[%H:%M:%S] ")
html = convertTags(msg, "html")+"<br />" bbcodemsg = time + convertTags(msg, "bbcode")
msg = convertTags(msg, "text") html = time + convertTags(msg, "html")+"<br />"
msg = time + convertTags(msg, "text")
modes = {"bbcode": bbcodemsg, "html": html, "text": msg} modes = {"bbcode": bbcodemsg, "html": html, "text": msg}
if not self.convos.has_key(handle): if not self.convos.has_key(handle):
time = datetime.now().strftime("%Y-%m-%d.%H.%M") time = datetime.now().strftime("%Y-%m-%d.%H.%M")
@ -128,7 +131,14 @@ class PesterProfileDB(dict):
json.dump(chumdict, fp) json.dump(chumdict, fp)
fp.close() fp.close()
converted = dict([(handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']))) for (handle, c) in chumdict.iteritems()]) u = []
for (handle, c) in chumdict.iteritems():
try:
g = c['group']
u.append((handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']), group=g)))
except KeyError:
u.append((handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']))))
converted = dict(u)
self.update(converted) self.update(converted)
def save(self): def save(self):
@ -149,6 +159,17 @@ class PesterProfileDB(dict):
self[handle].color = color self[handle].color = color
else: else:
self[handle] = PesterProfile(handle, color) self[handle] = PesterProfile(handle, color)
def getGroup(self, handle, default="Chums"):
if not self.has_key(handle):
return default
else:
return self[handle].group
def setGroup(self, handle, theGroup):
if self.has_key(handle):
self[handle].group = theGroup
else:
self[handle] = PesterProfile(handle, group=theGroup)
self.save()
def __setitem__(self, key, val): def __setitem__(self, key, val):
dict.__setitem__(self, key, val) dict.__setitem__(self, key, val)
self.save() self.save()
@ -249,6 +270,30 @@ class userConfig(object):
return None return None
def tabs(self): def tabs(self):
return self.config.get("tabs", True) return self.config.get("tabs", True)
def showTimeStamps(self):
if not self.config.has_key('showTimeStamps'):
self.set("showTimeStamps", True)
return self.config.get('showTimeStamps', True)
def time12Format(self):
if not self.config.has_key('time12Format'):
self.set("time12Format", True)
return self.config.get('time12Format', True)
def showSeconds(self):
if not self.config.has_key('showSeconds'):
self.set("showSeconds", False)
return self.config.get('showSeconds', False)
def useGroups(self):
if not self.config.has_key('useGroups'):
self.set("useGroups", False)
return self.config.get('useGroups', False)
def openDefaultGroup(self):
if not self.config.has_key('openDefaultGroup'):
self.set("openDefaultGroup", True)
return self.config.get('openDefaultGroup', True)
def showEmptyGroups(self):
if not self.config.has_key('emptyGroups'):
self.set("emptyGroups", False)
return self.config.get('emptyGroups', False)
def addChum(self, chum): def addChum(self, chum):
if chum.handle not in self.chums(): if chum.handle not in self.chums():
fp = open(self.filename) # what if we have two clients open?? fp = open(self.filename) # what if we have two clients open??
@ -276,6 +321,25 @@ class userConfig(object):
l = self.getBlocklist() l = self.getBlocklist()
l.pop(l.index(handle)) l.pop(l.index(handle))
self.set('block', l) self.set('block', l)
def getGroups(self):
if not self.config.has_key('groups'):
self.set('groups', [])
return self.config.get('groups', [])
def addGroup(self, group, open=False):
l = self.getGroups()
if group not in l:
l.append([group,open])
l.sort()
self.set('groups', l)
def delGroup(self, group):
l = self.getGroups()
i = 0
for g in l:
if g[0] == group: break
i = i+1
l.pop(i)
l.sort()
self.set('groups', l)
def server(self): def server(self):
return self.config.get('server', 'irc.mindfang.org') return self.config.get('server', 'irc.mindfang.org')
def port(self): def port(self):
@ -389,9 +453,9 @@ class WMButton(QtGui.QPushButton):
self.setStyleSheet("QPushButton { padding: 0px; }") self.setStyleSheet("QPushButton { padding: 0px; }")
self.setAutoDefault(False) self.setAutoDefault(False)
class chumListing(QtGui.QListWidgetItem): class chumListing(QtGui.QTreeWidgetItem):
def __init__(self, chum, window): def __init__(self, chum, window):
QtGui.QListWidgetItem.__init__(self, chum.handle) QtGui.QTreeWidgetItem.__init__(self, [chum.handle])
self.mainwindow = window self.mainwindow = window
self.chum = chum self.chum = chum
self.handle = chum.handle self.handle = chum.handle
@ -405,32 +469,44 @@ class chumListing(QtGui.QListWidgetItem):
mood = self.chum.mood mood = self.chum.mood
self.mood = mood self.mood = mood
icon = self.mood.icon(self.mainwindow.theme) icon = self.mood.icon(self.mainwindow.theme)
self.setIcon(icon) self.setIcon(0, icon)
try: try:
self.setTextColor(QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"])) self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
except KeyError: except KeyError:
self.setTextColor(QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"])) self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"]))
def changeTheme(self, theme): def changeTheme(self, theme):
icon = self.mood.icon(theme) icon = self.mood.icon(theme)
self.setIcon(icon) self.setIcon(0, icon)
try: try:
self.setTextColor(QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"])) self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
except KeyError: except KeyError:
self.setTextColor(QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"])) self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"]))
def __lt__(self, cl): def __lt__(self, cl):
h1 = self.handle.lower() h1 = self.handle.lower()
h2 = cl.handle.lower() h2 = cl.handle.lower()
return (h1 < h2) return (h1 < h2)
class chumArea(RightClickList): class chumArea(RightClickTree):
def __init__(self, chums, parent=None): def __init__(self, chums, parent=None):
QtGui.QListWidget.__init__(self, parent) QtGui.QTreeWidget.__init__(self, parent)
self.mainwindow = parent self.mainwindow = parent
theme = self.mainwindow.theme theme = self.mainwindow.theme
self.chums = chums self.chums = chums
gTemp = self.mainwindow.config.getGroups()
self.groups = [g[0] for g in gTemp]
self.openGroups = [g[1] for g in gTemp]
# quick hack to sort saved groups
self.mainwindow.config.addGroup("f3rskv9dssag[%3ffvsla09iv34G#$v")
self.mainwindow.config.delGroup("f3rskv9dssag[%3ffvsla09iv34G#$v")
# end quick hack
self.showAllGroups()
if not self.mainwindow.config.hideOfflineChums(): if not self.mainwindow.config.hideOfflineChums():
self.showAllChums() self.showAllChums()
self.optionsMenu = QtGui.QMenu(self) if not self.mainwindow.config.showEmptyGroups():
self.hideEmptyGroups()
self.chumoptions = QtGui.QMenu(self)
self.groupoptions = QtGui.QMenu(self)
self.optionsMenu = self.chumoptions
self.pester = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self) self.pester = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self)
self.connect(self.pester, QtCore.SIGNAL('triggered()'), self.connect(self.pester, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('activateChum()')) self, QtCore.SLOT('activateChum()'))
@ -440,12 +516,86 @@ class chumArea(RightClickList):
self.blockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self) self.blockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
self.connect(self.blockchum, QtCore.SIGNAL('triggered()'), self.connect(self.blockchum, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('blockChum()')) self, QtCore.SLOT('blockChum()'))
self.optionsMenu.addAction(self.pester) self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
self.optionsMenu.addAction(self.blockchum) self.connect(self.logchum, QtCore.SIGNAL('triggered()'),
self.optionsMenu.addAction(self.removechum) self, QtCore.SLOT('openChumLogs()'))
self.removegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/removegroup"], self)
self.connect(self.removegroup, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('removeGroup()'))
self.renamegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/renamegroup"], self)
self.connect(self.renamegroup, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('renameGroup()'))
self.chumoptions.addAction(self.pester)
self.chumoptions.addAction(self.logchum)
self.chumoptions.addAction(self.blockchum)
self.chumoptions.addAction(self.removechum)
self.moveMenu = QtGui.QMenu(self.mainwindow.theme["main/menus/rclickchumlist/movechum"], self)
self.chumoptions.addMenu(self.moveMenu)
self.moveGroupMenu()
self.groupoptions.addAction(self.renamegroup)
self.groupoptions.addAction(self.removegroup)
self.initTheme(theme) self.initTheme(theme)
self.sortItems() #self.sortItems()
#self.sortItems(1, QtCore.Qt.AscendingOrder)
self.setSortingEnabled(False)
self.header().hide()
self.setDropIndicatorShown(False)
self.setIndentation(0)
self.setDragEnabled(True)
self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
self.connect(self, QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem *, int)'),
self, QtCore.SLOT('expandGroup()'))
def dropEvent(self, event):
item = self.itemAt(event.pos())
if item:
if item.text(0) == "Chums" or item.text(0) in self.groups:
group = item.text(0)
else:
group = item.parent().text(0)
chumLabel = event.source().currentItem()
chumLabel.chum.group = group
self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, group)
self.takeItem(chumLabel)
self.addItem(chumLabel)
def chumoptionsmenu(self):
self.optionsMenu = self.chumoptions
def groupoptionsmenu(self):
self.optionsMenu = self.groupoptions
def moveGroupMenu(self):
currentGroup = self.currentItem()
if currentGroup:
currentGroup = currentGroup.parent().text(0)
self.moveMenu.clear()
actGroup = QtGui.QActionGroup(self)
groups = self.groups[:]
groups.insert(0, "Chums")
for gtext in groups:
if gtext == currentGroup:
continue
movegroup = self.moveMenu.addAction(gtext)
actGroup.addAction(movegroup)
self.connect(actGroup, QtCore.SIGNAL('triggered(QAction *)'),
self, QtCore.SLOT('moveToGroup(QAction *)'))
def contextMenuEvent(self, event):
#fuckin Qt
if event.reason() == QtGui.QContextMenuEvent.Mouse:
listing = self.itemAt(event.pos())
self.setCurrentItem(listing)
if self.currentItem().text(0) == "Chums" or \
self.currentItem().text(0) in self.groups:
self.groupoptionsmenu()
else:
self.chumoptionsmenu()
self.moveGroupMenu()
self.optionsMenu.popup(event.globalPos())
def addChum(self, chum): def addChum(self, chum):
if len([c for c in self.chums if c.handle == chum.handle]) != 0: if len([c for c in self.chums if c.handle == chum.handle]) != 0:
return return
@ -454,29 +604,95 @@ class chumArea(RightClickList):
chum.mood.name() == "offline"): chum.mood.name() == "offline"):
chumLabel = chumListing(chum, self.mainwindow) chumLabel = chumListing(chum, self.mainwindow)
self.addItem(chumLabel) self.addItem(chumLabel)
self.sortItems() #self.topLevelItem(0).addChild(chumLabel)
#self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
def getChums(self, handle): def getChums(self, handle):
chums = self.findItems(handle, QtCore.Qt.MatchFlags(0)) chums = self.findItems(handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive)
return chums return chums
def showAllChums(self): def showAllChums(self):
for c in self.chums: for c in self.chums:
chandle = c.handle chandle = c.handle
if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)): if not len(self.findItems(chandle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive)):
chumLabel = chumListing(c, self.mainwindow) chumLabel = chumListing(c, self.mainwindow)
self.addItem(chumLabel) self.addItem(chumLabel)
self.sortItems() #self.sortItems()
def hideOfflineChums(self): def hideOfflineChums(self):
for j in range(self.topLevelItemCount()):
i = 0
listing = self.topLevelItem(j).child(i)
while listing is not None:
if listing.chum.mood.name() == "offline":
self.topLevelItem(j).takeChild(i)
else:
i += 1
listing = self.topLevelItem(j).child(i)
self.topLevelItem(j).sortChildren(0, QtCore.Qt.AscendingOrder)
def showAllGroups(self):
curgroups = []
for i in range(self.topLevelItemCount()):
curgroups.append(self.topLevelItem(i).text(0))
if "Chums" not in curgroups:
child_1 = QtGui.QTreeWidgetItem(["Chums"])
self.addTopLevelItem(child_1)
if self.mainwindow.config.openDefaultGroup():
child_1.setExpanded(True)
for i,g in enumerate(self.groups):
if g not in curgroups:
child_1 = QtGui.QTreeWidgetItem(["%s" % (g)])
self.addTopLevelItem(child_1)
if self.openGroups[i]:
child_1.setExpanded(True)
def hideEmptyGroups(self):
i = 0 i = 0
listing = self.item(i) listing = self.topLevelItem(i)
while listing is not None: while listing is not None:
if listing.chum.mood.name() == "offline": if listing.childCount() == 0:
self.takeItem(i) self.takeTopLevelItem(i)
else: else:
i += 1 i += 1
listing = self.item(i) listing = self.topLevelItem(i)
self.sortItems() @QtCore.pyqtSlot()
def expandGroup(self):
item = self.currentItem()
if item.text(0) in self.groups:
self.mainwindow.config.delGroup(str(item.text(0)))
expand = item.isExpanded()
self.mainwindow.config.addGroup(str(item.text(0)), not expand)
elif item.text(0) == "Chums":
self.mainwindow.config.set("openDefaultGroup", not item.isExpanded())
def addItem(self, chumLabel):
if hasattr(self, 'groups'):
if chumLabel.chum.group not in self.groups:
self.topLevelItem(0).addChild(chumLabel)
self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
else:
if not self.findItems(chumLabel.handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive):
if not self.findItems(chumLabel.chum.group, QtCore.Qt.MatchFlags(0)):
child_1 = QtGui.QTreeWidgetItem(["%s" % (chumLabel.chum.group)])
self.addTopLevelItem(child_1)
if self.openGroups[self.groups.index("%s" % (chumLabel.chum.group))]:
child_1.setExpanded(True)
for i in range(self.topLevelItemCount()):
if self.topLevelItem(i).text(0) == chumLabel.chum.group:
break
self.topLevelItem(i).addChild(chumLabel)
self.topLevelItem(i).sortChildren(0, QtCore.Qt.AscendingOrder)
else: # usually means this is now the trollslum
if not self.findItems(chumLabel.handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive):
self.topLevelItem(0).addChild(chumLabel)
self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
def takeItem(self, chumLabel):
r = None
for i in range(self.topLevelItemCount()):
for j in range(self.topLevelItem(i).childCount()):
if self.topLevelItem(i).child(j).text(0) == chumLabel.chum.handle:
r = self.topLevelItem(i).takeChild(j)
break
if not self.mainwindow.config.showEmptyGroups():
self.hideEmptyGroups()
return r
def updateMood(self, handle, mood): def updateMood(self, handle, mood):
hideoff = self.mainwindow.config.hideOfflineChums() hideoff = self.mainwindow.config.hideOfflineChums()
chums = self.getChums(handle) chums = self.getChums(handle)
@ -487,7 +703,7 @@ class chumArea(RightClickList):
handle in [p.handle for p in self.chums]: handle in [p.handle for p in self.chums]:
newLabel = chumListing([p for p in self.chums if p.handle == handle][0], self.mainwindow) newLabel = chumListing([p for p in self.chums if p.handle == handle][0], self.mainwindow)
self.addItem(newLabel) self.addItem(newLabel)
self.sortItems() #self.sortItems()
chums = [newLabel] chums = [newLabel]
elif mood.name() == "offline" and \ elif mood.name() == "offline" and \
len(chums) > 0: len(chums) > 0:
@ -512,14 +728,28 @@ class chumArea(RightClickList):
self.pester.setText(theme["main/menus/rclickchumlist/pester"]) self.pester.setText(theme["main/menus/rclickchumlist/pester"])
self.removechum.setText(theme["main/menus/rclickchumlist/removechum"]) self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
self.blockchum.setText(theme["main/menus/rclickchumlist/blockchum"]) self.blockchum.setText(theme["main/menus/rclickchumlist/blockchum"])
self.logchum.setText(theme["main/menus/rclickchumlist/viewlog"])
self.removegroup.setText(theme["main/menus/rclickchumlist/removegroup"])
self.renamegroup.setText(theme["main/menus/rclickchumlist/renamegroup"])
self.moveMenu.setTitle(theme["main/menus/rclickchumlist/movechum"])
def changeTheme(self, theme): def changeTheme(self, theme):
self.initTheme(theme) self.initTheme(theme)
chumlistings = [self.item(i) for i in range(0, self.count())] chumlistings = []
for i in range(self.topLevelItemCount()):
for j in range(self.topLevelItem(i).childCount()):
chumlistings.append(self.topLevelItem(i).child(j))
#chumlistings = [self.item(i) for i in range(0, self.count())]
for c in chumlistings: for c in chumlistings:
c.changeTheme(theme) c.changeTheme(theme)
def count(self):
c = 0
for i in range(self.topLevelItemCount()):
c = c + self.topLevelItem(i).childCount()
return c
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def activateChum(self): def activateChum(self):
self.itemActivated.emit(self.currentItem()) self.itemActivated.emit(self.currentItem(), 0)
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def removeChum(self, handle = None): def removeChum(self, handle = None):
if handle: if handle:
@ -530,8 +760,8 @@ class chumArea(RightClickList):
return return
currentChum = self.currentItem().chum currentChum = self.currentItem().chum
self.chums = [c for c in self.chums if c.handle != currentChum.handle] self.chums = [c for c in self.chums if c.handle != currentChum.handle]
self.removeChumSignal.emit(self.currentItem()) self.removeChumSignal.emit(self.currentItem().chum.handle)
oldlist = self.takeItem(self.currentRow()) oldlist = self.takeItem(self.currentItem())
del oldlist del oldlist
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def blockChum(self): def blockChum(self):
@ -539,8 +769,78 @@ class chumArea(RightClickList):
if not currentChum: if not currentChum:
return return
self.blockChumSignal.emit(self.currentItem().chum.handle) self.blockChumSignal.emit(self.currentItem().chum.handle)
@QtCore.pyqtSlot()
def openChumLogs(self):
currentChum = self.currentItem().text(0)
if not currentChum:
return
self.pesterlogviewer = PesterLogViewer(currentChum, self.mainwindow.config, self.mainwindow.theme, self.mainwindow)
self.connect(self.pesterlogviewer, QtCore.SIGNAL('rejected()'),
self, QtCore.SLOT('closeActiveLog()'))
self.pesterlogviewer.show()
self.pesterlogviewer.raise_()
self.pesterlogviewer.activateWindow()
@QtCore.pyqtSlot()
def closeActiveLog(self):
self.pesterlogviewer.close()
self.pesterlogviewer = None
@QtCore.pyqtSlot()
def renameGroup(self):
if not hasattr(self, 'renamegroupdialog'):
self.renamegroupdialog = None
if not self.renamegroupdialog:
(gname, ok) = QtGui.QInputDialog.getText(self, "Rename Group", "Enter a new name for the group:")
if ok:
gname = unicode(gname)
currentGroup = self.currentItem()
if not currentGroup:
return
index = self.indexOfTopLevelItem(currentGroup)
if index != -1:
expanded = currentGroup.isExpanded()
self.mainwindow.config.delGroup(str(currentGroup.text(0)))
self.mainwindow.config.addGroup(gname, expanded)
gTemp = self.mainwindow.config.getGroups()
self.groups = [g[0] for g in gTemp]
self.openGroups = [g[1] for g in gTemp]
for i in range(currentGroup.childCount()):
currentGroup.child(i).chum.group = gname
self.mainwindow.chumdb.setGroup(currentGroup.child(i).chum.handle, gname)
currentGroup.setText(0, gname)
self.renamegroupdialog = None
@QtCore.pyqtSlot()
def removeGroup(self):
currentGroup = self.currentItem()
if not currentGroup:
return
self.mainwindow.config.delGroup(currentGroup.text(0))
gTemp = self.mainwindow.config.getGroups()
self.groups = [g[0] for g in gTemp]
self.openGroups = [g[1] for g in gTemp]
for i in range(self.topLevelItemCount()):
if self.topLevelItem(i).text(0) == currentGroup.text(0):
break
while self.topLevelItem(i) and self.topLevelItem(i).child(0):
chumLabel = self.topLevelItem(i).child(0)
chumLabel.chum.group = "Chums"
self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, "Chums")
self.takeItem(chumLabel)
self.addItem(chumLabel)
self.takeTopLevelItem(i)
@QtCore.pyqtSlot(QtGui.QAction)
def moveToGroup(self, item):
if not item:
return
group = str(item.text())
chumLabel = self.currentItem()
if not chumLabel:
return
chumLabel.chum.group = group
self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, group)
self.takeItem(chumLabel)
self.addItem(chumLabel)
removeChumSignal = QtCore.pyqtSignal(QtGui.QListWidgetItem) removeChumSignal = QtCore.pyqtSignal(QtCore.QString)
blockChumSignal = QtCore.pyqtSignal(QtCore.QString) blockChumSignal = QtCore.pyqtSignal(QtCore.QString)
class trollSlum(chumArea): class trollSlum(chumArea):
@ -550,19 +850,34 @@ class trollSlum(chumArea):
theme = self.mainwindow.theme theme = self.mainwindow.theme
self.setStyleSheet(theme["main/trollslum/chumroll/style"]) self.setStyleSheet(theme["main/trollslum/chumroll/style"])
self.chums = trolls self.chums = trolls
child_1 = QtGui.QTreeWidgetItem([""])
self.addTopLevelItem(child_1)
child_1.setExpanded(True)
for c in self.chums: for c in self.chums:
chandle = c.handle chandle = c.handle
if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)): if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)):
chumLabel = chumListing(c, self.mainwindow) chumLabel = chumListing(c, self.mainwindow)
self.addItem(chumLabel) self.addItem(chumLabel)
self.setSortingEnabled(False)
self.header().hide()
self.setDropIndicatorShown(False)
self.setIndentation(0)
self.optionsMenu = QtGui.QMenu(self) self.optionsMenu = QtGui.QMenu(self)
self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self) self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'), self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'),
self, QtCore.SIGNAL('unblockChumSignal()')) self, QtCore.SIGNAL('unblockChumSignal()'))
self.optionsMenu.addAction(self.unblockchum) self.optionsMenu.addAction(self.unblockchum)
self.sortItems() #self.sortItems()
def contextMenuEvent(self, event):
#fuckin Qt
if event.reason() == QtGui.QContextMenuEvent.Mouse:
listing = self.itemAt(event.pos())
self.setCurrentItem(listing)
if self.currentItem().text(0) != "":
self.optionsMenu.popup(event.globalPos())
def changeTheme(self, theme): def changeTheme(self, theme):
self.setStyleSheet(theme["main/trollslum/chumroll/style"]) self.setStyleSheet(theme["main/trollslum/chumroll/style"])
self.removechum.setText(theme["main/menus/rclickchumlist/removechum"]) self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
@ -754,9 +1069,8 @@ class MovingWindow(QtGui.QFrame):
class PesterWindow(MovingWindow): class PesterWindow(MovingWindow):
def __init__(self, parent=None): def __init__(self, parent=None):
MovingWindow.__init__(self, parent, MovingWindow.__init__(self, parent,
flags=(QtCore.Qt.CustomizeWindowHint | (QtCore.Qt.CustomizeWindowHint |
QtCore.Qt.FramelessWindowHint)) QtCore.Qt.FramelessWindowHint))
self.convos = {} self.convos = {}
self.memos = {} self.memos = {}
self.tabconvo = None self.tabconvo = None
@ -776,6 +1090,14 @@ class PesterWindow(MovingWindow):
self.move(100, 100) self.move(100, 100)
logv = QtGui.QAction(self.theme["main/menus/client/logviewer"], self)
self.logv = logv
self.connect(logv, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('openLogv()'))
grps = QtGui.QAction(self.theme["main/menus/client/addgroup"], self)
self.grps = grps
self.connect(grps, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('addGroupWindow()'))
opts = QtGui.QAction(self.theme["main/menus/client/options"], self) opts = QtGui.QAction(self.theme["main/menus/client/options"], self)
self.opts = opts self.opts = opts
self.connect(opts, QtCore.SIGNAL('triggered()'), self.connect(opts, QtCore.SIGNAL('triggered()'),
@ -809,8 +1131,10 @@ class PesterWindow(MovingWindow):
self.filemenu = filemenu self.filemenu = filemenu
filemenu.addAction(opts) filemenu.addAction(opts)
filemenu.addAction(memoaction) filemenu.addAction(memoaction)
filemenu.addAction(logv)
filemenu.addAction(userlistaction) filemenu.addAction(userlistaction)
filemenu.addAction(self.idleaction) filemenu.addAction(self.idleaction)
filemenu.addAction(grps)
filemenu.addAction(self.importaction) filemenu.addAction(self.importaction)
filemenu.addAction(self.reconnectAction) filemenu.addAction(self.reconnectAction)
filemenu.addAction(exitaction) filemenu.addAction(exitaction)
@ -871,13 +1195,13 @@ class PesterWindow(MovingWindow):
chums = [PesterProfile(c, chumdb=self.chumdb) for c in set(self.config.chums())] chums = [PesterProfile(c, chumdb=self.chumdb) for c in set(self.config.chums())]
self.chumList = chumArea(chums, self) self.chumList = chumArea(chums, self)
self.connect(self.chumList, self.connect(self.chumList,
QtCore.SIGNAL('itemActivated(QListWidgetItem *)'), QtCore.SIGNAL('itemActivated(QTreeWidgetItem *, int)'),
self, self,
QtCore.SLOT('newConversationWindow(QListWidgetItem *)')) QtCore.SLOT('pesterSelectedChum()'))
self.connect(self.chumList, self.connect(self.chumList,
QtCore.SIGNAL('removeChumSignal(QListWidgetItem *)'), QtCore.SIGNAL('removeChumSignal(QString)'),
self, self,
QtCore.SLOT('removeChum(QListWidgetItem *)')) QtCore.SLOT('removeChum(QString)'))
self.connect(self.chumList, self.connect(self.chumList,
QtCore.SIGNAL('blockChumSignal(QString)'), QtCore.SIGNAL('blockChumSignal(QString)'),
self, self,
@ -1106,6 +1430,8 @@ class PesterWindow(MovingWindow):
self.miniButton.move(*theme["main/minimize/loc"]) self.miniButton.move(*theme["main/minimize/loc"])
# menus # menus
self.menu.move(*theme["main/menu/loc"]) self.menu.move(*theme["main/menu/loc"])
self.logv.setText(theme["main/menus/client/logviewer"])
self.grps.setText(theme["main/menus/client/addgroup"])
self.opts.setText(theme["main/menus/client/options"]) self.opts.setText(theme["main/menus/client/options"])
self.exitaction.setText(theme["main/menus/client/exit"]) self.exitaction.setText(theme["main/menus/client/exit"])
self.userlistaction.setText(theme["main/menus/client/userlist"]) self.userlistaction.setText(theme["main/menus/client/userlist"])
@ -1260,7 +1586,9 @@ class PesterWindow(MovingWindow):
def pesterSelectedChum(self): def pesterSelectedChum(self):
curChum = self.chumList.currentItem() curChum = self.chumList.currentItem()
if curChum: if curChum:
self.newConversationWindow(curChum) if curChum.text(0) not in self.chumList.groups and \
curChum.text(0) != "Chums":
self.newConversationWindow(curChum)
@QtCore.pyqtSlot(QtGui.QListWidgetItem) @QtCore.pyqtSlot(QtGui.QListWidgetItem)
def newConversationWindow(self, chumlisting): def newConversationWindow(self, chumlisting):
# check chumdb # check chumdb
@ -1389,9 +1717,9 @@ class PesterWindow(MovingWindow):
chum = PesterProfile(handle, chumdb=self.chumdb) chum = PesterProfile(handle, chumdb=self.chumdb)
self.addChum(chum) self.addChum(chum)
self.addchumdialog = None self.addchumdialog = None
@QtCore.pyqtSlot(QtGui.QListWidgetItem) @QtCore.pyqtSlot(QtCore.QString)
def removeChum(self, chumlisting): def removeChum(self, chumlisting):
self.config.removeChum(chumlisting.chum) self.config.removeChum(chumlisting)
@QtCore.pyqtSlot(QtCore.QString) @QtCore.pyqtSlot(QtCore.QString)
def blockChum(self, handle): def blockChum(self, handle):
h = unicode(handle) h = unicode(handle)
@ -1525,7 +1853,7 @@ class PesterWindow(MovingWindow):
channel = re.sub(r"[^A-Za-z0-9#_]", "", channel) channel = re.sub(r"[^A-Za-z0-9#_]", "", channel)
self.newMemo(channel, time, secret=secret) self.newMemo(channel, time, secret=secret)
elif selectedmemo: elif selectedmemo:
channel = "#"+unicode(selectedmemo.text()) channel = "#"+unicode(selectedmemo.target)
self.newMemo(channel, time) self.newMemo(channel, time)
self.memochooser = None self.memochooser = None
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
@ -1585,6 +1913,42 @@ class PesterWindow(MovingWindow):
def closeQuirks(self): def closeQuirks(self):
self.quirkmenu = None self.quirkmenu = None
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def openLogv(self):
if not hasattr(self, 'logusermenu'):
self.logusermenu = None
if not self.logusermenu:
self.logusermenu = PesterLogUserSelect(self.config, self.theme, self)
self.connect(self.logusermenu, QtCore.SIGNAL('accepted()'),
self, QtCore.SLOT('closeLogUsers()'))
self.connect(self.logusermenu, QtCore.SIGNAL('rejected()'),
self, QtCore.SLOT('closeLogUsers()'))
self.logusermenu.show()
self.logusermenu.raise_()
self.logusermenu.activateWindow()
@QtCore.pyqtSlot()
def closeLogUsers(self):
self.logusermenu.close()
self.logusermenu = None
@QtCore.pyqtSlot()
def addGroupWindow(self):
if not hasattr(self, 'addgroupdialog'):
self.addgroupdialog = None
if not self.addgroupdialog:
(gname, ok) = QtGui.QInputDialog.getText(self, "Add Group", "Enter a name for the new group:")
if ok:
gname = unicode(gname)
self.config.addGroup(gname)
gTemp = self.config.getGroups()
self.chumList.groups = [g[0] for g in gTemp]
self.chumList.openGroups = [g[1] for g in gTemp]
self.chumList.showAllGroups()
if not self.config.showEmptyGroups():
self.chumList.hideEmptyGroups()
self.addgroupdialog = None
@QtCore.pyqtSlot()
def openOpts(self): def openOpts(self):
if not hasattr(self, 'optionmenu'): if not hasattr(self, 'optionmenu'):
self.optionmenu = None self.optionmenu = None
@ -1655,6 +2019,26 @@ class PesterWindow(MovingWindow):
# sound # sound
soundsetting = self.optionmenu.soundcheck.isChecked() soundsetting = self.optionmenu.soundcheck.isChecked()
self.config.set("soundon", soundsetting) self.config.set("soundon", soundsetting)
# timestamps
timestampsetting = self.optionmenu.timestampcheck.isChecked()
self.config.set("showTimeStamps", timestampsetting)
timeformatsetting = unicode(self.optionmenu.timestampBox.currentText())
if timeformatsetting == "12 hour":
self.config.set("time12Format", True)
else:
self.config.set("time12Format", False)
secondssetting = self.optionmenu.secondscheck.isChecked()
self.config.set("showSeconds", secondssetting)
# groups
#groupssetting = self.optionmenu.groupscheck.isChecked()
#self.config.set("useGroups", groupssetting)
emptygroupssetting = self.optionmenu.showemptycheck.isChecked()
curemptygroup = self.config.showEmptyGroups()
if curemptygroup and not emptygroupssetting:
self.chumList.hideEmptyGroups()
elif emptygroupssetting and not curemptygroup:
self.chumList.showAllGroups()
self.config.set("emptyGroups", emptygroupssetting)
self.optionmenu = None self.optionmenu = None
@QtCore.pyqtSlot() @QtCore.pyqtSlot()

View file

@ -36,11 +36,15 @@ style.js file will be documented soon, but feel free to poke at it.
allow you to appear at multiple times in one chat. allow you to appear at multiple times in one chat.
- Quirks: Prefix, suffix, simple replace, regexp replace (like in - Quirks: Prefix, suffix, simple replace, regexp replace (like in
2.5), random replacement, and an auto-mispeller :P 2.5), random replacement, and an auto-mispeller :P
- Chum groups. Organize your chums into collapsible groups for easy
management.
- Block/user list - Block/user list
- Add/block chums directly from a conversation, the userlist, or memo - Add/block chums directly from a conversation, the userlist, or memo
userlist. userlist.
- Timestamps saved in logs and shown in conversations if wanted.
- Logging. Logs are output in bbcode (for easy forum posting), html, - Logging. Logs are output in bbcode (for easy forum posting), html,
and plain text. and plain text.
- Logviewer for easy log reading inside Pesterchum
- Idling. You can set yourself idle manually, and the computer will - Idling. You can set yourself idle manually, and the computer will
set it for you after 10 minutes. set it for you after 10 minutes.
- Improved /me. Any letters immediately following /me will be - Improved /me. Any letters immediately following /me will be
@ -126,15 +130,15 @@ While pestering your chum, here are some useful features:
tags. These work like in TC 1.5: <c=(color)>colored text</c>. But in tags. These work like in TC 1.5: <c=(color)>colored text</c>. But in
PC 3.14, you can use type your color in a lot of different ways: PC 3.14, you can use type your color in a lot of different ways:
- You can use the familiar r,g,b method: - You can use the familiar r,g,b method:
"<c=0,255,0>The Green Sun</c>" "<c=0,255,0>The Green Sun</c>"
- You can use HTML tags: - You can use HTML tags:
"<c=#7f7f7f>DURR I'M KARKAT AND I'M A HUGE IDIOT</c>" "<c=#7f7f7f>DURR I'M KARKAT AND I'M A HUGE IDIOT</c>"
- You can even use plain color names: - You can even use plain color names:
"<c=red>D4V3 TH1S 1S SO D3C4D3NT</c>" "<c=red>D4V3 TH1S 1S SO D3C4D3NT</c>"
(list: http://www.w3schools.com/css/css_colornames.asp) (list: http://www.w3schools.com/css/css_colornames.asp)
- You don't even have to add the </c> if you are lazy. Just use a - You don't even have to add the </c> if you are lazy. Just use a
new color tag whenever you want to change colors and PC 3.14 will new color tag whenever you want to change colors and PC 3.14 will
add the extra tags for you. add the extra tags for you.
* URLS (anything with http:// in front of it) will automatically be * URLS (anything with http:// in front of it) will automatically be
detected and made into a link you can CLIPK. detected and made into a link you can CLIPK.
@ -226,6 +230,15 @@ Sounds On: Uncheck to shut it the fuck up.
Hide Offline Chums: Turning this option on will hide all offline chums Hide Offline Chums: Turning this option on will hide all offline chums
off your chumroll. off your chumroll.
Show Empty Groups: Turning this option of will show empty groups.
Time Stamps: Turning this on will show timestamps in your chats.
12/24 hour: Formatting for timestamps. Whether you want them in 12 or
24 hour time.
Show Seconds: Turning this on will show the seconds in your timestamps.
MEMOS: Opens the Memo list as above. MEMOS: Opens the Memo list as above.
USERLIST: Shows a list of all the users that are currently logged onto USERLIST: Shows a list of all the users that are currently logged onto
@ -385,6 +398,28 @@ either "a" or "A" will be matched and replaced with "4," and likewise,
"i" and "I" will be replaced with "1", and "e" and "E" will be "i" and "I" will be replaced with "1", and "e" and "E" will be
replaced with "3." replaced with "3."
Just like there is an "upper()" function, there is also a "lower()"
function. It acts just like "upper()" but instead makes everything
inside the parentheses lowercase. This allows you to do things like:
Regexp: "(.)" Replace with: "lower(\1)"
You type: "I AM YELLING"
Result:
GD: i am yelling
Along with the upper and lower functions is a "scramble()" function.
The purpose of this function is to randomly scramble anything inside
the parentheses.
Regexp: "(\w)(\w*)(\w)" Replace with: "\1scramble(\2)\3"
You type: "hello there"
Result:
GD: hlelo trhee
This particular regular expression scrambles all of the letters in
the middle of a word. Notice that the "h" and "o" at the beginning
and end of hello remain in place while the other letters are scrambled.
You should also know that "^" is a special character in brackets. If You should also know that "^" is a special character in brackets. If
placed immediately after the opening bracket (like "[^"), then the placed immediately after the opening bracket (like "[^"), then the
brackets instead match every character *except* the ones in the brackets instead match every character *except* the ones in the

View file

@ -18,10 +18,12 @@
"menus": {"client": {"_name": "Client", "menus": {"client": {"_name": "Client",
"options": "Options", "options": "Options",
"memos": "Memos", "memos": "Memos",
"logviewer": "Pesterlogs",
"userlist": "Userlist", "userlist": "Userlist",
"addgroup": "Add Group",
"import": "Import", "import": "Import",
"reconnect": "Reconnect", "reconnect": "Reconnect",
"idle": "Idle", "idle": "Idle",
"exit": "Exit"}, "exit": "Exit"},
"profile": {"_name": "Profile", "profile": {"_name": "Profile",
"switch": "Switch", "switch": "Switch",
@ -35,7 +37,11 @@
"removechum": "Remove Chum", "removechum": "Remove Chum",
"blockchum": "Block", "blockchum": "Block",
"addchum": "Add Chum", "addchum": "Add Chum",
"viewlog": "View Pesterlog",
"unblockchum": "Unblock", "unblockchum": "Unblock",
"removegroup": "Remove Group",
"renamegroup": "Rename Group",
"movechum": "Move To",
"banuser": "Ban User", "banuser": "Ban User",
"opuser": "Make OP", "opuser": "Make OP",
"quirksoff": "Quirks Off" "quirksoff": "Quirks Off"
@ -145,82 +151,82 @@
}, },
"defaultmood": 0, "defaultmood": 0,
"moodlabel": { "style": "", "moodlabel": { "style": "",
"loc": [20, 430], "loc": [20, 430],
"text": "" "text": ""
}, },
"moods": [ "moods": [
{ "style": "background-image:url($path/mood1.png); border:0px;", { "style": "background-image:url($path/mood1.png); border:0px;",
"selected": "background-image:url($path/mood1c.png); border:0px;", "selected": "background-image:url($path/mood1c.png); border:0px;",
"loc": [0, 258], "loc": [0, 258],
"size": [100,110], "size": [100,110],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 0 "mood": 0
}, },
{ "style": "background-image:url($path/mood2.png); border:0px;", { "style": "background-image:url($path/mood2.png); border:0px;",
"selected": "background-image:url($path/mood2c.png); border:0px;", "selected": "background-image:url($path/mood2c.png); border:0px;",
"loc": [106, 258], "loc": [106, 258],
"size": [100, 110], "size": [100, 110],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 19 "mood": 19
}, },
{ "style": "background-image:url($path/mood3.png); border:0px;", { "style": "background-image:url($path/mood3.png); border:0px;",
"selected": "background-image:url($path/mood3c.png); border:0px;", "selected": "background-image:url($path/mood3c.png); border:0px;",
"loc": [212, 258], "loc": [212, 258],
"size": [100, 110], "size": [100, 110],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 22 "mood": 22
}, },
{ "style": "background-image:url($path/mood4.png); border:0px;", { "style": "background-image:url($path/mood4.png); border:0px;",
"selected": "background-image:url($path/mood4c.png); border:0px;", "selected": "background-image:url($path/mood4c.png); border:0px;",
"loc": [318, 258], "loc": [318, 258],
"size": [100, 110], "size": [100, 110],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 4 "mood": 4
}, },
{ "style": "background-image:url($path/mood5.png); border:0px;", { "style": "background-image:url($path/mood5.png); border:0px;",
"selected": "background-image:url($path/mood5c.png); border:0px;", "selected": "background-image:url($path/mood5c.png); border:0px;",
"loc": [0, 382], "loc": [0, 382],
"size": [100, 110], "size": [100, 110],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 3 "mood": 3
}, },
{ "style": "background-image:url($path/mood6.png); border:0px;", { "style": "background-image:url($path/mood6.png); border:0px;",
"selected": "background-image:url($path/mood6c.png); border:0px;", "selected": "background-image:url($path/mood6c.png); border:0px;",
"loc": [106, 382], "loc": [106, 382],
"size": [100, 110], "size": [100, 110],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 20 "mood": 20
}, },
{ "style": "background-image:url($path/mood7.png); border:0px;", { "style": "background-image:url($path/mood7.png); border:0px;",
"selected": "background-image:url($path/mood7c.png); border:0px;", "selected": "background-image:url($path/mood7c.png); border:0px;",
"loc": [212, 382], "loc": [212, 382],
"size": [100, 110], "size": [100, 110],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 5 "mood": 5
}, },
{ "style": "background-image:url($path/mood8.png); border:0px;", { "style": "background-image:url($path/mood8.png); border:0px;",
"selected": "background-image:url($path/mood8c.png); border:0px;", "selected": "background-image:url($path/mood8c.png); border:0px;",
"loc": [318, 382], "loc": [318, 382],
"size": [100, 110], "size": [100, 110],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 1 "mood": 1
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "border:0px;", "selected": "border:0px;",
"loc": [0, 0], "loc": [0, 0],
"size": [100, 100], "size": [100, 100],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 2 "mood": 2
} }
] ]
}, },
"convo": "convo":
@ -256,12 +262,12 @@
"ceasepester": "ceased pestering", "ceasepester": "ceased pestering",
"blocked": "blocked", "blocked": "blocked",
"unblocked": "unblocked", "unblocked": "unblocked",
"blockedmsg": "did not receive message from", "blockedmsg": "did not receive message from",
"openmemo": "opened memo on board", "openmemo": "opened memo on board",
"joinmemo": "responded to memo", "joinmemo": "responded to memo",
"closememo": "ceased responding to memo", "closememo": "ceased responding to memo",
"kickedmemo": "You have been banned from this memo!", "kickedmemo": "You have been banned from this memo!",
"idle": "is now an idle chum!" "idle": "is now an idle chum!"
}, },
"systemMsgColor": "#646464" "systemMsgColor": "#646464"
}, },

View file

@ -16,14 +16,16 @@
"loc": [150,22] "loc": [150,22]
}, },
"sounds": { "alertsound": "$path/alarm.wav", "sounds": { "alertsound": "$path/alarm.wav",
"ceasesound": "$path/cease.wav" }, "ceasesound": "$path/cease.wav" },
"menus": {"client": {"_name": "Client", "menus": {"client": {"_name": "Client",
"options": "Options", "options": "Options",
"memos": "Memos", "memos": "Memos",
"logviewer": "Pesterlogs",
"userlist": "Userlist", "userlist": "Userlist",
"addgroup": "Add Group",
"import": "Import", "import": "Import",
"reconnect": "Reconnect", "reconnect": "Reconnect",
"idle": "Idle", "idle": "Idle",
"exit": "Exit"}, "exit": "Exit"},
"profile": {"_name": "Profile", "profile": {"_name": "Profile",
"switch": "Switch", "switch": "Switch",
@ -37,7 +39,11 @@
"removechum": "Remove Chum", "removechum": "Remove Chum",
"blockchum": "Block", "blockchum": "Block",
"addchum": "Add Chum", "addchum": "Add Chum",
"viewlog": "View Pesterlog",
"unblockchum": "Unblock", "unblockchum": "Unblock",
"removegroup": "Remove Group",
"renamegroup": "Rename Group",
"movechum": "Move To",
"banuser": "Ban User", "banuser": "Ban User",
"opuser": "Make OP", "opuser": "Make OP",
"quirksoff": "Quirks Off" "quirksoff": "Quirks Off"
@ -140,90 +146,90 @@
}, },
"defaultmood": 0, "defaultmood": 0,
"moodlabel": { "style": "", "moodlabel": { "style": "",
"loc": [20, 430], "loc": [20, 430],
"text": "MOODS" "text": "MOODS"
}, },
"moods": [ "moods": [
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "background-image:url($path/moodcheck1.png); border:0px;", "selected": "background-image:url($path/moodcheck1.png); border:0px;",
"loc": [13, 204], "loc": [13, 204],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 0 "mood": 0
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "background-image:url($path/moodcheck2.png); border:0px;", "selected": "background-image:url($path/moodcheck2.png); border:0px;",
"loc": [13, 231], "loc": [13, 231],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 19 "mood": 19
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "background-image:url($path/moodcheck3.png); border:0px;", "selected": "background-image:url($path/moodcheck3.png); border:0px;",
"loc": [13, 258], "loc": [13, 258],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 20 "mood": 20
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "background-image:url($path/moodcheck4.png); border:0px;", "selected": "background-image:url($path/moodcheck4.png); border:0px;",
"loc": [116, 204], "loc": [116, 204],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 21 "mood": 21
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "background-image:url($path/moodcheck5.png); border:0px;", "selected": "background-image:url($path/moodcheck5.png); border:0px;",
"loc": [116, 231], "loc": [116, 231],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 22 "mood": 22
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "background-image:url($path/moodcheck6.png); border:0px;", "selected": "background-image:url($path/moodcheck6.png); border:0px;",
"loc": [116, 258], "loc": [116, 258],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 5 "mood": 5
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "background-image:url($path/moodcheck7.png); border:0px;", "selected": "background-image:url($path/moodcheck7.png); border:0px;",
"loc": [219, 204], "loc": [219, 204],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 6 "mood": 6
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "background-image:url($path/moodcheck8.png); border:0px;", "selected": "background-image:url($path/moodcheck8.png); border:0px;",
"loc": [219, 231], "loc": [219, 231],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 3 "mood": 3
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "background-image:url($path/moodcheck9.png); border:0px;", "selected": "background-image:url($path/moodcheck9.png); border:0px;",
"loc": [219, 258], "loc": [219, 258],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 1 "mood": 1
}, },
{ "style": "border:0px;", { "style": "border:0px;",
"selected": "border:0px;", "selected": "border:0px;",
"loc": [13, 175], "loc": [13, 175],
"size": [101, 27], "size": [101, 27],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 2 "mood": 2
} }
] ]
}, },
"convo": "convo":
@ -261,12 +267,12 @@
"ceasepester": "ceased pestering", "ceasepester": "ceased pestering",
"blocked": "blocked", "blocked": "blocked",
"unblocked": "unblocked", "unblocked": "unblocked",
"blockedmsg": "did not receive message from", "blockedmsg": "did not receive message from",
"openmemo": "opened memo on board", "openmemo": "opened memo on board",
"joinmemo": "responded to memo", "joinmemo": "responded to memo",
"closememo": "ceased responding to memo", "closememo": "ceased responding to memo",
"kickedmemo": "You have been banned from this memo!", "kickedmemo": "You have been banned from this memo!",
"idle": "is now an idle chum!" "idle": "is now an idle chum!"
}, },
"systemMsgColor": "#646464" "systemMsgColor": "#646464"
}, },

View file

@ -16,14 +16,16 @@
"loc": [10,0] "loc": [10,0]
}, },
"sounds": { "alertsound": "$path/alarm.wav", "sounds": { "alertsound": "$path/alarm.wav",
"ceasesound": "$path/cease.wav" }, "ceasesound": "$path/cease.wav" },
"menus": {"client": {"_name": "CLIENT", "menus": {"client": {"_name": "CLIENT",
"options": "OPTIONS", "options": "OPTIONS",
"memos": "MEMOS", "memos": "MEMOS",
"logviewer": "PESTERLOGS",
"userlist": "USERLIST", "userlist": "USERLIST",
"addgroup": "ADD GROUP",
"import": "IMPORT", "import": "IMPORT",
"reconnect": "RECONNECT", "reconnect": "RECONNECT",
"idle": "IDLE", "idle": "IDLE",
"exit": "EXIT"}, "exit": "EXIT"},
"profile": {"_name": "PROFILE", "profile": {"_name": "PROFILE",
"switch": "SWITCH", "switch": "SWITCH",
@ -37,7 +39,11 @@
"removechum": "REMOVE CHUM", "removechum": "REMOVE CHUM",
"blockchum": "BLOCK", "blockchum": "BLOCK",
"addchum": "ADD CHUM", "addchum": "ADD CHUM",
"viewlog": "VIEW PESTERLOG",
"unblockchum": "UNBLOCK", "unblockchum": "UNBLOCK",
"removegroup": "REMOVE GROUP",
"renamegroup": "RENAME GROUP",
"movechum": "MOVE TO",
"banuser": "BAN USER", "banuser": "BAN USER",
"opuser": "MAKE OP", "opuser": "MAKE OP",
"quirksoff": "QUIRKS OFF" "quirksoff": "QUIRKS OFF"
@ -142,66 +148,66 @@
}, },
"defaultmood": 0, "defaultmood": 0,
"moodlabel": { "style": "", "moodlabel": { "style": "",
"loc": [20, 430], "loc": [20, 430],
"text": "MOODS" "text": "MOODS"
}, },
"moods": [ "moods": [
{ "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'", { "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'",
"selected": "text-align:left; background-image:url($path/moodcheck1.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';", "selected": "text-align:left; background-image:url($path/moodcheck1.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';",
"loc": [12, 288], "loc": [12, 288],
"size": [104, 22], "size": [104, 22],
"text": "CHUMMY", "text": "CHUMMY",
"icon": "$path/chummy.png", "icon": "$path/chummy.png",
"mood": 0 "mood": 0
}, },
{ "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'", { "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'",
"selected": "text-align:left; background-image:url($path/moodcheck2.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';", "selected": "text-align:left; background-image:url($path/moodcheck2.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';",
"loc": [12, 308], "loc": [12, 308],
"size": [104, 22], "size": [104, 22],
"text": "PALSY", "text": "PALSY",
"icon": "$path/chummy.png", "icon": "$path/chummy.png",
"mood": 3 "mood": 3
}, },
{ "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'", { "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'",
"selected": "text-align:left; background-image:url($path/moodcheck3.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';", "selected": "text-align:left; background-image:url($path/moodcheck3.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';",
"loc": [12, 328], "loc": [12, 328],
"size": [104, 22], "size": [104, 22],
"text": "CHIPPER", "text": "CHIPPER",
"icon": "$path/chummy.png", "icon": "$path/chummy.png",
"mood": 4 "mood": 4
}, },
{ "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'", { "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'",
"selected": "text-align:left; background-image:url($path/moodcheck2.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';", "selected": "text-align:left; background-image:url($path/moodcheck2.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';",
"loc": [117, 288], "loc": [117, 288],
"size": [104, 22], "size": [104, 22],
"text": "BULLY", "text": "BULLY",
"icon": "$path/chummy.png", "icon": "$path/chummy.png",
"mood": 5 "mood": 5
}, },
{ "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'", { "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'",
"selected": "text-align:left; background-image:url($path/moodcheck2.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';", "selected": "text-align:left; background-image:url($path/moodcheck2.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';",
"loc": [117, 308], "loc": [117, 308],
"size": [104, 22], "size": [104, 22],
"text": "PEPPY", "text": "PEPPY",
"icon": "$path/chummy.png", "icon": "$path/chummy.png",
"mood": 6 "mood": 6
}, },
{ "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'", { "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'",
"selected": "text-align:left; background-image:url($path/moodcheck4.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';", "selected": "text-align:left; background-image:url($path/moodcheck4.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';",
"loc": [117, 328], "loc": [117, 328],
"size": [104, 22], "size": [104, 22],
"text": "RANCOROUS", "text": "RANCOROUS",
"icon": "$path/rancorous.png", "icon": "$path/rancorous.png",
"mood": 1 "mood": 1
}, },
{ "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'", { "style": "text-align:left; border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier'",
"selected": "text-align:left; background-image:url($path/moodcheck5.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';", "selected": "text-align:left; background-image:url($path/moodcheck5.png); border:2px solid #c48a00; padding: 5px;color: rgba(0, 0, 0, 0%); font-family:'Courier';",
"loc": [12, 348], "loc": [12, 348],
"size": [209, 22], "size": [209, 22],
"text": "ABSCOND", "text": "ABSCOND",
"icon": "", "icon": "",
"mood": 2 "mood": 2
} }
] ]
}, },
"convo": "convo":
@ -228,7 +234,7 @@
"style": "background: white; border:2px solid #c48a00;margin-top:5px; margin-right:10px; margin-left:10px; font-size: 12px;font-family: 'Courier'" "style": "background: white; border:2px solid #c48a00;margin-top:5px; margin-right:10px; margin-left:10px; font-size: 12px;font-family: 'Courier'"
}, },
"tabwindow" : { "tabwindow" : {
"style": "background-color:#fdb302;border:0px" "style": "background-color:#fdb302;border:0px"
}, },
"tabs": { "tabs": {
"style": "background-color: #7f7f7f; font-family: 'Courier';font:bold;font-size:12px;min-height:25px;", "style": "background-color: #7f7f7f; font-family: 'Courier';font:bold;font-size:12px;min-height:25px;",
@ -241,12 +247,12 @@
"ceasepester": "ceased pestering", "ceasepester": "ceased pestering",
"blocked": "blocked", "blocked": "blocked",
"unblocked": "unblocked", "unblocked": "unblocked",
"blockedmsg": "did not receive message from", "blockedmsg": "did not receive message from",
"openmemo": "opened memo on board", "openmemo": "opened memo on board",
"joinmemo": "responded to memo", "joinmemo": "responded to memo",
"closememo": "ceased responding to memo", "closememo": "ceased responding to memo",
"kickedmemo": "You have been banned from this memo!", "kickedmemo": "You have been banned from this memo!",
"idle": "is now an idle chum!" "idle": "is now an idle chum!"
}, },
"systemMsgColor": "#646464" "systemMsgColor": "#646464"
}, },

View file

@ -19,9 +19,12 @@
"menus": {"client": {"_name": "Trollian", "menus": {"client": {"_name": "Trollian",
"options": "Options", "options": "Options",
"memos": "Memos", "memos": "Memos",
"logviewer": "Pesterlogs",
"userlist": "Fresh Targets", "userlist": "Fresh Targets",
"addgroup": "Add Group",
"import": "import U2;", "import": "import U2;",
"idle": "Idle", "reconnect": "Reconnect",
"idle": "Idle",
"exit": "Abscond"}, "exit": "Abscond"},
"profile": {"_name": "View", "profile": {"_name": "View",
"switch": "Trolltag", "switch": "Trolltag",
@ -35,7 +38,11 @@
"removechum": "Trash", "removechum": "Trash",
"blockchum": "Block", "blockchum": "Block",
"addchum": "Add Chump", "addchum": "Add Chump",
"viewlog": "View Pesterlog",
"unblockchum": "Mercy", "unblockchum": "Mercy",
"removegroup": "Remove Group",
"renamegroup": "Rename Group",
"movechum": "Move To",
"banuser": "Ban", "banuser": "Ban",
"opuser": "Promote", "opuser": "Promote",
"quirksoff": "Quirks Off" } "quirksoff": "Quirks Off" }
@ -264,7 +271,7 @@
"style": "background: white;margin-top:5px; border:1px solid #c2c2c2; margin-right: 54px; font-size: 12px; height: 19px;" "style": "background: white;margin-top:5px; border:1px solid #c2c2c2; margin-right: 54px; font-size: 12px; height: 19px;"
}, },
"tabwindow" : { "tabwindow" : {
"style": "background: rgb(190, 19, 4); font-family: 'Arial'" "style": "background: rgb(190, 19, 4); font-family: 'Arial'"
}, },
"tabs": { "tabs": {
"style": "", "style": "",

View file

@ -16,14 +16,16 @@
"loc": [43,220] "loc": [43,220]
}, },
"sounds": { "alertsound": "$path/alarm.wav", "sounds": { "alertsound": "$path/alarm.wav",
"ceasesound": "$path/cease.wav" }, "ceasesound": "$path/cease.wav" },
"menus": {"client": {"_name": "Typewriter", "menus": {"client": {"_name": "Typewriter",
"options": "Preferences", "options": "Preferences",
"memos": "Bulletin Boards", "memos": "Bulletin Boards",
"logviewer": "Pesterlogs",
"userlist": "Userlist", "userlist": "Userlist",
"addgroup": "Add Group",
"import": "Import", "import": "Import",
"idle": "Idle", "idle": "Idle",
"reconnect": "Reconnect", "reconnect": "Reconnect",
"exit": "Cease"}, "exit": "Cease"},
"profile": {"_name": "Ink", "profile": {"_name": "Ink",
"switch": "Alias", "switch": "Alias",
@ -37,7 +39,11 @@
"removechum": "Erase User", "removechum": "Erase User",
"blockchum": "Condemn", "blockchum": "Condemn",
"addchum": "Add User", "addchum": "Add User",
"viewlog": "View Pesterlog",
"unblockchum": "Forgive", "unblockchum": "Forgive",
"removegroup": "Remove Group",
"renamegroup": "Rename Group",
"movechum": "Move To",
"banuser": "Expel User", "banuser": "Expel User",
"opuser": "Promote", "opuser": "Promote",
"quirksoff": "Quirks Off" "quirksoff": "Quirks Off"
@ -142,26 +148,26 @@
}, },
"defaultmood": 18, "defaultmood": 18,
"moodlabel": { "style": "", "moodlabel": { "style": "",
"loc": [20, 430], "loc": [20, 430],
"text": "MOODS" "text": "MOODS"
}, },
"moods": [ "moods": [
{ "style": "text-align:left; border:0px solid #c48a00; padding: 0px;color: rgba(0, 0, 0, 0%); font-family:'Courier'", { "style": "text-align:left; border:0px solid #c48a00; padding: 0px;color: rgba(0, 0, 0, 0%); font-family:'Courier'",
"selected": "text-align:left; background-image:url($path/moodcheck1.png); border:0px solid #c48a00; padding: 0px;color: rgba(0, 0, 0, 0%); font-family:'Courier';", "selected": "text-align:left; background-image:url($path/moodcheck1.png); border:0px solid #c48a00; padding: 0px;color: rgba(0, 0, 0, 0%); font-family:'Courier';",
"loc": [95, 323], "loc": [95, 323],
"size": [62, 9], "size": [62, 9],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 18 "mood": 18
}, },
{ "style": "text-align:left; border:0px solid #c48a00; padding: 0px;color: rgba(0, 0, 0, 0%); font-family:'Courier'", { "style": "text-align:left; border:0px solid #c48a00; padding: 0px;color: rgba(0, 0, 0, 0%); font-family:'Courier'",
"selected": "text-align:left; background-image:url($path/moodcheck2.png); border:0px solid #c48a00; padding: 0px;color: rgba(0, 0, 0, 0%); font-family:'Courier';", "selected": "text-align:left; background-image:url($path/moodcheck2.png); border:0px solid #c48a00; padding: 0px;color: rgba(0, 0, 0, 0%); font-family:'Courier';",
"loc": [165, 323], "loc": [165, 323],
"size": [70, 9], "size": [70, 9],
"text": "", "text": "",
"icon": "", "icon": "",
"mood": 2 "mood": 2
} }
] ]
}, },
"convo": "convo":
@ -192,12 +198,12 @@
"ceasepester": "ceased pestering", "ceasepester": "ceased pestering",
"blocked": "blocked", "blocked": "blocked",
"unblocked": "unblocked", "unblocked": "unblocked",
"blockedmsg": "did not receive message from", "blockedmsg": "did not receive message from",
"openmemo": "opened memo on board", "openmemo": "opened memo on board",
"joinmemo": "responded to memo", "joinmemo": "responded to memo",
"closememo": "ceased responding to memo", "closememo": "ceased responding to memo",
"kickedmemo": "You have been banned from this memo!", "kickedmemo": "You have been banned from this memo!",
"idle": "is now an idle chum!" "idle": "is now an idle chum!"
}, },
"systemMsgColor": "#646464" "systemMsgColor": "#646464"
}, },