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:
* 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.
* 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
@ -20,10 +24,7 @@ Features:
* # of users in each memo
* copy quirks between profiles?
* help button on quirks menu?
* chum list groups
* More complex quirks: by-sound
* log viewer
* time codes
* Theme checking
* Spy mode
* Animated

View file

@ -2,6 +2,7 @@ from string import Template
import re
import platform
import httplib, urllib
from time import strftime
from copy import copy
from datetime import datetime, timedelta
from PyQt4 import QtGui, QtCore
@ -221,6 +222,17 @@ class PesterText(QtGui.QTextEdit):
parent = self.parent()
window = parent.mainwindow
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":
parent.setChumOpen(True)
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)
else:
window.chatlog.log(chum.handle, memsg)
self.append(convertTags(memsg))
self.append(time + convertTags(memsg))
else:
if not parent.chumopen and chum is not me:
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),
"%s: " % (initials)]
lexmsg.append(colorEnd("</c>"))
self.append(convertTags(lexmsg))
self.append(time + convertTags(lexmsg))
if chum is me:
window.chatlog.log(parent.chum.handle, lexmsg)
else:

View file

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

View file

@ -37,6 +37,13 @@ class RightClickList(QtGui.QListWidget):
self.setCurrentItem(listing)
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):
def __init__(self, title, parent, *queries):
QtGui.QDialog.__init__(self, parent)

6
irc.py
View file

@ -335,12 +335,16 @@ class PesterHandler(DefaultCommandHandler):
self.channel_list = []
info = list(info)
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):
channel = info[self.channel_field]
usercount = info[1]
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):
pl = PesterList(self.channel_list)
logging.info("---> recv \"CHANNELS END\"")
self.parent.channelListReceived.emit(pl)
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.setText(unicode(quirk))
def __lt__(self, quirkitem):
"""Sets the order of quirks if auto-sorted by Qt. Obsolete now."""
if self.quirk.type == "prefix":
return True
elif (self.quirk.type == "replace" or self.quirk.type == "regexp") and \
@ -21,11 +22,11 @@ class PesterQuirkItem(QtGui.QListWidgetItem):
return True
else:
return False
class PesterQuirkList(QtGui.QListWidget):
def __init__(self, mainwindow, parent):
QtGui.QListWidget.__init__(self, parent)
self.resize(400, 200)
# make sure we have access to mainwindow info like profiles
self.mainwindow = mainwindow
self.setStyleSheet("background:black; color:white;")
@ -37,6 +38,20 @@ class PesterQuirkList(QtGui.QListWidget):
def currentQuirk(self):
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()
def removeCurrent(self):
i = self.currentRow()
@ -187,6 +202,19 @@ class PesterChooseQuirks(QtGui.QDialog):
self.addMispellingButton = QtGui.QPushButton("MISPELLER", self)
self.connect(self.addMispellingButton, QtCore.SIGNAL('clicked()'),
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.addWidget(self.addPrefixButton)
@ -219,7 +247,7 @@ class PesterChooseQuirks(QtGui.QDialog):
layout_ok.addWidget(self.ok)
layout_0 = QtGui.QVBoxLayout()
layout_0.addWidget(self.quirkList)
layout_0.addLayout(layout_quirklist)
layout_0.addLayout(layout_1)
layout_0.addLayout(layout_2)
layout_0.addLayout(layout_3)
@ -230,6 +258,15 @@ class PesterChooseQuirks(QtGui.QDialog):
return [self.quirkList.item(i).quirk for i in
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()
def editSelected(self):
q = self.quirkList.currentQuirk()
@ -507,6 +544,10 @@ class PesterOptions(QtGui.QDialog):
self.theme = theme
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)
if self.config.tabs():
self.tabcheck.setChecked(True)
@ -517,6 +558,28 @@ class PesterOptions(QtGui.QDialog):
self.soundcheck = QtGui.QCheckBox("Sounds On", self)
if self.config.soundOn():
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.setDefault(True)
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
@ -532,6 +595,12 @@ class PesterOptions(QtGui.QDialog):
layout_0.addWidget(self.tabcheck)
layout_0.addWidget(self.soundcheck)
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)
self.setLayout(layout_0)
@ -622,6 +691,13 @@ class PesterUserlist(QtGui.QDialog):
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):
def __init__(self, parent, channel=""):
QtGui.QDialog.__init__(self, parent)
@ -678,7 +754,7 @@ class PesterMemoList(QtGui.QDialog):
def updateChannels(self, 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.setIcon(QtGui.QIcon(self.theme["memos/memoicon"]))
self.channelarea.addItem(item)
@ -704,8 +780,8 @@ class PesterMemoList(QtGui.QDialog):
class LoadingScreen(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent, flags=(QtCore.Qt.CustomizeWindowHint |
QtCore.Qt.FramelessWindowHint))
QtGui.QDialog.__init__(self, parent, (QtCore.Qt.CustomizeWindowHint |
QtCore.Qt.FramelessWindowHint))
self.mainwindow = parent
self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])

View file

@ -12,16 +12,18 @@ import socket
import platform
from PyQt4 import QtGui, QtCore
import pygame
from time import strftime
from menus import PesterChooseQuirks, PesterChooseTheme, \
PesterChooseProfile, PesterOptions, PesterUserlist, PesterMemoList, \
LoadingScreen, AboutPesterchum
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 parsetools import convertTags, addTimeInitial
from memos import PesterMemo, MemoTabWindow, TimeTracker
from irc import PesterIRC
from logviewer import PesterLogUserSelect, PesterLogViewer
_datadir = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.DataLocation)+"Pesterchum/"
@ -76,9 +78,10 @@ class PesterLog(object):
self.logpath = _datadir+"logs"
def log(self, handle, msg):
bbcodemsg = convertTags(msg, "bbcode")
html = convertTags(msg, "html")+"<br />"
msg = convertTags(msg, "text")
time = strftime("[%H:%M:%S] ")
bbcodemsg = time + convertTags(msg, "bbcode")
html = time + convertTags(msg, "html")+"<br />"
msg = time + convertTags(msg, "text")
modes = {"bbcode": bbcodemsg, "html": html, "text": msg}
if not self.convos.has_key(handle):
time = datetime.now().strftime("%Y-%m-%d.%H.%M")
@ -128,7 +131,14 @@ class PesterProfileDB(dict):
json.dump(chumdict, fp)
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)
def save(self):
@ -149,6 +159,17 @@ class PesterProfileDB(dict):
self[handle].color = color
else:
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):
dict.__setitem__(self, key, val)
self.save()
@ -249,6 +270,30 @@ class userConfig(object):
return None
def tabs(self):
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):
if chum.handle not in self.chums():
fp = open(self.filename) # what if we have two clients open??
@ -276,6 +321,25 @@ class userConfig(object):
l = self.getBlocklist()
l.pop(l.index(handle))
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):
return self.config.get('server', 'irc.mindfang.org')
def port(self):
@ -389,9 +453,9 @@ class WMButton(QtGui.QPushButton):
self.setStyleSheet("QPushButton { padding: 0px; }")
self.setAutoDefault(False)
class chumListing(QtGui.QListWidgetItem):
class chumListing(QtGui.QTreeWidgetItem):
def __init__(self, chum, window):
QtGui.QListWidgetItem.__init__(self, chum.handle)
QtGui.QTreeWidgetItem.__init__(self, [chum.handle])
self.mainwindow = window
self.chum = chum
self.handle = chum.handle
@ -405,32 +469,44 @@ class chumListing(QtGui.QListWidgetItem):
mood = self.chum.mood
self.mood = mood
icon = self.mood.icon(self.mainwindow.theme)
self.setIcon(icon)
self.setIcon(0, icon)
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:
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):
icon = self.mood.icon(theme)
self.setIcon(icon)
self.setIcon(0, icon)
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:
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):
h1 = self.handle.lower()
h2 = cl.handle.lower()
return (h1 < h2)
class chumArea(RightClickList):
class chumArea(RightClickTree):
def __init__(self, chums, parent=None):
QtGui.QListWidget.__init__(self, parent)
QtGui.QTreeWidget.__init__(self, parent)
self.mainwindow = parent
theme = self.mainwindow.theme
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():
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.connect(self.pester, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('activateChum()'))
@ -440,12 +516,86 @@ class chumArea(RightClickList):
self.blockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
self.connect(self.blockchum, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('blockChum()'))
self.optionsMenu.addAction(self.pester)
self.optionsMenu.addAction(self.blockchum)
self.optionsMenu.addAction(self.removechum)
self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
self.connect(self.logchum, QtCore.SIGNAL('triggered()'),
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.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):
if len([c for c in self.chums if c.handle == chum.handle]) != 0:
return
@ -454,29 +604,95 @@ class chumArea(RightClickList):
chum.mood.name() == "offline"):
chumLabel = chumListing(chum, self.mainwindow)
self.addItem(chumLabel)
self.sortItems()
#self.topLevelItem(0).addChild(chumLabel)
#self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
def getChums(self, handle):
chums = self.findItems(handle, QtCore.Qt.MatchFlags(0))
chums = self.findItems(handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive)
return chums
def showAllChums(self):
for c in self.chums:
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)
self.addItem(chumLabel)
self.sortItems()
#self.sortItems()
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
listing = self.item(i)
listing = self.topLevelItem(i)
while listing is not None:
if listing.chum.mood.name() == "offline":
self.takeItem(i)
if listing.childCount() == 0:
self.takeTopLevelItem(i)
else:
i += 1
listing = self.item(i)
self.sortItems()
listing = self.topLevelItem(i)
@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):
hideoff = self.mainwindow.config.hideOfflineChums()
chums = self.getChums(handle)
@ -487,7 +703,7 @@ class chumArea(RightClickList):
handle in [p.handle for p in self.chums]:
newLabel = chumListing([p for p in self.chums if p.handle == handle][0], self.mainwindow)
self.addItem(newLabel)
self.sortItems()
#self.sortItems()
chums = [newLabel]
elif mood.name() == "offline" and \
len(chums) > 0:
@ -512,14 +728,28 @@ class chumArea(RightClickList):
self.pester.setText(theme["main/menus/rclickchumlist/pester"])
self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
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):
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:
c.changeTheme(theme)
def count(self):
c = 0
for i in range(self.topLevelItemCount()):
c = c + self.topLevelItem(i).childCount()
return c
@QtCore.pyqtSlot()
def activateChum(self):
self.itemActivated.emit(self.currentItem())
self.itemActivated.emit(self.currentItem(), 0)
@QtCore.pyqtSlot()
def removeChum(self, handle = None):
if handle:
@ -530,8 +760,8 @@ class chumArea(RightClickList):
return
currentChum = self.currentItem().chum
self.chums = [c for c in self.chums if c.handle != currentChum.handle]
self.removeChumSignal.emit(self.currentItem())
oldlist = self.takeItem(self.currentRow())
self.removeChumSignal.emit(self.currentItem().chum.handle)
oldlist = self.takeItem(self.currentItem())
del oldlist
@QtCore.pyqtSlot()
def blockChum(self):
@ -539,8 +769,78 @@ class chumArea(RightClickList):
if not currentChum:
return
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)
class trollSlum(chumArea):
@ -550,19 +850,34 @@ class trollSlum(chumArea):
theme = self.mainwindow.theme
self.setStyleSheet(theme["main/trollslum/chumroll/style"])
self.chums = trolls
child_1 = QtGui.QTreeWidgetItem([""])
self.addTopLevelItem(child_1)
child_1.setExpanded(True)
for c in self.chums:
chandle = c.handle
if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)):
chumLabel = chumListing(c, self.mainwindow)
self.addItem(chumLabel)
self.setSortingEnabled(False)
self.header().hide()
self.setDropIndicatorShown(False)
self.setIndentation(0)
self.optionsMenu = QtGui.QMenu(self)
self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'),
self, QtCore.SIGNAL('unblockChumSignal()'))
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):
self.setStyleSheet(theme["main/trollslum/chumroll/style"])
self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
@ -754,9 +1069,8 @@ class MovingWindow(QtGui.QFrame):
class PesterWindow(MovingWindow):
def __init__(self, parent=None):
MovingWindow.__init__(self, parent,
flags=(QtCore.Qt.CustomizeWindowHint |
QtCore.Qt.FramelessWindowHint))
(QtCore.Qt.CustomizeWindowHint |
QtCore.Qt.FramelessWindowHint))
self.convos = {}
self.memos = {}
self.tabconvo = None
@ -776,6 +1090,14 @@ class PesterWindow(MovingWindow):
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)
self.opts = opts
self.connect(opts, QtCore.SIGNAL('triggered()'),
@ -809,8 +1131,10 @@ class PesterWindow(MovingWindow):
self.filemenu = filemenu
filemenu.addAction(opts)
filemenu.addAction(memoaction)
filemenu.addAction(logv)
filemenu.addAction(userlistaction)
filemenu.addAction(self.idleaction)
filemenu.addAction(grps)
filemenu.addAction(self.importaction)
filemenu.addAction(self.reconnectAction)
filemenu.addAction(exitaction)
@ -871,13 +1195,13 @@ class PesterWindow(MovingWindow):
chums = [PesterProfile(c, chumdb=self.chumdb) for c in set(self.config.chums())]
self.chumList = chumArea(chums, self)
self.connect(self.chumList,
QtCore.SIGNAL('itemActivated(QListWidgetItem *)'),
QtCore.SIGNAL('itemActivated(QTreeWidgetItem *, int)'),
self,
QtCore.SLOT('newConversationWindow(QListWidgetItem *)'))
QtCore.SLOT('pesterSelectedChum()'))
self.connect(self.chumList,
QtCore.SIGNAL('removeChumSignal(QListWidgetItem *)'),
QtCore.SIGNAL('removeChumSignal(QString)'),
self,
QtCore.SLOT('removeChum(QListWidgetItem *)'))
QtCore.SLOT('removeChum(QString)'))
self.connect(self.chumList,
QtCore.SIGNAL('blockChumSignal(QString)'),
self,
@ -1106,6 +1430,8 @@ class PesterWindow(MovingWindow):
self.miniButton.move(*theme["main/minimize/loc"])
# menus
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.exitaction.setText(theme["main/menus/client/exit"])
self.userlistaction.setText(theme["main/menus/client/userlist"])
@ -1260,7 +1586,9 @@ class PesterWindow(MovingWindow):
def pesterSelectedChum(self):
curChum = self.chumList.currentItem()
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)
def newConversationWindow(self, chumlisting):
# check chumdb
@ -1389,9 +1717,9 @@ class PesterWindow(MovingWindow):
chum = PesterProfile(handle, chumdb=self.chumdb)
self.addChum(chum)
self.addchumdialog = None
@QtCore.pyqtSlot(QtGui.QListWidgetItem)
@QtCore.pyqtSlot(QtCore.QString)
def removeChum(self, chumlisting):
self.config.removeChum(chumlisting.chum)
self.config.removeChum(chumlisting)
@QtCore.pyqtSlot(QtCore.QString)
def blockChum(self, handle):
h = unicode(handle)
@ -1525,7 +1853,7 @@ class PesterWindow(MovingWindow):
channel = re.sub(r"[^A-Za-z0-9#_]", "", channel)
self.newMemo(channel, time, secret=secret)
elif selectedmemo:
channel = "#"+unicode(selectedmemo.text())
channel = "#"+unicode(selectedmemo.target)
self.newMemo(channel, time)
self.memochooser = None
@QtCore.pyqtSlot()
@ -1585,6 +1913,42 @@ class PesterWindow(MovingWindow):
def closeQuirks(self):
self.quirkmenu = None
@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):
if not hasattr(self, 'optionmenu'):
self.optionmenu = None
@ -1655,6 +2019,26 @@ class PesterWindow(MovingWindow):
# sound
soundsetting = self.optionmenu.soundcheck.isChecked()
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
@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.
- Quirks: Prefix, suffix, simple replace, regexp replace (like in
2.5), random replacement, and an auto-mispeller :P
- Chum groups. Organize your chums into collapsible groups for easy
management.
- Block/user list
- Add/block chums directly from a conversation, the userlist, or memo
userlist.
- Timestamps saved in logs and shown in conversations if wanted.
- Logging. Logs are output in bbcode (for easy forum posting), html,
and plain text.
- Logviewer for easy log reading inside Pesterchum
- Idling. You can set yourself idle manually, and the computer will
set it for you after 10 minutes.
- 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
PC 3.14, you can use type your color in a lot of different ways:
- 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:
"<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:
"<c=red>D4V3 TH1S 1S SO D3C4D3NT</c>"
(list: http://www.w3schools.com/css/css_colornames.asp)
"<c=red>D4V3 TH1S 1S SO D3C4D3NT</c>"
(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
new color tag whenever you want to change colors and PC 3.14 will
add the extra tags for you.
new color tag whenever you want to change colors and PC 3.14 will
add the extra tags for you.
* URLS (anything with http:// in front of it) will automatically be
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
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.
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
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
placed immediately after the opening bracket (like "[^"), then the
brackets instead match every character *except* the ones in the

View file

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

View file

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

View file

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

View file

@ -19,9 +19,12 @@
"menus": {"client": {"_name": "Trollian",
"options": "Options",
"memos": "Memos",
"logviewer": "Pesterlogs",
"userlist": "Fresh Targets",
"addgroup": "Add Group",
"import": "import U2;",
"idle": "Idle",
"reconnect": "Reconnect",
"idle": "Idle",
"exit": "Abscond"},
"profile": {"_name": "View",
"switch": "Trolltag",
@ -35,7 +38,11 @@
"removechum": "Trash",
"blockchum": "Block",
"addchum": "Add Chump",
"viewlog": "View Pesterlog",
"unblockchum": "Mercy",
"removegroup": "Remove Group",
"renamegroup": "Rename Group",
"movechum": "Move To",
"banuser": "Ban",
"opuser": "Promote",
"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;"
},
"tabwindow" : {
"style": "background: rgb(190, 19, 4); font-family: 'Arial'"
"style": "background: rgb(190, 19, 4); font-family: 'Arial'"
},
"tabs": {
"style": "",

View file

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