added system tray stuff and more im sure
This commit is contained in:
parent
99175a9f6d
commit
dd7c0a7887
12 changed files with 356 additions and 37 deletions
18
TODO
18
TODO
|
@ -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.
BIN
oyoyo/client.pyc
BIN
oyoyo/client.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
oyoyo/parse.pyc
BIN
oyoyo/parse.pyc
Binary file not shown.
|
@ -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"}
|
327
pesterchum.py
327
pesterchum.py
|
@ -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,10 +1044,12 @@ class PesterWindow(MovingWindow):
|
||||||
self, QtCore.SLOT('tabsClosed()'))
|
self, QtCore.SLOT('tabsClosed()'))
|
||||||
|
|
||||||
def changeProfile(self, collision=None):
|
def changeProfile(self, collision=None):
|
||||||
|
if not self.chooseprofile:
|
||||||
self.chooseprofile = PesterChooseProfile(self.userprofile, self.config, self.theme, self, collision=collision)
|
self.chooseprofile = PesterChooseProfile(self.userprofile, self.config, self.theme, self, collision=collision)
|
||||||
self.chooseprofile.exec_()
|
self.chooseprofile.exec_()
|
||||||
|
|
||||||
def themePicker(self):
|
def themePicker(self):
|
||||||
|
if not self.choosetheme:
|
||||||
self.choosetheme = PesterChooseTheme(self.config, self.theme, self)
|
self.choosetheme = PesterChooseTheme(self.config, self.theme, self)
|
||||||
self.choosetheme.exec_()
|
self.choosetheme.exec_()
|
||||||
def changeTheme(self, theme):
|
def changeTheme(self, theme):
|
||||||
|
@ -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,10 +1380,15 @@ 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"))
|
||||||
|
if newnick in self.mainwindow.chumList.chums:
|
||||||
self.getMood(newchum)
|
self.getMood(newchum)
|
||||||
|
|
||||||
def getMood(self, *chums):
|
def getMood(self, *chums):
|
||||||
|
@ -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()
|
trayicon = PesterTray(QtGui.QIcon(widget.theme["main/icon"]), widget, app)
|
||||||
traymenu.addAction("Hi!! HI!!")
|
|
||||||
trayicon.setContextMenu(traymenu)
|
|
||||||
trayicon.show()
|
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)'),
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"color": "#00aaff", "theme": "pesterchum", "quirks": [], "handle": "superGhost"}
|
{"color": "#00aaff", "theme": "trollian", "quirks": [], "handle": "superGhost"}
|
|
@ -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;"
|
||||||
},
|
},
|
||||||
|
"tabs": {
|
||||||
|
"style": "",
|
||||||
|
"newmsgcolor": "#fdb302",
|
||||||
"tabstyle": 0
|
"tabstyle": 0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;"
|
||||||
},
|
},
|
||||||
|
"tabs": {
|
||||||
|
"style": "",
|
||||||
|
"newmsgcolor": "red",
|
||||||
"tabstyle": 0
|
"tabstyle": 0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue