pesterchum/pesterchum.py

3442 lines
142 KiB
Python
Raw Normal View History

2011-01-21 05:18:22 -05:00
# pesterchum
2011-05-26 03:40:30 -04:00
import version
version.pcVerCalc()
2011-01-21 05:18:22 -05:00
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
import ostools
from time import strftime, time
import threading, Queue
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()
# Placed here before importing the rest of pesterchum, since bits of it need
# OSX's data directory and it doesn't hurt to have everything set up before
# plowing on. :o)
# ~Lex
_datadir = ostools.getDataDir()
# See, what I've done here is that _datadir is '' if we're not on OSX, so the
# concatination is the same as if it wasn't there.
if _datadir and 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.write("{}")
f.close()
if not os.path.exists(_datadir+"logs"):
os.mkdir(_datadir+"logs")
2011-03-02 18:36:10 -05:00
from menus import PesterChooseQuirks, PesterChooseTheme, \
PesterChooseProfile, PesterOptions, PesterUserlist, PesterMemoList, \
LoadingScreen, AboutPesterchum, UpdatePesterchum
from dataobjs import PesterProfile, Mood, pesterQuirk, pesterQuirks
from generic import PesterIcon, RightClickList, RightClickTree, MultiTextDialog, PesterList, CaseInsensitiveDict
from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo
from parsetools import convertTags, addTimeInitial, themeChecker, ThemeException
from memos import PesterMemo, MemoTabWindow, TimeTracker
from irc import PesterIRC
from logviewer import PesterLogUserSelect, PesterLogViewer
from bugreport import BugReporter
from randomer import RandomHandler
from updatecheck import MSPAChecker
from toast import PesterToastMachine, PesterToast
from libs import pytwmn
canon_handles = ["apocalypseArisen", "arsenicCatnip", "arachnidsGrip", "adiosToreador", \
"caligulasAquarium", "cuttlefishCuller", "carcinoGeneticist", "centaursTesticle", \
"grimAuxiliatrix", "gallowsCalibrator", "gardenGnostic", "ectoBiologist", \
"twinArmageddons", "terminallyCapricious", "turntechGodhead", "tentacleTherapist"]
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-06-24 12:27:18 -04:00
def set_volume(self, v): 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 = {}
self.logpath = _datadir+"logs"
2011-03-02 18:36:10 -05:00
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):
self.logpath = _datadir+"logs"
2011-03-02 18:36:10 -05:00
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():
2011-08-22 04:13:43 -04:00
options = dict()
if 'group' in c:
options['group'] = c['group']
if 'notes' in c:
options['notes'] = c['notes']
u.append((handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']), **options)))
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-08-22 04:13:43 -04:00
def getNotes(self, handle, default=""):
if not self.has_key(handle):
return default
else:
return self[handle].notes
def setNotes(self, handle, notes):
if self.has_key(handle):
self[handle].notes = notes
else:
self[handle] = PesterProfile(handle, notes=notes)
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):
self.path = _datadir+"themes/%s" % (name)
if not os.path.exists(self.path):
2011-03-02 18:36:10 -05:00
self.path = "themes/%s" % (name)
2011-01-28 06:17:42 -05:00
self.name = name
2011-01-22 04:36:24 -05:00
fp = open(self.path+"/style.js")
2011-01-24 02:34:07 -05:00
theme = json.load(fp, object_hook=self.pathHook)
self.update(theme)
2011-01-22 04:36:24 -05:00
fp.close()
2011-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
# Use for bit flag blink
self.PBLINK = 1
self.MBLINK = 2
self.filename = _datadir+"pesterchum.js"
2011-03-02 18:36:10 -05:00
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
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 checkForUpdates(self):
u = self.config.get('checkUpdates', 0)
if type(u) == type(bool()):
if u: u = 2
else: u = 3
return u
# Once a day
# Once a week
# Only on start
# Never
def lastUCheck(self):
return self.config.get('lastUCheck', 0)
2011-06-23 16:40:22 -04:00
def checkMSPA(self):
return self.config.get('mspa', False)
def blink(self):
return self.config.get('blink', self.PBLINK | self.MBLINK)
def notify(self):
return self.config.get('notify', True)
def notifyType(self):
return self.config.get('notifyType', "default")
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-07-08 04:41:49 -04:00
def memoPing(self):
return self.config.get('pingSound', True)
def nameSound(self):
return self.config.get('nameSound', True)
2011-06-24 12:27:18 -04:00
def volume(self):
return self.config.get('volume', 100)
def trayMessage(self):
return self.config.get('traymsg', 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 = []
# Load user themes.
for dirname, dirnames, filenames in os.walk(_datadir+'themes'):
2011-01-28 06:17:42 -05:00
for d in dirnames:
themes.append(d)
# For OSX, also load embedded themes.
if ostools.isOSX():
for dirname, dirnames, filenames in os.walk('themes'):
2011-07-10 07:26:48 -04:00
for d in dirnames:
if d not in themes:
themes.append(d)
2011-01-28 06:17:42 -05:00
themes.sort()
return themes
2011-01-27 21:21:02 -05:00
def availableProfiles(self):
profs = []
profileloc = _datadir+'profiles'
2011-07-10 07:26:48 -04:00
for dirname, dirnames, filenames in os.walk(profileloc):
2011-01-27 21:21:02 -05:00
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):
self.profiledir = _datadir+"profiles"
2011-03-02 18:36:10 -05:00
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([])
self.randoms = False
2011-08-23 03:51:50 -04:00
initials = self.chat.initials()
if len(initials) >= 2:
initials = (initials, "%s%s" % (initials[0].lower(), initials[1]), "%s%s" % (initials[0], initials[1].lower()))
self.mentions = [r"\b(%s)\b" % ("|".join(initials))]
else:
self.mentions = []
2011-01-27 21:21:02 -05:00
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"])
if "randoms" not in self.userprofile:
self.userprofile["randoms"] = False
self.randoms = self.userprofile["randoms"]
2011-08-23 03:51:50 -04:00
if "mentions" not in self.userprofile:
initials = self.chat.initials()
if len(initials) >= 2:
initials = (initials, "%s%s" % (initials[0].lower(), initials[1]), "%s%s" % (initials[0], initials[1].lower()))
self.userprofile["mentions"] = [r"\b(%s)\b" % ("|".join(initials))]
else:
self.userprofile["mentions"] = []
self.mentions = self.userprofile["mentions"]
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()
def getRandom(self):
return self.randoms
def setRandom(self, random):
self.randoms = random
self.userprofile["randoms"] = random
self.save()
2011-08-23 03:51:50 -04:00
def getMentions(self):
return self.mentions
def setMentions(self, mentions):
try:
for (i,m) in enumerate(mentions):
re.compile(m)
except re.error, e:
logging.error("#%s Not a valid regular expression: %s" % (i, e))
else:
self.mentions = mentions
self.userprofile["mentions"] = mentions
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())
self.resize(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"))
self.status = None
2011-08-22 04:13:43 -04:00
self.setToolTip(0, "%s: %s" % (chum.handle, window.chumdb.getNotes(chum.handle)))
2011-01-22 04:36:24 -05:00
def setMood(self, mood):
if hasattr(self.mainwindow, "chumList") and self.mainwindow.chumList.notify:
#print "%s -> %s" % (self.chum.mood.name(), mood.name())
if mood.name() == "offline" and self.chum.mood.name() != "offline":
#print "OFFLINE NOTIFY: " + self.handle
uri = "file://" + os.path.abspath(os.path.curdir) + "/themes/enamel/distraught2.gif"
n = self.mainwindow.tm.Toast(self.mainwindow.tm.appName,
"%s is Offline" % (self.handle), uri)
#n.show()
elif mood.name() != "offline" and self.chum.mood.name() == "offline":
#print "ONLINE NOTIFY: " + self.handle
uri = "file://" + os.path.abspath(os.path.curdir) + "/themes/enamel/chummy2.gif"
n = self.mainwindow.tm.Toast(self.mainwindow.tm.appName,
"%s is Online" % (self.handle), uri)
#n.show()
login = False
logout = False
if mood.name() == "offline" and self.chum.mood.name() != "offline":
logout = True
elif mood.name() != "offline" and self.chum.mood.name() == "offline":
login = True
2011-01-24 04:10:44 -05:00
self.chum.mood = mood
self.updateMood(login=login, logout=logout)
2011-01-28 04:07:20 -05:00
def setColor(self, color):
self.chum.color = color
def updateMood(self, unblock=False, login=False, logout=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)
if login:
self.login()
elif logout:
self.logout()
else:
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"]))
def login(self):
self.setIcon(0, PesterIcon("themes/arrow_right.png"))
self.status = "in"
QtCore.QTimer.singleShot(5000, self.doneLogin)
def doneLogin(self):
icon = self.mood.icon(self.mainwindow.theme)
self.setIcon(0, icon)
def logout(self):
self.setIcon(0, PesterIcon("themes/arrow_left.png"))
self.status = "out"
QtCore.QTimer.singleShot(5000, self.doneLogout)
def doneLogout(self):
hideoff = self.mainwindow.config.hideOfflineChums()
icon = self.mood.icon(self.mainwindow.theme)
self.setIcon(0, icon)
if hideoff and self.status and self.status == "out":
self.mainwindow.chumList.takeItem(self)
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.notify = False
QtCore.QTimer.singleShot(5000, self, QtCore.SLOT('beginNotify()'))
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()'))
2011-08-22 04:13:43 -04:00
self.notes = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/notes"], self)
self.connect(self.notes, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('editNotes()'))
self.optionsMenu.addAction(self.pester)
self.optionsMenu.addAction(self.logchum)
2011-08-22 04:13:43 -04:00
self.optionsMenu.addAction(self.notes)
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()'))
@QtCore.pyqtSlot()
def beginNotify(self):
print "BEGIN NOTIFY"
self.notify = True
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 startDrag(self, dropAction):
# create mime data object
mime = QtCore.QMimeData()
mime.setData('application/x-item', '???')
# start drag
drag = QtGui.QDrag(self)
drag.setMimeData(mime)
drag.start(QtCore.Qt.MoveAction)
def dragMoveEvent(self, event):
if event.mimeData().hasFormat("application/x-item"):
event.setDropAction(QtCore.Qt.MoveAction)
event.accept()
else:
event.ignore()
def dragEnterEvent(self, event):
if (event.mimeData().hasFormat('application/x-item')):
event.accept()
else:
event.ignore()
def dropEvent(self, event):
if (event.mimeData().hasFormat('application/x-item')):
event.acceptProposedAction()
else:
event.ignore()
return
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 = self.itemAt(event.pos())
if not droppos: return
droppos = str(droppos.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.MatchExactly | 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)
#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.reportchum.setText(theme["main/menus/rclickchumlist/report"])
2011-08-22 04:13:43 -04:00
self.notes.setText(theme["main/menus/rclickchumlist/notes"])
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)
if len(clistings) <= 0: return
2011-02-02 19:06:03 -05:00
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):
2011-08-22 04:13:43 -04:00
currentChum = self.currentItem()
if not currentChum:
return
2011-08-22 04:13:43 -04:00
currentChum = currentChum.text(0)
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()
2011-08-22 04:13:43 -04:00
def editNotes(self):
currentChum = self.currentItem()
if not currentChum:
return
(notes, ok) = QtGui.QInputDialog.getText(self, "Notes", "Enter your notes...")
if ok:
notes = unicode(notes)
self.mainwindow.chumdb.setNotes(currentChum.handle, notes)
currentChum.setToolTip(0, "%s: %s" % (currentChum.handle, notes))
@QtCore.pyqtSlot()
2011-03-29 03:02:05 -04:00
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
2011-08-23 06:23:59 -04:00
PesterProfile.checkValid(handle)[0]):
2011-02-02 19:06:03 -05:00
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-07-08 04:41:49 -04:00
if "honk" in options:
self.honk = options["honk"]
else: self.honk = True
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 = ""
self.randhandler = RandomHandler(self)
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.tm = PesterToastMachine(self, lambda: self.theme["main/windowtitle"], on=self.config.notify(),
type=self.config.notifyType(), extras={'pester': PesterToast, 'twmn': pytwmn.Notification})
self.tm.run()
t = self.tm.Toast(self.tm.appName, "!!---Started up ToastMachine---!!")
t.show()
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()'))
self.rand = QtGui.QAction(self.theme["main/menus/client/randen"], self)
self.connect(self.rand, QtCore.SIGNAL('triggered()'),
self.randhandler, QtCore.SLOT('getEncounter()'))
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)
self.menu.setNativeMenuBar(False)
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)
if self.randhandler.running:
filemenu.addAction(self.rand)
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-06-01 04:31:43 -04:00
self.reportBugAction = QtGui.QAction("REPORT BUG", self)
self.connect(self.reportBugAction, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('reportBug()'))
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-06-01 04:31:43 -04:00
self.helpmenu.addAction(self.reportBugAction)
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-06-23 16:40:22 -04:00
QtCore.QTimer.singleShot(1000, self, QtCore.SLOT('mspacheck()'))
self.connect(self, QtCore.SIGNAL('pcUpdate(QString, QString)'),
self, QtCore.SLOT('updateMsg(QString, QString)'))
self.pingtimer = QtCore.QTimer()
self.connect(self.pingtimer, QtCore.SIGNAL('timeout()'),
self, QtCore.SLOT('checkPing()'))
self.lastping = int(time())
self.pingtimer.start(1000*10)
2011-06-23 16:40:22 -04:00
@QtCore.pyqtSlot()
def mspacheck(self):
checker = MSPAChecker(self)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
def updateMsg(self, ver, url):
if not hasattr(self, 'updatemenu'):
self.updatemenu = None
if not self.updatemenu:
self.updatemenu = UpdatePesterchum(ver, url, self)
self.connect(self.updatemenu, QtCore.SIGNAL('accepted()'),
self, QtCore.SLOT('updatePC()'))
self.connect(self.updatemenu, QtCore.SIGNAL('rejected()'),
self, QtCore.SLOT('noUpdatePC()'))
self.updatemenu.show()
self.updatemenu.raise_()
self.updatemenu.activateWindow()
@QtCore.pyqtSlot()
def updatePC(self):
version.updateDownload(str(self.updatemenu.url))
self.updatemenu = None
@QtCore.pyqtSlot()
def noUpdatePC(self):
self.updatemenu = None
@QtCore.pyqtSlot()
def checkPing(self):
curtime = int(time())
if curtime - self.lastping > 600:
self.pingServer.emit()
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())
if handle == "ChanServ":
systemColor = QtGui.QColor(self.theme["memos/systemMsgColor"])
msg = "<c=%s>%s</c>" % (systemColor.name(), msg)
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():
2011-07-08 04:41:49 -04:00
if self.config.nameSound():
m = convertTags(msg, "text")
if m.find(":") <= 3:
m = m[m.find(":"):]
2011-08-23 03:51:50 -04:00
for search in self.userprofile.getMentions():
if re.search(search, m):
self.namesound.play()
return
2011-07-08 04:41:49 -04:00
if self.honk and re.search(r"\bhonk\b", convertTags(msg, "text"), re.I):
2011-06-20 12:25:38 -04:00
self.honksound.play()
2011-07-08 04:41:49 -04:00
elif self.config.memoPing():
2011-06-20 12:25:38 -04:00
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(QString)'),
memoWindow, QtCore.SLOT('namesUpdated(QString)'))
2011-05-20 14:45:41 -04:00
self.connect(self, QtCore.SIGNAL('modesUpdated(QString, QString)'),
memoWindow, QtCore.SLOT('modesUpdated(QString, QString)'))
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())
self.closeButton.resize(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())
self.miniButton.resize(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"])
self.rand.setText(self.theme["main/menus/client/randen"])
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"])
2011-07-12 03:15:47 -04:00
self.helpAction.setText(self.theme["main/menus/help/help"])
self.botAction.setText(self.theme["main/menus/help/calsprite"])
self.nickServAction.setText(self.theme["main/menus/help/nickserv"])
2011-02-09 01:26:23 -05:00
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-07-08 04:52:53 -04:00
self.namesound = NoneSound()
2011-02-10 20:55:45 -05:00
self.ceasesound = NoneSound()
2011-07-08 04:52:53 -04:00
self.honksound = 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"])
self.namesound = pygame.mixer.Sound("themes/namealarm.wav")
2011-03-07 19:13:47 -05:00
self.ceasesound = pygame.mixer.Sound(theme["main/sounds/ceasesound"])
2011-06-20 12:25:38 -04:00
self.honksound = pygame.mixer.Sound("themes/honk.wav")
2011-03-07 19:13:47 -05:00
except Exception, e:
self.alarm = NoneSound()
self.memosound = NoneSound()
self.namesound = NoneSound()
2011-03-07 19:13:47 -05:00
self.ceasesound = NoneSound()
2011-06-20 12:25:38 -04:00
self.honksound = NoneSound()
2011-07-08 04:52:53 -04:00
self.setVolume(self.config.volume())
2011-06-24 12:27:18 -04:00
def setVolume(self, vol):
vol = vol/100.0
self.alarm.set_volume(vol)
self.memosound.set_volume(vol)
self.namesound.set_volume(vol)
self.ceasesound.set_volume(vol)
self.honksound.set_volume(vol)
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 m.startswith("Your nickname is now being changed to"):
changedto = m[39:-1]
msgbox = QtGui.QMessageBox()
msgbox.setText("This chumhandle has been registered; you may not use it.")
msgbox.setInformativeText("Your handle is now being changed to %s." % (changedto))
2011-07-17 04:59:41 -04:00
msgbox.setStandardButtons(QtGui.QMessageBox.Ok)
ret = msgbox.exec_()
elif h == self.randhandler.randNick:
self.randhandler.incoming(msg)
elif 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):
self.inviteOnlyChan.emit(channel)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
def cannotSendToChan(self, channel, msg):
self.deliverMemo(channel, "ChanServ", msg)
2011-07-10 05:13:00 -04:00
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
def modesUpdated(self, channel, modes):
self.modesUpdated.emit(channel, modes)
@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-06-29 13:19:22 -04:00
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
def quirkDisable(self, channel, msg, op):
(c, msg, op) = (unicode(channel), unicode(msg), unicode(op))
if not self.memos.has_key(c):
return
memo = self.memos[c]
memo.quirkDisable(op, msg)
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(c)
2011-02-03 01:20:37 -05:00
@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]
2011-07-17 04:58:19 -04:00
if update in ("quit", "netsplit"):
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
2011-08-23 06:23:59 -04:00
PesterProfile.checkValid(handle)[0]):
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-06-28 19:26:13 -04:00
self.setAway.emit(True)
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:
2011-06-28 19:26:13 -04:00
self.setAway.emit(False)
2011-02-13 04:27:12 -05:00
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(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):
2011-05-25 04:38:36 -04:00
for i in range(self.quirkmenu.quirkList.topLevelItemCount()):
curgroup = unicode(self.quirkmenu.quirkList.topLevelItem(i).text(0))
for j in range(self.quirkmenu.quirkList.topLevelItem(i).childCount()):
item = self.quirkmenu.quirkList.topLevelItem(i).child(j)
item.quirk.quirk["on"] = item.quirk.on = (item.checkState(0) == QtCore.Qt.Checked)
item.quirk.quirk["group"] = item.quirk.group = curgroup
2011-01-29 16:55:35 -05:00
quirks = pesterQuirks(self.quirkmenu.quirks())
self.userprofile.setQuirks(quirks)
if hasattr(self.quirkmenu, 'quirktester') and self.quirkmenu.quirktester:
self.quirkmenu.quirktester.close()
2011-01-29 16:55:35 -05:00
self.quirkmenu = None
@QtCore.pyqtSlot()
def closeQuirks(self):
if hasattr(self.quirkmenu, 'quirktester') and self.quirkmenu.quirktester:
self.quirkmenu.quirktester.close()
2011-01-29 16:55:35 -05:00
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)
2011-07-08 04:41:49 -04:00
memopingsetting = self.optionmenu.memopingcheck.isChecked()
curmemoping = self.config.memoPing()
if memopingsetting != curmemoping:
self.config.set('pingSound', memopingsetting)
namesoundsetting = self.optionmenu.namesoundcheck.isChecked()
curnamesound = self.config.nameSound()
if namesoundsetting != curnamesound:
self.config.set('nameSound', namesoundsetting)
2011-06-24 12:27:18 -04:00
volumesetting = self.optionmenu.volume.value()
curvolume = self.config.volume()
if volumesetting != curvolume:
self.config.set('volume', volumesetting)
self.setVolume(volumesetting)
# 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()
# randoms
if self.randhandler.running:
self.randhandler.setRandomer(self.optionmenu.randomscheck.isChecked())
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)
self.animationSetting.emit(animatesetting)
# update checked
updatechecksetting = self.optionmenu.updateBox.currentIndex()
curupdatecheck = self.config.checkForUpdates()
if updatechecksetting != curupdatecheck:
self.config.set('checkUpdates', updatechecksetting)
2011-06-23 16:40:22 -04:00
# mspa update check
mspachecksetting = self.optionmenu.mspaCheck.isChecked()
curmspacheck = self.config.checkMSPA()
if mspachecksetting != curmspacheck:
self.config.set('mspa', mspachecksetting)
# Taskbar blink
blinksetting = 0
if self.optionmenu.pesterBlink.isChecked():
blinksetting = blinksetting | self.config.PBLINK
if self.optionmenu.memoBlink.isChecked():
blinksetting = blinksetting | self.config.MBLINK
curblink = self.config.blink()
if blinksetting != curblink:
self.config.set('blink', blinksetting)
# toast notifications
self.tm.setEnabled(self.optionmenu.notifycheck.isChecked())
self.tm.setCurrentType(str(self.optionmenu.notifyOptions.currentText()))
# 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-06-01 04:31:43 -04:00
@QtCore.pyqtSlot()
def reportBug(self):
if hasattr(self, 'bugreportwindow') and self.bugreportwindow:
return
self.bugreportwindow = BugReporter(self)
self.bugreportwindow.exec_()
self.bugreportwindow = None
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-06-20 19:18:47 -04:00
@QtCore.pyqtSlot()
def tooManyPeeps(self):
msg = QtGui.QMessageBox(self)
msg.setText("D: TOO MANY PEOPLE!!!")
msg.setInformativeText("The server has hit max capacity. Please try again later.")
msg.show()
pcUpdate = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
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)
sendNotice = 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()
animationSetting = QtCore.pyqtSignal(bool)
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(QtCore.QString)
2011-05-20 14:45:41 -04:00
modesUpdated = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
2011-02-03 01:20:37 -05:00
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-06-20 06:34:06 -04:00
gainAttention = QtCore.pyqtSignal(QtGui.QWidget)
pingServer = QtCore.pyqtSignal()
2011-06-28 19:26:13 -04:00
setAway = QtCore.pyqtSignal(bool)
2011-06-29 13:19:22 -04:00
killSomeQuirks = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
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()
pygame.mixer.init()
2011-02-06 19:50:21 -05:00
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,
QtCore.SLOT('trayiconShow()'))
2011-02-13 20:32:02 -05:00
self.trayicon.connect(self.widget,
QtCore.SIGNAL('closeSignal()'),
self.trayicon,
QtCore.SLOT('mainWindowClosed()'))
self.connect(self.trayicon,
QtCore.SIGNAL('messageClicked()'),
self,
QtCore.SLOT('trayMessageClick()'))
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
2011-06-20 06:34:06 -04:00
self.connect(self.widget, QtCore.SIGNAL('gainAttention(QWidget*)'),
self, QtCore.SLOT('alertWindow(QWidget*)'))
# 0 Once a day
# 1 Once a week
# 2 Only on start
# 3 Never
check = self.widget.config.checkForUpdates()
if check == 2:
self.runUpdateSlot()
elif check == 0:
seconds = 60 * 60 * 24
if int(time()) - self.widget.config.lastUCheck() < seconds:
seconds -= int(time()) - self.widget.config.lastUCheck()
if seconds < 0: seconds = 0
QtCore.QTimer.singleShot(1000*seconds, self, QtCore.SLOT('runUpdateSlot()'))
elif check == 1:
seconds = 60 * 60 * 24 * 7
if int(time()) - self.widget.config.lastUCheck() < seconds:
seconds -= int(time()) - self.widget.config.lastUCheck()
if seconds < 0: seconds = 0
QtCore.QTimer.singleShot(1000*seconds, self, QtCore.SLOT('runUpdateSlot()'))
@QtCore.pyqtSlot()
def runUpdateSlot(self):
q = Queue.Queue(1)
s = threading.Thread(target=version.updateCheck, args=(q,))
w = threading.Thread(target=self.showUpdate, args=(q,))
w.start()
s.start()
self.widget.config.set('lastUCheck', int(time()))
check = self.widget.config.checkForUpdates()
if check == 0:
seconds = 60 * 60 * 24
elif check == 1:
seconds = 60 * 60 * 24 * 7
else:
return
QtCore.QTimer.singleShot(1000*seconds, self, QtCore.SLOT('runUpdateSlot()'))
2011-06-20 06:34:06 -04:00
@QtCore.pyqtSlot(QtGui.QWidget)
def alertWindow(self, widget):
self.app.alert(widget)
@QtCore.pyqtSlot()
def trayiconShow(self):
self.trayicon.show()
if self.widget.config.trayMessage():
self.trayicon.showMessage("Pesterchum", "Pesterchum is still running in the system tray.\n\
Right click to close it.\n\
Click this message to never see this again.")
@QtCore.pyqtSlot()
def trayMessageClick(self):
self.widget.config.set('traymsg', False)
widget2irc = [('sendMessage(QString, QString)',
2011-02-19 18:06:54 -05:00
'sendMessage(QString, QString)'),
('sendNotice(QString, QString)',
'sendNotice(QString, QString)'),
2011-02-19 18:06:54 -05:00
('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)'),
2011-06-28 19:26:13 -04:00
('pingServer()', 'pingServer()'),
('setAway(bool)', 'setAway(bool)'),
2011-06-29 13:19:22 -04:00
('killSomeQuirks(QString, QString)',
'killSomeQuirks(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)',
2011-05-20 14:45:41 -04:00
'chanInviteOnly(QString)'),
('modesUpdated(QString, QString)',
'modesUpdated(QString, QString)'),
('cannotSendToChan(QString, QString)',
2011-06-20 19:18:47 -04:00
'cannotSendToChan(QString, QString)'),
('tooManyPeeps()',
2011-06-29 13:19:22 -04:00
'tooManyPeeps()'),
2011-07-17 04:59:41 -04:00
('quirkDisable(QString, QString, QString)',
'quirkDisable(QString, QString, 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 showUpdate(self, q):
new_url = q.get()
if new_url[0]:
self.widget.pcUpdate.emit(new_url[0], new_url[1])
q.task_done()
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-07-08 04:41:49 -04:00
opts, args = getopt.getopt(argv, "s:p:", ["server=", "port=", "advanced", "no-honk"])
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
2011-07-08 04:41:49 -04:00
elif opt in ("--no-honk"):
options["honk"] = False
2011-05-12 10:14:38 -04:00
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()