pesterchum/pesterchum.py

2986 lines
123 KiB
Python
Raw Normal View History

2011-01-21 05:18:22 -05:00
# pesterchum
import logging
2011-05-12 10:14:38 -04:00
import os, sys, getopt
2011-01-27 21:21:02 -05:00
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-02-08 02:56:30 -05:00
import codecs
import re
2011-02-06 19:50:21 -05:00
import socket
2011-02-11 18:37:31 -05:00
import platform
from time import strftime
2011-01-21 05:18:22 -05:00
missing = []
try:
from PyQt4 import QtGui, QtCore
except ImportError, e:
module = str(e)
if module[:16] == "No module named ": missing.append(module[16:])
else: print e
try:
import pygame
except ImportError, e:
module = str(e)
if module[:16] == "No module named ": missing.append(module[16:])
else: print e
if missing:
print "ERROR: The following modules are required for Pesterchum to run and are missing on your system:"
for m in missing: print "* "+m
exit()
vnum = QtCore.qVersion()
major = int(vnum[:vnum.find(".")])
if vnum.find(".", vnum.find(".")+1) != -1:
minor = int(vnum[vnum.find(".")+1:vnum.find(".", vnum.find(".")+1)])
else:
minor = int(vnum[vnum.find(".")+1:])
if not ((major > 4) or (major == 4 and minor >= 6)):
print "ERROR: Pesterchum requires Qt version >= 4.6"
print "You currently have version " + vnum + ". Please ungrade Qt"
exit()
2011-02-04 16:17:27 -05:00
from menus import PesterChooseQuirks, PesterChooseTheme, \
2011-02-04 19:50:56 -05:00
PesterChooseProfile, PesterOptions, PesterUserlist, PesterMemoList, \
2011-02-09 01:26:23 -05:00
LoadingScreen, AboutPesterchum
2011-02-04 16:17:27 -05:00
from dataobjs import PesterProfile, Mood, pesterQuirk, pesterQuirks
from generic import PesterIcon, RightClickList, RightClickTree, MultiTextDialog, PesterList, CaseInsensitiveDict
2011-02-04 16:17:27 -05:00
from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo
2011-05-10 02:33:59 -04:00
from parsetools import convertTags, addTimeInitial, themeChecker, ThemeException
2011-02-13 04:27:12 -05:00
from memos import PesterMemo, MemoTabWindow, TimeTracker
2011-02-15 12:10:57 -05:00
from irc import PesterIRC
from logviewer import PesterLogUserSelect, PesterLogViewer
2011-01-21 05:18:22 -05:00
2011-03-02 18:36:10 -05:00
_datadir = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.DataLocation)+"Pesterchum/"
2011-04-13 02:12:19 -04:00
canon_handles = ["apocalypseArisen", "arsenicCatnip", "arachnidsGrip", "adiosToreador", "caligulasAquarium", "cuttlefishCuller", "carcinoGeneticist", "centaursTesticle", "grimAuxiliatrix", "gallowsCalibrator", "gardenGnostic", "ectoBiologist", "twinArmageddons", "terminallyCapricious", "turntechGodhead", "tentacleTherapist"]
2011-03-02 18:36:10 -05:00
if sys.platform == "darwin":
if not os.path.exists(_datadir):
os.mkdir(_datadir)
if not os.path.exists(_datadir+"profiles"):
os.mkdir(_datadir+"profiles")
if not os.path.exists(_datadir+"pesterchum.js"):
f = open(_datadir+"pesterchum.js", 'w')
f.close()
else:
if not os.path.exists("logs"):
os.mkdir("logs")
if not os.path.exists("profiles"):
os.mkdir("profiles")
if not os.path.exists("pesterchum.js"):
f = open("pesterchum.js", 'w')
f.write("{}")
f.close()
2011-03-02 18:36:10 -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()
2011-02-10 13:00:06 -05:00
def waitingHandles(self):
return self.queue
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, parent=None):
2011-03-02 18:36:10 -05:00
global _datadir
self.parent = parent
2011-02-02 03:20:48 -05:00
self.handle = handle
self.convos = {}
2011-03-02 18:36:10 -05:00
if sys.platform != "darwin":
self.logpath = "logs"
else:
self.logpath = _datadir+"logs"
2011-02-02 03:20:48 -05:00
def log(self, handle, msg):
2011-05-12 16:09:30 -04:00
if self.parent.config.time12Format():
time = strftime("[%I:%M")
else:
time = strftime("[%H:%M")
if self.parent.config.showSeconds():
time += strftime(":%S] ")
else:
time += "] "
if handle[0] == '#':
2011-05-12 16:09:30 -04:00
if not self.parent.config.logMemos() & self.parent.config.LOG: return
if not self.parent.config.logMemos() & self.parent.config.STAMP:
time = ""
else:
2011-05-12 16:09:30 -04:00
if not self.parent.config.logPesters() & self.parent.config.LOG: return
if not self.parent.config.logPesters() & self.parent.config.STAMP:
time = ""
if str(handle).upper() == "NICKSERV": return
2011-04-08 03:39:19 -04:00
#watch out for illegal characters
handle = re.sub(r'[<>:"/\\|?*]', "_", handle)
2011-05-12 16:09:30 -04:00
bbcodemsg = time + convertTags(msg, "bbcode")
html = time + convertTags(msg, "html")+"<br />"
msg = time +convertTags(msg, "text")
2011-02-13 04:27:12 -05:00
modes = {"bbcode": bbcodemsg, "html": html, "text": msg}
2011-02-02 03:20:48 -05:00
if not self.convos.has_key(handle):
2011-02-13 04:27:12 -05:00
time = datetime.now().strftime("%Y-%m-%d.%H.%M")
self.convos[handle] = {}
for (format, t) in modes.iteritems():
2011-03-02 18:36:10 -05:00
if not os.path.exists("%s/%s/%s/%s" % (self.logpath, self.handle, handle, format)):
os.makedirs("%s/%s/%s/%s" % (self.logpath, self.handle, handle, format))
fp = codecs.open("%s/%s/%s/%s/%s.%s.txt" % (self.logpath, self.handle, handle, format, handle, time), encoding='utf-8', mode='a')
2011-02-13 04:27:12 -05:00
self.convos[handle][format] = fp
for (format, t) in modes.iteritems():
f = self.convos[handle][format]
if platform.system() == "Windows":
f.write(t+"\r\n")
else:
f.write(t+"\r\n")
f.flush()
2011-02-02 03:20:48 -05:00
def finish(self, handle):
if not self.convos.has_key(handle):
return
2011-02-13 04:27:12 -05:00
for f in self.convos[handle].values():
f.close()
2011-02-02 03:20:48 -05:00
del self.convos[handle]
def close(self):
for h in self.convos.keys():
2011-02-13 04:27:12 -05:00
for f in self.convos[h].values():
f.close()
2011-02-02 03:20:48 -05:00
2011-01-31 18:43:49 -05:00
class PesterProfileDB(dict):
def __init__(self):
2011-03-02 18:36:10 -05:00
if sys.platform != "darwin":
self.logpath = "logs"
else:
self.logpath = _datadir+"logs"
if not os.path.exists(self.logpath):
os.makedirs(self.logpath)
2011-01-31 18:43:49 -05:00
try:
2011-03-02 18:36:10 -05:00
fp = open("%s/chums.js" % (self.logpath), 'r')
2011-01-31 18:43:49 -05:00
chumdict = json.load(fp)
fp.close()
except IOError:
chumdict = {}
2011-03-02 18:36:10 -05:00
fp = open("%s/chums.js" % (self.logpath), 'w')
2011-01-31 18:43:49 -05:00
json.dump(chumdict, fp)
fp.close()
2011-03-05 00:07:31 -05:00
except ValueError:
chumdict = {}
fp = open("%s/chums.js" % (self.logpath), 'w')
json.dump(chumdict, fp)
fp.close()
u = []
for (handle, c) in chumdict.iteritems():
try:
g = c['group']
u.append((handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']), group=g)))
except KeyError:
u.append((handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']))))
converted = dict(u)
2011-01-31 18:43:49 -05:00
self.update(converted)
def save(self):
2011-03-05 00:07:31 -05:00
try:
fp = open("%s/chums.js" % (self.logpath), 'w')
chumdict = dict([p.plaindict() for p in self.itervalues()])
json.dump(chumdict, fp)
fp.close()
except Exception, e:
raise e
2011-01-31 18:43:49 -05:00
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 getGroup(self, handle, default="Chums"):
if not self.has_key(handle):
return default
else:
return self[handle].group
def setGroup(self, handle, theGroup):
if self.has_key(handle):
self[handle].group = theGroup
else:
self[handle] = PesterProfile(handle, group=theGroup)
self.save()
2011-01-31 18:43:49 -05:00
def __setitem__(self, key, val):
dict.__setitem__(self, key, val)
self.save()
2011-01-24 02:34:07 -05:00
class pesterTheme(dict):
2011-02-09 01:26:23 -05:00
def __init__(self, name, default=False):
2011-03-02 18:36:10 -05:00
if sys.platform != "darwin":
self.path = "themes/%s" % (name)
else:
self.path = _datadir+"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-02-14 05:18:38 -05:00
if self.has_key("inherits"):
self.inheritedTheme = pesterTheme(self["inherits"])
2011-02-09 01:26:23 -05:00
if not default:
self.defaultTheme = pesterTheme("pesterchum", default=True)
2011-01-24 02:34:07 -05:00
def __getitem__(self, key):
keys = key.split("/")
2011-02-14 18:54:44 -05:00
try:
v = dict.__getitem__(self, keys.pop(0))
except KeyError, e:
if hasattr(self, 'inheritedTheme'):
return self.inheritedTheme[key]
if hasattr(self, 'defaultTheme'):
return self.defaultTheme[key]
else:
raise e
2011-01-24 02:34:07 -05:00
for k in keys:
2011-02-08 02:56:30 -05:00
try:
v = v[k]
2011-02-09 01:26:23 -05:00
except KeyError, e:
2011-02-14 05:18:38 -05:00
if hasattr(self, 'inheritedTheme'):
return self.inheritedTheme[key]
2011-02-09 01:26:23 -05:00
if hasattr(self, 'defaultTheme'):
return self.defaultTheme[key]
else:
raise e
2011-01-24 02:34:07 -05:00
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-02-06 19:50:21 -05:00
def get(self, key, default):
2011-02-09 01:26:23 -05:00
keys = key.split("/")
2011-02-14 05:18:38 -05:00
try:
v = dict.__getitem__(self, keys.pop(0))
2011-02-16 06:11:09 -05:00
for k in keys:
2011-02-09 01:26:23 -05:00
v = v[k]
2011-02-18 21:02:54 -05:00
return default if v is None else v
2011-02-16 06:11:09 -05:00
except KeyError:
if hasattr(self, 'inheritedTheme'):
return self.inheritedTheme.get(key, default)
else:
2011-02-09 01:26:23 -05:00
return default
2011-02-16 06:11:09 -05:00
2011-02-06 19:50:21 -05:00
def has_key(self, key):
2011-02-09 01:26:23 -05:00
keys = key.split("/")
2011-02-14 05:18:38 -05:00
try:
v = dict.__getitem__(self, keys.pop(0))
2011-02-16 06:11:09 -05:00
for k in keys:
2011-02-09 01:26:23 -05:00
v = v[k]
2011-02-18 21:02:54 -05:00
return False if v is None else True
2011-02-16 06:11:09 -05:00
except KeyError:
if hasattr(self, 'inheritedTheme'):
return self.inheritedTheme.has_key(key)
else:
2011-02-09 01:26:23 -05:00
return False
2011-01-29 07:33:35 -05:00
2011-01-21 05:18:22 -05:00
class userConfig(object):
2011-05-12 10:14:38 -04:00
def __init__(self, parent):
self.parent = parent
2011-05-12 16:09:30 -04:00
# Use for bit flag log setting
self.LOG = 1
self.STAMP = 2
if sys.platform != "darwin":
2011-03-02 18:36:10 -05:00
self.filename = "pesterchum.js"
else:
self.filename = _datadir+"pesterchum.js"
fp = open(self.filename)
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"):
self.userprofile = userProfile(self.config["defaultprofile"])
2011-01-27 21:21:02 -05:00
else:
self.userprofile = None
if sys.platform != "darwin":
self.logpath = "logs"
else:
self.logpath = _datadir+"logs"
if not os.path.exists(self.logpath):
os.makedirs(self.logpath)
try:
fp = open("%s/groups.js" % (self.logpath), 'r')
self.groups = json.load(fp)
fp.close()
except IOError:
self.groups = {}
fp = open("%s/groups.js" % (self.logpath), 'w')
json.dump(self.groups, fp)
fp.close()
except ValueError:
self.groups = {}
fp = open("%s/groups.js" % (self.logpath), 'w')
json.dump(self.groups, fp)
fp.close()
2011-01-21 05:18:22 -05:00
def chums(self):
2011-03-02 18:36:10 -05:00
if not self.config.has_key('chums'):
self.set("chums", [])
return self.config.get('chums', [])
2011-02-24 13:07:37 -05:00
def hideOfflineChums(self):
return self.config.get('hideOfflineChums', False)
def defaultprofile(self):
try:
return self.config['defaultprofile']
except KeyError:
return None
2011-01-26 05:32:35 -05:00
def tabs(self):
2011-03-02 18:36:10 -05:00
return self.config.get("tabs", True)
def showTimeStamps(self):
if not self.config.has_key('showTimeStamps'):
self.set("showTimeStamps", True)
return self.config.get('showTimeStamps', True)
def time12Format(self):
if not self.config.has_key('time12Format'):
self.set("time12Format", True)
return self.config.get('time12Format', True)
def showSeconds(self):
if not self.config.has_key('showSeconds'):
self.set("showSeconds", False)
return self.config.get('showSeconds', False)
def sortMethod(self):
return self.config.get('sortMethod', 0)
def useGroups(self):
return self.config.get('useGroups', False)
def openDefaultGroup(self):
groups = self.getGroups()
for g in groups:
if g[0] == "Chums":
return g[1]
return True
def showEmptyGroups(self):
if not self.config.has_key('emptyGroups'):
self.set("emptyGroups", False)
return self.config.get('emptyGroups', False)
def showOnlineNumbers(self):
if not self.config.has_key('onlineNumbers'):
self.set("onlineNumbers", False)
return self.config.get('onlineNumbers', False)
def logPesters(self):
2011-05-12 16:09:30 -04:00
return self.config.get('logPesters', self.LOG | self.STAMP)
def logMemos(self):
2011-05-12 16:09:30 -04:00
return self.config.get('logMemos', self.LOG)
def disableUserLinks(self):
return not self.config.get('userLinks', True)
2011-04-28 03:51:02 -04:00
def idleTime(self):
return self.config.get('idleTime', 10)
2011-05-05 02:48:44 -04:00
def minimizeAction(self):
return self.config.get('miniAction', 0)
def closeAction(self):
return self.config.get('closeAction', 1)
def opvoiceMessages(self):
return self.config.get('opvMessages', True)
def animations(self):
return self.config.get('animations', True)
def addChum(self, chum):
2011-03-02 18:36:10 -05:00
if chum.handle not in self.chums():
fp = open(self.filename) # what if we have two clients open??
2011-02-24 13:07:37 -05:00
newconfig = json.load(fp)
fp.close()
newchums = newconfig['chums'] + [chum.handle]
2011-02-06 19:50:21 -05:00
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]
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)
def getGroups(self):
if not self.groups.has_key('groups'):
self.saveGroups([["Chums", True]])
2011-05-06 02:25:51 -04:00
return self.groups.get('groups', [["Chums", True]])
def addGroup(self, group, open=True):
l = self.getGroups()
2011-05-06 02:25:51 -04:00
exists = False
for g in l:
if g[0] == group:
exists = True
break
if not exists:
l.append([group,open])
l.sort()
self.saveGroups(l)
def delGroup(self, group):
l = self.getGroups()
i = 0
for g in l:
if g[0] == group: break
i = i+1
l.pop(i)
l.sort()
self.saveGroups(l)
2011-05-06 02:25:51 -04:00
def expandGroup(self, group, open=True):
l = self.getGroups()
for g in l:
if g[0] == group:
g[1] = open
break
self.saveGroups(l)
def saveGroups(self, groups):
self.groups['groups'] = groups
try:
jsonoutput = json.dumps(self.groups)
except ValueError, e:
raise e
fp = open("%s/groups.js" % (self.logpath), 'w')
fp.write(jsonoutput)
fp.close()
2011-02-13 21:01:58 -05:00
def server(self):
2011-05-12 10:14:38 -04:00
if hasattr(self.parent, 'serverOverride'):
return self.parent.serverOverride
2011-03-05 20:21:45 -05:00
return self.config.get('server', 'irc.mindfang.org')
2011-02-13 21:01:58 -05:00
def port(self):
2011-05-12 10:14:38 -04:00
if hasattr(self.parent, 'portOverride'):
return self.parent.portOverride
2011-02-13 21:01:58 -05:00
return self.config.get('port', '6667')
2011-02-08 02:56:30 -05:00
def soundOn(self):
if not self.config.has_key('soundon'):
self.set('soundon', True)
return self.config['soundon']
def chatSound(self):
return self.config.get('chatSound', True)
def memoSound(self):
return self.config.get('memoSound', True)
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-03-02 18:36:10 -05:00
fp = open(self.filename, '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 sys.platform != "darwin":
2011-03-02 18:36:10 -05:00
self.profiledir = "profiles"
else:
self.profiledir = _datadir+"profiles"
2011-01-27 21:21:02 -05:00
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-03-02 18:36:10 -05:00
self.lastmood = self.chat.mood.value()
2011-01-27 21:21:02 -05:00
self.quirks = pesterQuirks([])
else:
2011-03-02 18:36:10 -05:00
fp = open("%s/%s.js" % (self.profiledir, user))
2011-01-27 21:21:02 -05:00
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-03-02 18:36:10 -05:00
self.lastmood = self.userprofile.get('lastmood', self.theme["main/defaultmood"])
2011-01-27 21:21:02 -05:00
self.chat = PesterProfile(self.userprofile["handle"],
QtGui.QColor(self.userprofile["color"]),
2011-03-02 18:36:10 -05:00
Mood(self.lastmood))
2011-01-27 21:21:02 -05:00
self.quirks = pesterQuirks(self.userprofile["quirks"])
2011-03-02 18:36:10 -05:00
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-03-02 18:36:10 -05:00
def getLastMood(self):
return self.lastmood
def setLastMood(self, mood):
self.lastmood = mood.value()
self.userprofile["lastmood"] = self.lastmood
self.save()
2011-01-27 21:21:02 -05:00
def getTheme(self):
return self.theme
def save(self):
handle = self.chat.handle
2011-04-08 03:39:19 -04:00
if handle[0:12] == "pesterClient":
# dont save temp profiles
return
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-03-02 18:36:10 -05:00
fp = open("%s/%s.js" % (self.profiledir, 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.QTreeWidgetItem):
def __init__(self, chum, window):
QtGui.QTreeWidgetItem.__init__(self, [chum.handle])
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(0, icon)
2011-02-03 01:20:37 -05:00
try:
self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
2011-02-03 01:20:37 -05:00
except KeyError:
self.setTextColor(0, 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(0, icon)
2011-02-03 01:20:37 -05:00
try:
self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
2011-02-03 01:20:37 -05:00
except KeyError:
self.setTextColor(0, 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
class chumArea(RightClickTree):
def __init__(self, chums, parent=None):
QtGui.QTreeWidget.__init__(self, parent)
self.mainwindow = parent
theme = self.mainwindow.theme
2011-01-21 05:18:22 -05:00
self.chums = chums
gTemp = self.mainwindow.config.getGroups()
self.groups = [g[0] for g in gTemp]
self.openGroups = [g[1] for g in gTemp]
self.showAllGroups(True)
2011-02-24 18:46:09 -05:00
if not self.mainwindow.config.hideOfflineChums():
self.showAllChums()
if not self.mainwindow.config.showEmptyGroups():
self.hideEmptyGroups()
self.groupMenu = QtGui.QMenu(self)
2011-04-13 02:12:19 -04:00
self.canonMenu = QtGui.QMenu(self)
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()'),
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()'),
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()'))
self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
self.connect(self.logchum, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('openChumLogs()'))
2011-04-13 02:12:19 -04:00
self.reportchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self)
self.connect(self.reportchum, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('reportChum()'))
self.findalts = QtGui.QAction("Find Alts", self)
self.connect(self.findalts, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('findAlts()'))
self.removegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/removegroup"], self)
self.connect(self.removegroup, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('removeGroup()'))
self.renamegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/renamegroup"], self)
self.connect(self.renamegroup, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('renameGroup()'))
self.optionsMenu.addAction(self.pester)
self.optionsMenu.addAction(self.logchum)
self.optionsMenu.addAction(self.blockchum)
self.optionsMenu.addAction(self.removechum)
self.moveMenu = QtGui.QMenu(self.mainwindow.theme["main/menus/rclickchumlist/movechum"], self)
self.optionsMenu.addMenu(self.moveMenu)
self.optionsMenu.addAction(self.reportchum)
self.moveGroupMenu()
self.groupMenu.addAction(self.renamegroup)
self.groupMenu.addAction(self.removegroup)
2011-04-13 02:12:19 -04:00
self.canonMenu.addAction(self.pester)
self.canonMenu.addAction(self.logchum)
self.canonMenu.addAction(self.blockchum)
self.canonMenu.addAction(self.removechum)
self.canonMenu.addMenu(self.moveMenu)
2011-04-13 02:12:19 -04:00
self.canonMenu.addAction(self.reportchum)
self.canonMenu.addAction(self.findalts)
2011-02-11 04:07:07 -05:00
self.initTheme(theme)
#self.sortItems()
#self.sortItems(1, QtCore.Qt.AscendingOrder)
self.setSortingEnabled(False)
self.header().hide()
self.setDropIndicatorShown(True)
self.setIndentation(4)
self.setDragEnabled(True)
self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
self.setAnimated(True)
self.setRootIsDecorated(False)
self.connect(self, QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem *, int)'),
self, QtCore.SLOT('expandGroup()'))
2011-04-13 02:12:19 -04:00
def getOptionsMenu(self):
text = str(self.currentItem().text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
if text == "Chums":
return None
elif text in self.groups:
return self.groupMenu
2011-04-13 02:12:19 -04:00
else:
currenthandle = self.currentItem().chum.handle
if currenthandle in canon_handles:
return self.canonMenu
else:
return self.optionsMenu
def dropEvent(self, event):
thisitem = str(event.source().currentItem().text(0))
if thisitem.rfind(" ") != -1:
thisitem = thisitem[0:thisitem.rfind(" ")]
if thisitem == "Chums" or thisitem in self.groups:
droppos = str(self.itemAt(event.pos()).text(0))
if droppos.rfind(" ") != -1:
droppos = droppos[0:droppos.rfind(" ")]
if droppos == "Chums" or droppos in self.groups:
saveOpen = event.source().currentItem().isExpanded()
saveDrop = self.itemAt(event.pos())
saveItem = self.takeTopLevelItem(self.indexOfTopLevelItem(event.source().currentItem()))
self.insertTopLevelItems(self.indexOfTopLevelItem(saveDrop)+1, [saveItem])
if saveOpen:
saveItem.setExpanded(True)
gTemp = []
for i in range(self.topLevelItemCount()):
text = str(self.topLevelItem(i).text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
gTemp.append([unicode(text), self.topLevelItem(i).isExpanded()])
self.mainwindow.config.saveGroups(gTemp)
else:
item = self.itemAt(event.pos())
if item:
text = str(item.text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
if text == "Chums" or text in self.groups:
group = text
else:
ptext = str(item.parent().text(0))
if ptext.rfind(" ") != -1:
ptext = ptext[0:ptext.rfind(" ")]
group = ptext
chumLabel = event.source().currentItem()
chumLabel.chum.group = group
self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, group)
self.takeItem(chumLabel)
self.addItem(chumLabel)
if self.mainwindow.config.showOnlineNumbers():
self.showOnlineNumbers()
def moveGroupMenu(self):
currentGroup = self.currentItem()
if currentGroup:
2011-05-06 02:25:51 -04:00
if currentGroup.parent():
text = str(currentGroup.parent().text(0))
else:
text = str(currentGroup.text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
currentGroup = text
self.moveMenu.clear()
actGroup = QtGui.QActionGroup(self)
groups = self.groups[:]
for gtext in groups:
if gtext == currentGroup:
continue
movegroup = self.moveMenu.addAction(gtext)
actGroup.addAction(movegroup)
self.connect(actGroup, QtCore.SIGNAL('triggered(QAction *)'),
self, QtCore.SLOT('moveToGroup(QAction *)'))
def addChum(self, chum):
if len([c for c in self.chums if c.handle == chum.handle]) != 0:
return
self.chums.append(chum)
if not (self.mainwindow.config.hideOfflineChums() and
2011-02-25 01:28:35 -05:00
chum.mood.name() == "offline"):
chumLabel = chumListing(chum, self.mainwindow)
self.addItem(chumLabel)
#self.topLevelItem(0).addChild(chumLabel)
#self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
2011-02-02 07:26:17 -05:00
def getChums(self, handle):
chums = self.findItems(handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive)
2011-02-02 07:26:17 -05:00
return chums
2011-02-24 18:46:09 -05:00
def showAllChums(self):
for c in self.chums:
chandle = c.handle
if not len(self.findItems(chandle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive)):
2011-02-24 18:46:09 -05:00
chumLabel = chumListing(c, self.mainwindow)
self.addItem(chumLabel)
self.sort()
2011-02-24 18:46:09 -05:00
def hideOfflineChums(self):
for j in range(self.topLevelItemCount()):
i = 0
listing = self.topLevelItem(j).child(i)
while listing is not None:
if listing.chum.mood.name() == "offline":
self.topLevelItem(j).takeChild(i)
else:
i += 1
listing = self.topLevelItem(j).child(i)
self.sort()
def showAllGroups(self, first=False):
if first:
for i,g in enumerate(self.groups):
child_1 = QtGui.QTreeWidgetItem(["%s" % (g)])
self.addTopLevelItem(child_1)
if self.openGroups[i]:
child_1.setExpanded(True)
return
curgroups = []
for i in range(self.topLevelItemCount()):
text = str(self.topLevelItem(i).text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
curgroups.append(text)
for i,g in enumerate(self.groups):
if g not in curgroups:
child_1 = QtGui.QTreeWidgetItem(["%s" % (g)])
j = 0
for h in self.groups:
if h == g:
self.insertTopLevelItem(j, child_1)
break
if h in curgroups:
j += 1
if self.openGroups[i]:
child_1.setExpanded(True)
if self.mainwindow.config.showOnlineNumbers():
self.showOnlineNumbers()
def showOnlineNumbers(self):
if hasattr(self, 'groups'):
self.hideOnlineNumbers()
totals = {'Chums': 0}
online = {'Chums': 0}
for g in self.groups:
totals[str(g)] = 0
online[str(g)] = 0
for c in self.chums:
yes = c.mood.name() != "offline"
if c.group == "Chums":
totals[str(c.group)] = totals[str(c.group)]+1
if yes:
online[str(c.group)] = online[str(c.group)]+1
elif c.group in totals:
totals[str(c.group)] = totals[str(c.group)]+1
if yes:
online[str(c.group)] = online[str(c.group)]+1
else:
totals["Chums"] = totals["Chums"]+1
if yes:
online["Chums"] = online["Chums"]+1
for i in range(self.topLevelItemCount()):
text = str(self.topLevelItem(i).text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
self.topLevelItem(i).setText(0, "%s (%i/%i)" % (text, online[text], totals[text]))
def hideOnlineNumbers(self):
for i in range(self.topLevelItemCount()):
text = str(self.topLevelItem(i).text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
self.topLevelItem(i).setText(0, "%s" % (text))
def hideEmptyGroups(self):
2011-02-24 18:46:09 -05:00
i = 0
listing = self.topLevelItem(i)
2011-02-24 18:46:09 -05:00
while listing is not None:
if listing.childCount() == 0:
self.takeTopLevelItem(i)
2011-02-24 18:46:09 -05:00
else:
i += 1
listing = self.topLevelItem(i)
@QtCore.pyqtSlot()
def expandGroup(self):
item = self.currentItem()
text = str(item.text(0))
2011-05-06 02:25:51 -04:00
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
if text in self.groups:
expand = item.isExpanded()
2011-05-06 02:25:51 -04:00
self.mainwindow.config.expandGroup(text, not expand)
def addItem(self, chumLabel):
if hasattr(self, 'groups'):
if chumLabel.chum.group not in self.groups:
2011-05-06 02:25:51 -04:00
chumLabel.chum.group = "Chums"
if "Chums" not in self.groups:
self.mainwindow.config.addGroup("Chums")
curgroups = []
for i in range(self.topLevelItemCount()):
text = str(self.topLevelItem(i).text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
curgroups.append(text)
2011-05-06 02:25:51 -04:00
if not self.findItems(chumLabel.handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive):
if chumLabel.chum.group not in curgroups:
2011-05-06 02:25:51 -04:00
child_1 = QtGui.QTreeWidgetItem(["%s" % (chumLabel.chum.group)])
i = 0
for g in self.groups:
if g == chumLabel.chum.group:
self.insertTopLevelItem(i, child_1)
break
if g in curgroups:
i += 1
2011-05-06 02:25:51 -04:00
if self.openGroups[self.groups.index("%s" % (chumLabel.chum.group))]:
child_1.setExpanded(True)
2011-05-06 02:25:51 -04:00
for i in range(self.topLevelItemCount()):
text = str(self.topLevelItem(i).text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
2011-05-06 02:25:51 -04:00
if text == chumLabel.chum.group:
break
self.topLevelItem(i).addChild(chumLabel)
self.sort()
2011-05-06 02:25:51 -04:00
if self.mainwindow.config.showOnlineNumbers():
self.showOnlineNumbers()
else: # usually means this is now the trollslum
if not self.findItems(chumLabel.handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive):
self.topLevelItem(0).addChild(chumLabel)
self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
def takeItem(self, chumLabel):
r = None
if not hasattr(chumLabel, 'chum'):
return r
for i in range(self.topLevelItemCount()):
for j in range(self.topLevelItem(i).childCount()):
if self.topLevelItem(i).child(j).text(0) == chumLabel.chum.handle:
r = self.topLevelItem(i).takeChild(j)
break
if not self.mainwindow.config.showEmptyGroups():
self.hideEmptyGroups()
if self.mainwindow.config.showOnlineNumbers():
self.showOnlineNumbers()
return r
2011-02-02 07:26:17 -05:00
def updateMood(self, handle, mood):
2011-02-24 18:46:09 -05:00
hideoff = self.mainwindow.config.hideOfflineChums()
2011-02-02 07:26:17 -05:00
chums = self.getChums(handle)
2011-02-08 17:47:07 -05:00
oldmood = None
2011-02-24 18:46:09 -05:00
if hideoff:
if mood.name() != "offline" and \
len(chums) == 0 and \
handle in [p.handle for p in self.chums]:
newLabel = chumListing([p for p in self.chums if p.handle == handle][0], self.mainwindow)
self.addItem(newLabel)
#self.sortItems()
2011-02-24 18:46:09 -05:00
chums = [newLabel]
elif mood.name() == "offline" and \
len(chums) > 0:
for c in chums:
if (hasattr(c, 'mood')):
c.setMood(mood)
2011-05-06 02:25:51 -04:00
self.takeItem(c)
2011-02-24 18:46:09 -05:00
chums = []
2011-01-22 04:36:24 -05:00
for c in chums:
if (hasattr(c, 'mood')):
oldmood = c.mood
c.setMood(mood)
if self.mainwindow.config.sortMethod() == 1:
for i in range(self.topLevelItemCount()):
saveCurrent = self.currentItem()
self.moodSort(i)
self.setCurrentItem(saveCurrent)
if self.mainwindow.config.showOnlineNumbers():
self.showOnlineNumbers()
2011-02-08 17:47:07 -05:00
return oldmood
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-02-11 04:07:07 -05:00
def initTheme(self, theme):
2011-03-05 20:21:45 -05:00
self.resize(*theme["main/chums/size"])
self.move(*theme["main/chums/loc"])
2011-02-11 04:07:07 -05:00
if theme.has_key("main/chums/scrollbar"):
self.setStyleSheet("QListWidget { %s } QScrollBar { %s } QScrollBar::handle { %s } QScrollBar::add-line { %s } QScrollBar::sub-line { %s } QScrollBar:up-arrow { %s } QScrollBar:down-arrow { %s }" % (theme["main/chums/style"], theme["main/chums/scrollbar/style"], theme["main/chums/scrollbar/handle"], theme["main/chums/scrollbar/downarrow"], theme["main/chums/scrollbar/uparrow"], theme["main/chums/scrollbar/uarrowstyle"], theme["main/chums/scrollbar/darrowstyle"] ))
else:
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"])
self.logchum.setText(theme["main/menus/rclickchumlist/viewlog"])
self.removegroup.setText(theme["main/menus/rclickchumlist/removegroup"])
self.renamegroup.setText(theme["main/menus/rclickchumlist/renamegroup"])
self.moveMenu.setTitle(theme["main/menus/rclickchumlist/movechum"])
2011-02-11 04:07:07 -05:00
def changeTheme(self, theme):
self.initTheme(theme)
chumlistings = []
for i in range(self.topLevelItemCount()):
for j in range(self.topLevelItem(i).childCount()):
chumlistings.append(self.topLevelItem(i).child(j))
#chumlistings = [self.item(i) for i in range(0, self.count())]
for c in chumlistings:
2011-01-28 06:17:42 -05:00
c.changeTheme(theme)
def count(self):
c = 0
for i in range(self.topLevelItemCount()):
c = c + self.topLevelItem(i).childCount()
return c
def sort(self):
if self.mainwindow.config.sortMethod() == 1:
for i in range(self.topLevelItemCount()):
self.moodSort(i)
else:
for i in range(self.topLevelItemCount()):
self.topLevelItem(i).sortChildren(0, QtCore.Qt.AscendingOrder)
def moodSort(self, group):
scrollPos = self.verticalScrollBar().sliderPosition()
chums = []
listing = self.topLevelItem(group).child(0)
while listing is not None:
chums.append(self.topLevelItem(group).takeChild(0))
listing = self.topLevelItem(group).child(0)
chums.sort(key=lambda x: ((999 if x.chum.mood.value() == 2 else x.chum.mood.value()), x.chum.handle), reverse=False)
for c in chums:
self.topLevelItem(group).addChild(c)
self.verticalScrollBar().setSliderPosition(scrollPos)
@QtCore.pyqtSlot()
def activateChum(self):
self.itemActivated.emit(self.currentItem(), 0)
@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
currentChum = self.currentItem().chum
self.chums = [c for c in self.chums if c.handle != currentChum.handle]
self.removeChumSignal.emit(self.currentItem().chum.handle)
oldlist = self.takeItem(self.currentItem())
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)
@QtCore.pyqtSlot()
2011-04-13 02:12:19 -04:00
def reportChum(self):
currentChum = self.currentItem()
if not currentChum:
return
self.mainwindow.reportChum(self.currentItem().chum.handle)
@QtCore.pyqtSlot()
def findAlts(self):
currentChum = self.currentItem()
if not currentChum:
return
self.mainwindow.sendMessage.emit("ALT %s" % (currentChum.chum.handle) , "calSprite")
@QtCore.pyqtSlot()
def openChumLogs(self):
currentChum = self.currentItem().text(0)
if not currentChum:
return
self.pesterlogviewer = PesterLogViewer(currentChum, self.mainwindow.config, self.mainwindow.theme, self.mainwindow)
self.connect(self.pesterlogviewer, QtCore.SIGNAL('rejected()'),
self, QtCore.SLOT('closeActiveLog()'))
self.pesterlogviewer.show()
self.pesterlogviewer.raise_()
self.pesterlogviewer.activateWindow()
@QtCore.pyqtSlot()
def closeActiveLog(self):
self.pesterlogviewer.close()
self.pesterlogviewer = None
2011-03-29 03:02:05 -04:00
@QtCore.pyqtSlot()
def renameGroup(self):
if not hasattr(self, 'renamegroupdialog'):
self.renamegroupdialog = None
if not self.renamegroupdialog:
(gname, ok) = QtGui.QInputDialog.getText(self, "Rename Group", "Enter a new name for the group:")
if ok:
gname = unicode(gname)
currentGroup = self.currentItem()
if not currentGroup:
return
index = self.indexOfTopLevelItem(currentGroup)
if index != -1:
expanded = currentGroup.isExpanded()
text = str(currentGroup.text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
self.mainwindow.config.delGroup(text)
self.mainwindow.config.addGroup(gname, expanded)
gTemp = self.mainwindow.config.getGroups()
self.groups = [g[0] for g in gTemp]
self.openGroups = [g[1] for g in gTemp]
for i in range(currentGroup.childCount()):
currentGroup.child(i).chum.group = gname
self.mainwindow.chumdb.setGroup(currentGroup.child(i).chum.handle, gname)
currentGroup.setText(0, gname)
if self.mainwindow.config.showOnlineNumbers():
self.showOnlineNumbers()
self.renamegroupdialog = None
2011-03-29 03:02:05 -04:00
@QtCore.pyqtSlot()
def removeGroup(self):
currentGroup = self.currentItem()
if not currentGroup:
return
text = str(currentGroup.text(0))
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
self.mainwindow.config.delGroup(text)
gTemp = self.mainwindow.config.getGroups()
self.groups = [g[0] for g in gTemp]
self.openGroups = [g[1] for g in gTemp]
for i in range(self.topLevelItemCount()):
if self.topLevelItem(i).text(0) == currentGroup.text(0):
break
while self.topLevelItem(i) and self.topLevelItem(i).child(0):
chumLabel = self.topLevelItem(i).child(0)
chumLabel.chum.group = "Chums"
self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, "Chums")
self.takeItem(chumLabel)
self.addItem(chumLabel)
self.takeTopLevelItem(i)
2011-03-29 03:02:05 -04:00
@QtCore.pyqtSlot(QtGui.QAction)
def moveToGroup(self, item):
if not item:
return
group = str(item.text())
chumLabel = self.currentItem()
if not chumLabel:
return
chumLabel.chum.group = group
self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, group)
self.takeItem(chumLabel)
self.addItem(chumLabel)
removeChumSignal = QtCore.pyqtSignal(QtCore.QString)
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
child_1 = QtGui.QTreeWidgetItem([""])
self.addTopLevelItem(child_1)
child_1.setExpanded(True)
2011-02-02 19:06:03 -05:00
for c in self.chums:
chandle = c.handle
if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)):
chumLabel = chumListing(c, self.mainwindow)
self.addItem(chumLabel)
self.setSortingEnabled(False)
self.header().hide()
self.setDropIndicatorShown(False)
self.setIndentation(0)
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 contextMenuEvent(self, event):
#fuckin Qt
if event.reason() == QtGui.QContextMenuEvent.Mouse:
listing = self.itemAt(event.pos())
self.setCurrentItem(listing)
if self.currentItem().text(0) != "":
self.optionsMenu.popup(event.globalPos())
2011-02-02 19:06:03 -05:00
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 or not hasattr(currentListing, 'chum'):
2011-02-02 19:06:03 -05:00
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-02-10 00:55:45 -05:00
class PesterMoodAction(QtCore.QObject):
def __init__(self, m, func):
QtCore.QObject.__init__(self)
self.mood = m
self.func = func
@QtCore.pyqtSlot()
def updateMood(self):
self.func(self.mood)
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):
2011-02-24 18:46:09 -05:00
# update MY mood
2011-01-28 21:36:12 -05:00
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-02-10 00:55:45 -05:00
try:
newbutton = self.buttons[m]
newbutton.setSelected(True)
except KeyError:
pass
2011-01-28 21:36:12 -05:00
newmood = Mood(m)
self.mainwindow.userprofile.chat.mood = newmood
2011-03-02 18:36:10 -05:00
self.mainwindow.userprofile.setLastMood(newmood)
2011-02-06 19:50:21 -05:00
if self.mainwindow.currentMoodIcon:
moodicon = newmood.icon(self.mainwindow.theme)
self.mainwindow.currentMoodIcon.setPixmap(moodicon.pixmap(moodicon.realsize()))
2011-02-24 20:03:17 -05:00
if oldmood.name() != newmood.name():
for c in self.mainwindow.convos.values():
c.myUpdateMood(newmood)
2011-01-28 21:36:12 -05:00
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):
2011-02-24 18:46:09 -05:00
# updates OUR mood
2011-01-28 21:36:12 -05:00
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-02-02 03:20:48 -05:00
2011-01-22 04:36:24 -05:00
class PesterWindow(MovingWindow):
2011-05-12 10:14:38 -04:00
def __init__(self, options, parent=None):
2011-04-11 02:17:47 -04:00
MovingWindow.__init__(self, parent,
(QtCore.Qt.CustomizeWindowHint |
2011-03-31 17:57:30 -04:00
QtCore.Qt.FramelessWindowHint))
2011-04-14 05:50:55 -04:00
self.convos = CaseInsensitiveDict()
self.memos = CaseInsensitiveDict()
2011-01-31 06:04:03 -05:00
self.tabconvo = None
2011-02-04 19:50:56 -05:00
self.tabmemo = None
2011-05-12 10:14:38 -04:00
if "advanced" in options:
self.advanced = options["advanced"]
else: self.advanced = False
if "server" in options:
self.serverOverride = options["server"]
if "port" in options:
self.portOverride = options["port"]
2011-01-31 06:04:03 -05:00
2011-02-06 19:50:21 -05:00
self.setAutoFillBackground(True)
2011-01-22 04:36:24 -05:00
self.setObjectName("main")
2011-05-12 10:14:38 -04:00
self.config = userConfig(self)
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()
self.modes = ""
2011-05-10 02:33:59 -04:00
try:
themeChecker(self.theme)
except ThemeException, (inst):
print "Caught: "+inst.parameter
themeWarning = QtGui.QMessageBox(self)
themeWarning.setText("Theme Error: %s" % (inst))
2011-05-10 02:33:59 -04:00
themeWarning.exec_()
self.theme = pesterTheme("pesterchum")
self.chatlog = PesterLog(self.profile().handle, self)
2011-02-02 03:20:48 -05:00
2011-01-31 06:04:03 -05:00
self.move(100, 100)
2011-01-22 04:36:24 -05:00
logv = QtGui.QAction(self.theme["main/menus/client/logviewer"], self)
self.logv = logv
self.connect(logv, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('openLogv()'))
grps = QtGui.QAction(self.theme["main/menus/client/addgroup"], self)
self.grps = grps
self.connect(grps, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('addGroupWindow()'))
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-02-04 16:17:27 -05:00
memoaction = QtGui.QAction(self.theme["main/menus/client/memos"], self)
self.memoaction = memoaction
self.connect(memoaction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('showMemos()'))
2011-02-06 19:50:21 -05:00
self.importaction = QtGui.QAction(self.theme["main/menus/client/import"], self)
self.connect(self.importaction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('importExternalConfig()'))
2011-02-13 04:27:12 -05:00
self.idleaction = QtGui.QAction(self.theme["main/menus/client/idle"], self)
self.idleaction.setCheckable(True)
self.connect(self.idleaction, QtCore.SIGNAL('toggled(bool)'),
self, QtCore.SLOT('toggleIdle(bool)'))
2011-02-14 16:15:32 -05:00
self.reconnectAction = QtGui.QAction(self.theme["main/menus/client/reconnect"], self)
self.connect(self.reconnectAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SIGNAL('reconnectIRC()'))
2011-02-10 20:55:45 -05:00
2011-01-27 04:46:47 -05:00
self.menu = QtGui.QMenuBar(self)
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-04 16:17:27 -05:00
filemenu.addAction(memoaction)
filemenu.addAction(logv)
2011-02-03 01:20:37 -05:00
filemenu.addAction(userlistaction)
2011-02-13 04:27:12 -05:00
filemenu.addAction(self.idleaction)
filemenu.addAction(grps)
2011-02-06 19:50:21 -05:00
filemenu.addAction(self.importaction)
2011-02-14 16:15:32 -05:00
filemenu.addAction(self.reconnectAction)
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
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-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-05-10 02:33:59 -04:00
self.helpAction = QtGui.QAction(self.theme["main/menus/help/help"], self)
2011-03-05 21:25:52 -05:00
self.connect(self.helpAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('launchHelp()'))
2011-05-10 02:33:59 -04:00
self.botAction = QtGui.QAction(self.theme["main/menus/help/calsprite"], self)
self.connect(self.botAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('loadCalsprite()'))
2011-05-10 02:33:59 -04:00
self.nickServAction = QtGui.QAction(self.theme["main/menus/help/nickserv"], self)
self.connect(self.nickServAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('loadNickServ()'))
self.aboutAction = QtGui.QAction(self.theme["main/menus/help/about"], self)
self.connect(self.aboutAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('aboutPesterchum()'))
2011-02-09 01:26:23 -05:00
helpmenu = self.menu.addMenu(self.theme["main/menus/help/_name"])
self.helpmenu = helpmenu
2011-03-05 21:25:52 -05:00
self.helpmenu.addAction(self.helpAction)
2011-04-13 02:12:19 -04:00
self.helpmenu.addAction(self.botAction)
self.helpmenu.addAction(self.nickServAction)
2011-02-09 01:26:23 -05:00
self.helpmenu.addAction(self.aboutAction)
2011-02-02 03:20:48 -05:00
self.closeButton = WMButton(PesterIcon(self.theme["main/close/image"]), self)
2011-05-05 02:48:44 -04:00
self.setButtonAction(self.closeButton, self.config.closeAction(), -1)
2011-02-02 03:20:48 -05:00
self.miniButton = WMButton(PesterIcon(self.theme["main/minimize/image"]), self)
2011-05-05 02:48:44 -04:00
self.setButtonAction(self.miniButton, self.config.minimizeAction(), -1)
2011-01-27 04:46:47 -05:00
2011-04-14 05:50:55 -04:00
self.namesdb = CaseInsensitiveDict()
2011-01-31 18:43:49 -05:00
self.chumdb = PesterProfileDB()
2011-02-24 18:46:09 -05:00
chums = [PesterProfile(c, chumdb=self.chumdb) for c in set(self.config.chums())]
self.chumList = chumArea(chums, self)
self.connect(self.chumList,
QtCore.SIGNAL('itemActivated(QTreeWidgetItem *, int)'),
self,
QtCore.SLOT('pesterSelectedChum()'))
self.connect(self.chumList,
QtCore.SIGNAL('removeChumSignal(QString)'),
self,
QtCore.SLOT('removeChum(QString)'))
2011-02-02 07:26:17 -05:00
self.connect(self.chumList,
QtCore.SIGNAL('blockChumSignal(QString)'),
self,
QtCore.SLOT('blockChum(QString)'))
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-31 06:04:03 -05:00
self.initTheme(self.theme)
self.waitingMessages = waitingMessageHolder(self)
2011-01-31 06:04:03 -05:00
2011-02-13 04:27:12 -05:00
self.autoidle = False
2011-04-28 03:51:02 -04:00
self.idlethreshold = 60*self.config.idleTime()
2011-02-10 20:55:45 -05:00
self.idletimer = QtCore.QTimer(self)
self.idleposition = QtGui.QCursor.pos()
self.idletime = 0
self.connect(self.idletimer, QtCore.SIGNAL('timeout()'),
self, QtCore.SLOT('checkIdle()'))
self.idletimer.start(1000)
2011-01-31 06:04:03 -05:00
if not self.config.defaultprofile():
self.changeProfile()
2011-01-28 21:36:12 -05:00
def profile(self):
return self.userprofile.chat
def closeConversations(self, switch=False):
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-02-04 19:50:56 -05:00
if self.tabmemo:
if not switch:
self.tabmemo.close()
else:
for m in self.tabmemo.convos:
self.tabmemo.convos[m].sendtime()
2011-02-04 19:50:56 -05:00
else:
for m in self.memos.values():
if not switch:
m.close()
else:
m.sendtime()
2011-02-06 19:50:21 -05:00
def paintEvent(self, event):
palette = QtGui.QPalette()
palette.setBrush(QtGui.QPalette.Window, QtGui.QBrush(self.backgroundImage))
self.setPalette(palette)
2011-02-04 19:50:56 -05:00
2011-02-08 02:56:30 -05:00
@QtCore.pyqtSlot()
def closeToTray(self):
self.hide()
self.closeToTraySignal.emit()
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-02-13 20:32:02 -05:00
self.closeSignal.emit()
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
2011-02-10 20:55:45 -05:00
self.sendMessage.emit("PESTERCHUM:BLOCKED", handle)
2011-02-02 07:26:17 -05:00
return
2011-01-24 04:10:44 -05:00
if not self.convos.has_key(handle):
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-02-08 02:56:30 -05:00
if self.config.soundOn():
if self.config.chatSound():
if msg in ["PESTERCHUM:CEASE", "PESTERCHUM:BLOCK"]:
self.ceasesound.play()
else:
self.alarm.play()
2011-02-04 19:50:56 -05:00
def newMemoMsg(self, chan, handle, msg):
2011-04-14 05:50:55 -04:00
if not self.memos.has_key(chan):
2011-02-04 19:50:56 -05:00
# silently ignore in case we forgot to /part
return
2011-04-14 05:50:55 -04:00
memo = self.memos[chan]
2011-02-13 04:27:12 -05:00
msg = unicode(msg)
if not memo.times.has_key(handle):
# new chum! time current
newtime = timedelta(0)
time = TimeTracker(newtime)
memo.times[handle] = time
if msg[0:3] != "/me" and msg[0:13] != "PESTERCHUM:ME":
msg = addTimeInitial(msg, memo.times[handle].getGrammar())
2011-02-04 19:50:56 -05:00
memo.addMessage(msg, handle)
2011-03-07 23:13:46 -05:00
if self.config.soundOn():
if self.config.memoSound():
self.memosound.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):
2011-02-24 18:46:09 -05:00
# updates OTHER chums' moods
2011-02-08 17:47:07 -05:00
oldmood = self.chumList.updateMood(handle, mood)
2011-01-24 02:34:07 -05:00
if self.convos.has_key(handle):
2011-02-08 17:47:07 -05:00
self.convos[handle].updateMood(mood, old=oldmood)
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-04-13 02:12:19 -04:00
if type(chum) in [str, unicode]:
matchingChums = [c for c in self.chumList.chums if c.handle == chum]
if len(matchingChums) > 0:
mood = matchingChums[0].mood
else:
mood = Mood(2)
chum = PesterProfile(chum, mood=mood, chumdb=self.chumdb)
if len(matchingChums) == 0:
self.moodRequest.emit(chum)
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-02-04 19:50:56 -05:00
self.connect(convoWindow, QtCore.SIGNAL('messageSent(QString, QString)'),
self, QtCore.SIGNAL('sendMessage(QString, QString)'))
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
if str(chum.handle).upper() == "NICKSERV" or \
str(chum.handle).upper() == "CHANSERV" or \
str(chum.handle).upper() == "MEMOSERV" or \
str(chum.handle).upper() == "OPERSERV" or \
str(chum.handle).upper() == "HELPSERV":
convoWindow.toggleQuirks(True)
convoWindow.quirksOff.setChecked(True)
else:
if str(chum.handle).upper() == "CALSPRITE" or \
str(chum.handle).upper() == "RANDOMENCOUNTER":
convoWindow.toggleQuirks(True)
convoWindow.quirksOff.setChecked(True)
self.newConvoStarted.emit(QtCore.QString(chum.handle), initiated)
2011-01-24 02:34:07 -05:00
convoWindow.show()
2011-02-04 19:50:56 -05:00
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-02-04 19:50:56 -05:00
def createMemoTabWindow(self):
self.tabmemo = MemoTabWindow(self)
self.connect(self.tabmemo, QtCore.SIGNAL('windowClosed()'),
self, QtCore.SLOT('memoTabsClosed()'))
2011-02-04 16:17:27 -05:00
def newMemo(self, channel, timestr, secret=False, invite=False):
2011-02-04 19:50:56 -05:00
if channel == "#pesterchum":
return
2011-04-14 05:50:55 -04:00
if self.memos.has_key(channel):
self.memos[channel].showChat()
2011-02-04 16:17:27 -05:00
return
# do slider dialog then set
2011-02-04 19:50:56 -05:00
if self.config.tabs():
if not self.tabmemo:
self.createMemoTabWindow()
memoWindow = PesterMemo(channel, timestr, self, self.tabmemo)
2011-02-04 19:50:56 -05:00
self.tabmemo.show()
2011-02-04 16:17:27 -05:00
else:
memoWindow = PesterMemo(channel, timestr, self, None)
2011-02-04 16:17:27 -05:00
# connect signals
self.connect(self, QtCore.SIGNAL('inviteOnlyChan(QString)'),
memoWindow, QtCore.SLOT('closeInviteOnly(QString)'))
2011-02-04 19:50:56 -05:00
self.connect(memoWindow, QtCore.SIGNAL('messageSent(QString, QString)'),
self, QtCore.SIGNAL('sendMessage(QString, QString)'))
self.connect(memoWindow, QtCore.SIGNAL('windowClosed(QString)'),
self, QtCore.SLOT('closeMemo(QString)'))
self.connect(self, QtCore.SIGNAL('namesUpdated()'),
memoWindow, QtCore.SLOT('namesUpdated()'))
self.connect(self,
QtCore.SIGNAL('userPresentSignal(QString, QString, QString)'),
memoWindow, QtCore.SLOT('userPresentChange(QString, QString, QString)'))
2011-02-04 16:17:27 -05:00
# chat client send memo open
2011-04-14 05:50:55 -04:00
self.memos[channel] = memoWindow
self.joinChannel.emit(channel) # race condition?
2011-02-06 19:50:21 -05:00
self.secret = secret
if self.secret:
self.secret = True
self.setChannelMode.emit(channel, "+s", "")
if invite:
self.setChannelMode.emit(channel, "+i", "")
memoWindow.sendTimeInfo()
2011-02-04 19:50:56 -05:00
memoWindow.show()
2011-02-04 16:17:27 -05:00
def addChum(self, chum):
self.chumList.addChum(chum)
self.config.addChum(chum)
self.moodRequest.emit(chum)
def changeProfile(self, collision=None):
2011-01-31 06:04:03 -05:00
if not hasattr(self, 'chooseprofile'):
self.chooseprofile = None
if not self.chooseprofile:
self.chooseprofile = PesterChooseProfile(self.userprofile, self.config, self.theme, self, collision=collision)
self.chooseprofile.exec_()
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
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"])
2011-02-06 19:50:21 -05:00
self.setStyleSheet("QFrame#main { %s }" % (theme["main/style"]))
self.backgroundImage = QtGui.QPixmap(theme["main/background-image"])
self.backgroundMask = self.backgroundImage.mask()
self.setMask(self.backgroundMask)
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.logv.setText(theme["main/menus/client/logviewer"])
self.grps.setText(theme["main/menus/client/addgroup"])
2011-02-01 06:14:56 -05:00
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"])
self.memoaction.setText(theme["main/menus/client/memos"])
2011-02-06 19:50:21 -05:00
self.importaction.setText(theme["main/menus/client/import"])
2011-02-13 04:27:12 -05:00
self.idleaction.setText(theme["main/menus/client/idle"])
2011-02-14 16:15:32 -05:00
self.reconnectAction.setText(theme["main/menus/client/reconnect"])
2011-02-01 06:14:56 -05:00
self.filemenu.setTitle(theme["main/menus/client/_name"])
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-02-09 01:26:23 -05:00
self.aboutAction.setText(self.theme["main/menus/help/about"])
self.helpmenu.setTitle(self.theme["main/menus/help/_name"])
2011-02-01 06:14:56 -05:00
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()
2011-02-23 16:31:20 -05:00
mood_list = theme["main/moods"]
mood_list = [dict([(str(k),v) for (k,v) in d.iteritems()])
2011-02-23 16:31:20 -05:00
for d in mood_list]
self.moods = PesterMoodHandler(self, *[PesterMoodButton(self, **d) for d in mood_list])
2011-01-28 21:36:12 -05:00
self.moods.showButtons()
# chum
2011-02-06 19:50:21 -05:00
addChumStyle = "QPushButton { %s }" % (theme["main/addchum/style"])
if theme.has_key("main/addchum/pressed"):
addChumStyle += "QPushButton:pressed { %s }" % (theme["main/addchum/pressed"])
pesterButtonStyle = "QPushButton { %s }" % (theme["main/pester/style"])
if theme.has_key("main/pester/pressed"):
pesterButtonStyle += "QPushButton:pressed { %s }" % (theme["main/pester/pressed"])
blockButtonStyle = "QPushButton { %s }" % (theme["main/block/style"])
if theme.has_key("main/block/pressed"):
pesterButtonStyle += "QPushButton:pressed { %s }" % (theme["main/block/pressed"])
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"])
2011-02-06 19:50:21 -05:00
self.addChumButton.setStyleSheet(addChumStyle)
2011-01-31 06:04:03 -05:00
self.pesterButton.setText(theme["main/pester/text"])
self.pesterButton.resize(*theme["main/pester/size"])
self.pesterButton.move(*theme["main/pester/loc"])
2011-02-06 19:50:21 -05:00
self.pesterButton.setStyleSheet(pesterButtonStyle)
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"])
2011-02-06 19:50:21 -05:00
self.blockButton.setStyleSheet(blockButtonStyle)
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-02-06 19:50:21 -05:00
if self.theme.has_key("main/mychumhandle/currentMood"):
moodicon = self.profile().mood.icon(theme)
2011-02-08 05:18:37 -05:00
if hasattr(self, 'currentMoodIcon') and self.currentMoodIcon:
self.currentMoodIcon.hide()
self.currentMoodIcon = None
2011-02-06 19:50:21 -05:00
self.currentMoodIcon = QtGui.QLabel(self)
self.currentMoodIcon.setPixmap(moodicon.pixmap(moodicon.realsize()))
self.currentMoodIcon.move(*theme["main/mychumhandle/currentMood"])
self.currentMoodIcon.show()
else:
if hasattr(self, 'currentMoodIcon') and self.currentMoodIcon:
self.currentMoodIcon.hide()
self.currentMoodIcon = None
2011-01-31 06:04:03 -05:00
if theme["main/mychumhandle/colorswatch/text"]:
self.mychumcolor.setText(theme["main/mychumhandle/colorswatch/text"])
2011-02-16 06:11:09 -05:00
else:
self.mychumcolor.setText("")
2011-01-29 07:33:35 -05:00
# sounds
if not pygame.mixer:
self.alarm = NoneSound()
self.memosound = NoneSound()
2011-02-10 20:55:45 -05:00
self.ceasesound = NoneSound()
else:
2011-03-07 19:13:47 -05:00
try:
self.alarm = pygame.mixer.Sound(theme["main/sounds/alertsound"])
self.memosound = pygame.mixer.Sound(theme["main/sounds/memosound"])
2011-03-07 19:13:47 -05:00
self.ceasesound = pygame.mixer.Sound(theme["main/sounds/ceasesound"])
except Exception, e:
self.alarm = NoneSound()
self.memosound = NoneSound()
2011-03-07 19:13:47 -05:00
self.ceasesound = NoneSound()
2011-01-31 06:04:03 -05:00
def changeTheme(self, theme):
2011-05-10 02:33:59 -04:00
# check theme
try:
themeChecker(theme)
except ThemeException, (inst):
themeWarning = QtGui.QMessageBox(self)
themeWarning.setText("Theme Error: %s" % (inst))
2011-05-10 02:33:59 -04:00
themeWarning.exec_()
theme = pesterTheme("pesterchum")
return
2011-01-31 06:04:03 -05:00
self.theme = theme
# do self
self.initTheme(theme)
2011-02-06 19:50:21 -05:00
# set mood
self.moods.updateMood(theme['main/defaultmood'])
2011-01-31 06:04:03 -05:00
# chum area
self.chumList.changeTheme(theme)
# do open windows
if self.tabconvo:
self.tabconvo.changeTheme(theme)
2011-02-05 22:24:27 -05:00
if self.tabmemo:
self.tabmemo.changeTheme(theme)
2011-01-31 06:04:03 -05:00
for c in self.convos.values():
c.changeTheme(theme)
2011-02-05 22:27:13 -05:00
for m in self.memos.values():
m.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)
# system tray icon
self.updateSystemTray()
2011-01-31 06:04:03 -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()
2011-02-08 02:56:30 -05:00
elif self.isHidden():
self.show()
else:
if self.isActiveWindow():
2011-03-05 20:21:45 -05:00
self.closeToTray()
else:
self.raise_()
self.activateWindow()
else:
self.waitingMessages.answerMessage()
2011-01-28 06:17:42 -05:00
2011-02-04 19:50:56 -05:00
@QtCore.pyqtSlot()
def connected(self):
if self.loadingscreen:
2011-02-21 14:07:59 -05:00
self.loadingscreen.done(QtGui.QDialog.Accepted)
2011-02-04 19:50:56 -05:00
self.loadingscreen = None
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:
text = str(curChum.text(0))
2011-05-06 02:25:51 -04:00
if text.rfind(" (") != -1:
text = text[0:text.rfind(" (")]
if text not in self.chumList.groups and \
text != "Chums":
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-13 04:27:12 -05:00
self.chatlog.log(chum.handle, self.profile().pestermsg(chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/ceasepester"]))
2011-01-31 18:43:49 -05:00
self.convoClosed.emit(handle)
self.chatlog.finish(h)
2011-02-02 03:20:48 -05:00
del self.convos[h]
@QtCore.pyqtSlot(QtCore.QString)
def closeMemo(self, channel):
c = unicode(channel)
self.chatlog.finish(c)
self.leftChannel.emit(channel)
2011-04-14 05:50:55 -04:00
del self.memos[c]
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-02-04 19:50:56 -05:00
@QtCore.pyqtSlot()
def memoTabsClosed(self):
del self.tabmemo
self.tabmemo = None
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-04 19:50:56 -05:00
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
def deliverMemo(self, chan, handle, msg):
(c, h, m) = (unicode(chan), unicode(handle), unicode(msg))
self.newMemoMsg(c,h,m)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
def deliverNotice(self, handle, msg):
h = unicode(handle)
m = unicode(msg)
if self.convos.has_key(h):
self.newMessage(h, m)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
def deliverInvite(self, handle, channel):
msgbox = QtGui.QMessageBox()
msgbox.setText("You're invited!")
msgbox.setInformativeText("%s has invited you to the memo: %s\nWould you like to join them?" % (handle, channel))
msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
ret = msgbox.exec_()
if ret == QtGui.QMessageBox.Ok:
self.newMemo(unicode(channel), "+0:00")
@QtCore.pyqtSlot(QtCore.QString)
def chanInviteOnly(self, channel):
print "Invite only: %s" % channel
self.inviteOnlyChan.emit(channel)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
def timeCommand(self, chan, handle, command):
(c, h, cmd) = (unicode(chan), unicode(handle), unicode(command))
2011-04-14 05:50:55 -04:00
if self.memos[c]:
self.memos[c].timeUpdate(h, cmd)
2011-01-24 07:17:12 -05:00
2011-02-03 01:20:37 -05:00
@QtCore.pyqtSlot(QtCore.QString, PesterList)
def updateNames(self, channel, names):
2011-04-14 05:50:55 -04:00
c = unicode(channel)
2011-02-03 01:20:37 -05:00
# 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):
2011-04-14 05:50:55 -04:00
c = unicode(channel)
2011-02-03 01:20:37 -05:00
n = unicode(handle)
2011-02-06 01:02:39 -05:00
if update == "nick":
l = n.split(":")
oldnick = l[0]
newnick = l[1]
if update == "quit":
2011-02-03 01:20:37 -05:00
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] = []
2011-02-06 01:02:39 -05:00
elif update == "nick":
2011-02-05 22:24:10 -05:00
for c in self.namesdb.keys():
try:
2011-02-06 01:02:39 -05:00
i = self.namesdb[c].index(oldnick)
self.namesdb[c].pop(i)
self.namesdb[c].append(newnick)
2011-02-05 22:24:10 -05:00
except ValueError:
2011-02-06 01:02:39 -05:00
pass
2011-02-05 22:24:10 -05:00
except KeyError:
2011-02-06 01:02:39 -05:00
pass
2011-02-03 01:20:37 -05:00
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()
def addChumWindow(self):
2011-01-31 06:04:03 -05:00
if not hasattr(self, 'addchumdialog'):
self.addchumdialog = None
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)
self.addchumdialog = None
@QtCore.pyqtSlot(QtCore.QString)
def removeChum(self, chumlisting):
self.config.removeChum(chumlisting)
def reportChum(self, handle):
2011-04-13 02:12:19 -04:00
(reason, ok) = QtGui.QInputDialog.getText(self, "Report User", "Enter the reason you are reporting this user (optional):")
if ok:
self.sendMessage.emit("REPORT %s %s" % (handle, reason) , "calSprite")
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))
2011-02-13 04:27:12 -05:00
self.chatlog.log(convo.chum.handle, msg)
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))
2011-02-13 04:27:12 -05:00
self.chatlog.log(convo.chum.handle, msg)
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-02-10 20:55:45 -05:00
@QtCore.pyqtSlot(bool)
def toggleIdle(self, idle):
2011-02-13 04:27:12 -05:00
if idle:
2011-02-10 20:55:45 -05:00
sysColor = QtGui.QColor(self.theme["convo/systemMsgColor"])
verb = self.theme["convo/text/idle"]
for (h, convo) in self.convos.iteritems():
2011-02-14 01:28:25 -05:00
if convo.chumopen:
msg = self.profile().idlemsg(sysColor, verb)
convo.textArea.append(convertTags(msg))
self.chatlog.log(h, msg)
self.sendMessage.emit("PESTERCHUM:IDLE", h)
2011-02-13 04:27:12 -05:00
else:
self.idletime = 0
2011-02-10 20:55:45 -05:00
@QtCore.pyqtSlot()
def checkIdle(self):
newpos = QtGui.QCursor.pos()
if newpos == self.idleposition:
self.idletime += 1
else:
self.idletime = 0
if self.idletime >= self.idlethreshold:
2011-02-13 04:27:12 -05:00
if not self.idleaction.isChecked():
self.idleaction.toggle()
self.autoidle = True
2011-02-10 20:55:45 -05:00
else:
2011-02-13 04:27:12 -05:00
if self.autoidle:
if self.idleaction.isChecked():
self.idleaction.toggle()
self.autoidle = False
2011-02-10 20:55:45 -05:00
self.idleposition = newpos
@QtCore.pyqtSlot()
2011-02-06 19:50:21 -05:00
def importExternalConfig(self):
f = QtGui.QFileDialog.getOpenFileName(self)
2011-02-21 14:07:59 -05:00
if f == "":
return
2011-02-06 19:50:21 -05:00
fp = open(f, 'r')
2011-02-24 21:15:21 -05:00
regexp_state = None
2011-02-06 19:50:21 -05:00
for l in fp.xreadlines():
# import chumlist
2011-02-24 21:15:21 -05:00
l = l.rstrip()
2011-02-06 19:50:21 -05:00
chum_mo = re.match("handle: ([A-Za-z0-9]+)", l)
if chum_mo is not None:
chum = PesterProfile(chum_mo.group(1))
self.addChum(chum)
2011-02-24 21:15:21 -05:00
continue
if regexp_state is not None:
replace_mo = re.match("replace: (.+)", l)
if replace_mo is not None:
replace = replace_mo.group(1)
try:
re.compile(regexp_state)
except re.error, e:
continue
newquirk = pesterQuirk({"type": "regexp",
"from": regexp_state,
"to": replace})
qs = self.userprofile.quirks
qs.addQuirk(newquirk)
self.userprofile.setQuirks(qs)
regexp_state = None
continue
search_mo = re.match("search: (.+)", l)
if search_mo is not None:
regexp_state = search_mo.group(1)
continue
other_mo = re.match("(prefix|suffix): (.+)", l)
if other_mo is not None:
newquirk = pesterQuirk({"type": other_mo.group(1),
"value": other_mo.group(2)})
qs = self.userprofile.quirks
qs.addQuirk(newquirk)
self.userprofile.setQuirks(qs)
2011-02-06 19:50:21 -05:00
@QtCore.pyqtSlot()
def showMemos(self, channel=""):
2011-02-04 16:17:27 -05:00
if not hasattr(self, 'memochooser'):
self.memochooser = None
if self.memochooser:
return
2011-02-06 19:50:21 -05:00
self.memochooser = PesterMemoList(self, channel)
2011-02-04 16:17:27 -05:00
self.connect(self.memochooser, QtCore.SIGNAL('accepted()'),
self, QtCore.SLOT('joinSelectedMemo()'))
self.connect(self.memochooser, QtCore.SIGNAL('rejected()'),
self, QtCore.SLOT('memoChooserClose()'))
self.requestChannelList.emit()
self.memochooser.show()
@QtCore.pyqtSlot()
def joinSelectedMemo(self):
newmemo = self.memochooser.newmemoname()
selectedmemo = self.memochooser.selectedmemo()
time = unicode(self.memochooser.timeinput.text())
2011-02-06 19:50:21 -05:00
secret = self.memochooser.secretChannel.isChecked()
invite = self.memochooser.inviteChannel.isChecked()
2011-02-04 16:17:27 -05:00
if newmemo:
2011-02-05 13:56:25 -05:00
channel = "#"+unicode(newmemo).replace(" ", "_")
2011-02-06 19:50:21 -05:00
channel = re.sub(r"[^A-Za-z0-9#_]", "", channel)
self.newMemo(channel, time, secret=secret, invite=invite)
2011-02-04 19:50:56 -05:00
elif selectedmemo:
2011-03-31 17:57:30 -04:00
channel = "#"+unicode(selectedmemo.target)
self.newMemo(channel, time)
2011-02-04 16:17:27 -05:00
self.memochooser = None
@QtCore.pyqtSlot()
def memoChooserClose(self):
self.memochooser = None
@QtCore.pyqtSlot()
def memoChooserClose(self):
self.memochooser = None
@QtCore.pyqtSlot(PesterList)
def updateChannelList(self, channels):
if hasattr(self, 'memochooser') and self.memochooser:
self.memochooser.updateChannels(channels)
@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)'))
2011-04-13 02:12:19 -04:00
self.connect(self.allusers, QtCore.SIGNAL('pesterChum(QString)'),
self, QtCore.SLOT('userListPester(QString)'))
2011-02-03 01:20:37 -05:00
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)
2011-04-13 02:12:19 -04:00
@QtCore.pyqtSlot(QtCore.QString)
def userListPester(self, handle):
h = unicode(handle)
self.newConversation(h)
2011-02-03 01:20:37 -05:00
@QtCore.pyqtSlot()
def userListClose(self):
self.allusers = None
2011-02-04 16:17:27 -05:00
2011-02-03 01:20:37 -05:00
@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):
for i in range(self.quirkmenu.quirkList.count()):
item = self.quirkmenu.quirkList.item(i)
item.quirk.quirk["on"] = item.quirk.on = (item.checkState() == QtCore.Qt.Checked)
2011-01-29 16:55:35 -05:00
quirks = pesterQuirks(self.quirkmenu.quirks())
self.userprofile.setQuirks(quirks)
self.quirkmenu = None
@QtCore.pyqtSlot()
def closeQuirks(self):
self.quirkmenu = None
@QtCore.pyqtSlot()
def openLogv(self):
if not hasattr(self, 'logusermenu'):
self.logusermenu = None
if not self.logusermenu:
self.logusermenu = PesterLogUserSelect(self.config, self.theme, self)
self.connect(self.logusermenu, QtCore.SIGNAL('accepted()'),
self, QtCore.SLOT('closeLogUsers()'))
self.connect(self.logusermenu, QtCore.SIGNAL('rejected()'),
self, QtCore.SLOT('closeLogUsers()'))
self.logusermenu.show()
self.logusermenu.raise_()
self.logusermenu.activateWindow()
@QtCore.pyqtSlot()
def closeLogUsers(self):
self.logusermenu.close()
self.logusermenu = None
@QtCore.pyqtSlot()
def addGroupWindow(self):
if not hasattr(self, 'addgroupdialog'):
self.addgroupdialog = None
if not self.addgroupdialog:
(gname, ok) = QtGui.QInputDialog.getText(self, "Add Group", "Enter a name for the new group:")
if ok:
gname = unicode(gname)
2011-05-06 02:25:51 -04:00
if re.search("[^A-Za-z0-9_\s]", gname) is not None:
msgbox = QtGui.QMessageBox()
msgbox.setInformativeText("THIS IS NOT A VALID GROUP NAME")
msgbox.setStandardButtons(QtGui.QMessageBox.Ok)
ret = msgbox.exec_()
self.addgroupdialog = None
return
self.config.addGroup(gname)
gTemp = self.config.getGroups()
self.chumList.groups = [g[0] for g in gTemp]
self.chumList.openGroups = [g[1] for g in gTemp]
2011-04-30 03:51:53 -04:00
self.chumList.moveGroupMenu()
self.chumList.showAllGroups()
if not self.config.showEmptyGroups():
self.chumList.hideEmptyGroups()
if self.config.showOnlineNumbers():
self.chumList.showOnlineNumbers()
self.addgroupdialog = 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
windows = []
2011-01-27 06:05:36 -05:00
if self.tabconvo:
windows = list(self.tabconvo.convos.values())
if self.tabmemo:
windows += list(self.tabmemo.convos.values())
for w in windows:
w.setParent(None)
w.show()
w.raiseChat()
if self.tabconvo:
2011-01-27 06:05:36 -05:00
self.tabconvo.closeSoft()
if self.tabmemo:
self.tabmemo.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
newmemos = {}
self.createMemoTabWindow()
for (h,m) in self.memos.iteritems():
m.setParent(self.tabmemo)
self.tabmemo.addChat(m)
self.tabmemo.show()
newmemos[h] = m
self.memos = newmemos
2011-01-27 04:46:47 -05:00
# save options
self.config.set("tabs", tabsetting)
2011-02-24 18:46:09 -05:00
# hidden chums
chumsetting = self.optionmenu.hideOffline.isChecked()
curchum = self.config.hideOfflineChums()
if curchum and not chumsetting:
self.chumList.showAllChums()
elif chumsetting and not curchum:
self.chumList.hideOfflineChums()
self.config.set("hideOfflineChums", chumsetting)
# sorting method
sortsetting = self.optionmenu.sortBox.currentIndex()
cursort = self.config.sortMethod()
self.config.set("sortMethod", sortsetting)
if sortsetting != cursort:
self.chumList.sort()
2011-02-08 02:56:30 -05:00
# sound
soundsetting = self.optionmenu.soundcheck.isChecked()
self.config.set("soundon", soundsetting)
chatsoundsetting = self.optionmenu.chatsoundcheck.isChecked()
curchatsound = self.config.chatSound()
if chatsoundsetting != curchatsound:
self.config.set('chatSound', chatsoundsetting)
memosoundsetting = self.optionmenu.memosoundcheck.isChecked()
curmemosound = self.config.memoSound()
if memosoundsetting != curmemosound:
self.config.set('memoSound', memosoundsetting)
# timestamps
timestampsetting = self.optionmenu.timestampcheck.isChecked()
self.config.set("showTimeStamps", timestampsetting)
timeformatsetting = unicode(self.optionmenu.timestampBox.currentText())
if timeformatsetting == "12 hour":
self.config.set("time12Format", True)
else:
self.config.set("time12Format", False)
secondssetting = self.optionmenu.secondscheck.isChecked()
self.config.set("showSeconds", secondssetting)
# groups
#groupssetting = self.optionmenu.groupscheck.isChecked()
#self.config.set("useGroups", groupssetting)
emptygroupssetting = self.optionmenu.showemptycheck.isChecked()
curemptygroup = self.config.showEmptyGroups()
if curemptygroup and not emptygroupssetting:
self.chumList.hideEmptyGroups()
elif emptygroupssetting and not curemptygroup:
self.chumList.showAllGroups()
self.config.set("emptyGroups", emptygroupssetting)
# online numbers
onlinenumsetting = self.optionmenu.showonlinenumbers.isChecked()
curonlinenum = self.config.showOnlineNumbers()
if onlinenumsetting and not curonlinenum:
self.chumList.showOnlineNumbers()
elif curonlinenum and not onlinenumsetting:
self.chumList.hideOnlineNumbers()
self.config.set("onlineNumbers", onlinenumsetting)
# logging
2011-05-12 16:09:30 -04:00
logpesterssetting = 0
if self.optionmenu.logpesterscheck.isChecked():
logpesterssetting = logpesterssetting | self.config.LOG
if self.optionmenu.stamppestercheck.isChecked():
logpesterssetting = logpesterssetting | self.config.STAMP
curlogpesters = self.config.logPesters()
if logpesterssetting != curlogpesters:
self.config.set('logPesters', logpesterssetting)
2011-05-12 16:09:30 -04:00
logmemossetting = 0
if self.optionmenu.logmemoscheck.isChecked():
logmemossetting = logmemossetting | self.config.LOG
if self.optionmenu.stampmemocheck.isChecked():
logmemossetting = logmemossetting | self.config.STAMP
curlogmemos = self.config.logMemos()
if logmemossetting != curlogmemos:
self.config.set('logMemos', logmemossetting)
# memo and user links
linkssetting = self.optionmenu.userlinkscheck.isChecked()
curlinks = self.config.disableUserLinks()
if linkssetting != curlinks:
self.config.set('userLinks', not linkssetting)
2011-04-28 03:51:02 -04:00
# idle time
idlesetting = self.optionmenu.idleBox.value()
2011-04-28 03:51:02 -04:00
curidle = self.config.idleTime()
if idlesetting != curidle:
self.config.set('idleTime', idlesetting)
self.idlethreshold = 60*idlesetting
2011-05-04 00:24:11 -04:00
# theme
self.themeSelected()
2011-05-05 02:48:44 -04:00
# button actions
minisetting = self.optionmenu.miniBox.currentIndex()
curmini = self.config.minimizeAction()
if minisetting != curmini:
self.config.set('miniAction', minisetting)
self.setButtonAction(self.miniButton, minisetting, curmini)
closesetting = self.optionmenu.closeBox.currentIndex()
curclose = self.config.closeAction()
if closesetting != curclose:
self.config.set('closeAction', closesetting)
self.setButtonAction(self.closeButton, closesetting, curclose)
# op and voice messages
opvmesssetting = self.optionmenu.memomessagecheck.isChecked()
curopvmess = self.config.opvoiceMessages()
if opvmesssetting != curopvmess:
self.config.set('opvMessages', opvmesssetting)
# animated smiles
animatesetting = self.optionmenu.animationscheck.isChecked()
curanimate = self.config.animations()
if animatesetting != curanimate:
self.config.set('animations', animatesetting)
# advanced
## user mode
if self.advanced:
newmodes = self.optionmenu.modechange.text()
if newmodes:
self.setChannelMode.emit(self.profile().handle, newmodes, "")
2011-01-27 04:46:47 -05:00
self.optionmenu = None
2011-01-27 21:21:02 -05:00
2011-05-05 02:48:44 -04:00
def setButtonAction(self, button, setting, old):
if old == 0: # minimize to taskbar
self.disconnect(button, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('showMinimized()'));
elif old == 1: # minimize to tray
self.disconnect(button, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('closeToTray()'));
elif old == 2: # quit
self.disconnect(button, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('close()'));
if setting == 0: # minimize to taskbar
self.connect(button, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('showMinimized()'));
elif setting == 1: # minimize to tray
self.connect(button, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('closeToTray()'));
elif setting == 2: # quit
self.connect(button, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('close()'));
2011-01-27 21:21:02 -05:00
@QtCore.pyqtSlot()
2011-01-28 06:17:42 -05:00
def themeSelected(self):
2011-05-04 00:24:11 -04:00
themename = unicode(self.optionmenu.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, self)
2011-02-02 03:20:48 -05:00
2011-01-28 21:36:12 -05:00
# is default?
if self.chooseprofile.defaultcheck.isChecked():
self.config.set("defaultprofile", self.userprofile.chat.handle)
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,
2011-02-02 19:06:03 -05:00
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)
2011-02-04 16:17:27 -05:00
if not color.isValid():
color = self.profile().color
2011-01-29 07:33:35 -05:00
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):
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!")
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-02-09 01:26:23 -05:00
@QtCore.pyqtSlot()
def aboutPesterchum(self):
if hasattr(self, 'aboutwindow') and self.aboutwindow:
return
self.aboutwindow = AboutPesterchum(self)
self.aboutwindow.exec_()
self.aboutwindow = None
2011-03-05 21:25:52 -05:00
@QtCore.pyqtSlot()
2011-04-13 02:12:19 -04:00
def loadCalsprite(self):
self.newConversation("calSprite")
@QtCore.pyqtSlot()
def loadNickServ(self):
self.newConversation("nickServ")
@QtCore.pyqtSlot()
2011-03-05 21:25:52 -05:00
def launchHelp(self):
QtGui.QDesktopServices.openUrl(QtCore.QUrl("http://nova.xzibition.com/~illuminatedwax/help.html", QtCore.QUrl.TolerantMode))
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)
2011-02-19 18:06:54 -05:00
self.userprofile = userProfile(PesterProfile("pesterClient%d" % (random.randint(100,999)), QtGui.QColor("black"), Mood(0)))
self.changeTheme(self.userprofile.getTheme())
2011-02-01 06:14:56 -05:00
if not hasattr(self, 'chooseprofile'):
self.chooseprofile = None
if not self.chooseprofile:
h = unicode(handle)
self.changeProfile(collision=h)
2011-03-06 22:02:47 -05:00
@QtCore.pyqtSlot(QtCore.QString)
def myHandleChanged(self, handle):
if self.profile().handle == handle:
return
else:
self.nickCollision(self.profile().handle, handle)
2011-01-28 06:17:42 -05:00
@QtCore.pyqtSlot()
def pickTheme(self):
self.themePicker()
@QtCore.pyqtSlot(QtGui.QSystemTrayIcon.ActivationReason)
def systemTrayActivated(self, reason):
if reason == QtGui.QSystemTrayIcon.Trigger:
self.systemTrayFunction()
elif reason == QtGui.QSystemTrayIcon.Context:
pass
2011-02-09 11:44:48 -05:00
# show context menu i guess
#self.showTrayContext.emit()
2011-02-08 02:56:30 -05:00
closeToTraySignal = QtCore.pyqtSignal()
2011-01-24 04:10:44 -05:00
newConvoStarted = QtCore.pyqtSignal(QtCore.QString, bool, name="newConvoStarted")
2011-02-04 19:50:56 -05:00
sendMessage = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
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-04 16:17:27 -05:00
requestChannelList = 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()
trayIconSignal = QtCore.pyqtSignal(int)
2011-02-02 07:26:17 -05:00
blockedChum = QtCore.pyqtSignal(QtCore.QString)
unblockedChum = QtCore.pyqtSignal(QtCore.QString)
2011-02-06 01:02:39 -05:00
kickUser = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
2011-02-04 19:50:56 -05:00
joinChannel = QtCore.pyqtSignal(QtCore.QString)
leftChannel = QtCore.pyqtSignal(QtCore.QString)
2011-02-06 19:50:21 -05:00
setChannelMode = QtCore.pyqtSignal(QtCore.QString, QtCore.QString, QtCore.QString)
channelNames = QtCore.pyqtSignal(QtCore.QString)
inviteChum = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
inviteOnlyChan = QtCore.pyqtSignal(QtCore.QString)
2011-02-13 20:32:02 -05:00
closeSignal = QtCore.pyqtSignal()
2011-02-14 16:15:32 -05:00
reconnectIRC = QtCore.pyqtSignal()
2011-01-21 05:18:22 -05:00
class PesterTray(QtGui.QSystemTrayIcon):
def __init__(self, icon, mainwindow, parent):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
self.mainwindow = mainwindow
@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"]))
else:
2011-02-02 03:20:48 -05:00
self.setIcon(PesterIcon(self.mainwindow.theme["main/newmsgicon"]))
2011-02-13 20:32:02 -05:00
@QtCore.pyqtSlot()
def mainWindowClosed(self):
self.hide()
2011-02-06 19:50:21 -05:00
class MainProgram(QtCore.QObject):
def __init__(self):
QtCore.QObject.__init__(self)
self.app = QtGui.QApplication(sys.argv)
self.app.setApplicationName("Pesterchum 3.14")
2011-05-12 10:14:38 -04:00
options = self.oppts(sys.argv[1:])
2011-02-06 19:50:21 -05:00
if pygame.mixer:
# we could set the frequency higher but i love how cheesy it sounds
try:
pygame.mixer.init()
except pygame.error, e:
print "Warning: No sound! %s" % (e)
else:
print "Warning: No sound!"
2011-05-12 10:14:38 -04:00
self.widget = PesterWindow(options)
2011-02-06 19:50:21 -05:00
self.widget.show()
self.trayicon = PesterTray(PesterIcon(self.widget.theme["main/icon"]), self.widget, self.app)
2011-02-09 11:44:48 -05:00
self.traymenu = QtGui.QMenu()
2011-02-10 00:55:45 -05:00
moodMenu = self.traymenu.addMenu("SET MOOD")
2011-02-23 06:06:00 -05:00
moodCategories = {}
for k in Mood.moodcats:
moodCategories[k] = moodMenu.addMenu(k.upper())
2011-02-10 00:55:45 -05:00
self.moodactions = {}
for (i,m) in enumerate(Mood.moods):
maction = QtGui.QAction(m.upper(), self)
mobj = PesterMoodAction(i, self.widget.moods.updateMood)
self.trayicon.connect(maction, QtCore.SIGNAL('triggered()'),
mobj, QtCore.SLOT('updateMood()'))
self.moodactions[i] = mobj
2011-02-23 06:06:00 -05:00
moodCategories[Mood.revmoodcats[m]].addAction(maction)
2011-03-06 02:08:08 -05:00
miniAction = QtGui.QAction("MINIMIZE", self)
self.trayicon.connect(miniAction, QtCore.SIGNAL('triggered()'),
self.widget, QtCore.SLOT('showMinimized()'))
2011-02-10 13:00:06 -05:00
exitAction = QtGui.QAction("EXIT", self)
self.trayicon.connect(exitAction, QtCore.SIGNAL('triggered()'),
self.widget, QtCore.SLOT('close()'))
2011-03-06 02:08:08 -05:00
self.traymenu.addAction(miniAction)
2011-02-10 13:00:06 -05:00
self.traymenu.addAction(exitAction)
2011-02-10 00:55:45 -05:00
2011-02-09 11:44:48 -05:00
self.trayicon.setContextMenu(self.traymenu)
2011-02-06 19:50:21 -05:00
self.trayicon.show()
self.trayicon.connect(self.trayicon,
2011-02-06 19:50:21 -05:00
QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
self.widget,
QtCore.SLOT('systemTrayActivated(QSystemTrayIcon::ActivationReason)'))
self.trayicon.connect(self.widget,
QtCore.SIGNAL('trayIconSignal(int)'),
self.trayicon,
QtCore.SLOT('changeTrayIcon(int)'))
2011-02-08 02:56:30 -05:00
self.trayicon.connect(self.widget,
QtCore.SIGNAL('closeToTraySignal()'),
self.trayicon,
QtCore.SLOT('show()'))
2011-02-13 20:32:02 -05:00
self.trayicon.connect(self.widget,
QtCore.SIGNAL('closeSignal()'),
self.trayicon,
QtCore.SLOT('mainWindowClosed()'))
2011-02-06 19:50:21 -05:00
2011-02-19 21:38:06 -05:00
self.attempts = 0
2011-02-13 21:01:58 -05:00
self.irc = PesterIRC(self.widget.config, self.widget)
2011-02-19 18:06:54 -05:00
self.connectWidgets(self.irc, self.widget)
2011-02-06 19:50:21 -05:00
widget2irc = [('sendMessage(QString, QString)',
2011-02-19 18:06:54 -05:00
'sendMessage(QString, QString)'),
('newConvoStarted(QString, bool)',
'startConvo(QString, bool)'),
('convoClosed(QString)',
'endConvo(QString)'),
('profileChanged()',
'updateProfile()'),
('moodRequest(PyQt_PyObject)',
'getMood(PyQt_PyObject)'),
('moodsRequest(PyQt_PyObject)',
'getMoods(PyQt_PyObject)'),
('moodUpdated()', 'updateMood()'),
('mycolorUpdated()','updateColor()'),
('blockedChum(QString)', 'blockedChum(QString)'),
('unblockedChum(QString)', 'unblockedChum(QString)'),
('requestNames(QString)','requestNames(QString)'),
('requestChannelList()', 'requestChannelList()'),
('joinChannel(QString)', 'joinChannel(QString)'),
('leftChannel(QString)', 'leftChannel(QString)'),
('kickUser(QString, QString)',
2011-02-19 18:06:54 -05:00
'kickUser(QString, QString)'),
('setChannelMode(QString, QString, QString)',
'setChannelMode(QString, QString, QString)'),
('channelNames(QString)',
'channelNames(QString)'),
('inviteChum(QString, QString)',
'inviteChum(QString, QString)'),
('reconnectIRC()', 'reconnectIRC()')
2011-02-19 18:06:54 -05:00
]
# IRC --> Main window
irc2widget = [('connected()', 'connected()'),
('moodUpdated(QString, PyQt_PyObject)',
2011-02-19 18:06:54 -05:00
'updateMoodSlot(QString, PyQt_PyObject)'),
('colorUpdated(QString, QColor)',
'updateColorSlot(QString, QColor)'),
('messageReceived(QString, QString)',
'deliverMessage(QString, QString)'),
('memoReceived(QString, QString, QString)',
'deliverMemo(QString, QString, QString)'),
('noticeReceived(QString, QString)',
'deliverNotice(QString, QString)'),
('inviteReceived(QString, QString)',
'deliverInvite(QString, QString)'),
2011-02-19 18:06:54 -05:00
('nickCollision(QString, QString)',
'nickCollision(QString, QString)'),
2011-03-06 22:02:47 -05:00
('myHandleChanged(QString)',
'myHandleChanged(QString)'),
2011-02-19 18:06:54 -05:00
('namesReceived(QString, PyQt_PyObject)',
'updateNames(QString, PyQt_PyObject)'),
('userPresentUpdate(QString, QString, QString)',
'userPresentUpdate(QString, QString, QString)'),
('channelListReceived(PyQt_PyObject)',
'updateChannelList(PyQt_PyObject)'),
('timeCommand(QString, QString, QString)',
'timeCommand(QString, QString, QString)'),
('chanInviteOnly(QString)',
'chanInviteOnly(QString)')
2011-02-19 18:06:54 -05:00
]
2011-02-06 19:50:21 -05:00
def connectWidgets(self, irc, widget):
2011-02-19 21:38:06 -05:00
self.connect(irc, QtCore.SIGNAL('finished()'),
self, QtCore.SLOT('restartIRC()'))
self.connect(irc, QtCore.SIGNAL('connected()'),
self, QtCore.SLOT('connected()'))
2011-02-19 18:06:54 -05:00
for c in self.widget2irc:
self.connect(widget, QtCore.SIGNAL(c[0]),
irc, QtCore.SLOT(c[1]))
for c in self.irc2widget:
self.connect(irc, QtCore.SIGNAL(c[0]),
widget, QtCore.SLOT(c[1]))
def disconnectWidgets(self, irc, widget):
for c in self.widget2irc:
self.disconnect(widget, QtCore.SIGNAL(c[0]),
irc, QtCore.SLOT(c[1]))
for c in self.irc2widget:
self.disconnect(irc, QtCore.SIGNAL(c[0]),
widget, QtCore.SLOT(c[1]))
2011-02-19 21:38:06 -05:00
self.disconnect(irc, QtCore.SIGNAL('connected()'),
self, QtCore.SLOT('connected()'))
self.disconnect(self.irc, QtCore.SIGNAL('finished()'),
self, QtCore.SLOT('restartIRC()'))
2011-02-19 18:06:54 -05:00
def showLoading(self, widget, msg="CONN3CT1NG"):
2011-02-06 19:50:21 -05:00
self.widget.show()
2011-02-21 14:07:59 -05:00
if hasattr(self.widget, 'loadingscreen') and widget.loadingscreen:
widget.loadingscreen.loadinglabel.setText(msg)
if self.reconnectok:
widget.loadingscreen.showReconnect()
else:
widget.loadingscreen.hideReconnect()
else:
widget.loadingscreen = LoadingScreen(widget)
widget.loadingscreen.loadinglabel.setText(msg)
self.connect(widget.loadingscreen, QtCore.SIGNAL('rejected()'),
widget, QtCore.SLOT('close()'))
self.connect(self.widget.loadingscreen, QtCore.SIGNAL('tryAgain()'),
self, QtCore.SLOT('tryAgain()'))
if hasattr(self, 'irc') and self.irc.registeredIRC:
return
if self.reconnectok:
widget.loadingscreen.showReconnect()
else:
widget.loadingscreen.hideReconnect()
status = widget.loadingscreen.exec_()
if status == QtGui.QDialog.Rejected:
sys.exit(0)
else:
if self.widget.tabmemo:
for c in self.widget.tabmemo.convos:
self.irc.joinChannel(c)
else:
for c in self.widget.memos.values():
self.irc.joinChannel(c.channel)
2011-02-21 14:07:59 -05:00
return True
2011-02-19 18:06:54 -05:00
@QtCore.pyqtSlot()
2011-02-19 21:38:06 -05:00
def connected(self):
self.attempts = 0
@QtCore.pyqtSlot()
2011-02-19 18:06:54 -05:00
def tryAgain(self):
2011-02-21 14:07:59 -05:00
if not self.reconnectok:
return
2011-02-19 21:38:06 -05:00
if self.widget.loadingscreen:
2011-02-21 14:07:59 -05:00
self.widget.loadingscreen.done(QtGui.QDialog.Accepted)
self.widget.loadingscreen = None
2011-02-19 21:38:06 -05:00
self.attempts += 1
if hasattr(self, 'irc') and self.irc:
self.irc.reconnectIRC()
self.irc.quit()
else:
self.restartIRC()
2011-02-19 18:06:54 -05:00
@QtCore.pyqtSlot()
def restartIRC(self):
2011-02-19 21:38:06 -05:00
if hasattr(self, 'irc') and self.irc:
2011-02-19 18:06:54 -05:00
self.disconnectWidgets(self.irc, self.widget)
stop = self.irc.stopIRC
del self.irc
else:
stop = None
2011-02-21 14:07:59 -05:00
if stop is None:
2011-02-19 18:06:54 -05:00
self.irc = PesterIRC(self.widget.config, self.widget)
self.connectWidgets(self.irc, self.widget)
self.irc.start()
2011-02-19 21:38:06 -05:00
if self.attempts == 1:
msg = "R3CONN3CT1NG"
elif self.attempts > 1:
msg = "R3CONN3CT1NG %d" % (self.attempts)
else:
msg = "CONN3CT1NG"
2011-02-21 14:07:59 -05:00
self.reconnectok = False
2011-02-19 21:38:06 -05:00
self.showLoading(self.widget, msg)
2011-02-18 03:17:13 -05:00
else:
2011-02-21 14:07:59 -05:00
self.reconnectok = True
2011-02-19 18:06:54 -05:00
self.showLoading(self.widget, "F41L3D: %s" % stop)
2011-02-06 19:50:21 -05:00
def oppts(self, argv):
2011-05-12 10:14:38 -04:00
options = {}
try:
2011-05-12 10:14:38 -04:00
opts, args = getopt.getopt(argv, "s:p:", ["server=", "port=", "advanced"])
except getopt.GetoptError:
2011-05-12 10:14:38 -04:00
return options
for opt, arg in opts:
2011-05-12 10:14:38 -04:00
if opt in ("-s", "--server"):
options["server"] = arg
elif opt in ("-p", "--port"):
options["port"] = arg
elif opt in ("--advanced"):
options["advanced"] = True
return options
2011-02-06 19:50:21 -05:00
def run(self):
2011-02-19 18:06:54 -05:00
self.irc.start()
2011-02-21 14:07:59 -05:00
self.reconnectok = False
2011-02-19 18:06:54 -05:00
self.showLoading(self.widget)
2011-02-13 20:32:02 -05:00
sys.exit(self.app.exec_())
2011-02-06 19:50:21 -05:00
pesterchum = MainProgram()
pesterchum.run()