This commit is contained in:
Stephen Dranger 2011-02-08 01:56:30 -06:00
parent e39590d60b
commit 10d0ede71d
22 changed files with 112 additions and 55 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
logs/*
build/*

31
TODO
View file

@ -1,35 +1,29 @@
Features:
* dropped messages when chatting
* X closes to tray
* color text is not being translated to server?
* comment history (up button)
* page up/down scrolling
* System tray menu
* troll colors
* ctrl-tab should prefer new convos
* Idling
* More complex quirks: random, spelling, by-sound
* change profile only once we have confirmation from server
* convo backgrounds -- make them more like http://www.mspaintadventures.com/storyfiles/hs2/02546_2.gif
* make other ppl ops
* turn off sound option!!
* help button on quirks menu?
* help menu -- about and forum
* dropped messages when chatting ?
-- release alpha
* scroll bar style?
* User commands/stop user from sending commands accidentally
* shared buddy lists - changes to the buddy list should refresh it?
multiple clients share buddy list???
* System tray menu
* new sound on CEASE and BEGIN?
* comment history (up button)
* page up/down scrolling
* get rid of border on chat window?
* Idling
* ctrl-tab should prefer new convos
* More complex quirks: random, spelling, by-sound
* Implement TC options
* chumList not scaling -- QListView + delegate?
* spell check?
* Help menu
* change profile only once we have confirmation from server
-- release beta
* log viewer
* pick your own icon
* time codes
* theme elements define, implement
* Theme checking
* don't clear new message when clicking away from tab?
* Spy mode
@ -37,10 +31,3 @@ Features:
* put code into separate files
* hide offline chums
* chum list groups
-- MEMOS:
list has "CREATE" CACNCEL JOIN buttons
no "--" for sys mesg

View file

@ -343,6 +343,7 @@ class PesterConvo(QtGui.QFrame):
self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.title(), convertTags(msg, "bbcode"))
self.newmessage = False
self.history = []
def title(self):
return self.chum.handle
@ -448,21 +449,21 @@ class PesterConvo(QtGui.QFrame):
@QtCore.pyqtSlot()
def sentMessage(self):
text = self.textInput.text()
text = unicode(self.textInput.text())
if text == "":
return
# deal with quirks here
if self.applyquirks:
qtext = self.mainwindow.userprofile.quirks.apply(unicode(text))
text = QtCore.QString(qtext)
self.textInput.setText("")
qtext = self.mainwindow.userprofile.quirks.apply(text)
text = qtext
self.addMessage(text, True)
# if ceased, rebegin
if hasattr(self, 'chumopen') and not self.chumopen:
self.mainwindow.newConvoStarted.emit(QtCore.QString(self.title()), True)
# convert color tags
text = convertTags(unicode(text), "ctag")
text = convertTags(text, "ctag")
self.messageSent.emit(text, self.title())
self.textInput.setText("")
@QtCore.pyqtSlot()
def addThisChum(self):

BIN
convo.pyc

Binary file not shown.

2
irc.py
View file

@ -229,6 +229,8 @@ class PesterHandler(DefaultCommandHandler):
self.parent.userPresentUpdate.emit(handle, channel, "join")
if channel == "#pesterchum":
self.parent.moodUpdated.emit(handle, Mood("chummy"))
def mode(self, op, channel, mode, handle=""):
self.parent.userPresentUpdate.emit(handle, channel, mode)
def nick(self, oldnick, newnick):
oldhandle = oldnick[0:oldnick.find("!")]
newchum = PesterProfile(newnick, chumdb=self.mainwindow.chumdb)

BIN
irc.pyc

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -243,6 +243,9 @@ class MemoText(PesterText):
if chum is not me:
if parent.times.has_key(chum.handle):
time = parent.times[chum.handle]
if not time.getTime():
# MY WAY OR THE HIGHWAY
time.addTime(timedelta(0))
else:
# new chum! time current
newtime = timedelta(0)
@ -309,8 +312,11 @@ class PesterMemo(PesterConvo):
self.banuserAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/banuser"], self)
self.connect(self.banuserAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('banSelectedUser()'))
self.opAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/opuser"], self)
self.connect(self.opAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('opSelectedUser()'))
self.userlist.optionsMenu.addAction(self.addchumAction)
# ban list added if we are op
# ban & op list added if we are op
self.timeslider = TimeSlider(QtCore.Qt.Horizontal, self)
self.timeinput = TimeInput(self.timeslider, self)
@ -424,10 +430,12 @@ class PesterMemo(PesterConvo):
self.channelLabel.setMaximumHeight(theme["memos/label/maxheight"])
self.channelLabel.setMinimumHeight(theme["memos/label/minheight"])
self.userlist.optionsMenu.setStyleSheet(theme["main/defaultwindow/style"])
self.userlist.setStyleSheet(theme["memos/userlist/style"])
self.userlist.setFixedWidth(theme["memos/userlist/width"])
self.addchumAction.setText(theme["main/menus/rclickchumlist/addchum"])
self.banuserAction.setText(theme["main/menus/rclickchumlist/banuser"])
self.opAction.setText(theme["main/menus/rclickchumlist/opuser"])
self.timeinput.setFixedWidth(theme["memos/time/text/width"])
self.timeinput.setStyleSheet(theme["memos/time/text/style"])
@ -454,6 +462,10 @@ class PesterMemo(PesterConvo):
margins = theme["memos/margins"]
self.layout.setContentsMargins(margins["left"], margins["top"],
margins["right"], margins["bottom"])
for item in [self.userlist.row(i) for i in range(0,self.userlist.count())]:
if item.op:
icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
item.setIcon(icon)
def addUser(self, handle):
chumdb = self.mainwindow.chumdb
@ -463,6 +475,7 @@ class PesterMemo(PesterConvo):
op = True
handle = handle[1:]
if handle == self.mainwindow.profile().handle:
self.userlist.optionsMenu.addAction(self.opAction)
self.userlist.optionsMenu.addAction(self.banuserAction)
self.op = True
item = QtGui.QListWidgetItem(handle)
@ -471,6 +484,10 @@ class PesterMemo(PesterConvo):
else:
color = chumdb.getColor(handle, defaultcolor)
item.setTextColor(color)
item.op = op
if op:
icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
item.setIcon(icon)
self.userlist.addItem(item)
def timeUpdate(self, handle, cmd):
@ -561,7 +578,8 @@ class PesterMemo(PesterConvo):
oldnick = l[0]
newnick = l[1]
h = oldnick
if (update in ["join","left", "kick"]) and channel != self.channel:
if (update in ["join","left", "kick", "+o"]) \
and channel != self.channel:
return
chums = self.userlist.findItems(h, QtCore.Qt.MatchFlags(0))
systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
@ -639,6 +657,14 @@ class PesterMemo(PesterConvo):
time = self.time.getTime()
serverText = "PESTERCHUM:TIME>"+delta2txt(time, "server")
self.messageSent.emit(serverText, self.title())
elif update == "+o":
chums = self.userlist.findItems(h, QtCore.Qt.MatchFlags(0))
for c in chums:
icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
c.setIcon(icon)
if unicode(c.text()) == self.mainwindow.profile().handle:
self.userlist.optionsMenu.addAction(self.opAction)
self.userlist.optionsMenu.addAction(self.banuserAction)
@QtCore.pyqtSlot()
def addChumSlot(self):
@ -652,6 +678,12 @@ class PesterMemo(PesterConvo):
return
currentHandle = unicode(self.userlist.currentItem().text())
self.mainwindow.kickUser.emit(currentHandle, self.channel)
@QtCore.pyqtSlot()
def opSelectedUser(self):
if not self.userlist.currentItem():
return
currentHandle = unicode(self.userlist.currentItem().text())
self.mainwindow.setChannelMode.emit(self.channel, "+o", currentHandle)
def resetSlider(self, time, send=True):
self.timeinput.setText(delta2txt(time))
self.timeinput.setSlider()

BIN
memos.pyc

Binary file not shown.

View file

@ -280,14 +280,13 @@ class PesterOptions(QtGui.QDialog):
self.theme = theme
self.setStyleSheet(self.theme["main/defaultwindow/style"])
self.tabcheck = QtGui.QCheckBox(self)
self.tabcheck = QtGui.QCheckBox("Tabbed Conversations", self)
if self.config.tabs():
self.tabcheck.setChecked(True)
self.tablabel = QtGui.QLabel("Tabbed Conversations", self)
layout_1 = QtGui.QHBoxLayout()
layout_1.addWidget(self.tablabel)
layout_1.addWidget(self.tabcheck)
self.soundcheck = QtGui.QCheckBox("Sounds On", self)
if self.config.soundOn():
self.soundcheck.setChecked(True)
self.ok = QtGui.QPushButton("OK", self)
self.ok.setDefault(True)
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
@ -300,7 +299,8 @@ class PesterOptions(QtGui.QDialog):
layout_2.addWidget(self.ok)
layout_0 = QtGui.QVBoxLayout()
layout_0.addLayout(layout_1)
layout_0.addWidget(self.tabcheck)
layout_0.addWidget(self.soundcheck)
layout_0.addLayout(layout_2)
self.setLayout(layout_0)
@ -410,7 +410,7 @@ class PesterMemoList(QtGui.QDialog):
self.orjoinlabel = QtGui.QLabel("OR MAKE A NEW MEMO:")
self.newmemo = QtGui.QLineEdit(channel, self)
self.secretChannel = QtGui.QCheckBox("HIDDEN?", self)
self.secretChannel = QtGui.QCheckBox("HIDDEN CHANNEL?", self)
self.timelabel = QtGui.QLabel("TIMEFRAME:")
self.timeslider = TimeSlider(QtCore.Qt.Horizontal, self)

BIN
menus.pyc

Binary file not shown.

View file

@ -43,6 +43,9 @@ def convertTags(string, format="html"):
string = _urlre.sub(urlrep, string)
if format == "html":
string = _memore.sub(r" <a href='\1'>\1</a>", string)
string = string.replace(" :trollcool:", " <img src='%s' />" % ("themes/pesterchum/trollcool.gif")) # ugh hardcoded, gross i know. but its just 1 smiley
elif format == "bbcode":
string = string.replace(" :trollcool:", " [img]http://www.mspaintadventures.com/storyfiles/hs2/scraps/trollcool.gif[/img]")
return string
def escapeBrackets(string):

Binary file not shown.

BIN
pesterchum.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -1 +1 @@
{"tabs": false, "chums": ["marineAquist", "unknownTraveler", "tentacleTherapist", "macruralAlchemist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium", "terminallyCapricious", "illuminatedWax", "aquaMarinist", "maxiumumFatness", "elegantDiversion", "moirailBunp", "uroborosUnbound", "androidTechnician", "midnightSparrow", "apocalypseArisen"], "defaultprofile": "testProfile", "block": []}
{"tabs": true, "soundon": true, "chums": ["marineAquist", "unknownTraveler", "tentacleTherapist", "macruralAlchemist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium", "terminallyCapricious", "illuminatedWax", "aquaMarinist", "maxiumumFatness", "elegantDiversion", "moirailBunp", "uroborosUnbound", "androidTechnician", "midnightSparrow", "apocalypseArisen", "acapellaWaterfall", "anguillaNuntia", "oilslickOrchid"], "defaultprofile": "testProfile", "block": []}

View file

@ -6,6 +6,7 @@ from datetime import *
from string import Template
import random
import json
import codecs
import re
import socket
from PyQt4 import QtGui, QtCore
@ -61,7 +62,7 @@ class PesterLog(object):
time = datetime.now().strftime("%Y-%m-%d.%H.%M.txt")
if not os.path.exists("logs/%s/%s" % (self.handle, handle)):
os.mkdir("logs/%s/%s" % (self.handle, handle))
fp = open("logs/%s/%s/%s.%s" % (self.handle, handle, handle, time), 'a')
fp = codecs.open("logs/%s/%s/%s.%s" % (self.handle, handle, handle, time), encoding='utf-8', mode='a')
self.convos[handle] = fp
self.convos[handle].write(msg+"\n")
self.convos[handle].flush()
@ -115,11 +116,18 @@ class pesterTheme(dict):
theme = json.load(fp, object_hook=self.pathHook)
self.update(theme)
fp.close()
defaultfp = open("themes/pesterchum/style.js") # set default
defaultTheme = json.load(defaultfp, object_hook=self.pathHook)
self.defaultTheme = defaultTheme
defaultfp.close()
def __getitem__(self, key):
keys = key.split("/")
v = dict.__getitem__(self, keys.pop(0))
for k in keys:
v = v[k]
try:
v = v[k]
except KeyError:
v = self.defaultTheme[k]
return v
def pathHook(self, d):
for (k, v) in d.iteritems():
@ -184,6 +192,10 @@ class userConfig(object):
l = self.getBlocklist()
l.pop(l.index(handle))
self.set('block', l)
def soundOn(self):
if not self.config.has_key('soundon'):
self.set('soundon', True)
return self.config['soundon']
def set(self, item, setting):
self.config[item] = setting
try:
@ -671,7 +683,7 @@ class PesterWindow(MovingWindow):
self.closeButton = WMButton(PesterIcon(self.theme["main/close/image"]), self)
self.connect(self.closeButton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('close()'))
self, QtCore.SLOT('closeToTray()'))
self.miniButton = WMButton(PesterIcon(self.theme["main/minimize/image"]), self)
self.connect(self.miniButton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('showMinimized()'))
@ -746,6 +758,10 @@ class PesterWindow(MovingWindow):
palette.setBrush(QtGui.QPalette.Window, QtGui.QBrush(self.backgroundImage))
self.setPalette(palette)
@QtCore.pyqtSlot()
def closeToTray(self):
self.hide()
self.closeToTraySignal.emit()
def closeEvent(self, event):
self.closeConversations()
if hasattr(self, 'trollslum') and self.trollslum:
@ -770,7 +786,8 @@ class PesterWindow(MovingWindow):
convo = self.convos[handle]
convo.addMessage(msg, False)
# play sound here
self.alarm.play()
if self.config.soundOn():
self.alarm.play()
def newMemoMsg(self, chan, handle, msg):
if not self.memos.has_key(chan):
# silently ignore in case we forgot to /part
@ -1001,9 +1018,11 @@ class PesterWindow(MovingWindow):
if len(self.waitingMessages) == 0:
if self.isMinimized():
self.showNormal()
elif self.isHidden():
self.show()
else:
if self.isActiveWindow():
self.showMinimized()
self.hide()
else:
self.raise_()
self.activateWindow()
@ -1346,6 +1365,9 @@ class PesterWindow(MovingWindow):
self.memos = newmemos
# save options
self.config.set("tabs", tabsetting)
# sound
soundsetting = self.optionmenu.soundcheck.isChecked()
self.config.set("soundon", soundsetting)
self.optionmenu = None
@QtCore.pyqtSlot()
@ -1467,6 +1489,7 @@ class PesterWindow(MovingWindow):
# show context menu i guess
pass
closeToTraySignal = QtCore.pyqtSignal()
newConvoStarted = QtCore.pyqtSignal(QtCore.QString, bool, name="newConvoStarted")
sendMessage = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
convoClosed = QtCore.pyqtSignal(QtCore.QString)
@ -1542,6 +1565,10 @@ class MainProgram(QtCore.QObject):
QtCore.SIGNAL('trayIconSignal(int)'),
self.trayicon,
QtCore.SLOT('changeTrayIcon(int)'))
self.trayicon.connect(self.widget,
QtCore.SIGNAL('closeToTraySignal()'),
self.trayicon,
QtCore.SLOT('show()'))
self.irc = PesterIRC(self.widget)
self.connectWidgets(self.irc, self.widget)

View file

@ -19,14 +19,14 @@ setup(
)])
if sys.platform == "win32":
os.rename("build/exe.win32-2.6", "build/pesterchum")
shutil.copytree("imageformats", "build/pesterchum/imageformats")
shutil.copy("C:/Dev/Py26MSdlls-9.0.21022.8/msvc/msvcm90.dll", "build/pesterchum")
shutil.copy("C:/Dev/Py26MSdlls-9.0.21022.8/msvc/msvcp90.dll", "build/pesterchum")
shutil.copy("C:/Dev/Py26MSdlls-9.0.21022.8/msvc/msvcr90.dll", "build/pesterchum")
shutil.copy("C:/Dev/Py26MSdlls-9.0.21022.8/msvc/x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375.manifest",
"build/pesterchum")
shutil.copytree("themes", "build/pesterchum/themes")
shutil.copytree("imageformats", "build/pesterchum/imageformats")
shutil.copy("pesterchum.js", "build/pesterchum/")
shutil.copy("C:/Dev/Py26MSdlls-9.0.21022.8/msvc/msvcm90.dll", "build/pesterchum")
shutil.copy("C:/Dev/Py26MSdlls-9.0.21022.8/msvc/msvcp90.dll", "build/pesterchum")
shutil.copy("C:/Dev/Py26MSdlls-9.0.21022.8/msvc/msvcr90.dll", "build/pesterchum")
shutil.copy("C:/Dev/Py26MSdlls-9.0.21022.8/msvc/x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375.manifest",
"build/pesterchum")
os.mkdir("build/pesterchum/profiles")
os.mkdir("build/pesterchum/logs")

BIN
themes/pesterchum/op.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

View file

@ -34,6 +34,7 @@
"addchum": "ADD CHUM",
"unblockchum": "UNBLOCK",
"banuser": "BAN USER",
"opuser": "MAKE OP",
"quirksoff": "QUIRKS OFF"
}
},
@ -84,7 +85,7 @@
"protective": { "icon": "$path/protective.gif", "color": "#00ff00" },
"blocked": { "icon": "$path/blocked.gif", "color": "black" }
"blocked": { "icon": "$path/blocked.gif", "color": "black" }
}
},
@ -259,6 +260,7 @@
"style": " border:0px; margin-top: 5px; margin-right:10px;"
}
},
"systemMsgColor": "#646464"
"systemMsgColor": "#646464",
"op": { "icon": "$path/op.gif" }
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

BIN
themes/trollian/op.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

View file

@ -34,6 +34,7 @@
"addchum": "Add Chump",
"unblockchum": "Mercy",
"banuser": "Ban",
"opuser": "Promote",
"quirksoff": "Quirks Off" }
},
"chums": { "style": "font-size: 12px; background: white; border:2px solid #c2c2c2; padding: 5px; font-family: 'Arial';selection-background-color:rgb(200,200,200); ",
@ -309,6 +310,7 @@
"style": "width: 19px; height: 19px; border:0px; margin-left: 2px;"
}
},
"systemMsgColor": "#646464"
"systemMsgColor": "#646464",
"op": { "icon": "$path/op.gif" }
}
}