2011-01-21 05:18:22 -05:00
|
|
|
# pesterchum
|
|
|
|
from oyoyo.client import IRCClient
|
|
|
|
from oyoyo.cmdhandler import DefaultCommandHandler
|
|
|
|
from oyoyo import helpers
|
|
|
|
import logging
|
2011-01-27 21:21:02 -05:00
|
|
|
import os, sys
|
|
|
|
import os.path
|
2011-01-28 03:10:00 -05:00
|
|
|
from datetime import *
|
2011-02-01 06:14:56 -05:00
|
|
|
from string import Template
|
2011-01-27 21:21:02 -05:00
|
|
|
import random
|
2011-01-21 05:18:22 -05:00
|
|
|
import json
|
2011-01-29 06:31:41 -05:00
|
|
|
import re
|
2011-01-21 05:18:22 -05:00
|
|
|
from PyQt4 import QtGui, QtCore
|
2011-01-29 06:31:41 -05:00
|
|
|
import pygame
|
2011-01-21 05:18:22 -05:00
|
|
|
|
2011-02-02 19:32:35 -05:00
|
|
|
from pestermenus import PesterChooseQuirks, PesterChooseTheme, \
|
|
|
|
PesterChooseProfile, PesterOptions, PesterUserlist
|
2011-02-03 01:20:37 -05:00
|
|
|
from pesterdata import PesterProfile, Mood, pesterQuirk, pesterQuirks
|
|
|
|
from generic import PesterIcon, RightClickList, MultiTextDialog
|
2011-02-02 19:32:35 -05:00
|
|
|
|
2011-01-21 05:18:22 -05:00
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
|
2011-02-02 03:20:48 -05:00
|
|
|
_ctag_begin = re.compile(r'<c=(.*?)>')
|
|
|
|
_ctag_rgb = re.compile(r'\d+,\d+,\d+')
|
2011-02-03 03:51:22 -05:00
|
|
|
_urlre = re.compile(r"(?i)(http://[^\s<]+)")
|
2011-02-02 03:20:48 -05:00
|
|
|
|
2011-02-03 03:51:22 -05:00
|
|
|
def convertTags(string, format="html"):
|
2011-02-02 03:20:48 -05:00
|
|
|
if format not in ["html", "bbcode", "ctag"]:
|
|
|
|
raise ValueError("Color format not recognized")
|
2011-02-03 03:51:22 -05:00
|
|
|
def colorrepfunc(matchobj):
|
2011-02-02 03:20:48 -05:00
|
|
|
color = matchobj.group(1)
|
|
|
|
if _ctag_rgb.match(color) is not None:
|
|
|
|
if format=='ctag':
|
|
|
|
return "<c=%s,%s,%s>"
|
2011-02-02 07:26:17 -05:00
|
|
|
try:
|
|
|
|
qc = QtGui.QColor(*[int(c) for c in color.split(",")])
|
|
|
|
except ValueError:
|
|
|
|
qc = QtGui.QColor("black")
|
2011-02-02 03:20:48 -05:00
|
|
|
else:
|
|
|
|
qc = QtGui.QColor(color)
|
|
|
|
if not qc.isValid():
|
|
|
|
qc = QtGui.QColor("black")
|
|
|
|
if format == "html":
|
|
|
|
return '<span style="color:%s">' % (qc.name())
|
|
|
|
elif format == "bbcode":
|
|
|
|
return '[color=%s]' % (qc.name())
|
|
|
|
elif format == "ctag":
|
|
|
|
(r,g,b,a) = qc.getRgb()
|
|
|
|
return '<c=%s,%s,%s>' % (r,g,b)
|
2011-02-03 03:51:22 -05:00
|
|
|
string = _ctag_begin.sub(colorrepfunc, string)
|
2011-02-02 03:20:48 -05:00
|
|
|
endtag = {"html": "</span>", "bbcode": "[/color]", "ctag": "</c>"}
|
|
|
|
string = string.replace("</c>", endtag[format])
|
2011-02-03 03:51:22 -05:00
|
|
|
urlrep = {"html": r"<a href='\1'>\1</a>",
|
|
|
|
"bbcode": r"[url]\1[/url]",
|
|
|
|
"ctag": r"\1" }
|
|
|
|
string = _urlre.sub(urlrep[format], string)
|
2011-02-02 03:20:48 -05:00
|
|
|
return string
|
|
|
|
|
|
|
|
def escapeBrackets(string):
|
|
|
|
class beginTag(object):
|
|
|
|
def __init__(self, tag):
|
|
|
|
self.tag = tag
|
|
|
|
class endTag(object):
|
|
|
|
pass
|
|
|
|
newlist = []
|
|
|
|
begintagpos = [(m.start(), m.end()) for m in _ctag_begin.finditer(string)]
|
|
|
|
lasti = 0
|
|
|
|
for (s, e) in begintagpos:
|
|
|
|
newlist.append(string[lasti:s])
|
|
|
|
newlist.append(beginTag(string[s:e]))
|
|
|
|
lasti = e
|
|
|
|
if lasti < len(string):
|
|
|
|
newlist.append(string[lasti:])
|
|
|
|
tmp = []
|
|
|
|
for o in newlist:
|
|
|
|
if type(o) is not beginTag:
|
|
|
|
l = o.split("</c>")
|
|
|
|
tmp.append(l[0])
|
|
|
|
l = l[1:]
|
|
|
|
for item in l:
|
|
|
|
tmp.append(endTag())
|
|
|
|
tmp.append(item)
|
|
|
|
else:
|
|
|
|
tmp.append(o)
|
|
|
|
btlen = 0
|
|
|
|
etlen = 0
|
|
|
|
retval = ""
|
|
|
|
newlist = tmp
|
|
|
|
for o in newlist:
|
|
|
|
if type(o) is beginTag:
|
|
|
|
retval += o.tag.replace("&", "&")
|
|
|
|
btlen +=1
|
|
|
|
elif type(o) is endTag:
|
|
|
|
if etlen >= btlen:
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
retval += "</c>"
|
|
|
|
etlen += 1
|
|
|
|
else:
|
|
|
|
retval += o.replace("&", "&").replace("<", "<").replace(">", ">")
|
|
|
|
if btlen > etlen:
|
|
|
|
for i in range(0, btlen-etlen):
|
|
|
|
retval += "</c>"
|
|
|
|
return retval
|
2011-02-03 01:56:59 -05:00
|
|
|
|
2011-01-29 06:31:41 -05:00
|
|
|
class waitingMessageHolder(object):
|
|
|
|
def __init__(self, mainwindow, **msgfuncs):
|
|
|
|
self.mainwindow = mainwindow
|
|
|
|
self.funcs = msgfuncs
|
|
|
|
self.queue = msgfuncs.keys()
|
|
|
|
if len(self.queue) > 0:
|
|
|
|
self.mainwindow.updateSystemTray()
|
|
|
|
def answerMessage(self):
|
|
|
|
func = self.funcs[self.queue[0]]
|
|
|
|
func()
|
|
|
|
def messageAnswered(self, handle):
|
|
|
|
if handle not in self.queue:
|
|
|
|
return
|
|
|
|
self.queue = [q for q in self.queue if q != handle]
|
|
|
|
del self.funcs[handle]
|
|
|
|
if len(self.queue) == 0:
|
|
|
|
self.mainwindow.updateSystemTray()
|
|
|
|
def addMessage(self, handle, func):
|
|
|
|
if not self.funcs.has_key(handle):
|
|
|
|
self.queue.append(handle)
|
|
|
|
self.funcs[handle] = func
|
|
|
|
if len(self.queue) > 0:
|
|
|
|
self.mainwindow.updateSystemTray()
|
|
|
|
def __len__(self):
|
|
|
|
return len(self.queue)
|
|
|
|
|
|
|
|
class NoneSound(object):
|
|
|
|
def play(self): pass
|
|
|
|
|
2011-02-02 03:20:48 -05:00
|
|
|
class PesterLog(object):
|
|
|
|
def __init__(self, handle):
|
|
|
|
self.handle = handle
|
|
|
|
if not os.path.exists("logs/%s" % (handle)):
|
|
|
|
os.mkdir("logs/%s" % (handle))
|
|
|
|
self.convos = {}
|
|
|
|
def log(self, handle, msg):
|
|
|
|
if not self.convos.has_key(handle):
|
|
|
|
time = datetime.now().strftime("%Y-%m-%d.%H:%M")
|
|
|
|
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')
|
|
|
|
self.convos[handle] = fp
|
|
|
|
self.convos[handle].write(msg+"\n")
|
|
|
|
self.convos[handle].flush()
|
|
|
|
def finish(self, handle):
|
|
|
|
if not self.convos.has_key(handle):
|
|
|
|
return
|
|
|
|
self.convos[handle].close()
|
|
|
|
del self.convos[handle]
|
|
|
|
def close(self):
|
|
|
|
for h in self.convos.keys():
|
2011-02-02 19:06:03 -05:00
|
|
|
self.convos[h].close()
|
2011-02-02 03:20:48 -05:00
|
|
|
|
2011-01-31 18:43:49 -05:00
|
|
|
class PesterProfileDB(dict):
|
|
|
|
def __init__(self):
|
|
|
|
try:
|
|
|
|
fp = open("logs/chums.js", 'r')
|
|
|
|
chumdict = json.load(fp)
|
|
|
|
fp.close()
|
|
|
|
except IOError:
|
|
|
|
chumdict = {}
|
|
|
|
fp = open("logs/chums.js", 'w')
|
|
|
|
json.dump(chumdict, fp)
|
|
|
|
fp.close()
|
2011-02-01 02:46:25 -05:00
|
|
|
converted = dict([(handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']))) for (handle, c) in chumdict.iteritems()])
|
2011-01-31 18:43:49 -05:00
|
|
|
self.update(converted)
|
|
|
|
|
|
|
|
def save(self):
|
|
|
|
fp = open("logs/chums.js", 'w')
|
|
|
|
chumdict = dict([p.plaindict() for p in self.itervalues()])
|
|
|
|
json.dump(chumdict, fp)
|
|
|
|
fp.close()
|
|
|
|
def getColor(self, handle, default=None):
|
|
|
|
if not self.has_key(handle):
|
|
|
|
return default
|
|
|
|
else:
|
2011-02-01 06:14:56 -05:00
|
|
|
return self[handle].color
|
2011-01-31 18:43:49 -05:00
|
|
|
def setColor(self, handle, color):
|
|
|
|
if self.has_key(handle):
|
|
|
|
self[handle].color = color
|
|
|
|
else:
|
|
|
|
self[handle] = PesterProfile(handle, color)
|
|
|
|
def __setitem__(self, key, val):
|
|
|
|
dict.__setitem__(self, key, val)
|
|
|
|
self.save()
|
|
|
|
|
2011-02-03 01:20:37 -05:00
|
|
|
class PesterList(list):
|
2011-02-02 19:06:03 -05:00
|
|
|
def __init__(self, l):
|
|
|
|
self.extend(l)
|
|
|
|
|
2011-01-24 02:34:07 -05:00
|
|
|
class pesterTheme(dict):
|
2011-01-22 04:36:24 -05:00
|
|
|
def __init__(self, name):
|
|
|
|
self.path = "themes/%s" % (name)
|
2011-01-28 06:17:42 -05:00
|
|
|
self.name = name
|
2011-01-22 04:36:24 -05:00
|
|
|
fp = open(self.path+"/style.js")
|
2011-01-24 02:34:07 -05:00
|
|
|
theme = json.load(fp, object_hook=self.pathHook)
|
|
|
|
self.update(theme)
|
2011-01-22 04:36:24 -05:00
|
|
|
fp.close()
|
2011-01-24 02:34:07 -05:00
|
|
|
def __getitem__(self, key):
|
|
|
|
keys = key.split("/")
|
|
|
|
v = dict.__getitem__(self, keys.pop(0))
|
|
|
|
for k in keys:
|
|
|
|
v = v[k]
|
|
|
|
return v
|
2011-01-22 04:36:24 -05:00
|
|
|
def pathHook(self, d):
|
|
|
|
for (k, v) in d.iteritems():
|
|
|
|
if type(v) is unicode:
|
|
|
|
s = Template(v)
|
2011-02-01 06:14:56 -05:00
|
|
|
d[k] = s.safe_substitute(path=self.path)
|
2011-01-22 04:36:24 -05:00
|
|
|
return d
|
2011-01-21 05:18:22 -05:00
|
|
|
|
2011-01-29 07:33:35 -05:00
|
|
|
|
2011-01-21 05:18:22 -05:00
|
|
|
class userConfig(object):
|
2011-01-27 04:46:47 -05:00
|
|
|
def __init__(self):
|
|
|
|
fp = open("pesterchum.js")
|
2011-01-21 05:18:22 -05:00
|
|
|
self.config = json.load(fp)
|
|
|
|
fp.close()
|
2011-01-27 21:21:02 -05:00
|
|
|
if self.config.has_key("defaultprofile"):
|
2011-01-28 01:08:56 -05:00
|
|
|
self.userprofile = userProfile(self.config["defaultprofile"])
|
2011-01-27 21:21:02 -05:00
|
|
|
else:
|
2011-01-28 01:08:56 -05:00
|
|
|
self.userprofile = None
|
2011-01-21 05:18:22 -05:00
|
|
|
def chums(self):
|
|
|
|
return self.config['chums']
|
2011-01-28 01:08:56 -05:00
|
|
|
def defaultprofile(self):
|
|
|
|
try:
|
|
|
|
return self.config['defaultprofile']
|
|
|
|
except KeyError:
|
|
|
|
return None
|
2011-01-26 05:32:35 -05:00
|
|
|
def tabs(self):
|
|
|
|
return self.config["tabs"]
|
2011-01-29 06:31:41 -05:00
|
|
|
def addChum(self, chum):
|
|
|
|
newchums = self.config['chums'] + [chum.handle]
|
|
|
|
self.set("chums", newchums)
|
|
|
|
def removeChum(self, chum):
|
2011-02-02 19:06:03 -05:00
|
|
|
if type(chum) is PesterProfile:
|
|
|
|
handle = chum.handle
|
|
|
|
else:
|
|
|
|
handle = chum
|
|
|
|
newchums = [c for c in self.config['chums'] if c != handle]
|
2011-01-29 06:31:41 -05:00
|
|
|
self.set("chums", newchums)
|
2011-02-02 19:06:03 -05:00
|
|
|
def getBlocklist(self):
|
|
|
|
if not self.config.has_key('block'):
|
|
|
|
self.set('block', [])
|
|
|
|
return self.config['block']
|
|
|
|
def addBlocklist(self, handle):
|
|
|
|
l = self.getBlocklist()
|
|
|
|
if handle not in l:
|
|
|
|
l.append(handle)
|
|
|
|
self.set('block', l)
|
|
|
|
def delBlocklist(self, handle):
|
|
|
|
l = self.getBlocklist()
|
|
|
|
l.pop(l.index(handle))
|
|
|
|
self.set('block', l)
|
2011-01-27 04:46:47 -05:00
|
|
|
def set(self, item, setting):
|
|
|
|
self.config[item] = setting
|
2011-02-03 01:20:37 -05:00
|
|
|
try:
|
|
|
|
jsonoutput = json.dumps(self.config)
|
|
|
|
except ValueError, e:
|
|
|
|
raise e
|
2011-01-27 04:46:47 -05:00
|
|
|
fp = open("pesterchum.js", 'w')
|
2011-02-03 01:20:37 -05:00
|
|
|
fp.write(jsonoutput)
|
2011-01-27 04:46:47 -05:00
|
|
|
fp.close()
|
2011-01-28 06:17:42 -05:00
|
|
|
def availableThemes(self):
|
|
|
|
themes = []
|
|
|
|
for dirname, dirnames, filenames in os.walk('themes'):
|
|
|
|
for d in dirnames:
|
|
|
|
themes.append(d)
|
|
|
|
themes.sort()
|
|
|
|
return themes
|
2011-01-27 21:21:02 -05:00
|
|
|
def availableProfiles(self):
|
|
|
|
profs = []
|
|
|
|
for dirname, dirnames, filenames in os.walk('profiles'):
|
|
|
|
for filename in filenames:
|
|
|
|
l = len(filename)
|
|
|
|
if filename[l-3:l] == ".js":
|
|
|
|
profs.append(filename[0:l-3])
|
|
|
|
profs.sort()
|
|
|
|
return [userProfile(p) for p in profs]
|
|
|
|
class userProfile(object):
|
|
|
|
def __init__(self, user):
|
|
|
|
if type(user) is PesterProfile:
|
|
|
|
self.chat = user
|
|
|
|
self.userprofile = {"handle":user.handle,
|
|
|
|
"color": unicode(user.color.name()),
|
|
|
|
"quirks": [],
|
|
|
|
"theme": "pesterchum"}
|
|
|
|
self.theme = pesterTheme("pesterchum")
|
2011-01-28 21:36:12 -05:00
|
|
|
self.chat.mood = Mood(self.theme["main/defaultmood"])
|
2011-01-27 21:21:02 -05:00
|
|
|
self.quirks = pesterQuirks([])
|
|
|
|
else:
|
|
|
|
fp = open("profiles/%s.js" % (user))
|
|
|
|
self.userprofile = json.load(fp)
|
|
|
|
fp.close()
|
2011-01-31 18:43:49 -05:00
|
|
|
try:
|
|
|
|
self.theme = pesterTheme(self.userprofile["theme"])
|
|
|
|
except ValueError, e:
|
|
|
|
self.theme = pesterTheme("pesterchum")
|
|
|
|
|
2011-01-27 21:21:02 -05:00
|
|
|
self.chat = PesterProfile(self.userprofile["handle"],
|
|
|
|
QtGui.QColor(self.userprofile["color"]),
|
2011-01-28 21:36:12 -05:00
|
|
|
Mood(self.theme["main/defaultmood"]))
|
2011-01-27 21:21:02 -05:00
|
|
|
self.quirks = pesterQuirks(self.userprofile["quirks"])
|
2011-01-28 21:36:12 -05:00
|
|
|
def setMood(self, mood):
|
|
|
|
self.chat.mood = mood
|
2011-01-28 06:26:13 -05:00
|
|
|
def setTheme(self, theme):
|
|
|
|
self.theme = theme
|
|
|
|
self.userprofile["theme"] = theme.name
|
|
|
|
self.save()
|
|
|
|
def setColor(self, color):
|
|
|
|
self.chat.color = color
|
2011-01-29 07:33:35 -05:00
|
|
|
self.userprofile["color"] = unicode(color.name())
|
2011-01-28 06:26:13 -05:00
|
|
|
self.save()
|
|
|
|
def setQuirks(self, quirks):
|
|
|
|
self.quirks = quirks
|
2011-01-29 16:55:35 -05:00
|
|
|
self.userprofile["quirks"] = self.quirks.plainList()
|
2011-01-28 06:26:13 -05:00
|
|
|
self.save()
|
2011-01-27 21:21:02 -05:00
|
|
|
def getTheme(self):
|
|
|
|
return self.theme
|
|
|
|
def save(self):
|
|
|
|
handle = self.chat.handle
|
2011-02-03 01:20:37 -05:00
|
|
|
try:
|
2011-02-03 01:56:59 -05:00
|
|
|
jsonoutput = json.dumps(self.userprofile)
|
2011-02-03 01:20:37 -05:00
|
|
|
except ValueError, e:
|
|
|
|
raise e
|
2011-01-27 21:21:02 -05:00
|
|
|
fp = open("profiles/%s.js" % (handle), 'w')
|
2011-02-03 01:20:37 -05:00
|
|
|
fp.write(jsonoutput)
|
2011-01-27 21:21:02 -05:00
|
|
|
fp.close()
|
|
|
|
@staticmethod
|
|
|
|
def newUserProfile(chatprofile):
|
|
|
|
if os.path.exists("profiles/%s.js" % (chatprofile.handle)):
|
|
|
|
newprofile = userProfile(chatprofile.handle)
|
|
|
|
else:
|
|
|
|
newprofile = userProfile(chatprofile)
|
|
|
|
newprofile.save()
|
|
|
|
return newprofile
|
2011-01-29 16:55:35 -05:00
|
|
|
|
2011-01-21 05:18:22 -05:00
|
|
|
|
2011-01-27 04:46:47 -05:00
|
|
|
class WMButton(QtGui.QPushButton):
|
2011-01-21 05:18:22 -05:00
|
|
|
def __init__(self, icon, parent=None):
|
|
|
|
QtGui.QPushButton.__init__(self, icon, "", parent)
|
2011-02-02 03:20:48 -05:00
|
|
|
self.setIconSize(icon.realsize())
|
2011-01-21 05:18:22 -05:00
|
|
|
self.setFlat(True)
|
2011-01-22 04:36:24 -05:00
|
|
|
self.setStyleSheet("QPushButton { padding: 0px; }")
|
|
|
|
self.setAutoDefault(False)
|
|
|
|
|
|
|
|
class chumListing(QtGui.QListWidgetItem):
|
2011-01-28 01:08:56 -05:00
|
|
|
def __init__(self, chum, window):
|
2011-01-24 02:34:07 -05:00
|
|
|
QtGui.QListWidgetItem.__init__(self, chum.handle)
|
2011-01-28 03:59:03 -05:00
|
|
|
self.mainwindow = window
|
2011-01-24 02:34:07 -05:00
|
|
|
self.chum = chum
|
|
|
|
self.handle = chum.handle
|
2011-01-22 04:36:24 -05:00
|
|
|
self.setMood(Mood("offline"))
|
|
|
|
def setMood(self, mood):
|
2011-01-24 04:10:44 -05:00
|
|
|
self.chum.mood = mood
|
|
|
|
self.updateMood()
|
2011-01-28 04:07:20 -05:00
|
|
|
def setColor(self, color):
|
|
|
|
self.chum.color = color
|
2011-02-02 07:26:17 -05:00
|
|
|
def updateMood(self, unblock=False):
|
2011-01-24 04:10:44 -05:00
|
|
|
mood = self.chum.mood
|
2011-01-22 04:36:24 -05:00
|
|
|
self.mood = mood
|
2011-02-03 03:51:22 -05:00
|
|
|
icon = self.mood.icon(self.mainwindow.theme)
|
|
|
|
self.setIcon(icon)
|
2011-02-03 01:20:37 -05:00
|
|
|
try:
|
|
|
|
self.setTextColor(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"]))
|
2011-01-28 06:17:42 -05:00
|
|
|
def changeTheme(self, theme):
|
2011-02-03 03:51:22 -05:00
|
|
|
icon = self.mood.icon(theme)
|
|
|
|
self.setIcon(icon)
|
2011-02-03 01:20:37 -05:00
|
|
|
try:
|
|
|
|
self.setTextColor(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"]))
|
2011-01-22 04:36:24 -05:00
|
|
|
def __lt__(self, cl):
|
|
|
|
h1 = self.handle.lower()
|
|
|
|
h2 = cl.handle.lower()
|
|
|
|
return (h1 < h2)
|
2011-01-21 05:18:22 -05:00
|
|
|
|
2011-02-02 19:32:35 -05:00
|
|
|
class chumArea(RightClickList):
|
2011-01-28 01:08:56 -05:00
|
|
|
def __init__(self, chums, parent=None):
|
2011-01-21 05:18:22 -05:00
|
|
|
QtGui.QListWidget.__init__(self, parent)
|
2011-01-28 03:59:03 -05:00
|
|
|
self.mainwindow = parent
|
|
|
|
theme = self.mainwindow.theme
|
2011-01-24 02:34:07 -05:00
|
|
|
geometry = theme["main/chums/loc"] + theme["main/chums/size"]
|
2011-01-22 04:36:24 -05:00
|
|
|
self.setGeometry(*geometry)
|
2011-01-24 02:34:07 -05:00
|
|
|
self.setStyleSheet(theme["main/chums/style"])
|
2011-01-21 05:18:22 -05:00
|
|
|
self.chums = chums
|
|
|
|
for c in self.chums:
|
2011-01-24 02:34:07 -05:00
|
|
|
chandle = c.handle
|
|
|
|
if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)):
|
2011-01-28 03:59:03 -05:00
|
|
|
chumLabel = chumListing(c, self.mainwindow)
|
2011-01-22 04:36:24 -05:00
|
|
|
self.addItem(chumLabel)
|
2011-01-29 06:31:41 -05:00
|
|
|
|
|
|
|
self.optionsMenu = QtGui.QMenu(self)
|
2011-02-01 06:14:56 -05:00
|
|
|
self.pester = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self)
|
|
|
|
self.connect(self.pester, QtCore.SIGNAL('triggered()'),
|
2011-01-29 06:31:41 -05:00
|
|
|
self, QtCore.SLOT('activateChum()'))
|
2011-02-01 06:14:56 -05:00
|
|
|
self.removechum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/removechum"], self)
|
|
|
|
self.connect(self.removechum, QtCore.SIGNAL('triggered()'),
|
2011-01-29 06:31:41 -05:00
|
|
|
self, QtCore.SLOT('removeChum()'))
|
2011-02-02 07:26:17 -05:00
|
|
|
self.blockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
|
|
|
|
self.connect(self.blockchum, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SLOT('blockChum()'))
|
2011-02-01 06:14:56 -05:00
|
|
|
self.optionsMenu.addAction(self.pester)
|
2011-02-02 07:26:17 -05:00
|
|
|
self.optionsMenu.addAction(self.blockchum)
|
2011-02-01 06:14:56 -05:00
|
|
|
self.optionsMenu.addAction(self.removechum)
|
2011-01-29 06:31:41 -05:00
|
|
|
|
2011-01-22 04:36:24 -05:00
|
|
|
self.sortItems()
|
2011-01-29 06:31:41 -05:00
|
|
|
def addChum(self, chum):
|
|
|
|
if len([c for c in self.chums if c.handle == chum.handle]) != 0:
|
|
|
|
return
|
|
|
|
self.chums.append(chum)
|
|
|
|
chumLabel = chumListing(chum, self.mainwindow)
|
|
|
|
self.addItem(chumLabel)
|
|
|
|
self.sortItems()
|
|
|
|
|
2011-02-02 07:26:17 -05:00
|
|
|
def getChums(self, handle):
|
2011-01-24 02:34:07 -05:00
|
|
|
chums = self.findItems(handle, QtCore.Qt.MatchFlags(0))
|
2011-02-02 07:26:17 -05:00
|
|
|
return chums
|
|
|
|
def updateMood(self, handle, mood):
|
|
|
|
chums = self.getChums(handle)
|
2011-01-22 04:36:24 -05:00
|
|
|
for c in chums:
|
|
|
|
c.setMood(mood)
|
2011-01-28 04:07:20 -05:00
|
|
|
def updateColor(self, handle, color):
|
|
|
|
chums = self.findItems(handle, QtCore.Qt.MatchFlags(0))
|
|
|
|
for c in chums:
|
|
|
|
c.setColor(color)
|
2011-01-28 06:17:42 -05:00
|
|
|
def changeTheme(self, theme):
|
|
|
|
self.setGeometry(*(theme["main/chums/loc"]+theme["main/chums/size"]))
|
|
|
|
self.setStyleSheet(theme["main/chums/style"])
|
2011-02-01 06:14:56 -05:00
|
|
|
self.pester.setText(theme["main/menus/rclickchumlist/pester"])
|
|
|
|
self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
|
2011-02-02 07:26:17 -05:00
|
|
|
self.blockchum.setText(theme["main/menus/rclickchumlist/blockchum"])
|
2011-02-01 06:14:56 -05:00
|
|
|
|
2011-01-29 06:31:41 -05:00
|
|
|
chumlistings = [self.item(i) for i in range(0, self.count())]
|
|
|
|
for c in chumlistings:
|
2011-01-28 06:17:42 -05:00
|
|
|
c.changeTheme(theme)
|
2011-01-29 06:31:41 -05:00
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def activateChum(self):
|
|
|
|
self.itemActivated.emit(self.currentItem())
|
|
|
|
@QtCore.pyqtSlot()
|
2011-02-02 19:06:03 -05:00
|
|
|
def removeChum(self, handle = None):
|
|
|
|
if handle:
|
|
|
|
clistings = self.getChums(handle)
|
|
|
|
for c in clistings:
|
|
|
|
self.setCurrentItem(c)
|
|
|
|
if not self.currentItem():
|
|
|
|
return
|
2011-01-29 06:31:41 -05:00
|
|
|
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())
|
|
|
|
del oldlist
|
2011-02-02 07:26:17 -05:00
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def blockChum(self):
|
|
|
|
currentChum = self.currentItem()
|
2011-02-02 19:06:03 -05:00
|
|
|
if not currentChum:
|
|
|
|
return
|
2011-02-02 07:26:17 -05:00
|
|
|
self.blockChumSignal.emit(self.currentItem().chum.handle)
|
2011-01-29 06:31:41 -05:00
|
|
|
|
|
|
|
removeChumSignal = QtCore.pyqtSignal(QtGui.QListWidgetItem)
|
2011-02-02 07:26:17 -05:00
|
|
|
blockChumSignal = QtCore.pyqtSignal(QtCore.QString)
|
2011-02-02 19:06:03 -05:00
|
|
|
|
|
|
|
class trollSlum(chumArea):
|
|
|
|
def __init__(self, trolls, mainwindow, parent=None):
|
|
|
|
QtGui.QListWidget.__init__(self, parent)
|
|
|
|
self.mainwindow = mainwindow
|
|
|
|
theme = self.mainwindow.theme
|
|
|
|
self.setStyleSheet(theme["main/trollslum/chumroll/style"])
|
|
|
|
self.chums = trolls
|
|
|
|
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)
|
|
|
|
|
2011-02-02 19:32:35 -05:00
|
|
|
self.optionsMenu = QtGui.QMenu(self)
|
2011-02-02 19:06:03 -05:00
|
|
|
self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
|
|
|
|
self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SIGNAL('unblockChumSignal()'))
|
2011-02-02 19:32:35 -05:00
|
|
|
self.optionsMenu.addAction(self.unblockchum)
|
2011-02-02 19:06:03 -05:00
|
|
|
|
|
|
|
self.sortItems()
|
|
|
|
def changeTheme(self, theme):
|
|
|
|
self.setStyleSheet(theme["main/trollslum/chumroll/style"])
|
|
|
|
self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
|
|
|
|
self.unblockchum.setText(theme["main/menus/rclickchumlist/blockchum"])
|
|
|
|
|
|
|
|
chumlistings = [self.item(i) for i in range(0, self.count())]
|
|
|
|
for c in chumlistings:
|
|
|
|
c.changeTheme(theme)
|
|
|
|
|
|
|
|
unblockChumSignal = QtCore.pyqtSignal(QtCore.QString)
|
|
|
|
|
|
|
|
class TrollSlumWindow(QtGui.QFrame):
|
|
|
|
def __init__(self, trolls, mainwindow, parent=None):
|
|
|
|
QtGui.QFrame.__init__(self, parent)
|
|
|
|
self.mainwindow = mainwindow
|
|
|
|
theme = self.mainwindow.theme
|
|
|
|
self.slumlabel = QtGui.QLabel(self)
|
|
|
|
self.initTheme(theme)
|
|
|
|
|
|
|
|
self.trollslum = trollSlum(trolls, self.mainwindow, self)
|
|
|
|
self.connect(self.trollslum, QtCore.SIGNAL('unblockChumSignal()'),
|
|
|
|
self, QtCore.SLOT('removeCurrentTroll()'))
|
|
|
|
layout_1 = QtGui.QHBoxLayout()
|
|
|
|
self.addButton = QtGui.QPushButton("ADD", self)
|
|
|
|
self.connect(self.addButton, QtCore.SIGNAL('clicked()'),
|
|
|
|
self, QtCore.SLOT('addTrollWindow()'))
|
|
|
|
self.removeButton = QtGui.QPushButton("REMOVE", self)
|
|
|
|
self.connect(self.removeButton, QtCore.SIGNAL('clicked()'),
|
|
|
|
self, QtCore.SLOT('removeCurrentTroll()'))
|
|
|
|
layout_1.addWidget(self.addButton)
|
|
|
|
layout_1.addWidget(self.removeButton)
|
|
|
|
|
|
|
|
layout_0 = QtGui.QVBoxLayout()
|
|
|
|
layout_0.addWidget(self.slumlabel)
|
|
|
|
layout_0.addWidget(self.trollslum)
|
|
|
|
layout_0.addLayout(layout_1)
|
|
|
|
self.setLayout(layout_0)
|
|
|
|
|
|
|
|
def initTheme(self, theme):
|
|
|
|
self.resize(*theme["main/trollslum/size"])
|
|
|
|
self.setStyleSheet(theme["main/trollslum/style"])
|
|
|
|
self.slumlabel.setText(theme["main/trollslum/label/text"])
|
|
|
|
self.slumlabel.setStyleSheet(theme["main/trollslum/label/style"])
|
|
|
|
if not self.parent():
|
|
|
|
self.setWindowTitle(theme["main/menus/profile/block"])
|
|
|
|
self.setWindowIcon(self.mainwindow.windowIcon())
|
|
|
|
def changeTheme(self, theme):
|
|
|
|
self.initTheme(theme)
|
|
|
|
self.trollslum.changeTheme(theme)
|
|
|
|
# move unblocked trolls from slum to chumarea
|
|
|
|
def closeEvent(self, event):
|
|
|
|
self.mainwindow.closeTrollSlum()
|
|
|
|
|
|
|
|
def updateMood(self, handle, mood):
|
|
|
|
self.trollslum.updateMood(handle, mood)
|
|
|
|
def addTroll(self, chum):
|
|
|
|
self.trollslum.addChum(chum)
|
|
|
|
def removeTroll(self, handle):
|
|
|
|
self.trollslum.removeChum(handle)
|
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def removeCurrentTroll(self):
|
|
|
|
currentListing = self.trollslum.currentItem()
|
|
|
|
if not currentListing:
|
|
|
|
return
|
|
|
|
self.unblockChumSignal.emit(currentListing.chum.handle)
|
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def addTrollWindow(self):
|
|
|
|
if not hasattr(self, 'addtrolldialog'):
|
|
|
|
self.addtrolldialog = None
|
|
|
|
if self.addtrolldialog:
|
|
|
|
return
|
|
|
|
self.addtrolldialog = QtGui.QInputDialog(self)
|
|
|
|
(handle, ok) = self.addtrolldialog.getText(self, "Add Troll", "Enter Troll Handle:")
|
|
|
|
if ok:
|
|
|
|
handle = unicode(handle)
|
|
|
|
if not (PesterProfile.checkLength(handle) and
|
|
|
|
PesterProfile.checkValid(handle)):
|
|
|
|
errormsg = QtGui.QErrorMessage(self)
|
|
|
|
errormsg.showMessage("THIS IS NOT A VALID CHUMTAG!")
|
|
|
|
self.addchumdialog = None
|
|
|
|
return
|
|
|
|
self.blockChumSignal.emit(handle)
|
|
|
|
self.addtrolldialog = None
|
|
|
|
|
|
|
|
blockChumSignal = QtCore.pyqtSignal(QtCore.QString)
|
2011-02-02 07:26:17 -05:00
|
|
|
unblockChumSignal = QtCore.pyqtSignal(QtCore.QString)
|
2011-01-21 05:18:22 -05:00
|
|
|
|
2011-01-28 21:36:12 -05:00
|
|
|
class PesterMoodHandler(QtCore.QObject):
|
|
|
|
def __init__(self, parent, *buttons):
|
|
|
|
QtCore.QObject.__init__(self)
|
|
|
|
self.buttons = {}
|
|
|
|
self.mainwindow = parent
|
|
|
|
for b in buttons:
|
|
|
|
self.buttons[b.mood.value()] = b
|
|
|
|
if b.mood.value() == self.mainwindow.profile().mood.value():
|
|
|
|
b.setSelected(True)
|
|
|
|
self.connect(b, QtCore.SIGNAL('clicked()'),
|
|
|
|
b, QtCore.SLOT('updateMood()'))
|
|
|
|
self.connect(b, QtCore.SIGNAL('moodUpdated(int)'),
|
|
|
|
self, QtCore.SLOT('updateMood(int)'))
|
|
|
|
def removeButtons(self):
|
|
|
|
for b in self.buttons.values():
|
|
|
|
b.close()
|
|
|
|
def showButtons(self):
|
|
|
|
for b in self.buttons.values():
|
|
|
|
b.show()
|
|
|
|
b.raise_()
|
|
|
|
@QtCore.pyqtSlot(int)
|
|
|
|
def updateMood(self, m):
|
|
|
|
oldmood = self.mainwindow.profile().mood
|
2011-02-03 01:20:37 -05:00
|
|
|
try:
|
|
|
|
oldbutton = self.buttons[oldmood.value()]
|
|
|
|
oldbutton.setSelected(False)
|
|
|
|
except KeyError:
|
|
|
|
pass
|
2011-01-28 21:36:12 -05:00
|
|
|
newbutton = self.buttons[m]
|
|
|
|
newbutton.setSelected(True)
|
|
|
|
newmood = Mood(m)
|
|
|
|
self.mainwindow.userprofile.chat.mood = newmood
|
|
|
|
self.mainwindow.moodUpdated.emit()
|
|
|
|
|
|
|
|
class PesterMoodButton(QtGui.QPushButton):
|
|
|
|
def __init__(self, parent, **options):
|
2011-02-02 03:20:48 -05:00
|
|
|
icon = PesterIcon(options["icon"])
|
2011-01-28 21:36:12 -05:00
|
|
|
QtGui.QPushButton.__init__(self, icon, options["text"], parent)
|
2011-02-02 03:20:48 -05:00
|
|
|
self.setIconSize(icon.realsize())
|
2011-01-28 21:36:12 -05:00
|
|
|
self.setFlat(True)
|
|
|
|
self.resize(*options["size"])
|
|
|
|
self.move(*options["loc"])
|
|
|
|
self.unselectedSheet = options["style"]
|
|
|
|
self.selectedSheet = options["selected"]
|
|
|
|
self.setStyleSheet(self.unselectedSheet)
|
|
|
|
self.mainwindow = parent
|
|
|
|
self.mood = Mood(options["mood"])
|
|
|
|
def setSelected(self, selected):
|
|
|
|
if selected:
|
|
|
|
self.setStyleSheet(self.selectedSheet)
|
|
|
|
else:
|
|
|
|
self.setStyleSheet(self.unselectedSheet)
|
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def updateMood(self):
|
|
|
|
self.moodUpdated.emit(self.mood.value())
|
|
|
|
moodUpdated = QtCore.pyqtSignal(int)
|
|
|
|
|
2011-02-02 03:20:48 -05:00
|
|
|
|
2011-01-22 04:36:24 -05:00
|
|
|
class MovingWindow(QtGui.QFrame):
|
|
|
|
def __init__(self, *x, **y):
|
|
|
|
QtGui.QFrame.__init__(self, *x, **y)
|
2011-01-21 05:18:22 -05:00
|
|
|
self.moving = None
|
2011-01-21 19:37:02 -05:00
|
|
|
self.moveupdate = 0
|
2011-01-21 05:18:22 -05:00
|
|
|
def mouseMoveEvent(self, event):
|
|
|
|
if self.moving:
|
|
|
|
move = event.globalPos() - self.moving
|
2011-01-21 19:37:02 -05:00
|
|
|
self.move(move)
|
|
|
|
self.moveupdate += 1
|
|
|
|
if self.moveupdate > 5:
|
|
|
|
self.moveupdate = 0
|
|
|
|
self.update()
|
2011-01-21 05:18:22 -05:00
|
|
|
def mousePressEvent(self, event):
|
|
|
|
if event.button() == 1:
|
2011-01-21 19:37:02 -05:00
|
|
|
self.moving = event.globalPos() - self.pos()
|
2011-01-21 05:18:22 -05:00
|
|
|
def mouseReleaseEvent(self, event):
|
|
|
|
if event.button() == 1:
|
2011-01-21 19:37:02 -05:00
|
|
|
self.update()
|
2011-01-21 05:18:22 -05:00
|
|
|
self.moving = None
|
2011-01-22 04:36:24 -05:00
|
|
|
|
2011-01-26 05:32:35 -05:00
|
|
|
class PesterTabWindow(QtGui.QFrame):
|
|
|
|
def __init__(self, mainwindow, parent=None):
|
|
|
|
QtGui.QFrame.__init__(self, parent)
|
2011-01-29 06:31:41 -05:00
|
|
|
self.setFocusPolicy(QtCore.Qt.ClickFocus)
|
2011-01-26 05:32:35 -05:00
|
|
|
self.mainwindow = mainwindow
|
2011-01-28 01:08:56 -05:00
|
|
|
self.resize(*self.mainwindow.theme["convo/size"])
|
|
|
|
self.setStyleSheet(self.mainwindow.theme["convo/style"])
|
2011-01-26 05:32:35 -05:00
|
|
|
|
|
|
|
self.tabs = QtGui.QTabBar(self)
|
2011-01-27 05:41:53 -05:00
|
|
|
self.tabs.setTabsClosable(True)
|
2011-01-26 05:32:35 -05:00
|
|
|
self.connect(self.tabs, QtCore.SIGNAL('currentChanged(int)'),
|
|
|
|
self, QtCore.SLOT('changeTab(int)'))
|
2011-01-27 05:41:53 -05:00
|
|
|
self.connect(self.tabs, QtCore.SIGNAL('tabCloseRequested(int)'),
|
|
|
|
self, QtCore.SLOT('tabClose(int)'))
|
2011-01-29 06:31:41 -05:00
|
|
|
self.tabs.setShape(self.mainwindow.theme["convo/tabs/tabstyle"])
|
2011-02-02 03:20:48 -05:00
|
|
|
self.tabs.setStyleSheet("QTabBar::tab{ %s } QTabBar::tab:selected { %s }" % (self.mainwindow.theme["convo/tabs/style"], self.mainwindow.theme["convo/tabs/selectedstyle"]))
|
2011-01-26 05:32:35 -05:00
|
|
|
|
|
|
|
self.layout = QtGui.QVBoxLayout()
|
|
|
|
self.layout.setContentsMargins(0,0,0,0)
|
|
|
|
self.layout.addWidget(self.tabs)
|
|
|
|
self.setLayout(self.layout)
|
|
|
|
self.convos = {}
|
|
|
|
self.tabIndices = {}
|
|
|
|
self.currentConvo = None
|
|
|
|
self.changedTab = False
|
2011-01-27 06:05:36 -05:00
|
|
|
self.softclose = False
|
2011-01-29 06:31:41 -05:00
|
|
|
|
|
|
|
# get default tab color i guess
|
|
|
|
self.defaultTabTextColor = self.getTabTextColor()
|
|
|
|
def getTabTextColor(self):
|
|
|
|
# ugly, ugly hack
|
|
|
|
self.changedTab = True
|
|
|
|
i = self.tabs.addTab(".")
|
|
|
|
c = self.tabs.tabTextColor(i)
|
|
|
|
self.tabs.removeTab(i)
|
|
|
|
self.changedTab = False
|
|
|
|
return c
|
2011-01-26 05:32:35 -05:00
|
|
|
def addChat(self, convo):
|
|
|
|
self.convos[convo.chum.handle] = convo
|
|
|
|
# either addTab or setCurrentIndex will trigger changed()
|
|
|
|
newindex = self.tabs.addTab(convo.chum.handle)
|
|
|
|
self.tabIndices[convo.chum.handle] = newindex
|
|
|
|
self.tabs.setCurrentIndex(newindex)
|
2011-01-28 01:08:56 -05:00
|
|
|
self.tabs.setTabIcon(newindex, convo.chum.mood.icon(self.mainwindow.theme))
|
2011-01-26 05:32:35 -05:00
|
|
|
def showChat(self, handle):
|
2011-01-29 06:31:41 -05:00
|
|
|
tabi = self.tabIndices[handle]
|
|
|
|
if self.tabs.currentIndex() == tabi:
|
|
|
|
self.activateWindow()
|
|
|
|
self.raise_()
|
|
|
|
self.convos[handle].raiseChat()
|
|
|
|
else:
|
|
|
|
self.tabs.setCurrentIndex(tabi)
|
|
|
|
|
|
|
|
def convoHasFocus(self, convo):
|
|
|
|
if ((self.hasFocus() or self.tabs.hasFocus()) and
|
|
|
|
self.tabs.tabText(self.tabs.currentIndex()) == convo.chum.handle):
|
|
|
|
return True
|
|
|
|
|
2011-01-26 05:32:35 -05:00
|
|
|
def keyPressEvent(self, event):
|
|
|
|
keypress = event.key()
|
|
|
|
mods = event.modifiers()
|
|
|
|
if ((mods & QtCore.Qt.ControlModifier) and
|
|
|
|
keypress == QtCore.Qt.Key_Tab):
|
|
|
|
nexti = (self.tabIndices[self.currentConvo.chum.handle] + 1) % self.tabs.count()
|
|
|
|
self.tabs.setCurrentIndex(nexti)
|
|
|
|
|
2011-01-27 06:05:36 -05:00
|
|
|
def closeSoft(self):
|
|
|
|
self.softclose = True
|
|
|
|
self.close()
|
2011-02-02 07:26:17 -05:00
|
|
|
def updateBlocked(self, handle):
|
2011-01-26 05:50:00 -05:00
|
|
|
i = self.tabIndices[handle]
|
2011-02-02 07:26:17 -05:00
|
|
|
icon = QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"])
|
|
|
|
self.tabs.setTabIcon(i, icon)
|
2011-01-28 04:09:51 -05:00
|
|
|
if self.tabs.currentIndex() == i:
|
2011-02-02 07:26:17 -05:00
|
|
|
self.setWindowIcon(icon)
|
|
|
|
def updateMood(self, handle, mood, unblocked=False):
|
|
|
|
i = self.tabIndices[handle]
|
2011-02-02 19:06:03 -05:00
|
|
|
if handle in self.mainwindow.config.getBlocklist() and not unblocked:
|
2011-02-02 07:26:17 -05:00
|
|
|
icon = QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"])
|
|
|
|
else:
|
|
|
|
icon = mood.icon(self.mainwindow.theme)
|
|
|
|
self.tabs.setTabIcon(i, icon)
|
|
|
|
if self.tabs.currentIndex() == i:
|
|
|
|
self.setWindowIcon(icon)
|
2011-01-27 05:41:53 -05:00
|
|
|
def closeEvent(self, event):
|
2011-01-27 06:05:36 -05:00
|
|
|
if not self.softclose:
|
|
|
|
while self.tabs.count() > 0:
|
|
|
|
self.tabClose(0)
|
2011-01-27 05:41:53 -05:00
|
|
|
self.windowClosed.emit()
|
2011-01-29 06:31:41 -05:00
|
|
|
def focusInEvent(self, event):
|
|
|
|
# make sure we're not switching tabs!
|
|
|
|
i = self.tabs.tabAt(self.mapFromGlobal(QtGui.QCursor.pos()))
|
|
|
|
if i == -1:
|
|
|
|
i = self.tabs.currentIndex()
|
|
|
|
handle = unicode(self.tabs.tabText(i))
|
|
|
|
self.clearNewMessage(handle)
|
|
|
|
def convoHasFocus(self, handle):
|
|
|
|
i = self.tabIndices[handle]
|
|
|
|
if (self.tabs.currentIndex() == i and
|
|
|
|
(self.hasFocus() or self.tabs.hasFocus())):
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def notifyNewMessage(self, handle):
|
|
|
|
i = self.tabIndices[handle]
|
|
|
|
self.tabs.setTabTextColor(i, QtGui.QColor(self.mainwindow.theme["convo/tabs/newmsgcolor"]))
|
|
|
|
convo = self.convos[handle]
|
|
|
|
def func():
|
|
|
|
convo.showChat()
|
|
|
|
self.mainwindow.waitingMessages.addMessage(handle, func)
|
|
|
|
# set system tray
|
|
|
|
def clearNewMessage(self, handle):
|
2011-02-03 01:20:37 -05:00
|
|
|
try:
|
|
|
|
i = self.tabIndices[handle]
|
|
|
|
except KeyError:
|
|
|
|
pass
|
2011-01-29 06:31:41 -05:00
|
|
|
self.tabs.setTabTextColor(i, self.defaultTabTextColor)
|
|
|
|
self.mainwindow.waitingMessages.messageAnswered(handle)
|
2011-01-28 06:17:42 -05:00
|
|
|
def changeTheme(self, theme):
|
|
|
|
self.resize(*theme["convo/size"])
|
|
|
|
self.setStyleSheet(theme["convo/style"])
|
2011-01-29 06:31:41 -05:00
|
|
|
self.tabs.setShape(theme["convo/tabs/tabstyle"])
|
|
|
|
self.tabs.setStyleSheet("QTabBar::tabs{ %s }" % (theme["convo/tabs/style"]))
|
2011-01-28 06:17:42 -05:00
|
|
|
for c in self.convos.values():
|
|
|
|
tabi = self.tabIndices[c.chum.handle]
|
|
|
|
self.tabs.setTabIcon(tabi, c.chum.mood.icon(theme))
|
2011-01-30 00:56:13 -05:00
|
|
|
currenttabi = self.tabs.currentIndex()
|
|
|
|
if currenttabi >= 0:
|
|
|
|
currentHandle = unicode(self.tabs.tabText(self.tabs.currentIndex()))
|
|
|
|
self.setWindowIcon(self.convos[currentHandle].chum.mood.icon(theme))
|
2011-01-29 06:31:41 -05:00
|
|
|
self.defaultTabTextColor = self.getTabTextColor()
|
2011-01-27 05:41:53 -05:00
|
|
|
|
|
|
|
@QtCore.pyqtSlot(int)
|
|
|
|
def tabClose(self, i):
|
|
|
|
handle = unicode(self.tabs.tabText(i))
|
2011-01-29 06:31:41 -05:00
|
|
|
self.mainwindow.waitingMessages.messageAnswered(handle)
|
2011-01-27 05:41:53 -05:00
|
|
|
convo = self.convos[handle]
|
|
|
|
del self.convos[handle]
|
|
|
|
del self.tabIndices[handle]
|
|
|
|
self.tabs.removeTab(i)
|
|
|
|
for (h, j) in self.tabIndices.iteritems():
|
|
|
|
if j > i:
|
|
|
|
self.tabIndices[h] = j-1
|
|
|
|
self.layout.removeWidget(convo)
|
|
|
|
convo.close()
|
|
|
|
if self.tabs.count() == 0:
|
|
|
|
self.close()
|
|
|
|
return
|
|
|
|
if self.currentConvo == convo:
|
|
|
|
currenti = self.tabs.currentIndex()
|
|
|
|
currenth = unicode(self.tabs.tabText(currenti))
|
|
|
|
self.currentConvo = self.convos[currenth]
|
|
|
|
self.currentConvo.raiseChat()
|
|
|
|
|
2011-01-26 05:32:35 -05:00
|
|
|
@QtCore.pyqtSlot(int)
|
|
|
|
def changeTab(self, i):
|
2011-01-27 05:41:53 -05:00
|
|
|
if i < 0:
|
|
|
|
return
|
2011-01-26 05:32:35 -05:00
|
|
|
if self.changedTab:
|
|
|
|
self.changedTab = False
|
|
|
|
return
|
|
|
|
handle = unicode(self.tabs.tabText(i))
|
|
|
|
convo = self.convos[handle]
|
|
|
|
if self.currentConvo:
|
|
|
|
self.layout.removeWidget(self.currentConvo)
|
|
|
|
self.currentConvo = convo
|
|
|
|
self.layout.addWidget(convo)
|
2011-01-28 01:08:56 -05:00
|
|
|
self.setWindowIcon(convo.chum.mood.icon(self.mainwindow.theme))
|
2011-01-27 17:16:14 -05:00
|
|
|
self.setWindowTitle(convo.chum.handle)
|
2011-01-26 05:50:00 -05:00
|
|
|
self.activateWindow()
|
|
|
|
self.raise_()
|
2011-01-26 05:32:35 -05:00
|
|
|
convo.raiseChat()
|
|
|
|
|
2011-01-27 05:41:53 -05:00
|
|
|
windowClosed = QtCore.pyqtSignal()
|
|
|
|
|
2011-01-24 02:34:07 -05:00
|
|
|
class PesterText(QtGui.QTextEdit):
|
|
|
|
def __init__(self, theme, parent=None):
|
|
|
|
QtGui.QTextEdit.__init__(self, parent)
|
|
|
|
self.setStyleSheet(theme["convo/textarea/style"])
|
|
|
|
self.setReadOnly(True)
|
|
|
|
def addMessage(self, text, chum):
|
2011-01-24 04:10:44 -05:00
|
|
|
color = chum.colorhtml()
|
2011-02-02 03:20:48 -05:00
|
|
|
systemColor = QtGui.QColor(self.parent().mainwindow.theme["convo/systemMsgColor"])
|
2011-01-24 02:34:07 -05:00
|
|
|
initials = chum.initials()
|
2011-01-28 03:10:00 -05:00
|
|
|
msg = unicode(text)
|
2011-02-02 07:26:17 -05:00
|
|
|
parent = self.parent()
|
|
|
|
window = parent.mainwindow
|
|
|
|
me = window.profile()
|
2011-01-28 03:10:00 -05:00
|
|
|
if msg == "PESTERCHUM:BEGIN":
|
2011-01-28 03:59:03 -05:00
|
|
|
parent.setChumOpen(True)
|
2011-02-02 07:26:17 -05:00
|
|
|
msg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
|
2011-02-03 03:51:22 -05:00
|
|
|
window.chatlog.log(chum.handle, convertTags(msg, "bbcode"))
|
|
|
|
self.append(convertTags(msg))
|
2011-01-28 03:59:03 -05:00
|
|
|
elif msg == "PESTERCHUM:CEASE":
|
|
|
|
parent.setChumOpen(False)
|
2011-02-02 07:26:17 -05:00
|
|
|
msg = chum.pestermsg(me, systemColor, window.theme["convo/text/ceasepester"])
|
2011-02-03 03:51:22 -05:00
|
|
|
window.chatlog.log(chum.handle, convertTags(msg, "bbcode"))
|
|
|
|
self.append(convertTags(msg))
|
2011-02-02 07:26:17 -05:00
|
|
|
elif msg == "PESTERCHUM:BLOCK":
|
|
|
|
msg = chum.pestermsg(me, systemColor, window.theme['convo/text/blocked'])
|
2011-02-03 03:51:22 -05:00
|
|
|
window.chatlog.log(chum.handle, convertTags(msg, "bbcode"))
|
|
|
|
self.append(convertTags(msg))
|
2011-02-02 07:26:17 -05:00
|
|
|
elif msg == "PESTERCHUM:UNBLOCK":
|
|
|
|
msg = chum.pestermsg(me, systemColor, window.theme['convo/text/unblocked'])
|
2011-02-03 03:51:22 -05:00
|
|
|
window.chatlog.log(chum.handle, convertTags(msg, "bbcode"))
|
|
|
|
self.append(convertTags(msg))
|
2011-01-28 03:10:00 -05:00
|
|
|
else:
|
2011-02-02 07:26:17 -05:00
|
|
|
if not parent.chumopen and chum is not me:
|
|
|
|
beginmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
|
|
|
|
parent.setChumOpen(True)
|
2011-02-03 03:51:22 -05:00
|
|
|
window.chatlog.log(chum.handle, convertTags(beginmsg, "bbcode"))
|
|
|
|
self.append(convertTags(beginmsg))
|
2011-02-02 07:26:17 -05:00
|
|
|
|
2011-02-02 03:20:48 -05:00
|
|
|
msg = "<c=%s>%s: %s</c>" % (color, initials, msg)
|
|
|
|
msg = escapeBrackets(msg)
|
2011-02-03 03:51:22 -05:00
|
|
|
self.append(convertTags(msg))
|
2011-02-02 07:26:17 -05:00
|
|
|
if chum is me:
|
2011-02-03 03:51:22 -05:00
|
|
|
window.chatlog.log(parent.chum.handle, convertTags(msg, "bbcode"))
|
2011-02-02 03:20:48 -05:00
|
|
|
else:
|
2011-02-03 03:51:22 -05:00
|
|
|
window.chatlog.log(chum.handle, convertTags(msg, "bbcode"))
|
2011-01-28 06:17:42 -05:00
|
|
|
def changeTheme(self, theme):
|
|
|
|
self.setStyleSheet(theme["convo/textarea/style"])
|
2011-02-02 07:26:17 -05:00
|
|
|
sb = self.verticalScrollBar()
|
|
|
|
sb.setMaximum(sb.maximum()+1000) # ugly hack but whatcha gonna do
|
|
|
|
sb.setValue(sb.maximum())
|
2011-01-29 06:31:41 -05:00
|
|
|
def focusInEvent(self, event):
|
|
|
|
self.parent().clearNewMessage()
|
|
|
|
QtGui.QTextEdit.focusInEvent(self, event)
|
2011-01-24 02:34:07 -05:00
|
|
|
|
2011-02-03 03:51:22 -05:00
|
|
|
def mousePressEvent(self, event):
|
|
|
|
url = self.anchorAt(event.pos())
|
|
|
|
if url == "":
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
QtGui.QDesktopServices.openUrl(QtCore.QUrl(url, QtCore.QUrl.TolerantMode))
|
|
|
|
|
2011-01-24 02:34:07 -05:00
|
|
|
class PesterInput(QtGui.QLineEdit):
|
|
|
|
def __init__(self, theme, parent=None):
|
|
|
|
QtGui.QLineEdit.__init__(self, parent)
|
|
|
|
self.setStyleSheet(theme["convo/input/style"])
|
2011-01-28 06:17:42 -05:00
|
|
|
def changeTheme(self, theme):
|
|
|
|
self.setStyleSheet(theme["convo/input/style"])
|
2011-01-29 06:31:41 -05:00
|
|
|
def focusInEvent(self, event):
|
|
|
|
self.parent().clearNewMessage()
|
|
|
|
QtGui.QLineEdit.focusInEvent(self, event)
|
2011-01-24 02:34:07 -05:00
|
|
|
|
|
|
|
class PesterConvo(QtGui.QFrame):
|
2011-01-24 04:10:44 -05:00
|
|
|
def __init__(self, chum, initiated, mainwindow, parent=None):
|
2011-01-24 02:34:07 -05:00
|
|
|
QtGui.QFrame.__init__(self, parent)
|
2011-01-29 06:31:41 -05:00
|
|
|
self.setFocusPolicy(QtCore.Qt.ClickFocus)
|
2011-01-24 04:10:44 -05:00
|
|
|
self.chum = chum
|
2011-01-24 02:34:07 -05:00
|
|
|
self.mainwindow = mainwindow
|
2011-01-28 01:08:56 -05:00
|
|
|
convo = self.mainwindow.theme["convo"]
|
2011-01-24 02:34:07 -05:00
|
|
|
self.resize(*convo["size"])
|
|
|
|
self.setStyleSheet(convo["style"])
|
2011-01-28 01:08:56 -05:00
|
|
|
self.setWindowIcon(chum.mood.icon(self.mainwindow.theme))
|
2011-01-24 04:10:44 -05:00
|
|
|
self.setWindowTitle(chum.handle)
|
2011-01-24 02:34:07 -05:00
|
|
|
|
2011-02-01 06:14:56 -05:00
|
|
|
t = Template(self.mainwindow.theme["convo/chumlabel/text"])
|
|
|
|
|
|
|
|
self.chumLabel = QtGui.QLabel(t.safe_substitute(handle=chum.handle), self)
|
2011-01-28 01:08:56 -05:00
|
|
|
self.chumLabel.setStyleSheet(self.mainwindow.theme["convo/chumlabel/style"])
|
2011-02-02 03:20:48 -05:00
|
|
|
self.chumLabel.setAlignment(self.aligndict["h"][self.mainwindow.theme["convo/chumlabel/align/h"]] | self.aligndict["v"][self.mainwindow.theme["convo/chumlabel/align/v"]])
|
|
|
|
self.chumLabel.setMaximumHeight(self.mainwindow.theme["convo/chumlabel/maxheight"])
|
|
|
|
self.chumLabel.setMinimumHeight(self.mainwindow.theme["convo/chumlabel/minheight"])
|
|
|
|
self.chumLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding))
|
2011-01-28 01:08:56 -05:00
|
|
|
self.textArea = PesterText(self.mainwindow.theme, self)
|
|
|
|
self.textInput = PesterInput(self.mainwindow.theme, self)
|
2011-01-24 04:10:44 -05:00
|
|
|
self.textInput.setFocus()
|
2011-01-24 02:34:07 -05:00
|
|
|
|
|
|
|
self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
|
|
|
|
self, QtCore.SLOT('sentMessage()'))
|
|
|
|
|
|
|
|
self.layout = QtGui.QVBoxLayout()
|
|
|
|
self.layout.addWidget(self.chumLabel)
|
|
|
|
self.layout.addWidget(self.textArea)
|
|
|
|
self.layout.addWidget(self.textInput)
|
2011-02-02 03:20:48 -05:00
|
|
|
self.layout.setSpacing(0)
|
2011-02-03 04:08:28 -05:00
|
|
|
self.layout.setMargin(0)
|
2011-02-02 03:20:48 -05:00
|
|
|
|
2011-01-24 02:34:07 -05:00
|
|
|
self.setLayout(self.layout)
|
2011-01-28 03:59:03 -05:00
|
|
|
|
|
|
|
self.chumopen = False
|
2011-01-24 02:34:07 -05:00
|
|
|
|
2011-01-26 05:32:35 -05:00
|
|
|
if parent:
|
|
|
|
parent.addChat(self)
|
2011-01-28 03:10:00 -05:00
|
|
|
if initiated:
|
2011-02-02 07:26:17 -05:00
|
|
|
msg = self.mainwindow.profile().pestermsg(self.chum, QtGui.QColor(self.mainwindow.theme["convo/systemMsgColor"]), self.mainwindow.theme["convo/text/beganpester"])
|
2011-02-03 01:20:37 -05:00
|
|
|
self.setChumOpen(True)
|
2011-02-03 03:51:22 -05:00
|
|
|
self.textArea.append(convertTags(msg))
|
|
|
|
self.mainwindow.chatlog.log(self.chum.handle, convertTags(msg, "bbcode"))
|
2011-01-29 06:31:41 -05:00
|
|
|
self.newmessage = False
|
2011-01-26 05:32:35 -05:00
|
|
|
|
2011-02-02 07:26:17 -05:00
|
|
|
def updateMood(self, mood, unblocked=False):
|
2011-02-02 19:06:03 -05:00
|
|
|
if mood.name() == "offline" and self.chumopen == True and not unblocked:
|
2011-02-02 07:26:17 -05:00
|
|
|
msg = self.chum.pestermsg(self.mainwindow.profile(), QtGui.QColor(self.mainwindow.theme["convo/systemMsgColor"]), self.mainwindow.theme["convo/text/ceasepester"])
|
2011-02-03 03:51:22 -05:00
|
|
|
self.textArea.append(convertTags(msg))
|
|
|
|
self.mainwindow.chatlog.log(self.chum.handle, convertTags(msg, "bbcode"))
|
2011-01-28 21:36:12 -05:00
|
|
|
self.chumopen = False
|
2011-01-26 05:50:00 -05:00
|
|
|
if self.parent():
|
2011-02-02 07:26:17 -05:00
|
|
|
self.parent().updateMood(self.chum.handle, mood, unblocked)
|
2011-01-26 05:50:00 -05:00
|
|
|
else:
|
2011-02-03 04:08:28 -05:00
|
|
|
if self.chum.blocked(self.mainwindow.config) and not unblocked:
|
2011-02-02 07:26:17 -05:00
|
|
|
self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
|
|
|
|
else:
|
|
|
|
self.setWindowIcon(mood.icon(self.mainwindow.theme))
|
2011-01-24 02:34:07 -05:00
|
|
|
# print mood update?
|
2011-02-02 07:26:17 -05:00
|
|
|
def updateBlocked(self):
|
|
|
|
if self.parent():
|
|
|
|
self.parent().updateBlocked(self.chum.handle)
|
|
|
|
else:
|
|
|
|
self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
|
2011-01-28 04:07:20 -05:00
|
|
|
def updateColor(self, color):
|
|
|
|
self.chum.color = color
|
2011-01-24 04:10:44 -05:00
|
|
|
def addMessage(self, text, me=True):
|
|
|
|
if me:
|
2011-01-28 21:36:12 -05:00
|
|
|
chum = self.mainwindow.profile()
|
2011-01-24 04:10:44 -05:00
|
|
|
else:
|
|
|
|
chum = self.chum
|
2011-01-29 06:31:41 -05:00
|
|
|
self.notifyNewMessage()
|
2011-01-24 02:34:07 -05:00
|
|
|
self.textArea.addMessage(text, chum)
|
2011-01-29 06:31:41 -05:00
|
|
|
|
|
|
|
def notifyNewMessage(self):
|
|
|
|
# first see if this conversation HASS the focus
|
|
|
|
if not (self.hasFocus() or self.textArea.hasFocus() or
|
|
|
|
self.textInput.hasFocus() or
|
|
|
|
(self.parent() and self.parent().convoHasFocus(self.chum.handle))):
|
|
|
|
# ok if it has a tabconvo parent, send that the notify.
|
|
|
|
if self.parent():
|
|
|
|
self.parent().notifyNewMessage(self.chum.handle)
|
|
|
|
# if not change the window title and update system tray
|
|
|
|
else:
|
|
|
|
self.newmessage = True
|
|
|
|
self.setWindowTitle(self.chum.handle+"*")
|
|
|
|
def func():
|
|
|
|
self.showChat()
|
|
|
|
self.mainwindow.waitingMessages.addMessage(self.chum.handle, func)
|
|
|
|
|
|
|
|
def clearNewMessage(self):
|
|
|
|
if self.parent():
|
|
|
|
self.parent().clearNewMessage(self.chum.handle)
|
|
|
|
elif self.newmessage:
|
|
|
|
self.newmessage = False
|
|
|
|
self.setWindowTitle(self.chum.handle)
|
|
|
|
self.mainwindow.waitingMessages.messageAnswered(self.chum.handle)
|
|
|
|
# reset system tray
|
|
|
|
def focusInEvent(self, event):
|
|
|
|
self.clearNewMessage()
|
2011-02-02 03:20:48 -05:00
|
|
|
self.textInput.setFocus()
|
2011-01-26 05:32:35 -05:00
|
|
|
def raiseChat(self):
|
2011-01-24 13:02:00 -05:00
|
|
|
self.activateWindow()
|
|
|
|
self.raise_()
|
|
|
|
self.textInput.setFocus()
|
2011-01-24 02:34:07 -05:00
|
|
|
|
2011-01-26 05:32:35 -05:00
|
|
|
def showChat(self):
|
|
|
|
if self.parent():
|
|
|
|
self.parent().showChat(self.chum.handle)
|
|
|
|
self.raiseChat()
|
|
|
|
|
|
|
|
def closeEvent(self, event):
|
2011-01-29 06:31:41 -05:00
|
|
|
self.mainwindow.waitingMessages.messageAnswered(self.chum.handle)
|
2011-01-26 05:32:35 -05:00
|
|
|
self.windowClosed.emit(self.chum.handle)
|
2011-01-28 03:59:03 -05:00
|
|
|
def setChumOpen(self, o):
|
|
|
|
self.chumopen = o
|
2011-01-28 06:17:42 -05:00
|
|
|
def changeTheme(self, theme):
|
|
|
|
self.resize(*theme["convo/size"])
|
|
|
|
self.setStyleSheet(theme["convo/style"])
|
|
|
|
self.setWindowIcon(self.chum.mood.icon(theme))
|
2011-02-01 06:14:56 -05:00
|
|
|
t = Template(self.mainwindow.theme["convo/chumlabel/text"])
|
|
|
|
self.chumLabel.setText(t.safe_substitute(handle=self.chum.handle))
|
2011-01-28 06:17:42 -05:00
|
|
|
self.chumLabel.setStyleSheet(theme["convo/chumlabel/style"])
|
2011-02-02 03:20:48 -05:00
|
|
|
self.chumLabel.setAlignment(self.aligndict["h"][self.mainwindow.theme["convo/chumlabel/align/h"]] | self.aligndict["v"][self.mainwindow.theme["convo/chumlabel/align/v"]])
|
|
|
|
self.chumLabel.setMaximumHeight(self.mainwindow.theme["convo/chumlabel/maxheight"])
|
|
|
|
self.chumLabel.setMinimumHeight(self.mainwindow.theme["convo/chumlabel/minheight"])
|
|
|
|
self.chumLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding))
|
2011-01-28 06:17:42 -05:00
|
|
|
self.textArea.changeTheme(theme)
|
|
|
|
self.textInput.changeTheme(theme)
|
2011-01-26 05:32:35 -05:00
|
|
|
|
2011-01-24 02:34:07 -05:00
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def sentMessage(self):
|
|
|
|
text = self.textInput.text()
|
2011-01-29 06:31:41 -05:00
|
|
|
if text == "":
|
|
|
|
return
|
2011-01-24 02:34:07 -05:00
|
|
|
# deal with quirks here
|
2011-01-29 16:55:35 -05:00
|
|
|
qtext = self.mainwindow.userprofile.quirks.apply(unicode(text))
|
|
|
|
text = QtCore.QString(qtext)
|
2011-01-24 02:34:07 -05:00
|
|
|
self.textInput.setText("")
|
2011-01-24 04:10:44 -05:00
|
|
|
self.addMessage(text, True)
|
2011-01-28 03:59:03 -05:00
|
|
|
# if ceased, rebegin
|
|
|
|
if not self.chumopen:
|
|
|
|
self.mainwindow.newConvoStarted.emit(QtCore.QString(self.chum.handle), True)
|
2011-02-03 03:51:22 -05:00
|
|
|
# convert color tags
|
|
|
|
text = convertTags(unicode(text), "ctag")
|
2011-01-24 04:10:44 -05:00
|
|
|
self.messageSent.emit(text, self.chum)
|
2011-01-24 02:34:07 -05:00
|
|
|
|
2011-01-24 04:10:44 -05:00
|
|
|
messageSent = QtCore.pyqtSignal(QtCore.QString, PesterProfile)
|
2011-01-26 05:32:35 -05:00
|
|
|
windowClosed = QtCore.pyqtSignal(QtCore.QString)
|
2011-01-24 02:34:07 -05:00
|
|
|
|
2011-02-02 03:20:48 -05:00
|
|
|
aligndict = {"h": {"center": QtCore.Qt.AlignHCenter,
|
|
|
|
"left": QtCore.Qt.AlignLeft,
|
|
|
|
"right": QtCore.Qt.AlignRight },
|
|
|
|
"v": {"center": QtCore.Qt.AlignVCenter,
|
|
|
|
"top": QtCore.Qt.AlignTop,
|
|
|
|
"bottom": QtCore.Qt.AlignBottom } }
|
|
|
|
|
2011-01-22 04:36:24 -05:00
|
|
|
class PesterWindow(MovingWindow):
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
MovingWindow.__init__(self, parent,
|
2011-02-02 03:20:48 -05:00
|
|
|
flags=(QtCore.Qt.CustomizeWindowHint |
|
|
|
|
QtCore.Qt.FramelessWindowHint))
|
2011-01-31 06:04:03 -05:00
|
|
|
|
|
|
|
self.convos = {}
|
|
|
|
self.tabconvo = None
|
|
|
|
|
2011-01-22 04:36:24 -05:00
|
|
|
self.setObjectName("main")
|
|
|
|
self.config = userConfig()
|
2011-01-28 01:08:56 -05:00
|
|
|
if self.config.defaultprofile():
|
|
|
|
self.userprofile = userProfile(self.config.defaultprofile())
|
|
|
|
self.theme = self.userprofile.getTheme()
|
|
|
|
else:
|
|
|
|
self.userprofile = userProfile(PesterProfile("pesterClient%d" % (random.randint(100,999)), QtGui.QColor("black"), Mood(0)))
|
|
|
|
self.theme = self.userprofile.getTheme()
|
|
|
|
|
2011-02-02 03:20:48 -05:00
|
|
|
self.chatlog = PesterLog(self.profile().handle)
|
|
|
|
|
2011-01-31 06:04:03 -05:00
|
|
|
self.move(100, 100)
|
2011-01-22 04:36:24 -05:00
|
|
|
|
2011-02-01 06:14:56 -05:00
|
|
|
opts = QtGui.QAction(self.theme["main/menus/client/options"], self)
|
|
|
|
self.opts = opts
|
2011-01-27 04:46:47 -05:00
|
|
|
self.connect(opts, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SLOT('openOpts()'))
|
2011-02-01 06:14:56 -05:00
|
|
|
exitaction = QtGui.QAction(self.theme["main/menus/client/exit"], self)
|
|
|
|
self.exitaction = exitaction
|
2011-01-27 04:46:47 -05:00
|
|
|
self.connect(exitaction, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SLOT('close()'))
|
2011-02-03 01:20:37 -05:00
|
|
|
userlistaction = QtGui.QAction(self.theme["main/menus/client/userlist"], self)
|
|
|
|
self.userlistaction = userlistaction
|
|
|
|
self.connect(userlistaction, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SLOT('showAllUsers()'))
|
2011-01-27 04:46:47 -05:00
|
|
|
self.menu = QtGui.QMenuBar(self)
|
2011-02-03 01:20:37 -05:00
|
|
|
|
2011-02-01 06:14:56 -05:00
|
|
|
filemenu = self.menu.addMenu(self.theme["main/menus/client/_name"])
|
|
|
|
self.filemenu = filemenu
|
2011-01-27 04:46:47 -05:00
|
|
|
filemenu.addAction(opts)
|
2011-02-03 01:20:37 -05:00
|
|
|
filemenu.addAction(userlistaction)
|
2011-01-27 04:46:47 -05:00
|
|
|
filemenu.addAction(exitaction)
|
2011-01-28 01:41:01 -05:00
|
|
|
|
2011-02-01 06:14:56 -05:00
|
|
|
changetheme = QtGui.QAction(self.theme["main/menus/profile/theme"], self)
|
|
|
|
self.changetheme = changetheme
|
2011-01-28 06:17:42 -05:00
|
|
|
self.connect(changetheme, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SLOT('pickTheme()'))
|
2011-02-01 06:14:56 -05:00
|
|
|
changequirks = QtGui.QAction(self.theme["main/menus/profile/quirks"], self)
|
|
|
|
self.changequirks = changequirks
|
2011-01-29 16:55:35 -05:00
|
|
|
self.connect(changequirks, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SLOT('openQuirks()'))
|
2011-02-02 19:06:03 -05:00
|
|
|
loadslum = QtGui.QAction(self.theme["main/menus/profile/block"], self)
|
|
|
|
self.loadslum = loadslum
|
|
|
|
self.connect(loadslum, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SLOT('showTrollSlum()'))
|
2011-01-29 16:55:35 -05:00
|
|
|
|
2011-02-02 07:26:17 -05:00
|
|
|
changecoloraction = QtGui.QAction(self.theme["main/menus/profile/color"], self)
|
|
|
|
self.changecoloraction = changecoloraction
|
|
|
|
self.connect(changecoloraction, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SLOT('changeMyColor()'))
|
|
|
|
|
2011-02-01 06:14:56 -05:00
|
|
|
switch = QtGui.QAction(self.theme["main/menus/profile/switch"], self)
|
|
|
|
self.switch = switch
|
|
|
|
self.connect(switch, QtCore.SIGNAL('triggered()'),
|
|
|
|
self, QtCore.SLOT('switchProfile()'))
|
|
|
|
|
|
|
|
profilemenu = self.menu.addMenu(self.theme["main/menus/profile/_name"])
|
|
|
|
self.profilemenu = profilemenu
|
2011-01-28 06:17:42 -05:00
|
|
|
profilemenu.addAction(changetheme)
|
2011-01-29 16:55:35 -05:00
|
|
|
profilemenu.addAction(changequirks)
|
2011-02-02 19:06:03 -05:00
|
|
|
profilemenu.addAction(loadslum)
|
2011-02-02 07:26:17 -05:00
|
|
|
profilemenu.addAction(changecoloraction)
|
2011-01-29 16:55:35 -05:00
|
|
|
profilemenu.addAction(switch)
|
2011-01-28 01:41:01 -05:00
|
|
|
|
2011-02-02 03:20:48 -05:00
|
|
|
self.closeButton = WMButton(PesterIcon(self.theme["main/close/image"]), self)
|
2011-01-22 04:36:24 -05:00
|
|
|
self.connect(self.closeButton, QtCore.SIGNAL('clicked()'),
|
|
|
|
self, QtCore.SLOT('close()'))
|
2011-02-02 03:20:48 -05:00
|
|
|
self.miniButton = WMButton(PesterIcon(self.theme["main/minimize/image"]), self)
|
2011-01-27 04:46:47 -05:00
|
|
|
self.connect(self.miniButton, QtCore.SIGNAL('clicked()'),
|
|
|
|
self, QtCore.SLOT('showMinimized()'))
|
|
|
|
|
2011-02-03 01:20:37 -05:00
|
|
|
self.namesdb = {}
|
2011-01-31 18:43:49 -05:00
|
|
|
self.chumdb = PesterProfileDB()
|
|
|
|
|
2011-02-01 06:14:56 -05:00
|
|
|
chums = [PesterProfile(c, chumdb=self.chumdb) for c in set(self.config.chums())]
|
2011-01-28 01:08:56 -05:00
|
|
|
self.chumList = chumArea(chums, self)
|
2011-01-29 06:31:41 -05:00
|
|
|
self.connect(self.chumList,
|
|
|
|
QtCore.SIGNAL('itemActivated(QListWidgetItem *)'),
|
|
|
|
self,
|
|
|
|
QtCore.SLOT('newConversationWindow(QListWidgetItem *)'))
|
|
|
|
self.connect(self.chumList,
|
|
|
|
QtCore.SIGNAL('removeChumSignal(QListWidgetItem *)'),
|
|
|
|
self,
|
|
|
|
QtCore.SLOT('removeChum(QListWidgetItem *)'))
|
2011-02-02 07:26:17 -05:00
|
|
|
self.connect(self.chumList,
|
|
|
|
QtCore.SIGNAL('blockChumSignal(QString)'),
|
|
|
|
self,
|
|
|
|
QtCore.SLOT('blockChum(QString)'))
|
2011-01-29 06:31:41 -05:00
|
|
|
|
|
|
|
self.addChumButton = QtGui.QPushButton(self.theme["main/addchum/text"], self)
|
|
|
|
self.connect(self.addChumButton, QtCore.SIGNAL('clicked()'),
|
|
|
|
self, QtCore.SLOT('addChumWindow()'))
|
2011-01-29 07:33:35 -05:00
|
|
|
self.pesterButton = QtGui.QPushButton(self.theme["main/pester/text"], self)
|
|
|
|
self.connect(self.pesterButton, QtCore.SIGNAL('clicked()'),
|
|
|
|
self, QtCore.SLOT('pesterSelectedChum()'))
|
2011-02-02 07:26:17 -05:00
|
|
|
self.blockButton = QtGui.QPushButton(self.theme["main/block/text"], self)
|
|
|
|
self.connect(self.blockButton, QtCore.SIGNAL('clicked()'),
|
|
|
|
self, QtCore.SLOT('blockSelectedChum()'))
|
2011-01-29 07:33:35 -05:00
|
|
|
|
2011-01-31 18:43:49 -05:00
|
|
|
self.moodsLabel = QtGui.QLabel(self.theme["main/moodlabel/text"], self)
|
|
|
|
|
2011-01-29 07:33:35 -05:00
|
|
|
self.mychumhandleLabel = QtGui.QLabel(self.theme["main/mychumhandle/label/text"], self)
|
|
|
|
self.mychumhandle = QtGui.QPushButton(self.profile().handle, self)
|
|
|
|
self.mychumhandle.setFlat(True)
|
|
|
|
self.connect(self.mychumhandle, QtCore.SIGNAL('clicked()'),
|
|
|
|
self, QtCore.SLOT('switchProfile()'))
|
|
|
|
|
|
|
|
self.mychumcolor = QtGui.QPushButton(self)
|
|
|
|
self.connect(self.mychumcolor, QtCore.SIGNAL('clicked()'),
|
|
|
|
self, QtCore.SLOT('changeMyColor()'))
|
2011-01-29 06:31:41 -05:00
|
|
|
|
2011-01-31 06:04:03 -05:00
|
|
|
self.initTheme(self.theme)
|
|
|
|
|
2011-01-29 06:31:41 -05:00
|
|
|
self.waitingMessages = waitingMessageHolder(self)
|
2011-01-31 06:04:03 -05:00
|
|
|
|
|
|
|
if not self.config.defaultprofile():
|
|
|
|
self.changeProfile()
|
2011-01-29 06:31:41 -05:00
|
|
|
|
2011-01-28 21:36:12 -05:00
|
|
|
def profile(self):
|
|
|
|
return self.userprofile.chat
|
2011-01-28 01:41:01 -05:00
|
|
|
def closeConversations(self):
|
2011-01-31 06:04:03 -05:00
|
|
|
if not hasattr(self, 'tabconvo'):
|
|
|
|
self.tabconvo = None
|
2011-01-26 05:32:35 -05:00
|
|
|
if self.tabconvo:
|
|
|
|
self.tabconvo.close()
|
2011-01-27 17:16:14 -05:00
|
|
|
else:
|
|
|
|
for c in self.convos.values():
|
|
|
|
c.close()
|
2011-01-28 01:41:01 -05:00
|
|
|
def closeEvent(self, event):
|
|
|
|
self.closeConversations()
|
2011-02-02 19:06:03 -05:00
|
|
|
if hasattr(self, 'trollslum') and self.trollslum:
|
|
|
|
self.trollslum.close()
|
2011-01-24 02:34:07 -05:00
|
|
|
event.accept()
|
|
|
|
def newMessage(self, handle, msg):
|
2011-02-02 19:06:03 -05:00
|
|
|
if handle in self.config.getBlocklist():
|
2011-02-02 07:26:17 -05:00
|
|
|
#yeah suck on this
|
|
|
|
return
|
2011-01-24 04:10:44 -05:00
|
|
|
if not self.convos.has_key(handle):
|
2011-01-28 03:59:03 -05:00
|
|
|
if msg == "PESTERCHUM:CEASE": # ignore cease after we hang up
|
|
|
|
return
|
2011-01-28 03:10:00 -05:00
|
|
|
matchingChums = [c for c in self.chumList.chums if c.handle == handle]
|
|
|
|
if len(matchingChums) > 0:
|
|
|
|
mood = matchingChums[0].mood
|
|
|
|
else:
|
|
|
|
mood = Mood(0)
|
2011-02-01 06:14:56 -05:00
|
|
|
chum = PesterProfile(handle, mood=mood, chumdb=self.chumdb)
|
2011-01-24 04:10:44 -05:00
|
|
|
self.newConversation(chum, False)
|
2011-01-28 03:10:00 -05:00
|
|
|
if len(matchingChums) == 0:
|
|
|
|
self.moodRequest.emit(chum)
|
2011-01-24 04:10:44 -05:00
|
|
|
convo = self.convos[handle]
|
|
|
|
convo.addMessage(msg, False)
|
|
|
|
# play sound here
|
2011-01-29 06:31:41 -05:00
|
|
|
self.alarm.play()
|
2011-01-24 04:10:44 -05:00
|
|
|
|
|
|
|
def changeColor(self, handle, color):
|
2011-01-28 04:07:20 -05:00
|
|
|
# pesterconvo and chumlist
|
|
|
|
self.chumList.updateColor(handle, color)
|
|
|
|
if self.convos.has_key(handle):
|
|
|
|
self.convos[handle].updateColor(color)
|
2011-01-31 18:43:49 -05:00
|
|
|
self.chumdb.setColor(handle, color)
|
2011-01-24 02:34:07 -05:00
|
|
|
|
|
|
|
def updateMood(self, handle, mood):
|
|
|
|
self.chumList.updateMood(handle, mood)
|
|
|
|
if self.convos.has_key(handle):
|
|
|
|
self.convos[handle].updateMood(mood)
|
2011-02-02 19:06:03 -05:00
|
|
|
if hasattr(self, 'trollslum') and self.trollslum:
|
|
|
|
self.trollslum.updateMood(handle, mood)
|
2011-01-24 02:34:07 -05:00
|
|
|
def newConversation(self, chum, initiated=True):
|
2011-01-24 13:02:00 -05:00
|
|
|
if self.convos.has_key(chum.handle):
|
|
|
|
self.convos[chum.handle].showChat()
|
|
|
|
return
|
2011-01-26 05:50:00 -05:00
|
|
|
if self.config.tabs():
|
2011-01-26 05:32:35 -05:00
|
|
|
if not self.tabconvo:
|
2011-01-27 17:16:14 -05:00
|
|
|
self.createTabWindow()
|
2011-01-26 05:32:35 -05:00
|
|
|
convoWindow = PesterConvo(chum, initiated, self, self.tabconvo)
|
|
|
|
self.tabconvo.show()
|
|
|
|
else:
|
|
|
|
convoWindow = PesterConvo(chum, initiated, self)
|
2011-01-24 02:34:07 -05:00
|
|
|
self.connect(convoWindow, QtCore.SIGNAL('messageSent(QString, PyQt_PyObject)'),
|
|
|
|
self, QtCore.SIGNAL('sendMessage(QString, PyQt_PyObject)'))
|
2011-01-27 04:46:47 -05:00
|
|
|
self.connect(convoWindow, QtCore.SIGNAL('windowClosed(QString)'),
|
|
|
|
self, QtCore.SLOT('closeConvo(QString)'))
|
2011-01-24 02:34:07 -05:00
|
|
|
self.convos[chum.handle] = convoWindow
|
2011-01-24 04:10:44 -05:00
|
|
|
self.newConvoStarted.emit(QtCore.QString(chum.handle), initiated)
|
2011-01-24 02:34:07 -05:00
|
|
|
convoWindow.show()
|
2011-01-27 17:16:14 -05:00
|
|
|
def createTabWindow(self):
|
|
|
|
self.tabconvo = PesterTabWindow(self)
|
|
|
|
self.connect(self.tabconvo, QtCore.SIGNAL('windowClosed()'),
|
|
|
|
self, QtCore.SLOT('tabsClosed()'))
|
2011-01-22 04:36:24 -05:00
|
|
|
|
2011-01-28 01:08:56 -05:00
|
|
|
def changeProfile(self, collision=None):
|
2011-01-31 06:04:03 -05:00
|
|
|
if not hasattr(self, 'chooseprofile'):
|
|
|
|
self.chooseprofile = None
|
2011-01-29 06:31:41 -05:00
|
|
|
if not self.chooseprofile:
|
|
|
|
self.chooseprofile = PesterChooseProfile(self.userprofile, self.config, self.theme, self, collision=collision)
|
|
|
|
self.chooseprofile.exec_()
|
2011-01-28 01:08:56 -05:00
|
|
|
|
2011-01-28 06:17:42 -05:00
|
|
|
def themePicker(self):
|
2011-01-31 06:04:03 -05:00
|
|
|
if not hasattr(self, 'choosetheme'):
|
|
|
|
self.choosetheme = None
|
2011-01-29 06:31:41 -05:00
|
|
|
if not self.choosetheme:
|
|
|
|
self.choosetheme = PesterChooseTheme(self.config, self.theme, self)
|
|
|
|
self.choosetheme.exec_()
|
2011-01-31 06:04:03 -05:00
|
|
|
def initTheme(self, theme):
|
|
|
|
self.resize(*theme["main/size"])
|
2011-02-02 03:20:48 -05:00
|
|
|
self.setWindowIcon(PesterIcon(theme["main/icon"]))
|
2011-01-31 06:04:03 -05:00
|
|
|
self.setWindowTitle(theme["main/windowtitle"])
|
|
|
|
self.setStyleSheet("QFrame#main { "+theme["main/style"]+" }")
|
2011-02-01 06:14:56 -05:00
|
|
|
self.menu.setStyleSheet("QMenuBar { background: transparent; %s } QMenuBar::item { background: transparent; %s } " % (theme["main/menubar/style"], theme["main/menu/menuitem"]) + "QMenu { background: transparent; %s } QMenu::item::selected { %s }" % (theme["main/menu/style"], theme["main/menu/selected"]))
|
2011-02-02 03:20:48 -05:00
|
|
|
newcloseicon = PesterIcon(theme["main/close/image"])
|
|
|
|
self.closeButton.setIcon(newcloseicon)
|
|
|
|
self.closeButton.setIconSize(newcloseicon.realsize())
|
2011-01-31 06:04:03 -05:00
|
|
|
self.closeButton.move(*theme["main/close/loc"])
|
2011-02-02 03:20:48 -05:00
|
|
|
newminiicon = PesterIcon(theme["main/minimize/image"])
|
|
|
|
self.miniButton.setIcon(newminiicon)
|
|
|
|
self.miniButton.setIconSize(newminiicon.realsize())
|
2011-01-31 06:04:03 -05:00
|
|
|
self.miniButton.move(*theme["main/minimize/loc"])
|
2011-02-01 06:14:56 -05:00
|
|
|
# menus
|
|
|
|
self.menu.move(*theme["main/menu/loc"])
|
|
|
|
self.opts.setText(theme["main/menus/client/options"])
|
|
|
|
self.exitaction.setText(theme["main/menus/client/exit"])
|
2011-02-03 01:20:37 -05:00
|
|
|
self.userlistaction.setText(theme["main/menus/client/userlist"])
|
2011-02-01 06:14:56 -05:00
|
|
|
self.filemenu.setTitle(theme["main/menus/client/_name"])
|
|
|
|
self.changetheme.setText(theme["main/menus/profile/theme"])
|
|
|
|
self.changequirks.setText(theme["main/menus/profile/quirks"])
|
2011-02-03 01:20:37 -05:00
|
|
|
self.loadslum.setText(theme["main/menus/profile/block"])
|
2011-02-02 07:26:17 -05:00
|
|
|
self.changecoloraction.setText(theme["main/menus/profile/color"])
|
2011-02-01 06:14:56 -05:00
|
|
|
self.switch.setText(theme["main/menus/profile/switch"])
|
|
|
|
self.profilemenu.setTitle(theme["main/menus/profile/_name"])
|
|
|
|
|
2011-01-28 21:36:12 -05:00
|
|
|
# moods
|
2011-01-31 18:43:49 -05:00
|
|
|
self.moodsLabel.setText(theme["main/moodlabel/text"])
|
|
|
|
self.moodsLabel.move(*theme["main/moodlabel/loc"])
|
|
|
|
self.moodsLabel.setStyleSheet(theme["main/moodlabel/style"])
|
|
|
|
|
2011-01-31 06:04:03 -05:00
|
|
|
if hasattr(self, 'moods'):
|
|
|
|
self.moods.removeButtons()
|
|
|
|
self.moods = PesterMoodHandler(self, *[PesterMoodButton(self, **d) for d in theme["main/moods"]])
|
2011-01-28 21:36:12 -05:00
|
|
|
self.moods.showButtons()
|
2011-01-29 06:31:41 -05:00
|
|
|
# chum
|
2011-01-31 06:04:03 -05:00
|
|
|
self.addChumButton.setText(theme["main/addchum/text"])
|
|
|
|
self.addChumButton.resize(*theme["main/addchum/size"])
|
|
|
|
self.addChumButton.move(*theme["main/addchum/loc"])
|
|
|
|
self.addChumButton.setStyleSheet(theme["main/addchum/style"])
|
|
|
|
self.pesterButton.setText(theme["main/pester/text"])
|
|
|
|
self.pesterButton.resize(*theme["main/pester/size"])
|
|
|
|
self.pesterButton.move(*theme["main/pester/loc"])
|
|
|
|
self.pesterButton.setStyleSheet(theme["main/pester/style"])
|
2011-02-02 07:26:17 -05:00
|
|
|
self.blockButton.setText(theme["main/block/text"])
|
|
|
|
self.blockButton.resize(*theme["main/block/size"])
|
|
|
|
self.blockButton.move(*theme["main/block/loc"])
|
|
|
|
self.blockButton.setStyleSheet(theme["main/block/style"])
|
2011-01-29 07:33:35 -05:00
|
|
|
# buttons
|
2011-01-31 06:04:03 -05:00
|
|
|
self.mychumhandleLabel.setText(theme["main/mychumhandle/label/text"])
|
|
|
|
self.mychumhandleLabel.move(*theme["main/mychumhandle/label/loc"])
|
|
|
|
self.mychumhandleLabel.setStyleSheet(theme["main/mychumhandle/label/style"])
|
2011-01-29 07:33:35 -05:00
|
|
|
self.mychumhandle.setText(self.profile().handle)
|
2011-01-31 06:04:03 -05:00
|
|
|
self.mychumhandle.move(*theme["main/mychumhandle/handle/loc"])
|
|
|
|
self.mychumhandle.resize(*theme["main/mychumhandle/handle/size"])
|
|
|
|
self.mychumhandle.setStyleSheet(theme["main/mychumhandle/handle/style"])
|
|
|
|
self.mychumcolor.resize(*theme["main/mychumhandle/colorswatch/size"])
|
|
|
|
self.mychumcolor.move(*theme["main/mychumhandle/colorswatch/loc"])
|
2011-01-29 07:33:35 -05:00
|
|
|
self.mychumcolor.setStyleSheet("background: %s" % (self.profile().colorhtml()))
|
2011-01-31 06:04:03 -05:00
|
|
|
if theme["main/mychumhandle/colorswatch/text"]:
|
|
|
|
self.mychumcolor.setText(theme["main/mychumhandle/colorswatch/text"])
|
2011-01-29 07:33:35 -05:00
|
|
|
|
2011-01-29 06:31:41 -05:00
|
|
|
# sounds
|
|
|
|
if not pygame.mixer:
|
|
|
|
self.alarm = NoneSound()
|
|
|
|
else:
|
2011-01-31 06:04:03 -05:00
|
|
|
self.alarm = pygame.mixer.Sound(theme["main/sounds/alertsound"]
|
2011-01-29 06:31:41 -05:00
|
|
|
)
|
2011-01-31 06:04:03 -05:00
|
|
|
|
2011-02-03 01:20:37 -05:00
|
|
|
def addChum(self, chum):
|
|
|
|
self.chumList.addChum(chum)
|
|
|
|
self.config.addChum(chum)
|
|
|
|
self.moodRequest.emit(chum)
|
|
|
|
|
2011-01-31 06:04:03 -05:00
|
|
|
def changeTheme(self, theme):
|
|
|
|
self.theme = theme
|
|
|
|
# do self
|
|
|
|
self.initTheme(theme)
|
|
|
|
# chum area
|
|
|
|
self.chumList.changeTheme(theme)
|
|
|
|
# do open windows
|
|
|
|
if self.tabconvo:
|
|
|
|
self.tabconvo.changeTheme(theme)
|
|
|
|
for c in self.convos.values():
|
|
|
|
c.changeTheme(theme)
|
2011-02-02 19:06:03 -05:00
|
|
|
if hasattr(self, 'trollslum') and self.trollslum:
|
|
|
|
self.trollslum.changeTheme(theme)
|
2011-02-03 01:20:37 -05:00
|
|
|
if hasattr(self, 'allusers') and self.allusers:
|
|
|
|
self.allusers.changeTheme(theme)
|
2011-01-29 06:31:41 -05:00
|
|
|
# system tray icon
|
|
|
|
self.updateSystemTray()
|
2011-01-31 06:04:03 -05:00
|
|
|
|
2011-01-29 06:31:41 -05:00
|
|
|
def updateSystemTray(self):
|
|
|
|
if len(self.waitingMessages) == 0:
|
|
|
|
self.trayIconSignal.emit(0)
|
|
|
|
else:
|
|
|
|
self.trayIconSignal.emit(1)
|
|
|
|
|
|
|
|
def systemTrayFunction(self):
|
|
|
|
if len(self.waitingMessages) == 0:
|
|
|
|
if self.isMinimized():
|
|
|
|
self.showNormal()
|
|
|
|
else:
|
|
|
|
if self.isActiveWindow():
|
|
|
|
self.showMinimized()
|
|
|
|
else:
|
|
|
|
self.raise_()
|
|
|
|
self.activateWindow()
|
|
|
|
else:
|
|
|
|
self.waitingMessages.answerMessage()
|
2011-01-28 06:17:42 -05:00
|
|
|
|
2011-01-29 07:33:35 -05:00
|
|
|
@QtCore.pyqtSlot()
|
2011-02-02 07:26:17 -05:00
|
|
|
def blockSelectedChum(self):
|
|
|
|
curChumListing = self.chumList.currentItem()
|
|
|
|
if curChumListing:
|
|
|
|
curChum = curChumListing.chum
|
2011-02-02 19:06:03 -05:00
|
|
|
self.blockChum(curChum.handle)
|
2011-02-02 07:26:17 -05:00
|
|
|
@QtCore.pyqtSlot()
|
2011-01-29 07:33:35 -05:00
|
|
|
def pesterSelectedChum(self):
|
|
|
|
curChum = self.chumList.currentItem()
|
|
|
|
if curChum:
|
|
|
|
self.newConversationWindow(curChum)
|
2011-01-24 04:10:44 -05:00
|
|
|
@QtCore.pyqtSlot(QtGui.QListWidgetItem)
|
|
|
|
def newConversationWindow(self, chumlisting):
|
2011-02-01 06:14:56 -05:00
|
|
|
# check chumdb
|
2011-01-24 04:10:44 -05:00
|
|
|
chum = chumlisting.chum
|
2011-02-01 06:14:56 -05:00
|
|
|
color = self.chumdb.getColor(chum)
|
|
|
|
if color:
|
|
|
|
chum.color = color
|
2011-01-24 04:10:44 -05:00
|
|
|
self.newConversation(chum)
|
2011-01-26 05:32:35 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString)
|
|
|
|
def closeConvo(self, handle):
|
2011-01-31 18:43:49 -05:00
|
|
|
h = unicode(handle)
|
2011-02-02 03:20:48 -05:00
|
|
|
chum = self.convos[h].chum
|
2011-01-31 18:43:49 -05:00
|
|
|
chumopen = self.convos[h].chumopen
|
|
|
|
if chumopen:
|
2011-02-03 03:51:22 -05:00
|
|
|
self.chatlog.log(chum.handle, convertTags(self.profile().pestermsg(chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/ceasepester"]), "bbcode"))
|
2011-02-02 03:20:48 -05:00
|
|
|
self.chatlog.finish(h)
|
2011-01-31 18:43:49 -05:00
|
|
|
self.convoClosed.emit(handle)
|
2011-02-02 03:20:48 -05:00
|
|
|
del self.convos[h]
|
2011-01-27 06:05:36 -05:00
|
|
|
@QtCore.pyqtSlot()
|
2011-01-27 05:41:53 -05:00
|
|
|
def tabsClosed(self):
|
|
|
|
del self.tabconvo
|
|
|
|
self.tabconvo = None
|
2011-01-28 21:36:12 -05:00
|
|
|
|
2011-01-24 07:17:12 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString, Mood)
|
|
|
|
def updateMoodSlot(self, handle, mood):
|
2011-01-31 18:43:49 -05:00
|
|
|
h = unicode(handle)
|
2011-01-24 07:17:12 -05:00
|
|
|
self.updateMood(h, mood)
|
|
|
|
|
|
|
|
@QtCore.pyqtSlot(QtCore.QString, QtGui.QColor)
|
|
|
|
def updateColorSlot(self, handle, color):
|
2011-01-31 18:43:49 -05:00
|
|
|
h = unicode(handle)
|
2011-01-24 07:17:12 -05:00
|
|
|
self.changeColor(h, color)
|
|
|
|
|
|
|
|
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
|
|
|
|
def deliverMessage(self, handle, msg):
|
2011-01-31 18:43:49 -05:00
|
|
|
h = unicode(handle)
|
|
|
|
m = unicode(msg)
|
2011-01-24 07:17:12 -05:00
|
|
|
self.newMessage(h, m)
|
|
|
|
|
2011-02-03 01:20:37 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString, PesterList)
|
|
|
|
def updateNames(self, channel, names):
|
|
|
|
c = unicode(channel)
|
|
|
|
# update name DB
|
|
|
|
self.namesdb[c] = names
|
|
|
|
# warn interested party of names
|
|
|
|
self.namesUpdated.emit()
|
|
|
|
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
|
|
|
|
def userPresentUpdate(self, handle, channel, update):
|
|
|
|
c = unicode(channel)
|
|
|
|
n = unicode(handle)
|
|
|
|
if update == "quit":
|
|
|
|
for c in self.namesdb.keys():
|
|
|
|
try:
|
|
|
|
i = self.namesdb[c].index(n)
|
|
|
|
self.namesdb[c].pop(i)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
except KeyError:
|
|
|
|
self.namesdb[c] = []
|
|
|
|
elif update == "left":
|
|
|
|
try:
|
|
|
|
i = self.namesdb[c].index(n)
|
|
|
|
self.namesdb[c].pop(i)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
except KeyError:
|
|
|
|
self.namesdb[c] = []
|
|
|
|
elif update == "join":
|
|
|
|
try:
|
|
|
|
i = self.namesdb[c].index(n)
|
|
|
|
except ValueError:
|
|
|
|
self.namesdb[c].append(n)
|
|
|
|
except KeyError:
|
|
|
|
self.namesdb[c] = [n]
|
|
|
|
|
|
|
|
self.userPresentSignal.emit(handle, channel, update)
|
|
|
|
|
2011-01-27 04:46:47 -05:00
|
|
|
@QtCore.pyqtSlot()
|
2011-01-29 06:31:41 -05:00
|
|
|
def addChumWindow(self):
|
2011-01-31 06:04:03 -05:00
|
|
|
if not hasattr(self, 'addchumdialog'):
|
|
|
|
self.addchumdialog = None
|
2011-01-29 06:31:41 -05:00
|
|
|
if not self.addchumdialog:
|
|
|
|
self.addchumdialog = QtGui.QInputDialog(self)
|
|
|
|
(handle, ok) = self.addchumdialog.getText(self, "New Chum", "Enter Chum Handle:")
|
|
|
|
if ok:
|
|
|
|
handle = unicode(handle)
|
|
|
|
if not (PesterProfile.checkLength(handle) and
|
|
|
|
PesterProfile.checkValid(handle)):
|
|
|
|
errormsg = QtGui.QErrorMessage(self)
|
|
|
|
errormsg.showMessage("THIS IS NOT A VALID CHUMTAG!")
|
|
|
|
self.addchumdialog = None
|
|
|
|
return
|
2011-02-01 06:14:56 -05:00
|
|
|
chum = PesterProfile(handle, chumdb=self.chumdb)
|
2011-02-03 01:20:37 -05:00
|
|
|
self.addChum(chum)
|
2011-01-29 06:31:41 -05:00
|
|
|
self.addchumdialog = None
|
|
|
|
@QtCore.pyqtSlot(QtGui.QListWidgetItem)
|
|
|
|
def removeChum(self, chumlisting):
|
|
|
|
self.config.removeChum(chumlisting.chum)
|
2011-02-02 07:26:17 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString)
|
|
|
|
def blockChum(self, handle):
|
|
|
|
h = unicode(handle)
|
2011-02-02 19:06:03 -05:00
|
|
|
self.config.addBlocklist(h)
|
|
|
|
self.config.removeChum(h)
|
2011-02-02 07:26:17 -05:00
|
|
|
if self.convos.has_key(h):
|
|
|
|
convo = self.convos[h]
|
|
|
|
msg = self.profile().pestermsg(convo.chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/blocked"])
|
2011-02-03 03:51:22 -05:00
|
|
|
convo.textArea.append(convertTags(msg))
|
|
|
|
self.chatlog.log(convo.chum.handle, convertTags(msg, "bbcode"))
|
2011-02-02 07:26:17 -05:00
|
|
|
convo.updateBlocked()
|
2011-02-02 19:06:03 -05:00
|
|
|
self.chumList.removeChum(h)
|
|
|
|
if hasattr(self, 'trollslum') and self.trollslum:
|
|
|
|
newtroll = PesterProfile(h)
|
|
|
|
self.trollslum.addTroll(newtroll)
|
|
|
|
self.moodRequest.emit(newtroll)
|
2011-02-02 07:26:17 -05:00
|
|
|
self.blockedChum.emit(handle)
|
|
|
|
|
|
|
|
@QtCore.pyqtSlot(QtCore.QString)
|
|
|
|
def unblockChum(self, handle):
|
|
|
|
h = unicode(handle)
|
2011-02-02 19:06:03 -05:00
|
|
|
self.config.delBlocklist(h)
|
2011-02-02 07:26:17 -05:00
|
|
|
if self.convos.has_key(h):
|
|
|
|
convo = self.convos[h]
|
|
|
|
msg = self.profile().pestermsg(convo.chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/unblocked"])
|
2011-02-03 03:51:22 -05:00
|
|
|
convo.textArea.append(convertTags(msg))
|
|
|
|
self.chatlog.log(convo.chum.handle, convertTags(msg, "bbcode"))
|
2011-02-02 07:26:17 -05:00
|
|
|
convo.updateMood(convo.chum.mood, unblocked=True)
|
2011-02-02 19:06:03 -05:00
|
|
|
chum = PesterProfile(h, chumdb=self.chumdb)
|
|
|
|
if hasattr(self, 'trollslum') and self.trollslum:
|
|
|
|
self.trollslum.removeTroll(handle)
|
|
|
|
self.config.addChum(chum)
|
|
|
|
self.chumList.addChum(chum)
|
|
|
|
self.moodRequest.emit(chum)
|
2011-02-02 07:26:17 -05:00
|
|
|
self.unblockedChum.emit(handle)
|
2011-02-02 19:06:03 -05:00
|
|
|
|
2011-01-29 06:31:41 -05:00
|
|
|
@QtCore.pyqtSlot()
|
2011-02-03 01:20:37 -05:00
|
|
|
def showAllUsers(self):
|
|
|
|
if not hasattr(self, 'allusers'):
|
|
|
|
self.allusers = None
|
|
|
|
if not self.allusers:
|
|
|
|
self.allusers = PesterUserlist(self.config, self.theme, self)
|
|
|
|
self.connect(self.allusers, QtCore.SIGNAL('accepted()'),
|
|
|
|
self, QtCore.SLOT('userListClose()'))
|
|
|
|
self.connect(self.allusers, QtCore.SIGNAL('rejected()'),
|
|
|
|
self, QtCore.SLOT('userListClose()'))
|
|
|
|
self.connect(self.allusers, QtCore.SIGNAL('addChum(QString)'),
|
|
|
|
self, QtCore.SLOT('userListAdd(QString)'))
|
|
|
|
self.requestNames.emit("#pesterchum")
|
|
|
|
self.allusers.show()
|
|
|
|
|
|
|
|
@QtCore.pyqtSlot(QtCore.QString)
|
|
|
|
def userListAdd(self, handle):
|
|
|
|
h = unicode(handle)
|
|
|
|
chum = PesterProfile(h, chumdb=self.chumdb)
|
|
|
|
self.addChum(chum)
|
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def userListClose(self):
|
|
|
|
self.allusers = None
|
|
|
|
@QtCore.pyqtSlot()
|
2011-01-29 16:55:35 -05:00
|
|
|
def openQuirks(self):
|
2011-01-31 06:04:03 -05:00
|
|
|
if not hasattr(self, 'quirkmenu'):
|
|
|
|
self.quirkmenu = None
|
2011-01-29 16:55:35 -05:00
|
|
|
if not self.quirkmenu:
|
|
|
|
self.quirkmenu = PesterChooseQuirks(self.config, self.theme, self)
|
|
|
|
self.connect(self.quirkmenu, QtCore.SIGNAL('accepted()'),
|
|
|
|
self, QtCore.SLOT('updateQuirks()'))
|
|
|
|
self.connect(self.quirkmenu, QtCore.SIGNAL('rejected()'),
|
|
|
|
self, QtCore.SLOT('closeQuirks()'))
|
|
|
|
self.quirkmenu.show()
|
|
|
|
self.quirkmenu.raise_()
|
|
|
|
self.quirkmenu.activateWindow()
|
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def updateQuirks(self):
|
|
|
|
quirks = pesterQuirks(self.quirkmenu.quirks())
|
|
|
|
self.userprofile.setQuirks(quirks)
|
|
|
|
self.quirkmenu = None
|
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def closeQuirks(self):
|
|
|
|
self.quirkmenu = None
|
|
|
|
@QtCore.pyqtSlot()
|
2011-01-27 04:46:47 -05:00
|
|
|
def openOpts(self):
|
2011-01-31 06:04:03 -05:00
|
|
|
if not hasattr(self, 'optionmenu'):
|
|
|
|
self.optionmenu = None
|
2011-01-27 04:46:47 -05:00
|
|
|
if not self.optionmenu:
|
|
|
|
self.optionmenu = PesterOptions(self.config, self.theme, self)
|
|
|
|
self.connect(self.optionmenu, QtCore.SIGNAL('accepted()'),
|
|
|
|
self, QtCore.SLOT('updateOptions()'))
|
2011-01-27 21:21:02 -05:00
|
|
|
self.connect(self.optionmenu, QtCore.SIGNAL('rejected()'),
|
|
|
|
self, QtCore.SLOT('closeOptions()'))
|
2011-01-27 04:46:47 -05:00
|
|
|
self.optionmenu.show()
|
|
|
|
self.optionmenu.raise_()
|
|
|
|
self.optionmenu.activateWindow()
|
|
|
|
@QtCore.pyqtSlot()
|
2011-01-27 21:21:02 -05:00
|
|
|
def closeOptions(self):
|
|
|
|
self.optionmenu.close()
|
|
|
|
self.optionmenu = None
|
|
|
|
@QtCore.pyqtSlot()
|
2011-01-27 04:46:47 -05:00
|
|
|
def updateOptions(self):
|
|
|
|
# tabs
|
|
|
|
curtab = self.config.tabs()
|
|
|
|
tabsetting = self.optionmenu.tabcheck.isChecked()
|
|
|
|
if curtab and not tabsetting:
|
|
|
|
# split tabs into windows
|
2011-01-27 06:05:36 -05:00
|
|
|
if self.tabconvo:
|
|
|
|
windows = list(self.tabconvo.convos.values())
|
|
|
|
for w in windows:
|
|
|
|
w.setParent(None)
|
|
|
|
w.show()
|
|
|
|
w.raiseChat()
|
|
|
|
self.tabconvo.closeSoft()
|
2011-01-27 04:46:47 -05:00
|
|
|
# save options
|
|
|
|
self.config.set("tabs", tabsetting)
|
|
|
|
elif tabsetting and not curtab:
|
|
|
|
# combine
|
2011-01-27 17:16:14 -05:00
|
|
|
self.createTabWindow()
|
|
|
|
newconvos = {}
|
|
|
|
for (h,c) in self.convos.iteritems():
|
|
|
|
c.setParent(self.tabconvo)
|
|
|
|
self.tabconvo.addChat(c)
|
|
|
|
self.tabconvo.show()
|
|
|
|
newconvos[h] = c
|
|
|
|
self.convos = newconvos
|
2011-01-27 04:46:47 -05:00
|
|
|
# save options
|
|
|
|
self.config.set("tabs", tabsetting)
|
|
|
|
self.optionmenu = None
|
2011-01-27 21:21:02 -05:00
|
|
|
|
|
|
|
@QtCore.pyqtSlot()
|
2011-01-28 06:17:42 -05:00
|
|
|
def themeSelected(self):
|
2011-01-28 06:26:13 -05:00
|
|
|
themename = unicode(self.choosetheme.themeBox.currentText())
|
2011-01-28 06:17:42 -05:00
|
|
|
if themename != self.theme.name:
|
2011-01-31 18:43:49 -05:00
|
|
|
try:
|
|
|
|
self.changeTheme(pesterTheme(themename))
|
|
|
|
except ValueError, e:
|
2011-02-01 06:14:56 -05:00
|
|
|
themeWarning = QtGui.QMessageBox(self)
|
|
|
|
themeWarning.setText("Theme Error: %s" % (e))
|
|
|
|
themeWarning.exec_()
|
|
|
|
self.choosetheme = None
|
2011-01-31 18:43:49 -05:00
|
|
|
return
|
2011-01-28 06:26:13 -05:00
|
|
|
# update profile
|
|
|
|
self.userprofile.setTheme(self.theme)
|
2011-01-28 06:17:42 -05:00
|
|
|
self.choosetheme = None
|
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def closeTheme(self):
|
|
|
|
self.choosetheme = None
|
|
|
|
@QtCore.pyqtSlot()
|
2011-01-27 21:21:02 -05:00
|
|
|
def profileSelected(self):
|
|
|
|
if self.chooseprofile.profileBox and \
|
2011-01-28 01:41:01 -05:00
|
|
|
self.chooseprofile.profileBox.currentIndex() > 0:
|
2011-01-27 21:21:02 -05:00
|
|
|
handle = unicode(self.chooseprofile.profileBox.currentText())
|
2011-01-28 21:36:12 -05:00
|
|
|
if handle == self.profile().handle:
|
2011-02-01 06:14:56 -05:00
|
|
|
self.chooseprofile = None
|
2011-01-28 21:36:12 -05:00
|
|
|
return
|
2011-01-27 21:21:02 -05:00
|
|
|
self.userprofile = userProfile(handle)
|
2011-01-28 06:26:13 -05:00
|
|
|
self.changeTheme(self.userprofile.getTheme())
|
2011-01-27 21:21:02 -05:00
|
|
|
else:
|
2011-01-28 21:36:12 -05:00
|
|
|
handle = unicode(self.chooseprofile.chumHandle.text())
|
|
|
|
if handle == self.profile().handle:
|
2011-02-01 06:14:56 -05:00
|
|
|
self.chooseprofile = None
|
2011-01-28 21:36:12 -05:00
|
|
|
return
|
|
|
|
profile = PesterProfile(handle,
|
|
|
|
self.chooseprofile.chumcolor)
|
2011-01-27 21:21:02 -05:00
|
|
|
self.userprofile = userProfile.newUserProfile(profile)
|
2011-01-31 06:04:03 -05:00
|
|
|
self.changeTheme(self.userprofile.getTheme())
|
2011-01-27 21:21:02 -05:00
|
|
|
|
2011-02-02 03:20:48 -05:00
|
|
|
self.chatlog.close()
|
|
|
|
self.chatlog = PesterLog(handle)
|
|
|
|
|
2011-01-28 21:36:12 -05:00
|
|
|
# is default?
|
|
|
|
if self.chooseprofile.defaultcheck.isChecked():
|
|
|
|
self.config.set("defaultprofile", self.userprofile.chat.handle)
|
2011-01-28 01:41:01 -05:00
|
|
|
# this may have to be fixed
|
|
|
|
self.closeConversations()
|
2011-02-02 19:06:03 -05:00
|
|
|
if hasattr(self, 'trollslum') and self.trollslum:
|
|
|
|
self.trollslum.close()
|
2011-02-01 06:14:56 -05:00
|
|
|
self.chooseprofile = None
|
2011-01-28 01:41:01 -05:00
|
|
|
self.profileChanged.emit()
|
2011-02-02 19:06:03 -05:00
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def showTrollSlum(self):
|
|
|
|
if not hasattr(self, 'trollslum'):
|
|
|
|
self.trollslum = None
|
|
|
|
if self.trollslum:
|
|
|
|
return
|
|
|
|
trolls = [PesterProfile(h) for h in self.config.getBlocklist()]
|
|
|
|
self.trollslum = TrollSlumWindow(trolls, self)
|
|
|
|
self.connect(self.trollslum, QtCore.SIGNAL('blockChumSignal(QString)'),
|
|
|
|
self, QtCore.SLOT('blockChum(QString)'))
|
|
|
|
self.connect(self.trollslum,
|
|
|
|
QtCore.SIGNAL('unblockChumSignal(QString)'),
|
|
|
|
self, QtCore.SLOT('unblockChum(QString)'))
|
2011-02-03 01:20:37 -05:00
|
|
|
self.moodsRequest.emit(PesterList(trolls))
|
2011-02-02 19:06:03 -05:00
|
|
|
self.trollslum.show()
|
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def closeTrollSlum(self):
|
|
|
|
self.trollslum = None
|
2011-01-27 21:21:02 -05:00
|
|
|
@QtCore.pyqtSlot()
|
2011-01-29 07:33:35 -05:00
|
|
|
def changeMyColor(self):
|
2011-01-31 06:04:03 -05:00
|
|
|
if not hasattr(self, 'colorDialog'):
|
|
|
|
self.colorDialog = None
|
2011-01-29 07:33:35 -05:00
|
|
|
if self.colorDialog:
|
|
|
|
return
|
|
|
|
self.colorDialog = QtGui.QColorDialog(self)
|
|
|
|
color = self.colorDialog.getColor(initial=self.profile().color)
|
|
|
|
self.mychumcolor.setStyleSheet("background: %s" % color.name())
|
|
|
|
self.userprofile.setColor(color)
|
2011-01-31 18:43:49 -05:00
|
|
|
self.mycolorUpdated.emit()
|
2011-01-29 07:33:35 -05:00
|
|
|
self.colorDialog = None
|
|
|
|
@QtCore.pyqtSlot()
|
2011-01-27 21:21:02 -05:00
|
|
|
def closeProfile(self):
|
|
|
|
self.chooseprofile = None
|
2011-01-28 01:41:01 -05:00
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def switchProfile(self):
|
2011-01-28 04:20:32 -05:00
|
|
|
if self.convos:
|
|
|
|
closeWarning = QtGui.QMessageBox()
|
2011-01-29 07:33:35 -05:00
|
|
|
closeWarning.setText("WARNING: CHANGING PROFILES WILL CLOSE ALL CONVERSATION WINDOWS!")
|
|
|
|
closeWarning.setInformativeText("i warned you about windows bro!!!! i told you dog!")
|
2011-01-28 04:20:32 -05:00
|
|
|
closeWarning.setStandardButtons(QtGui.QMessageBox.Cancel | QtGui.QMessageBox.Ok)
|
|
|
|
closeWarning.setDefaultButton(QtGui.QMessageBox.Ok)
|
|
|
|
ret = closeWarning.exec_()
|
|
|
|
if ret == QtGui.QMessageBox.Cancel:
|
|
|
|
return
|
|
|
|
self.changeProfile()
|
2011-01-27 21:21:02 -05:00
|
|
|
|
2011-02-01 06:14:56 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
|
|
|
|
def nickCollision(self, handle, tmphandle):
|
|
|
|
self.mychumhandle.setText(tmphandle)
|
|
|
|
if not hasattr(self, 'chooseprofile'):
|
|
|
|
self.chooseprofile = None
|
2011-01-28 01:08:56 -05:00
|
|
|
if not self.chooseprofile:
|
|
|
|
h = unicode(handle)
|
|
|
|
self.changeProfile(collision=h)
|
2011-01-27 04:46:47 -05:00
|
|
|
|
2011-01-28 06:17:42 -05:00
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def pickTheme(self):
|
|
|
|
self.themePicker()
|
|
|
|
|
2011-01-29 06:31:41 -05:00
|
|
|
@QtCore.pyqtSlot(QtGui.QSystemTrayIcon.ActivationReason)
|
|
|
|
def systemTrayActivated(self, reason):
|
|
|
|
if reason == QtGui.QSystemTrayIcon.Trigger:
|
|
|
|
self.systemTrayFunction()
|
|
|
|
elif reason == QtGui.QSystemTrayIcon.Context:
|
|
|
|
# show context menu i guess
|
|
|
|
pass
|
|
|
|
|
2011-01-24 04:10:44 -05:00
|
|
|
newConvoStarted = QtCore.pyqtSignal(QtCore.QString, bool, name="newConvoStarted")
|
|
|
|
sendMessage = QtCore.pyqtSignal(QtCore.QString, PesterProfile)
|
2011-01-27 04:46:47 -05:00
|
|
|
convoClosed = QtCore.pyqtSignal(QtCore.QString)
|
2011-01-28 01:41:01 -05:00
|
|
|
profileChanged = QtCore.pyqtSignal()
|
2011-01-28 03:10:00 -05:00
|
|
|
moodRequest = QtCore.pyqtSignal(PesterProfile)
|
2011-02-03 01:20:37 -05:00
|
|
|
moodsRequest = QtCore.pyqtSignal(PesterList)
|
2011-01-28 21:36:12 -05:00
|
|
|
moodUpdated = QtCore.pyqtSignal()
|
2011-02-03 01:20:37 -05:00
|
|
|
requestNames = QtCore.pyqtSignal(QtCore.QString)
|
|
|
|
namesUpdated = QtCore.pyqtSignal()
|
|
|
|
userPresentSignal = QtCore.pyqtSignal(QtCore.QString,QtCore.QString,QtCore.QString)
|
2011-01-31 18:43:49 -05:00
|
|
|
mycolorUpdated = QtCore.pyqtSignal()
|
2011-01-29 06:31:41 -05:00
|
|
|
trayIconSignal = QtCore.pyqtSignal(int)
|
2011-02-02 07:26:17 -05:00
|
|
|
blockedChum = QtCore.pyqtSignal(QtCore.QString)
|
|
|
|
unblockedChum = QtCore.pyqtSignal(QtCore.QString)
|
2011-01-24 02:34:07 -05:00
|
|
|
|
|
|
|
class PesterIRC(QtCore.QObject):
|
2011-01-28 01:08:56 -05:00
|
|
|
def __init__(self, window):
|
2011-01-24 02:34:07 -05:00
|
|
|
QtCore.QObject.__init__(self)
|
2011-01-28 03:59:03 -05:00
|
|
|
self.mainwindow = window
|
2011-01-24 02:34:07 -05:00
|
|
|
def IRCConnect(self):
|
2011-01-28 21:36:12 -05:00
|
|
|
self.cli = IRCClient(PesterHandler, host="irc.tymoon.eu", port=6667, nick=self.mainwindow.profile().handle, blocking=True)
|
2011-01-24 07:17:12 -05:00
|
|
|
self.cli.command_handler.parent = self
|
2011-01-28 03:59:03 -05:00
|
|
|
self.cli.command_handler.mainwindow = self.mainwindow
|
2011-01-24 02:34:07 -05:00
|
|
|
self.conn = self.cli.connect()
|
2011-01-24 04:10:44 -05:00
|
|
|
|
2011-01-28 03:10:00 -05:00
|
|
|
@QtCore.pyqtSlot(PesterProfile)
|
2011-01-24 04:10:44 -05:00
|
|
|
def getMood(self, *chums):
|
|
|
|
self.cli.command_handler.getMood(*chums)
|
2011-02-03 01:20:37 -05:00
|
|
|
@QtCore.pyqtSlot(PesterList)
|
2011-02-02 19:06:03 -05:00
|
|
|
def getMoods(self, chums):
|
|
|
|
self.cli.command_handler.getMood(*chums)
|
2011-01-24 02:34:07 -05:00
|
|
|
|
2011-01-24 04:10:44 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString, PesterProfile)
|
|
|
|
def sendMessage(self, text, chum):
|
|
|
|
handle = chum.handle
|
2011-01-24 02:34:07 -05:00
|
|
|
helpers.msg(self.cli, handle, text)
|
|
|
|
|
2011-01-24 04:10:44 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString, bool)
|
|
|
|
def startConvo(self, handle, initiated):
|
2011-01-31 18:43:49 -05:00
|
|
|
h = unicode(handle)
|
2011-01-24 04:10:44 -05:00
|
|
|
if initiated:
|
|
|
|
helpers.msg(self.cli, h, "PESTERCHUM:BEGIN")
|
2011-01-28 21:36:12 -05:00
|
|
|
helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
|
2011-01-27 04:46:47 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString)
|
|
|
|
def endConvo(self, handle):
|
2011-01-31 18:43:49 -05:00
|
|
|
h = unicode(handle)
|
2011-01-27 04:46:47 -05:00
|
|
|
helpers.msg(self.cli, h, "PESTERCHUM:CEASE")
|
2011-01-28 01:41:01 -05:00
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def updateProfile(self):
|
2011-01-28 21:36:12 -05:00
|
|
|
me = self.mainwindow.profile()
|
2011-01-28 04:20:32 -05:00
|
|
|
handle = me.handle
|
2011-01-28 01:41:01 -05:00
|
|
|
helpers.nick(self.cli, handle)
|
2011-01-28 21:36:12 -05:00
|
|
|
self.updateMood()
|
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def updateMood(self):
|
|
|
|
me = self.mainwindow.profile()
|
2011-01-28 04:20:32 -05:00
|
|
|
helpers.msg(self.cli, "#pesterchum", "MOOD >%d" % (me.mood.value()))
|
2011-01-31 18:43:49 -05:00
|
|
|
@QtCore.pyqtSlot()
|
|
|
|
def updateColor(self):
|
|
|
|
me = self.mainwindow.profile()
|
|
|
|
for h in self.mainwindow.convos.keys():
|
|
|
|
helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
|
2011-02-02 07:26:17 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString)
|
|
|
|
def blockedChum(self, handle):
|
|
|
|
h = unicode(handle)
|
|
|
|
helpers.msg(self.cli, h, "PESTERCHUM:BLOCK")
|
|
|
|
@QtCore.pyqtSlot(QtCore.QString)
|
|
|
|
def unblockedChum(self, handle):
|
|
|
|
h = unicode(handle)
|
|
|
|
helpers.msg(self.cli, h, "PESTERCHUM:UNBLOCK")
|
2011-02-03 01:20:37 -05:00
|
|
|
@QtCore.pyqtSlot(QtCore.QString)
|
|
|
|
def requestNames(self, channel):
|
|
|
|
c = unicode(channel)
|
|
|
|
helpers.names(self.cli, c)
|
2011-02-02 07:26:17 -05:00
|
|
|
|
2011-01-24 02:34:07 -05:00
|
|
|
def updateIRC(self):
|
|
|
|
self.conn.next()
|
|
|
|
|
2011-01-24 07:17:12 -05:00
|
|
|
moodUpdated = QtCore.pyqtSignal(QtCore.QString, Mood)
|
|
|
|
colorUpdated = QtCore.pyqtSignal(QtCore.QString, QtGui.QColor)
|
|
|
|
messageReceived = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
|
2011-02-03 01:20:37 -05:00
|
|
|
namesReceived = QtCore.pyqtSignal(QtCore.QString, PesterList)
|
2011-02-01 06:14:56 -05:00
|
|
|
nickCollision = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
|
2011-02-03 01:20:37 -05:00
|
|
|
userPresentUpdate = QtCore.pyqtSignal(QtCore.QString, QtCore.QString,
|
|
|
|
QtCore.QString)
|
2011-01-24 07:17:12 -05:00
|
|
|
|
2011-01-24 02:34:07 -05:00
|
|
|
class PesterHandler(DefaultCommandHandler):
|
|
|
|
def privmsg(self, nick, chan, msg):
|
|
|
|
# display msg, do other stuff
|
2011-01-24 04:10:44 -05:00
|
|
|
# silently ignore CTCP
|
|
|
|
if msg[0] == '\x01':
|
|
|
|
return
|
2011-01-24 02:34:07 -05:00
|
|
|
handle = nick[0:nick.find("!")]
|
2011-02-01 06:14:56 -05:00
|
|
|
logging.info("---> recv \"PRIVMSG %s :%s\"" % (handle, msg))
|
2011-01-24 02:34:07 -05:00
|
|
|
if chan == "#pesterchum":
|
|
|
|
# follow instructions
|
|
|
|
if msg[0:6] == "MOOD >":
|
|
|
|
try:
|
|
|
|
mood = Mood(int(msg[6:]))
|
|
|
|
except ValueError:
|
|
|
|
mood = Mood(0)
|
2011-01-24 07:17:12 -05:00
|
|
|
self.parent.moodUpdated.emit(handle, mood)
|
2011-01-24 02:34:07 -05:00
|
|
|
elif msg[0:7] == "GETMOOD":
|
2011-01-28 21:36:12 -05:00
|
|
|
mychumhandle = self.mainwindow.profile().handle
|
|
|
|
mymood = self.mainwindow.profile().mood.value()
|
2011-01-24 02:34:07 -05:00
|
|
|
if msg.find(mychumhandle, 8) != -1:
|
|
|
|
helpers.msg(self.client, "#pesterchum",
|
|
|
|
"MOOD >%d" % (mymood))
|
|
|
|
|
|
|
|
else:
|
|
|
|
# private message
|
2011-01-28 04:20:32 -05:00
|
|
|
# silently ignore messages to yourself.
|
2011-01-28 21:36:12 -05:00
|
|
|
if handle == self.mainwindow.profile().handle:
|
2011-01-28 04:20:32 -05:00
|
|
|
return
|
2011-01-24 04:10:44 -05:00
|
|
|
if msg[0:7] == "COLOR >":
|
|
|
|
colors = msg[7:].split(",")
|
|
|
|
try:
|
|
|
|
colors = [int(d) for d in colors]
|
|
|
|
except ValueError:
|
|
|
|
colors = [0,0,0]
|
|
|
|
color = QtGui.QColor(*colors)
|
2011-01-24 07:17:12 -05:00
|
|
|
self.parent.colorUpdated.emit(handle, color)
|
2011-01-24 04:10:44 -05:00
|
|
|
else:
|
2011-01-24 07:17:12 -05:00
|
|
|
self.parent.messageReceived.emit(handle, msg)
|
2011-01-24 04:10:44 -05:00
|
|
|
|
|
|
|
|
2011-01-24 02:34:07 -05:00
|
|
|
def welcome(self, server, nick, msg):
|
|
|
|
helpers.join(self.client, "#pesterchum")
|
2011-01-28 21:36:12 -05:00
|
|
|
mychumhandle = self.mainwindow.profile().handle
|
|
|
|
mymood = self.mainwindow.profile().mood.value()
|
2011-01-24 02:34:07 -05:00
|
|
|
helpers.msg(self.client, "#pesterchum", "MOOD >%d" % (mymood))
|
|
|
|
|
2011-01-28 03:59:03 -05:00
|
|
|
chums = self.mainwindow.chumList.chums
|
2011-01-24 04:10:44 -05:00
|
|
|
self.getMood(*chums)
|
2011-01-27 21:21:02 -05:00
|
|
|
|
|
|
|
def nicknameinuse(self, server, cmd, nick, msg):
|
2011-02-01 06:14:56 -05:00
|
|
|
newnick = "pesterClient%d" % (random.randint(100,999))
|
|
|
|
helpers.nick(self.client, newnick)
|
|
|
|
self.parent.nickCollision.emit(nick, newnick)
|
2011-01-28 21:36:12 -05:00
|
|
|
def quit(self, nick, reason):
|
|
|
|
handle = nick[0:nick.find("!")]
|
2011-02-03 01:20:37 -05:00
|
|
|
self.parent.userPresentUpdate.emit(handle, "", "quit")
|
2011-01-28 21:36:12 -05:00
|
|
|
self.parent.moodUpdated.emit(handle, Mood("offline"))
|
2011-01-31 18:43:49 -05:00
|
|
|
def part(self, nick, channel, reason="nanchos"):
|
|
|
|
handle = nick[0:nick.find("!")]
|
2011-02-03 01:20:37 -05:00
|
|
|
self.parent.userPresentUpdate.emit(handle, channel, "left")
|
2011-01-31 18:43:49 -05:00
|
|
|
if channel == "#pesterchum":
|
|
|
|
self.parent.moodUpdated.emit(handle, Mood("offline"))
|
|
|
|
def join(self, nick, channel):
|
2011-01-29 07:33:35 -05:00
|
|
|
handle = nick[0:nick.find("!")]
|
2011-02-03 01:20:37 -05:00
|
|
|
self.parent.userPresentUpdate.emit(handle, channel, "join")
|
2011-01-29 06:31:41 -05:00
|
|
|
if channel == "#pesterchum":
|
2011-01-31 18:43:49 -05:00
|
|
|
self.parent.moodUpdated.emit(handle, Mood("chummy"))
|
2011-01-28 21:36:12 -05:00
|
|
|
def nick(self, oldnick, newnick):
|
|
|
|
oldhandle = oldnick[0:oldnick.find("!")]
|
2011-02-01 06:14:56 -05:00
|
|
|
newchum = PesterProfile(newnick, chumdb=self.mainwindow.chumdb)
|
2011-01-28 21:36:12 -05:00
|
|
|
self.parent.moodUpdated.emit(oldhandle, Mood("offline"))
|
2011-01-29 06:31:41 -05:00
|
|
|
if newnick in self.mainwindow.chumList.chums:
|
|
|
|
self.getMood(newchum)
|
2011-02-03 01:20:37 -05:00
|
|
|
def namreply(self, server, nick, op, channel, names):
|
|
|
|
namelist = names.split(" ")
|
|
|
|
logging.info("---> recv \"NAMES %s: %d names\"" % (channel, len(namelist)))
|
|
|
|
if not hasattr(self, 'channelnames'):
|
|
|
|
self.channelnames = {}
|
|
|
|
if not self.channelnames.has_key(channel):
|
|
|
|
self.channelnames[channel] = []
|
|
|
|
self.channelnames[channel].extend(namelist)
|
|
|
|
def endofnames(self, server, nick, channel, msg):
|
|
|
|
namelist = self.channelnames[channel]
|
|
|
|
pl = PesterList(namelist)
|
|
|
|
del self.channelnames[channel]
|
|
|
|
self.parent.namesReceived.emit(channel, pl)
|
2011-01-28 21:36:12 -05:00
|
|
|
|
2011-01-24 04:10:44 -05:00
|
|
|
def getMood(self, *chums):
|
2011-01-24 02:34:07 -05:00
|
|
|
chumglub = "GETMOOD "
|
|
|
|
for c in chums:
|
|
|
|
chandle = c.handle
|
2011-01-28 21:36:12 -05:00
|
|
|
if len(chumglub+chandle) >= 350:
|
2011-01-24 02:34:07 -05:00
|
|
|
helpers.msg(self.client, "#pesterchum", chumglub)
|
|
|
|
chumglub = "GETMOOD "
|
|
|
|
chumglub += chandle
|
|
|
|
if chumglub != "GETMOOD ":
|
|
|
|
helpers.msg(self.client, "#pesterchum", chumglub)
|
2011-01-21 05:18:22 -05:00
|
|
|
|
2011-01-24 07:17:12 -05:00
|
|
|
class IRCThread(QtCore.QThread):
|
|
|
|
def __init__(self, ircobj):
|
|
|
|
QtCore.QThread.__init__(self)
|
|
|
|
self.irc = ircobj
|
|
|
|
def run(self):
|
|
|
|
irc = self.irc
|
|
|
|
while 1:
|
|
|
|
irc.updateIRC()
|
2011-01-21 05:18:22 -05:00
|
|
|
|
2011-01-29 06:31:41 -05:00
|
|
|
class PesterTray(QtGui.QSystemTrayIcon):
|
|
|
|
def __init__(self, icon, mainwindow, parent):
|
|
|
|
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
|
|
|
|
self.mainwindow = mainwindow
|
|
|
|
traymenu = QtGui.QMenu()
|
|
|
|
traymenu.addAction("Hi!! HI!!")
|
|
|
|
self.setContextMenu(traymenu)
|
|
|
|
|
|
|
|
@QtCore.pyqtSlot(int)
|
|
|
|
def changeTrayIcon(self, i):
|
|
|
|
if i == 0:
|
2011-02-02 03:20:48 -05:00
|
|
|
self.setIcon(PesterIcon(self.mainwindow.theme["main/icon"]))
|
2011-01-29 06:31:41 -05:00
|
|
|
else:
|
2011-02-02 03:20:48 -05:00
|
|
|
self.setIcon(PesterIcon(self.mainwindow.theme["main/newmsgicon"]))
|
2011-01-29 06:31:41 -05:00
|
|
|
|
2011-01-21 05:18:22 -05:00
|
|
|
def main():
|
|
|
|
|
|
|
|
app = QtGui.QApplication(sys.argv)
|
2011-01-29 06:31:41 -05:00
|
|
|
if pygame.mixer:
|
|
|
|
# we could set the frequency higher but i love how cheesy it sounds
|
|
|
|
pygame.mixer.init()
|
|
|
|
else:
|
|
|
|
print "Warning: No sound!"
|
2011-01-21 05:18:22 -05:00
|
|
|
widget = PesterWindow()
|
|
|
|
widget.show()
|
|
|
|
|
2011-02-02 03:20:48 -05:00
|
|
|
trayicon = PesterTray(PesterIcon(widget.theme["main/icon"]), widget, app)
|
2011-01-29 06:31:41 -05:00
|
|
|
trayicon.show()
|
|
|
|
|
|
|
|
trayicon.connect(trayicon,
|
|
|
|
QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
|
|
|
|
widget,
|
|
|
|
QtCore.SLOT('systemTrayActivated(QSystemTrayIcon::ActivationReason)'))
|
|
|
|
trayicon.connect(widget,
|
|
|
|
QtCore.SIGNAL('trayIconSignal(int)'),
|
|
|
|
trayicon,
|
|
|
|
QtCore.SLOT('changeTrayIcon(int)'))
|
|
|
|
|
|
|
|
|
2011-01-28 01:08:56 -05:00
|
|
|
irc = PesterIRC(widget)
|
2011-01-22 04:36:24 -05:00
|
|
|
irc.IRCConnect()
|
2011-01-24 02:34:07 -05:00
|
|
|
irc.connect(widget, QtCore.SIGNAL('sendMessage(QString, PyQt_PyObject)'),
|
|
|
|
irc, QtCore.SLOT('sendMessage(QString, PyQt_PyObject)'))
|
2011-01-24 04:10:44 -05:00
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('newConvoStarted(QString, bool)'),
|
|
|
|
irc, QtCore.SLOT('startConvo(QString, bool)'))
|
2011-01-27 04:46:47 -05:00
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('convoClosed(QString)'),
|
|
|
|
irc, QtCore.SLOT('endConvo(QString)'))
|
2011-01-28 01:41:01 -05:00
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('profileChanged()'),
|
|
|
|
irc,
|
|
|
|
QtCore.SLOT('updateProfile()'))
|
2011-01-28 03:10:00 -05:00
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('moodRequest(PyQt_PyObject)'),
|
|
|
|
irc,
|
|
|
|
QtCore.SLOT('getMood(PyQt_PyObject)'))
|
2011-02-02 19:06:03 -05:00
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('moodsRequest(PyQt_PyObject)'),
|
|
|
|
irc,
|
|
|
|
QtCore.SLOT('getMoods(PyQt_PyObject)'))
|
2011-01-28 21:36:12 -05:00
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('moodUpdated()'),
|
|
|
|
irc,
|
|
|
|
QtCore.SLOT('updateMood()'))
|
2011-01-31 18:43:49 -05:00
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('mycolorUpdated()'),
|
|
|
|
irc,
|
|
|
|
QtCore.SLOT('updateColor()'))
|
2011-02-02 07:26:17 -05:00
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('blockedChum(QString)'),
|
|
|
|
irc,
|
|
|
|
QtCore.SLOT('blockedChum(QString)'))
|
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('unblockedChum(QString)'),
|
|
|
|
irc,
|
|
|
|
QtCore.SLOT('unblockedChum(QString)'))
|
2011-02-03 01:20:37 -05:00
|
|
|
irc.connect(widget,
|
|
|
|
QtCore.SIGNAL('requestNames(QString)'),
|
|
|
|
irc,
|
|
|
|
QtCore.SLOT('requestNames(QString)'))
|
|
|
|
|
|
|
|
# IRC --> Main window
|
2011-01-24 07:17:12 -05:00
|
|
|
irc.connect(irc,
|
|
|
|
QtCore.SIGNAL('moodUpdated(QString, PyQt_PyObject)'),
|
|
|
|
widget,
|
|
|
|
QtCore.SLOT('updateMoodSlot(QString, PyQt_PyObject)'))
|
|
|
|
irc.connect(irc,
|
|
|
|
QtCore.SIGNAL('colorUpdated(QString, QColor)'),
|
|
|
|
widget,
|
|
|
|
QtCore.SLOT('updateColorSlot(QString, QColor)'))
|
|
|
|
irc.connect(irc,
|
|
|
|
QtCore.SIGNAL('messageReceived(QString, QString)'),
|
|
|
|
widget,
|
|
|
|
QtCore.SLOT('deliverMessage(QString, QString)'))
|
2011-01-27 21:21:02 -05:00
|
|
|
irc.connect(irc,
|
2011-02-01 06:14:56 -05:00
|
|
|
QtCore.SIGNAL('nickCollision(QString, QString)'),
|
2011-01-27 21:21:02 -05:00
|
|
|
widget,
|
2011-02-01 06:14:56 -05:00
|
|
|
QtCore.SLOT('nickCollision(QString, QString)'))
|
2011-02-03 01:20:37 -05:00
|
|
|
irc.connect(irc,
|
|
|
|
QtCore.SIGNAL('namesReceived(QString, PyQt_PyObject)'),
|
|
|
|
widget,
|
|
|
|
QtCore.SLOT('updateNames(QString, PyQt_PyObject)'))
|
|
|
|
irc.connect(irc,
|
|
|
|
QtCore.SIGNAL('userPresentUpdate(QString, QString, QString)'),
|
|
|
|
widget,
|
|
|
|
QtCore.SLOT('userPresentUpdate(QString, QString, QString)'))
|
2011-01-24 07:17:12 -05:00
|
|
|
|
|
|
|
ircapp = IRCThread(irc)
|
|
|
|
ircapp.start()
|
2011-01-21 05:18:22 -05:00
|
|
|
sys.exit(app.exec_())
|
|
|
|
|
|
|
|
main()
|