added system tray stuff and more im sure

This commit is contained in:
Stephen Dranger 2011-01-29 05:31:41 -06:00
parent 99175a9f6d
commit dd7c0a7887
12 changed files with 356 additions and 37 deletions

20
TODO
View file

@ -1,23 +1,25 @@
Features: Features:
* Add chum * mychumhandle/color/pester button
* REMOVE chum * User profile options (color...?)
* Sounds
* New message reminder
* User profile options
* menubar should pass on mouse move
* Quirks * Quirks
-- package -- package
* theme elements define, implement * menubar should pass on mouse move
* User signon? * User signon?
* Logging * Logging
* Block list * Block list
* User list/add from list * User list/add from list
* User commands/stop user from sending commands accidentally * User commands/stop user from sending commands accidentally
-- release alpha -- release alpha
* System tray stuff * System tray menu
* comment history (up button)
* Chat rooms * Chat rooms
* Implement TC options
-- release beta -- release beta
* theme elements define, implement
* Theme checking * Theme checking
* don't clear new message when clicking away from tab?
* Spy mode * Spy mode
* put code into separate files * put code into separate files
* hide offline chums
* chum list groups

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1 +1 @@
{"tabs": true, "chums": ["gamblingGenocider", "grimAuxiliatrix", "gardenGnostic", "ghostDunk", "spaceGhost", "aquaMarinist", "carcinoGeneticist", "tentacleTherapist", "nightmareKitty"], "defaultprofile": "superGhost"} {"tabs": true, "chums": ["gamblingGenocider", "grimAuxiliatrix", "gardenGnostic", "ghostDunk", "spaceGhost", "aquaMarinist", "carcinoGeneticist", "tentacleTherapist", "gallowsCalibrator", "waitWhat", "captainCaveman"], "defaultprofile": "ghostDunk"}

View file

@ -8,7 +8,9 @@ import os.path
from datetime import * from datetime import *
import random import random
import json import json
import re
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
import pygame
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
@ -33,6 +35,35 @@ class Mood(object):
f = theme["main/chums/moods"][self.name()]["icon"] f = theme["main/chums/moods"][self.name()]["icon"]
return QtGui.QIcon(f) return QtGui.QIcon(f)
class waitingMessageHolder(object):
def __init__(self, mainwindow, **msgfuncs):
self.mainwindow = mainwindow
self.funcs = msgfuncs
self.queue = msgfuncs.keys()
if len(self.queue) > 0:
self.mainwindow.updateSystemTray()
def answerMessage(self):
func = self.funcs[self.queue[0]]
func()
def messageAnswered(self, handle):
if handle not in self.queue:
return
self.queue = [q for q in self.queue if q != handle]
del self.funcs[handle]
if len(self.queue) == 0:
self.mainwindow.updateSystemTray()
def addMessage(self, handle, func):
if not self.funcs.has_key(handle):
self.queue.append(handle)
self.funcs[handle] = func
if len(self.queue) > 0:
self.mainwindow.updateSystemTray()
def __len__(self):
return len(self.queue)
class NoneSound(object):
def play(self): pass
class PesterProfile(object): class PesterProfile(object):
def __init__(self, handle, color=QtGui.QColor("black"), def __init__(self, handle, color=QtGui.QColor("black"),
mood=Mood("offline")): mood=Mood("offline")):
@ -55,6 +86,17 @@ class PesterProfile(object):
def ceasedpestermsg(self, otherchum): def ceasedpestermsg(self, otherchum):
return "<span style='color:black;'>-- %s <span style='color:%s'>[%s]</span> ceased pestering %s <span style='color:%s'>[%s]</span> at %s --</span>" % (self.handle, self.colorhtml(), self.initials(), otherchum.handle, otherchum.colorhtml(), otherchum.initials(), datetime.now().strftime("%H:%M")) return "<span style='color:black;'>-- %s <span style='color:%s'>[%s]</span> ceased pestering %s <span style='color:%s'>[%s]</span> at %s --</span>" % (self.handle, self.colorhtml(), self.initials(), otherchum.handle, otherchum.colorhtml(), otherchum.initials(), datetime.now().strftime("%H:%M"))
@staticmethod
def checkLength(handle):
return len(handle) <= 256
@staticmethod
def checkValid(handle):
caps = [l for l in handle if l.isupper()]
if len(caps) != 1 or handle[0].isupper():
return False
if re.search("[^A-Za-z0-9]", handle) is not None:
return False
return True
class pesterTheme(dict): class pesterTheme(dict):
def __init__(self, name): def __init__(self, name):
@ -96,6 +138,12 @@ class userConfig(object):
return None return None
def tabs(self): def tabs(self):
return self.config["tabs"] return self.config["tabs"]
def addChum(self, chum):
newchums = self.config['chums'] + [chum.handle]
self.set("chums", newchums)
def removeChum(self, chum):
newchums = [c for c in self.config['chums'] if c != chum.handle]
self.set("chums", newchums)
def set(self, item, setting): def set(self, item, setting):
self.config[item] = setting self.config[item] = setting
fp = open("pesterchum.js", 'w') fp = open("pesterchum.js", 'w')
@ -295,11 +343,10 @@ class PesterChooseProfile(QtGui.QDialog):
def validateProfile(self): def validateProfile(self):
if not self.profileBox or self.profileBox.currentIndex() == 0: if not self.profileBox or self.profileBox.currentIndex() == 0:
handle = unicode(self.chumHandle.text()) handle = unicode(self.chumHandle.text())
if len(handle) > 256: if not PesterProfile.checkLength(handle):
self.errorMsg.setText("PROFILE HANDLE IS TOO LONG") self.errorMsg.setText("PROFILE HANDLE IS TOO LONG")
return return
caps = [l for l in handle if l.isupper()] if not PesterProfile.checkValid(handle):
if len(caps) != 1 or handle[0].isupper():
self.errorMsg.setText("NOT A VALID CHUMTAG") self.errorMsg.setText("NOT A VALID CHUMTAG")
return return
self.accept() self.accept()
@ -383,7 +430,26 @@ class chumArea(QtGui.QListWidget):
if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)): if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)):
chumLabel = chumListing(c, self.mainwindow) chumLabel = chumListing(c, self.mainwindow)
self.addItem(chumLabel) self.addItem(chumLabel)
self.optionsMenu = QtGui.QMenu(self)
pester = QtGui.QAction("PESTER", self)
self.connect(pester, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('activateChum()'))
removechum = QtGui.QAction("REMOVE CHUM", self)
self.connect(removechum, QtCore.SIGNAL('triggered()'),
self, QtCore.SLOT('removeChum()'))
self.optionsMenu.addAction(pester)
self.optionsMenu.addAction(removechum)
self.sortItems() self.sortItems()
def addChum(self, chum):
if len([c for c in self.chums if c.handle == chum.handle]) != 0:
return
self.chums.append(chum)
chumLabel = chumListing(chum, self.mainwindow)
self.addItem(chumLabel)
self.sortItems()
def updateMood(self, handle, mood): def updateMood(self, handle, mood):
chums = self.findItems(handle, QtCore.Qt.MatchFlags(0)) chums = self.findItems(handle, QtCore.Qt.MatchFlags(0))
for c in chums: for c in chums:
@ -395,9 +461,27 @@ class chumArea(QtGui.QListWidget):
def changeTheme(self, theme): def changeTheme(self, theme):
self.setGeometry(*(theme["main/chums/loc"]+theme["main/chums/size"])) self.setGeometry(*(theme["main/chums/loc"]+theme["main/chums/size"]))
self.setStyleSheet(theme["main/chums/style"]) self.setStyleSheet(theme["main/chums/style"])
chums = [self.item(i) for i in range(0, self.count())] chumlistings = [self.item(i) for i in range(0, self.count())]
for c in chums: for c in chumlistings:
c.changeTheme(theme) c.changeTheme(theme)
def contextMenuEvent(self, event):
#fuckin Qt
if event.reason() == QtGui.QContextMenuEvent.Mouse:
chumlisting = self.itemAt(event.pos())
self.setCurrentItem(chumlisting)
self.optionsMenu.popup(event.globalPos())
@QtCore.pyqtSlot()
def activateChum(self):
self.itemActivated.emit(self.currentItem())
@QtCore.pyqtSlot()
def removeChum(self):
currentChum = self.currentItem().chum
self.chums = [c for c in self.chums if c.handle != currentChum.handle]
self.removeChumSignal.emit(self.currentItem())
oldlist = self.takeItem(self.currentRow())
del oldlist
removeChumSignal = QtCore.pyqtSignal(QtGui.QListWidgetItem)
class PesterMoodHandler(QtCore.QObject): class PesterMoodHandler(QtCore.QObject):
def __init__(self, parent, *buttons): def __init__(self, parent, *buttons):
@ -476,6 +560,7 @@ class MovingWindow(QtGui.QFrame):
class PesterTabWindow(QtGui.QFrame): class PesterTabWindow(QtGui.QFrame):
def __init__(self, mainwindow, parent=None): def __init__(self, mainwindow, parent=None):
QtGui.QFrame.__init__(self, parent) QtGui.QFrame.__init__(self, parent)
self.setFocusPolicy(QtCore.Qt.ClickFocus)
self.mainwindow = mainwindow self.mainwindow = mainwindow
self.resize(*self.mainwindow.theme["convo/size"]) self.resize(*self.mainwindow.theme["convo/size"])
self.setStyleSheet(self.mainwindow.theme["convo/style"]) self.setStyleSheet(self.mainwindow.theme["convo/style"])
@ -486,8 +571,8 @@ class PesterTabWindow(QtGui.QFrame):
self, QtCore.SLOT('changeTab(int)')) self, QtCore.SLOT('changeTab(int)'))
self.connect(self.tabs, QtCore.SIGNAL('tabCloseRequested(int)'), self.connect(self.tabs, QtCore.SIGNAL('tabCloseRequested(int)'),
self, QtCore.SLOT('tabClose(int)')) self, QtCore.SLOT('tabClose(int)'))
self.tabs.setShape(self.mainwindow.theme["convo/tabstyle"]) self.tabs.setShape(self.mainwindow.theme["convo/tabs/tabstyle"])
self.tabs.setStyleSheet("QTabBar::tabs{ %s }" % (self.mainwindow.theme["convo/tabs/style"]))
self.layout = QtGui.QVBoxLayout() self.layout = QtGui.QVBoxLayout()
self.layout.setContentsMargins(0,0,0,0) self.layout.setContentsMargins(0,0,0,0)
@ -498,6 +583,17 @@ class PesterTabWindow(QtGui.QFrame):
self.currentConvo = None self.currentConvo = None
self.changedTab = False self.changedTab = False
self.softclose = False self.softclose = False
# get default tab color i guess
self.defaultTabTextColor = self.getTabTextColor()
def getTabTextColor(self):
# ugly, ugly hack
self.changedTab = True
i = self.tabs.addTab(".")
c = self.tabs.tabTextColor(i)
self.tabs.removeTab(i)
self.changedTab = False
return c
def addChat(self, convo): def addChat(self, convo):
self.convos[convo.chum.handle] = convo self.convos[convo.chum.handle] = convo
# either addTab or setCurrentIndex will trigger changed() # either addTab or setCurrentIndex will trigger changed()
@ -506,7 +602,19 @@ class PesterTabWindow(QtGui.QFrame):
self.tabs.setCurrentIndex(newindex) self.tabs.setCurrentIndex(newindex)
self.tabs.setTabIcon(newindex, convo.chum.mood.icon(self.mainwindow.theme)) self.tabs.setTabIcon(newindex, convo.chum.mood.icon(self.mainwindow.theme))
def showChat(self, handle): def showChat(self, handle):
self.tabs.setCurrentIndex(self.tabIndices[handle]) tabi = self.tabIndices[handle]
if self.tabs.currentIndex() == tabi:
self.activateWindow()
self.raise_()
self.convos[handle].raiseChat()
else:
self.tabs.setCurrentIndex(tabi)
def convoHasFocus(self, convo):
if ((self.hasFocus() or self.tabs.hasFocus()) and
self.tabs.tabText(self.tabs.currentIndex()) == convo.chum.handle):
return True
def keyPressEvent(self, event): def keyPressEvent(self, event):
keypress = event.key() keypress = event.key()
mods = event.modifiers() mods = event.modifiers()
@ -528,19 +636,49 @@ class PesterTabWindow(QtGui.QFrame):
while self.tabs.count() > 0: while self.tabs.count() > 0:
self.tabClose(0) self.tabClose(0)
self.windowClosed.emit() self.windowClosed.emit()
def focusInEvent(self, event):
# make sure we're not switching tabs!
i = self.tabs.tabAt(self.mapFromGlobal(QtGui.QCursor.pos()))
if i == -1:
i = self.tabs.currentIndex()
handle = unicode(self.tabs.tabText(i))
self.clearNewMessage(handle)
def convoHasFocus(self, handle):
i = self.tabIndices[handle]
if (self.tabs.currentIndex() == i and
(self.hasFocus() or self.tabs.hasFocus())):
return True
else:
return False
def notifyNewMessage(self, handle):
i = self.tabIndices[handle]
self.tabs.setTabTextColor(i, QtGui.QColor(self.mainwindow.theme["convo/tabs/newmsgcolor"]))
convo = self.convos[handle]
def func():
convo.showChat()
self.mainwindow.waitingMessages.addMessage(handle, func)
# set system tray
def clearNewMessage(self, handle):
i = self.tabIndices[handle]
self.tabs.setTabTextColor(i, self.defaultTabTextColor)
self.mainwindow.waitingMessages.messageAnswered(handle)
def changeTheme(self, theme): def changeTheme(self, theme):
self.resize(*theme["convo/size"]) self.resize(*theme["convo/size"])
self.setStyleSheet(theme["convo/style"]) self.setStyleSheet(theme["convo/style"])
self.tabs.setShape(theme["convo/tabstyle"]) self.tabs.setShape(theme["convo/tabs/tabstyle"])
self.tabs.setStyleSheet("QTabBar::tabs{ %s }" % (theme["convo/tabs/style"]))
for c in self.convos.values(): for c in self.convos.values():
tabi = self.tabIndices[c.chum.handle] tabi = self.tabIndices[c.chum.handle]
self.tabs.setTabIcon(tabi, c.chum.mood.icon(theme)) self.tabs.setTabIcon(tabi, c.chum.mood.icon(theme))
currentHandle = unicode(self.tabs.tabText(self.tabs.currentIndex())) currentHandle = unicode(self.tabs.tabText(self.tabs.currentIndex()))
self.setWindowIcon(self.convos[currentHandle].chum.mood.icon(theme)) self.setWindowIcon(self.convos[currentHandle].chum.mood.icon(theme))
self.defaultTabTextColor = self.getTabTextColor()
@QtCore.pyqtSlot(int) @QtCore.pyqtSlot(int)
def tabClose(self, i): def tabClose(self, i):
handle = unicode(self.tabs.tabText(i)) handle = unicode(self.tabs.tabText(i))
self.mainwindow.waitingMessages.messageAnswered(handle)
convo = self.convos[handle] convo = self.convos[handle]
del self.convos[handle] del self.convos[handle]
del self.tabIndices[handle] del self.tabIndices[handle]
@ -615,6 +753,9 @@ class PesterText(QtGui.QTextEdit):
(color, initials, msg)) (color, initials, msg))
def changeTheme(self, theme): def changeTheme(self, theme):
self.setStyleSheet(theme["convo/textarea/style"]) self.setStyleSheet(theme["convo/textarea/style"])
def focusInEvent(self, event):
self.parent().clearNewMessage()
QtGui.QTextEdit.focusInEvent(self, event)
class PesterInput(QtGui.QLineEdit): class PesterInput(QtGui.QLineEdit):
def __init__(self, theme, parent=None): def __init__(self, theme, parent=None):
@ -622,11 +763,14 @@ class PesterInput(QtGui.QLineEdit):
self.setStyleSheet(theme["convo/input/style"]) self.setStyleSheet(theme["convo/input/style"])
def changeTheme(self, theme): def changeTheme(self, theme):
self.setStyleSheet(theme["convo/input/style"]) self.setStyleSheet(theme["convo/input/style"])
def focusInEvent(self, event):
self.parent().clearNewMessage()
QtGui.QLineEdit.focusInEvent(self, event)
class PesterConvo(QtGui.QFrame): class PesterConvo(QtGui.QFrame):
def __init__(self, chum, initiated, mainwindow, parent=None): def __init__(self, chum, initiated, mainwindow, parent=None):
QtGui.QFrame.__init__(self, parent) QtGui.QFrame.__init__(self, parent)
self.setFocusPolicy(QtCore.Qt.ClickFocus)
self.chum = chum self.chum = chum
self.mainwindow = mainwindow self.mainwindow = mainwindow
convo = self.mainwindow.theme["convo"] convo = self.mainwindow.theme["convo"]
@ -658,6 +802,7 @@ class PesterConvo(QtGui.QFrame):
if initiated: if initiated:
msg = self.mainwindow.profile().beganpestermsg(self.chum) msg = self.mainwindow.profile().beganpestermsg(self.chum)
self.textArea.append(msg) self.textArea.append(msg)
self.newmessage = False
def updateMood(self, mood): def updateMood(self, mood):
if mood.name() == "offline": if mood.name() == "offline":
@ -676,7 +821,35 @@ class PesterConvo(QtGui.QFrame):
chum = self.mainwindow.profile() chum = self.mainwindow.profile()
else: else:
chum = self.chum chum = self.chum
self.notifyNewMessage()
self.textArea.addMessage(text, chum) self.textArea.addMessage(text, chum)
def notifyNewMessage(self):
# first see if this conversation HASS the focus
if not (self.hasFocus() or self.textArea.hasFocus() or
self.textInput.hasFocus() or
(self.parent() and self.parent().convoHasFocus(self.chum.handle))):
# ok if it has a tabconvo parent, send that the notify.
if self.parent():
self.parent().notifyNewMessage(self.chum.handle)
# if not change the window title and update system tray
else:
self.newmessage = True
self.setWindowTitle(self.chum.handle+"*")
def func():
self.showChat()
self.mainwindow.waitingMessages.addMessage(self.chum.handle, func)
def clearNewMessage(self):
if self.parent():
self.parent().clearNewMessage(self.chum.handle)
elif self.newmessage:
self.newmessage = False
self.setWindowTitle(self.chum.handle)
self.mainwindow.waitingMessages.messageAnswered(self.chum.handle)
# reset system tray
def focusInEvent(self, event):
self.clearNewMessage()
def raiseChat(self): def raiseChat(self):
self.activateWindow() self.activateWindow()
self.raise_() self.raise_()
@ -688,6 +861,7 @@ class PesterConvo(QtGui.QFrame):
self.raiseChat() self.raiseChat()
def closeEvent(self, event): def closeEvent(self, event):
self.mainwindow.waitingMessages.messageAnswered(self.chum.handle)
self.windowClosed.emit(self.chum.handle) self.windowClosed.emit(self.chum.handle)
def setChumOpen(self, o): def setChumOpen(self, o):
self.chumopen = o self.chumopen = o
@ -702,6 +876,8 @@ class PesterConvo(QtGui.QFrame):
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def sentMessage(self): def sentMessage(self):
text = self.textInput.text() text = self.textInput.text()
if text == "":
return
# deal with quirks here # deal with quirks here
self.textInput.setText("") self.textInput.setText("")
self.addMessage(text, True) self.addMessage(text, True)
@ -769,14 +945,37 @@ class PesterWindow(MovingWindow):
chums = [PesterProfile(c) for c in set(self.config.chums())] chums = [PesterProfile(c) for c in set(self.config.chums())]
self.chumList = chumArea(chums, self) self.chumList = chumArea(chums, self)
self.connect(self.chumList, QtCore.SIGNAL('itemDoubleClicked(QListWidgetItem *)'), self.connect(self.chumList,
self, QtCore.SLOT('newConversationWindow(QListWidgetItem *)')) QtCore.SIGNAL('itemActivated(QListWidgetItem *)'),
self,
QtCore.SLOT('newConversationWindow(QListWidgetItem *)'))
self.connect(self.chumList,
QtCore.SIGNAL('removeChumSignal(QListWidgetItem *)'),
self,
QtCore.SLOT('removeChum(QListWidgetItem *)'))
self.moods = PesterMoodHandler(self, *[PesterMoodButton(self, **d) for d in self.theme["main/moods"]]) self.moods = PesterMoodHandler(self, *[PesterMoodButton(self, **d) for d in self.theme["main/moods"]])
self.addChumButton = QtGui.QPushButton(self.theme["main/addchum/text"], self)
self.addChumButton.resize(*self.theme["main/addchum/size"])
self.addChumButton.move(*self.theme["main/addchum/loc"])
self.addChumButton.setStyleSheet(self.theme["main/addchum/style"])
self.connect(self.addChumButton, QtCore.SIGNAL('clicked()'),
self, QtCore.SLOT('addChumWindow()'))
if not pygame.mixer:
self.alarm = NoneSound()
else:
self.alarm = pygame.mixer.Sound(self.theme["main/sounds/alertsound"])
self.waitingMessages = waitingMessageHolder(self)
self.convos = {} self.convos = {}
self.tabconvo = None self.tabconvo = None
self.optionmenu = None self.optionmenu = None
self.choosetheme = None
self.chooseprofile = None
self.addchumdialog = None
def profile(self): def profile(self):
return self.userprofile.chat return self.userprofile.chat
def mainSS(self): def mainSS(self):
@ -808,6 +1007,7 @@ class PesterWindow(MovingWindow):
convo = self.convos[handle] convo = self.convos[handle]
convo.addMessage(msg, False) convo.addMessage(msg, False)
# play sound here # play sound here
self.alarm.play()
def changeColor(self, handle, color): def changeColor(self, handle, color):
# pesterconvo and chumlist # pesterconvo and chumlist
@ -844,12 +1044,14 @@ class PesterWindow(MovingWindow):
self, QtCore.SLOT('tabsClosed()')) self, QtCore.SLOT('tabsClosed()'))
def changeProfile(self, collision=None): def changeProfile(self, collision=None):
self.chooseprofile = PesterChooseProfile(self.userprofile, self.config, self.theme, self, collision=collision) if not self.chooseprofile:
self.chooseprofile.exec_() self.chooseprofile = PesterChooseProfile(self.userprofile, self.config, self.theme, self, collision=collision)
self.chooseprofile.exec_()
def themePicker(self): def themePicker(self):
self.choosetheme = PesterChooseTheme(self.config, self.theme, self) if not self.choosetheme:
self.choosetheme.exec_() self.choosetheme = PesterChooseTheme(self.config, self.theme, self)
self.choosetheme.exec_()
def changeTheme(self, theme): def changeTheme(self, theme):
self.theme = theme self.theme = theme
# do self # do self
@ -867,11 +1069,41 @@ class PesterWindow(MovingWindow):
self.moods.removeButtons() self.moods.removeButtons()
self.moods = PesterMoodHandler(self, *[PesterMoodButton(self, **d) for d in self.theme["main/moods"]]) self.moods = PesterMoodHandler(self, *[PesterMoodButton(self, **d) for d in self.theme["main/moods"]])
self.moods.showButtons() self.moods.showButtons()
# chum
self.addChumButton.resize(*self.theme["main/addchum/size"])
self.addChumButton.move(*self.theme["main/addchum/loc"])
self.addChumButton.setStyleSheet(self.theme["main/addchum/style"])
# do open windows # do open windows
if self.tabconvo: if self.tabconvo:
self.tabconvo.changeTheme(theme) self.tabconvo.changeTheme(theme)
for c in self.convos.values(): for c in self.convos.values():
c.changeTheme(theme) c.changeTheme(theme)
# sounds
if not pygame.mixer:
self.alarm = NoneSound()
else:
self.alarm = pygame.mixer.Sound(self.theme["main/sounds/alertsound"]
)
# system tray icon
self.updateSystemTray()
def updateSystemTray(self):
if len(self.waitingMessages) == 0:
self.trayIconSignal.emit(0)
else:
self.trayIconSignal.emit(1)
def systemTrayFunction(self):
if len(self.waitingMessages) == 0:
if self.isMinimized():
self.showNormal()
else:
if self.isActiveWindow():
self.showMinimized()
else:
self.raise_()
self.activateWindow()
else:
self.waitingMessages.answerMessage()
@QtCore.pyqtSlot(QtGui.QListWidgetItem) @QtCore.pyqtSlot(QtGui.QListWidgetItem)
def newConversationWindow(self, chumlisting): def newConversationWindow(self, chumlisting):
@ -904,6 +1136,27 @@ class PesterWindow(MovingWindow):
self.newMessage(h, m) self.newMessage(h, m)
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def addChumWindow(self):
if not self.addchumdialog:
self.addchumdialog = QtGui.QInputDialog(self)
(handle, ok) = self.addchumdialog.getText(self, "New Chum", "Enter Chum Handle:")
if ok:
handle = unicode(handle)
if not (PesterProfile.checkLength(handle) and
PesterProfile.checkValid(handle)):
errormsg = QtGui.QErrorMessage(self)
errormsg.showMessage("THIS IS NOT A VALID CHUMTAG!")
self.addchumdialog = None
return
chum = PesterProfile(handle)
self.chumList.addChum(chum)
self.config.addChum(chum)
self.moodRequest.emit(chum)
self.addchumdialog = None
@QtCore.pyqtSlot(QtGui.QListWidgetItem)
def removeChum(self, chumlisting):
self.config.removeChum(chumlisting.chum)
@QtCore.pyqtSlot()
def openOpts(self): def openOpts(self):
if not self.optionmenu: if not self.optionmenu:
self.optionmenu = PesterOptions(self.config, self.theme, self) self.optionmenu = PesterOptions(self.config, self.theme, self)
@ -1010,12 +1263,21 @@ class PesterWindow(MovingWindow):
def pickTheme(self): def pickTheme(self):
self.themePicker() self.themePicker()
@QtCore.pyqtSlot(QtGui.QSystemTrayIcon.ActivationReason)
def systemTrayActivated(self, reason):
if reason == QtGui.QSystemTrayIcon.Trigger:
self.systemTrayFunction()
elif reason == QtGui.QSystemTrayIcon.Context:
# show context menu i guess
pass
newConvoStarted = QtCore.pyqtSignal(QtCore.QString, bool, name="newConvoStarted") newConvoStarted = QtCore.pyqtSignal(QtCore.QString, bool, name="newConvoStarted")
sendMessage = QtCore.pyqtSignal(QtCore.QString, PesterProfile) sendMessage = QtCore.pyqtSignal(QtCore.QString, PesterProfile)
convoClosed = QtCore.pyqtSignal(QtCore.QString) convoClosed = QtCore.pyqtSignal(QtCore.QString)
profileChanged = QtCore.pyqtSignal() profileChanged = QtCore.pyqtSignal()
moodRequest = QtCore.pyqtSignal(PesterProfile) moodRequest = QtCore.pyqtSignal(PesterProfile)
moodUpdated = QtCore.pyqtSignal() moodUpdated = QtCore.pyqtSignal()
trayIconSignal = QtCore.pyqtSignal(int)
class PesterIRC(QtCore.QObject): class PesterIRC(QtCore.QObject):
def __init__(self, window): def __init__(self, window):
@ -1118,11 +1380,16 @@ class PesterHandler(DefaultCommandHandler):
def quit(self, nick, reason): def quit(self, nick, reason):
handle = nick[0:nick.find("!")] handle = nick[0:nick.find("!")]
self.parent.moodUpdated.emit(handle, Mood("offline")) self.parent.moodUpdated.emit(handle, Mood("offline"))
def part(self, nick, channel):
handle = nick[0:oldnick.find("!")]
if channel == "#pesterchum":
self.parent.moodUpdated.emit(handle, Mood("offline"))
def nick(self, oldnick, newnick): def nick(self, oldnick, newnick):
oldhandle = oldnick[0:oldnick.find("!")] oldhandle = oldnick[0:oldnick.find("!")]
newchum = PesterProfile(newnick) newchum = PesterProfile(newnick)
self.parent.moodUpdated.emit(oldhandle, Mood("offline")) self.parent.moodUpdated.emit(oldhandle, Mood("offline"))
self.getMood(newchum) if newnick in self.mainwindow.chumList.chums:
self.getMood(newchum)
def getMood(self, *chums): def getMood(self, *chums):
chumglub = "GETMOOD " chumglub = "GETMOOD "
@ -1144,17 +1411,45 @@ class IRCThread(QtCore.QThread):
while 1: while 1:
irc.updateIRC() irc.updateIRC()
class PesterTray(QtGui.QSystemTrayIcon):
def __init__(self, icon, mainwindow, parent):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
self.mainwindow = mainwindow
traymenu = QtGui.QMenu()
traymenu.addAction("Hi!! HI!!")
self.setContextMenu(traymenu)
@QtCore.pyqtSlot(int)
def changeTrayIcon(self, i):
if i == 0:
self.setIcon(QtGui.QIcon(self.mainwindow.theme["main/icon"]))
else:
self.setIcon(QtGui.QIcon(self.mainwindow.theme["main/newmsgicon"]))
def main(): def main():
app = QtGui.QApplication(sys.argv) app = QtGui.QApplication(sys.argv)
if pygame.mixer:
# we could set the frequency higher but i love how cheesy it sounds
pygame.mixer.init()
else:
print "Warning: No sound!"
widget = PesterWindow() widget = PesterWindow()
widget.show() widget.show()
trayicon = QtGui.QSystemTrayIcon(QtGui.QIcon("themes/pesterchum/trayicon.gif"), app)
traymenu = QtGui.QMenu()
traymenu.addAction("Hi!! HI!!")
trayicon.setContextMenu(traymenu)
trayicon.show()
trayicon = PesterTray(QtGui.QIcon(widget.theme["main/icon"]), widget, app)
trayicon.show()
trayicon.connect(trayicon,
QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
widget,
QtCore.SLOT('systemTrayActivated(QSystemTrayIcon::ActivationReason)'))
trayicon.connect(widget,
QtCore.SIGNAL('trayIconSignal(int)'),
trayicon,
QtCore.SLOT('changeTrayIcon(int)'))
irc = PesterIRC(widget) irc = PesterIRC(widget)
irc.IRCConnect() irc.IRCConnect()
irc.connect(widget, QtCore.SIGNAL('sendMessage(QString, PyQt_PyObject)'), irc.connect(widget, QtCore.SIGNAL('sendMessage(QString, PyQt_PyObject)'),

View file

@ -1 +1 @@
{"color": "#00aaff", "theme": "pesterchum", "quirks": [], "handle": "superGhost"} {"color": "#00aaff", "theme": "trollian", "quirks": [], "handle": "superGhost"}

View file

@ -2,6 +2,7 @@
{"style": "background-image:url($path/pcbg.png);", {"style": "background-image:url($path/pcbg.png);",
"size": [300, 620], "size": [300, 620],
"icon": "$path/trayicon.gif", "icon": "$path/trayicon.gif",
"newmsgicon": "$path/trayicon2.png",
"close": { "image": "$path/x.gif", "close": { "image": "$path/x.gif",
"loc": [275, 0]}, "loc": [275, 0]},
"minimize": { "image": "$path/m.gif", "minimize": { "image": "$path/m.gif",
@ -10,9 +11,10 @@
"menu" : { "style": "font-family: 'Courier New'; font-weight: bold; font-size: 12px; background-color: #fdb302;border:2px solid #ffff00", "menu" : { "style": "font-family: 'Courier New'; font-weight: bold; font-size: 12px; background-color: #fdb302;border:2px solid #ffff00",
"selected": "background-color: #ffff00" "selected": "background-color: #ffff00"
}, },
"sounds": { "alertsound": "$path/alarm.wav" },
"chums": { "style": "background-color: black;color: white;font: bold;font-family: 'Courier New';selection-background-color:#919191; ", "chums": { "style": "background-color: black;color: white;font: bold;font-family: 'Courier New';selection-background-color:#919191; ",
"loc": [20, 65], "loc": [20, 65],
"size": [265, 350], "size": [266, 300],
"moods": { "chummy": { "icon": "$path/chummy.gif", "moods": { "chummy": { "icon": "$path/chummy.gif",
"color": "white" }, "color": "white" },
"offline": { "icon": "$path/offline.gif", "offline": { "icon": "$path/offline.gif",
@ -44,6 +46,11 @@
"defaultwindow": { "style": "background: #fdb302; font-family:'Courier New';font:bold;selection-background-color:#919191; " "defaultwindow": { "style": "background: #fdb302; font-family:'Courier New';font:bold;selection-background-color:#919191; "
}, },
"labels": { "mychumhandle": "MYCHUMHANDLE" }, "labels": { "mychumhandle": "MYCHUMHANDLE" },
"addchum": { "style": "background: #fdb302; border:5px solid yellow; font: bold;",
"loc": [20,370],
"size": [100, 50],
"text": "ADD CHUM"
},
"defaultmood": 0, "defaultmood": 0,
"moods": [ "moods": [
{ "style": "text-align:left; background: white; border:3px solid black; padding: 5px;color:#919191;", { "style": "text-align:left; background: white; border:3px solid black; padding: 5px;color:#919191;",
@ -114,7 +121,11 @@
"input": { "input": {
"style": "background: white;" "style": "background: white;"
}, },
"tabstyle": 0 "tabs": {
"style": "",
"newmsgcolor": "#fdb302",
"tabstyle": 0
}
} }
} }

View file

@ -2,6 +2,7 @@
{"style": "background-image:url($path/tnbg2.png);", {"style": "background-image:url($path/tnbg2.png);",
"size": [300, 620], "size": [300, 620],
"icon": "$path/trayicon3.png", "icon": "$path/trayicon3.png",
"newmsgicon": "$path/trayicon.gif",
"close": { "image": "$path/x.gif", "close": { "image": "$path/x.gif",
"loc": [275, 0]}, "loc": [275, 0]},
"minimize": { "image": "$path/m.gif", "minimize": { "image": "$path/m.gif",
@ -10,9 +11,10 @@
"menu" : { "style": "font-family: 'Courier New'; font-weight: bold; font-size: 12px; background-color: #e5000f; border:2px solid #ff0000", "menu" : { "style": "font-family: 'Courier New'; font-weight: bold; font-size: 12px; background-color: #e5000f; border:2px solid #ff0000",
"selected": "background-color: #ff0000" "selected": "background-color: #ff0000"
}, },
"sounds": { "alertsound": "$path/alarm.wav" },
"chums": { "style": "background-color: black;color: white;font: bold;font-family: 'Courier New';selection-background-color:#ffb6b6; ", "chums": { "style": "background-color: black;color: white;font: bold;font-family: 'Courier New';selection-background-color:#ffb6b6; ",
"loc": [20, 65], "loc": [20, 65],
"size": [266, 350], "size": [266, 300],
"moods": { "chummy": { "icon": "$path/chummy.gif", "moods": { "chummy": { "icon": "$path/chummy.gif",
"color": "white" }, "color": "white" },
"offline": { "icon": "$path/offline.gif", "offline": { "icon": "$path/offline.gif",
@ -44,6 +46,11 @@
"defaultwindow": { "style": "background: #e5000f; font-family:'Courier New';font:bold;selection-background-color:#ffb6b6; " "defaultwindow": { "style": "background: #e5000f; font-family:'Courier New';font:bold;selection-background-color:#ffb6b6; "
}, },
"labels": { "mychumhandle": "MYTROLLTAG" }, "labels": { "mychumhandle": "MYTROLLTAG" },
"addchum": { "style": "background: black; border:5px solid #550000; font: bold;color:white;",
"loc": [20,370],
"size": [100, 50],
"text": "ADD LOSER"
},
"defaultmood": 7, "defaultmood": 7,
"moods": [ "moods": [
{ "style": "text-align:left; background: black; border:3px solid black; padding: 5px;color:#dbdbdb;", { "style": "text-align:left; background: black; border:3px solid black; padding: 5px;color:#dbdbdb;",
@ -114,7 +121,11 @@
"input": { "input": {
"style": "background: white;" "style": "background: white;"
}, },
"tabstyle": 0 "tabs": {
"style": "",
"newmsgcolor": "red",
"tabstyle": 0
}
} }
} }