pesterchum/convo.py

929 lines
40 KiB
Python
Raw Normal View History

2011-02-04 16:17:27 -05:00
from string import Template
import re
2011-02-13 21:01:58 -05:00
import platform
2021-03-23 17:36:43 -04:00
import http.client, urllib.request, urllib.parse, urllib.error
from time import strftime
2011-02-13 04:27:12 -05:00
from copy import copy
2011-02-10 20:55:45 -05:00
from datetime import datetime, timedelta
2021-03-23 17:36:43 -04:00
from PyQt5 import QtCore, QtGui, QtWidgets
2011-02-04 16:17:27 -05:00
from mood import Mood
from dataobjs import PesterProfile, PesterHistory
2011-04-13 02:12:19 -04:00
from generic import PesterIcon
from parsetools import convertTags, lexMessage, mecmd, colorBegin, colorEnd, \
img2smiley, smiledict
import parsetools
import pnc.lexercon as lexercon
2017-03-07 22:28:15 -05:00
try:
from pnc.attrdict import AttrDict
except ImportError:
# Fall back on the old location - just in case
from pnc.dep.attrdict import AttrDict
2011-02-04 16:17:27 -05:00
2021-03-23 17:36:43 -04:00
class PesterTabWindow(QtWidgets.QFrame):
2011-02-04 19:50:56 -05:00
def __init__(self, mainwindow, parent=None, convo="convo"):
super(PesterTabWindow, self).__init__(parent)
2011-03-02 18:36:10 -05:00
self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
2011-02-04 16:17:27 -05:00
self.setFocusPolicy(QtCore.Qt.ClickFocus)
self.mainwindow = mainwindow
2021-03-23 17:36:43 -04:00
self.tabs = QtWidgets.QTabBar(self)
self.tabs.setMovable(True)
2011-02-04 16:17:27 -05:00
self.tabs.setTabsClosable(True)
2021-03-23 17:36:43 -04:00
self.tabs.currentChanged[int].connect(self.changeTab)
self.tabs.tabCloseRequested[int].connect(self.tabClose)
self.tabs.tabMoved[int, int].connect(self.tabMoved)
2011-02-04 16:17:27 -05:00
self.shortcuts = AttrDict()
2021-03-23 17:36:43 -04:00
self.shortcuts.tabNext = QtWidgets.QShortcut(
QtGui.QKeySequence('Ctrl+j'), self,
context=QtCore.Qt.WidgetWithChildrenShortcut)
2021-03-23 17:36:43 -04:00
self.shortcuts.tabLast = QtWidgets.QShortcut(
QtGui.QKeySequence('Ctrl+k'), self,
context=QtCore.Qt.WidgetWithChildrenShortcut)
# Note that we use reversed keys here.
2021-03-23 17:36:43 -04:00
self.shortcuts.tabUp = QtWidgets.QShortcut(
QtGui.QKeySequence('Ctrl+PgDown'), self,
context=QtCore.Qt.WidgetWithChildrenShortcut)
2021-03-23 17:36:43 -04:00
self.shortcuts.tabDn = QtWidgets.QShortcut(
QtGui.QKeySequence('Ctrl+PgUp'), self,
context=QtCore.Qt.WidgetWithChildrenShortcut)
2021-03-23 17:36:43 -04:00
self.shortcuts.tabNext.activated.connect(self.nudgeTabNext)
self.shortcuts.tabUp.activated.connect(self.nudgeTabNext)
self.shortcuts.tabLast.activated.connect(self.nudgeTabLast)
self.shortcuts.tabDn.activated.connect(self.nudgeTabLast)
2011-02-16 06:11:09 -05:00
self.initTheme(self.mainwindow.theme)
2021-03-23 17:36:43 -04:00
self.layout = QtWidgets.QVBoxLayout()
2011-02-04 16:17:27 -05:00
self.layout.setContentsMargins(0,0,0,0)
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
self.convos = {}
self.tabIndices = {}
self.currentConvo = None
self.changedTab = False
self.softclose = False
2011-02-04 19:50:56 -05:00
self.type = convo
2011-02-04 16:17:27 -05:00
# get default tab color i guess
self.defaultTabTextColor = self.getTabTextColor()
2011-02-04 19:50:56 -05:00
2011-02-04 16:17:27 -05:00
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):
2011-02-04 19:50:56 -05:00
self.convos[convo.title()] = convo
2011-02-04 16:17:27 -05:00
# either addTab or setCurrentIndex will trigger changed()
2011-02-04 19:50:56 -05:00
newindex = self.tabs.addTab(convo.title())
self.tabIndices[convo.title()] = newindex
2011-02-04 16:17:27 -05:00
self.tabs.setCurrentIndex(newindex)
2011-02-04 19:50:56 -05:00
self.tabs.setTabIcon(newindex, convo.icon())
2011-02-04 16:17:27 -05:00
def showChat(self, 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
2011-02-04 19:50:56 -05:00
self.tabs.tabText(self.tabs.currentIndex()) == convo.title()):
2011-02-04 16:17:27 -05:00
return True
2017-01-02 13:46:42 -05:00
def isBot(self, *args, **kwargs):
return self.mainwindow.isBot(*args, **kwargs)
2011-02-04 16:17:27 -05:00
def keyPressEvent(self, event):
2016-12-05 09:58:12 -05:00
# TODO: Clean this up. Our text areas now call this.
2011-02-04 16:17:27 -05:00
keypress = event.key()
mods = event.modifiers()
if ((mods & QtCore.Qt.ControlModifier) and
2011-02-04 16:17:27 -05:00
keypress == QtCore.Qt.Key_Tab):
2021-03-23 17:36:43 -04:00
handles = list(self.convos.keys())
2011-02-10 13:00:06 -05:00
waiting = self.mainwindow.waitingMessages.waitingHandles()
waitinghandles = list(set(handles) & set(waiting))
if len(waitinghandles) > 0:
nexti = self.tabIndices[waitinghandles[0]]
else:
nexti = (self.tabIndices[self.currentConvo.title()] + 1) % self.tabs.count()
2011-02-04 16:17:27 -05:00
self.tabs.setCurrentIndex(nexti)
@QtCore.pyqtSlot()
def nudgeTabNext(self): return self.nudgeTabIndex(+1)
@QtCore.pyqtSlot()
def nudgeTabLast(self): return self.nudgeTabIndex(-1)
def nudgeTabIndex(self, direction):
# Inverted controls. Might add an option for this if people want
# it.
#~if keypress == QtCore.Qt.Key_PageDown:
#~ direction = 1
#~elif keypress == QtCore.Qt.Key_PageUp:
#~ direction = -1
# ...Processing...
tabs = self.tabs
# Pick our new index by sliding up or down the tab range.
# NOTE: This feels like it could error. In fact, it /will/ if
# there are no tabs, but...that shouldn't happen, should it?
# There are probably other scenarios, too, so we'll have to
# check on this later.
#
# Calculate the new index.
ct = tabs.count()
cind = tabs.currentIndex()
nind = cind + direction
if nind > (ct - 1):
# The new index would be higher than the maximum; loop.
nind = nind % ct
# Otherwise, negative syntax should get it for us.
2021-03-23 17:36:43 -04:00
nind = list(range(ct))[nind]
# Change to the selected tab.
# Note that this will send out the usual callbacks that handle
# focusing and such.
tabs.setCurrentIndex(nind)
2016-12-05 09:58:12 -05:00
def contextMenuEvent(self, event):
#~if event.reason() == QtGui.QContextMenuEvent.Mouse:
tabi = self.tabs.tabAt(event.pos())
if tabi < 0:
tabi = self.tabs.currentIndex()
2021-03-23 17:36:43 -04:00
for h, i in list(self.tabIndices.items()):
if i == tabi:
# Our index matches, grab the object using our handle.
convo = self.convos[h]
break
else:
# No matches
return
# Pop up the options menu of the relevant tab.
convo.contextMenuEvent(event)
2011-02-04 16:17:27 -05:00
def closeSoft(self):
self.softclose = True
self.close()
def updateBlocked(self, handle):
i = self.tabIndices[handle]
icon = QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"])
self.tabs.setTabIcon(i, icon)
if self.tabs.currentIndex() == i:
self.setWindowIcon(icon)
def updateMood(self, handle, mood, unblocked=False):
i = self.tabIndices[handle]
if handle in self.mainwindow.config.getBlocklist() and not unblocked:
icon = QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"])
else:
icon = mood.icon(self.mainwindow.theme)
self.tabs.setTabIcon(i, icon)
if self.tabs.currentIndex() == i:
self.setWindowIcon(icon)
def closeEvent(self, event):
if not self.softclose:
while self.tabs.count() > 0:
self.tabClose(0)
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()
2021-03-23 17:36:43 -04:00
handle = str(self.tabs.tabText(i))
2011-02-04 16:17:27 -05:00
self.clearNewMessage(handle)
def convoHasFocus(self, handle):
i = self.tabIndices[handle]
if (self.tabs.currentIndex() == i and
2011-02-04 16:17:27 -05:00
(self.hasFocus() or self.tabs.hasFocus())):
return True
else:
return False
def notifyNewMessage(self, handle):
i = self.tabIndices[handle]
2011-02-04 19:50:56 -05:00
self.tabs.setTabTextColor(i, QtGui.QColor(self.mainwindow.theme["%s/tabs/newmsgcolor" % (self.type)]))
2011-02-04 16:17:27 -05:00
convo = self.convos[handle]
# Create a function for the icon to use
# TODO: Let us disable this.
2011-02-04 16:17:27 -05:00
def func():
convo.showChat()
self.mainwindow.waitingMessages.addMessage(handle, func)
# set system tray
def clearNewMessage(self, handle):
try:
i = self.tabIndices[handle]
self.tabs.setTabTextColor(i, self.defaultTabTextColor)
except KeyError:
pass
self.mainwindow.waitingMessages.messageAnswered(handle)
2011-02-16 06:11:09 -05:00
def initTheme(self, theme):
self.resize(*theme["convo/size"])
2011-02-24 20:03:17 -05:00
self.setStyleSheet(theme["convo/tabwindow/style"])
2011-02-16 06:11:09 -05:00
self.tabs.setShape(theme["convo/tabs/tabstyle"])
self.tabs.setStyleSheet("QTabBar::tab{ %s } QTabBar::tab:selected { %s }" % (theme["convo/tabs/style"], theme["convo/tabs/selectedstyle"]))
2011-02-04 19:50:56 -05:00
2011-02-04 16:17:27 -05:00
def changeTheme(self, theme):
2011-02-16 06:11:09 -05:00
self.initTheme(theme)
2021-03-23 17:36:43 -04:00
for c in list(self.convos.values()):
2011-02-05 22:24:10 -05:00
tabi = self.tabIndices[c.title()]
self.tabs.setTabIcon(tabi, c.icon())
2011-02-04 16:17:27 -05:00
currenttabi = self.tabs.currentIndex()
if currenttabi >= 0:
2021-03-23 17:36:43 -04:00
currentHandle = str(self.tabs.tabText(self.tabs.currentIndex()))
2011-02-05 22:24:10 -05:00
self.setWindowIcon(self.convos[currentHandle].icon())
2011-02-04 16:17:27 -05:00
self.defaultTabTextColor = self.getTabTextColor()
@QtCore.pyqtSlot(int)
def tabClose(self, i):
2021-03-23 17:36:43 -04:00
handle = str(self.tabs.tabText(i))
2011-02-04 16:17:27 -05:00
self.mainwindow.waitingMessages.messageAnswered(handle)
#print(self.convos.keys())
# I, legit don' t know why this is an issue, but, uh, yeah-
try:
convo = self.convos[handle]
except:
#handle = handle.replace("&","")
handle = ''.join(handle.split('&', 1))
convo = self.convos[handle]
2011-02-04 16:17:27 -05:00
del self.convos[handle]
del self.tabIndices[handle]
self.tabs.removeTab(i)
2021-03-23 17:36:43 -04:00
for (h, j) in self.tabIndices.items():
2011-02-04 16:17:27 -05:00
if j > i:
self.tabIndices[h] = j-1
self.layout.removeWidget(convo)
convo.close()
if self.tabs.count() == 0:
self.close()
return
if self.currentConvo == convo:
currenti = self.tabs.currentIndex()
2021-03-23 17:36:43 -04:00
currenth = str(self.tabs.tabText(currenti))
2011-02-04 16:17:27 -05:00
self.currentConvo = self.convos[currenth]
self.currentConvo.raiseChat()
@QtCore.pyqtSlot(int)
def changeTab(self, i):
if i < 0:
return
if self.changedTab:
self.changedTab = False
return
2021-03-23 17:36:43 -04:00
handle = str(self.tabs.tabText(i))
2011-02-04 16:17:27 -05:00
convo = self.convos[handle]
if self.currentConvo:
self.layout.removeWidget(self.currentConvo)
self.currentConvo = convo
self.layout.addWidget(convo)
2011-02-04 19:50:56 -05:00
self.setWindowIcon(convo.icon())
self.setWindowTitle(convo.title())
2011-02-04 16:17:27 -05:00
self.activateWindow()
self.raise_()
convo.raiseChat()
@QtCore.pyqtSlot(int, int)
def tabMoved(self, to, fr):
l = self.tabIndices
for i in l:
if l[i] == fr:
oldpos = i
if l[i] == to:
newpos = i
l[oldpos] = to
l[newpos] = fr
2011-02-04 16:17:27 -05:00
windowClosed = QtCore.pyqtSignal()
class PesterMovie(QtGui.QMovie):
def __init__(self, parent):
super(PesterMovie, self).__init__(parent)
self.textwindow = parent
@QtCore.pyqtSlot(int)
def animate(self, frame):
text = self.textwindow
if text.mainwindow.config.animations():
movie = self
url = text.urls[movie].toString()
2021-03-23 17:36:43 -04:00
html = str(text.toHtml())
if html.find(url) != -1:
if text.hasTabs:
i = text.tabobject.tabIndices[text.parent().title()]
if text.tabobject.tabs.currentIndex() == i:
text.document().addResource(QtGui.QTextDocument.ImageResource,
text.urls[movie], movie.currentPixmap())
text.setLineWrapColumnOrWidth(text.lineWrapColumnOrWidth())
else:
text.document().addResource(QtGui.QTextDocument.ImageResource,
text.urls[movie], movie.currentPixmap())
text.setLineWrapColumnOrWidth(text.lineWrapColumnOrWidth())
2021-03-23 17:36:43 -04:00
class PesterText(QtWidgets.QTextEdit):
2011-02-04 16:17:27 -05:00
def __init__(self, theme, parent=None):
super(PesterText, self).__init__(parent)
if hasattr(self.parent(), 'mainwindow'):
self.mainwindow = self.parent().mainwindow
else:
self.mainwindow = self.parent()
if type(parent.parent()) is PesterTabWindow:
self.tabobject = parent.parent()
self.hasTabs = True
else:
self.hasTabs = False
2011-02-11 04:07:07 -05:00
self.initTheme(theme)
2011-02-04 16:17:27 -05:00
self.setReadOnly(True)
self.setMouseTracking(True)
2011-02-22 19:49:47 -05:00
self.textSelected = False
2021-03-23 17:36:43 -04:00
self.copyAvailable[bool].connect(self.textReady)
2011-05-03 19:41:40 -04:00
self.urls = {}
for k in smiledict:
self.addAnimation(QtCore.QUrl("smilies/%s" % (smiledict[k])), "smilies/%s" % (smiledict[k]))
2021-03-23 17:36:43 -04:00
self.mainwindow.animationSetting[bool].connect(self.animateChanged)
2011-05-03 19:41:40 -04:00
def addAnimation(self, url, fileName):
movie = PesterMovie(self)
2011-05-03 19:41:40 -04:00
movie.setFileName(fileName)
movie.setCacheMode(QtGui.QMovie.CacheAll)
if movie.frameCount() > 1:
self.urls[movie] = url
2021-03-23 17:36:43 -04:00
movie.frameChanged[int].connect(movie.animate)
#movie.start()
@QtCore.pyqtSlot(bool)
def animateChanged(self, animate):
if animate:
for m in self.urls:
2021-03-23 17:36:43 -04:00
html = str(self.toHtml())
if html.find(self.urls[m].toString()) != -1:
if m.frameCount() > 1:
m.start()
else:
for m in self.urls:
2021-03-23 17:36:43 -04:00
html = str(self.toHtml())
if html.find(self.urls[m].toString()) != -1:
if m.frameCount() > 1:
m.stop()
2011-05-03 19:41:40 -04:00
2011-02-22 19:49:47 -05:00
@QtCore.pyqtSlot(bool)
def textReady(self, ready):
self.textSelected = ready
2011-02-11 04:07:07 -05:00
def initTheme(self, theme):
2021-03-23 17:36:43 -04:00
if "convo/scrollbar" in theme:
2011-02-11 04:07:07 -05:00
self.setStyleSheet("QTextEdit { %s } QScrollBar:vertical { %s } QScrollBar::handle:vertical { %s } QScrollBar::add-line:vertical { %s } QScrollBar::sub-line:vertical { %s } QScrollBar:up-arrow:vertical { %s } QScrollBar:down-arrow:vertical { %s }" % (theme["convo/textarea/style"], theme["convo/scrollbar/style"], theme["convo/scrollbar/handle"], theme["convo/scrollbar/downarrow"], theme["convo/scrollbar/uparrow"], theme["convo/scrollbar/uarrowstyle"], theme["convo/scrollbar/darrowstyle"] ))
else:
self.setStyleSheet("QTextEdit { %s }" % (theme["convo/textarea/style"]))
2011-02-13 04:27:12 -05:00
def addMessage(self, lexmsg, chum):
if len(lexmsg) == 0:
return
color = chum.colorcmd()
2011-02-04 16:17:27 -05:00
systemColor = QtGui.QColor(self.parent().mainwindow.theme["convo/systemMsgColor"])
initials = chum.initials()
parent = self.parent()
window = parent.mainwindow
me = window.profile()
if self.mainwindow.config.animations():
for m in self.urls:
if convertTags(lexmsg).find(self.urls[m].toString()) != -1:
if m.state() == QtGui.QMovie.NotRunning:
m.start()
if self.parent().mainwindow.config.showTimeStamps():
if self.parent().mainwindow.config.time12Format():
time = strftime("[%I:%M")
else:
time = strftime("[%H:%M")
if self.parent().mainwindow.config.showSeconds():
time += strftime(":%S] ")
else:
time += "] "
else:
time = ""
2011-02-13 04:27:12 -05:00
if lexmsg[0] == "PESTERCHUM:BEGIN":
2011-02-04 16:17:27 -05:00
parent.setChumOpen(True)
2011-02-13 04:27:12 -05:00
pmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(pmsg))
elif lexmsg[0] == "PESTERCHUM:CEASE":
2011-02-04 16:17:27 -05:00
parent.setChumOpen(False)
2011-02-13 04:27:12 -05:00
pmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/ceasepester"])
window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(pmsg))
elif lexmsg[0] == "PESTERCHUM:BLOCK":
pmsg = chum.pestermsg(me, systemColor, window.theme['convo/text/blocked'])
window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(pmsg))
elif lexmsg[0] == "PESTERCHUM:UNBLOCK":
pmsg = chum.pestermsg(me, systemColor, window.theme['convo/text/unblocked'])
window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(pmsg))
elif lexmsg[0] == "PESTERCHUM:BLOCKED":
pmsg = chum.pestermsg(me, systemColor, window.theme['convo/text/blockedmsg'])
window.chatlog.log(chum.handle, pmsg)
self.append(convertTags(pmsg))
elif lexmsg[0] == "PESTERCHUM:IDLE":
imsg = chum.idlemsg(systemColor, window.theme['convo/text/idle'])
window.chatlog.log(chum.handle, imsg)
self.append(convertTags(imsg))
elif type(lexmsg[0]) is mecmd:
memsg = chum.memsg(systemColor, lexmsg)
2011-02-04 16:17:27 -05:00
if chum is me:
2011-02-13 04:27:12 -05:00
window.chatlog.log(parent.chum.handle, memsg)
2011-02-04 16:17:27 -05:00
else:
2011-02-13 04:27:12 -05:00
window.chatlog.log(chum.handle, memsg)
self.append(time + convertTags(memsg))
2011-02-04 16:17:27 -05:00
else:
if not parent.chumopen and chum is not me:
beginmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
parent.setChumOpen(True)
2011-02-13 04:27:12 -05:00
window.chatlog.log(chum.handle, beginmsg)
2011-02-04 16:17:27 -05:00
self.append(convertTags(beginmsg))
lexmsg[0:0] = [colorBegin("<c=%s>" % (color), color),
2011-02-13 04:27:12 -05:00
"%s: " % (initials)]
lexmsg.append(colorEnd("</c>"))
self.append("<span style=\"color:#000000\">" + time + convertTags(lexmsg) + "</span>")
#self.append('<img src="/Users/lexi/pesterchum-lex/smilies/tab.gif" />'
# + '<img src="/Users/lexi/pesterchum/smilies/tab.gif" />'
# + '<img src="/Applications/Pesterchum.app/Contents/Resources/smilies/tab.gif" />'
# + '<img src="smilies/tab.gif" />');
2011-02-04 16:17:27 -05:00
if chum is me:
2011-02-13 04:27:12 -05:00
window.chatlog.log(parent.chum.handle, lexmsg)
2011-02-04 16:17:27 -05:00
else:
if ((window.idler.auto or window.idler.manual) and parent.chumopen
and not parent.isBot(chum.handle)):
2011-02-10 20:55:45 -05:00
idlethreshhold = 60
if (not hasattr(self, 'lastmsg')) or \
2011-02-13 04:27:12 -05:00
datetime.now() - self.lastmsg > timedelta(0,idlethreshhold):
2011-02-21 14:07:59 -05:00
verb = window.theme["convo/text/idle"]
2011-02-13 04:27:12 -05:00
idlemsg = me.idlemsg(systemColor, verb)
2011-02-21 14:07:59 -05:00
parent.textArea.append(convertTags(idlemsg))
2016-11-13 01:44:05 -05:00
window.chatlog.log(chum.handle, idlemsg)
2011-02-10 20:55:45 -05:00
parent.messageSent.emit("PESTERCHUM:IDLE", parent.title())
self.lastmsg = datetime.now()
2011-02-13 04:27:12 -05:00
window.chatlog.log(chum.handle, lexmsg)
2011-02-04 16:17:27 -05:00
def changeTheme(self, theme):
2011-02-11 04:07:07 -05:00
self.initTheme(theme)
2011-02-04 16:17:27 -05:00
sb = self.verticalScrollBar()
sb.setValue(sb.maximum())
def focusInEvent(self, event):
self.parent().clearNewMessage()
2021-03-23 17:36:43 -04:00
QtWidgets.QTextEdit.focusInEvent(self, event)
2011-02-04 16:17:27 -05:00
def isBot(self, *args, **kwargs):
2016-12-10 20:38:24 -05:00
return self.parent().isBot(*args, **kwargs)
def keyPressEvent(self, event):
2016-12-05 09:58:12 -05:00
# First parent is the PesterConvo containing this.
# Second parent is the PesterTabWindow containing *it*.
2017-01-09 05:20:48 -05:00
pass_to_super = (QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown,
QtCore.Qt.Key_Up, QtCore.Qt.Key_Down)
2016-12-05 09:58:12 -05:00
parent = self.parent()
key = event.key()
keymods = event.modifiers()
if hasattr(parent, 'textInput') and key not in pass_to_super:
2016-12-05 10:17:03 -05:00
# TODO: Shift focus here on bare (no modifiers) alphanumerics.
2016-12-05 09:58:12 -05:00
parent.textInput.keyPressEvent(event)
# Pass to the normal handler.
2016-12-05 10:17:03 -05:00
super(PesterText, self).keyPressEvent(event)
2011-02-04 16:17:27 -05:00
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
url = self.anchorAt(event.pos())
if url != "":
if url[0] == "#" and url != "#pesterchum":
self.parent().mainwindow.showMemos(url[1:])
elif url[0] == "@":
2021-03-23 17:36:43 -04:00
handle = str(url[1:])
self.parent().mainwindow.newConversation(handle)
else:
if event.modifiers() == QtCore.Qt.ControlModifier:
2021-03-23 17:36:43 -04:00
QtWidgets.QApplication.clipboard().setText(url)
else:
QtGui.QDesktopServices.openUrl(QtCore.QUrl(url, QtCore.QUrl.TolerantMode))
2021-03-23 17:36:43 -04:00
QtWidgets.QTextEdit.mousePressEvent(self, event)
2011-02-04 16:17:27 -05:00
def mouseMoveEvent(self, event):
2021-03-23 17:36:43 -04:00
QtWidgets.QTextEdit.mouseMoveEvent(self, event)
2011-02-04 16:17:27 -05:00
if self.anchorAt(event.pos()):
if self.viewport().cursor().shape != QtCore.Qt.PointingHandCursor:
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
else:
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
2011-02-22 19:49:47 -05:00
def contextMenuEvent(self, event):
textMenu = self.createStandardContextMenu()
#if self.textSelected:
# self.submitLogAction = QtGui.QAction("Submit to Pesterchum QDB", self)
# self.connect(self.submitLogAction, QtCore.SIGNAL('triggered()'),
# self, QtCore.SLOT('submitLog()'))
# textMenu.addAction(self.submitLogAction)
2011-02-22 19:49:47 -05:00
textMenu.exec_(event.globalPos())
2011-02-23 06:06:00 -05:00
def submitLogTitle(self):
return "[%s -> %s]" % (self.parent().mainwindow.profile().handle,
self.parent().chum.handle)
2011-02-22 19:49:47 -05:00
@QtCore.pyqtSlot()
def submitLog(self):
mimedata = self.createMimeDataFromSelection()
2011-02-23 06:06:00 -05:00
htmldata = img2smiley(mimedata.data("text/html"))
textdoc = QtGui.QTextDocument()
textdoc.setHtml(htmldata)
2011-02-23 06:27:37 -05:00
logdata = "%s\n%s" % (self.submitLogTitle(), textdoc.toPlainText())
2021-03-23 17:36:43 -04:00
self.sending = QtWidgets.QDialog(self)
layout = QtWidgets.QVBoxLayout()
self.sending.sendinglabel = QtWidgets.QLabel("S3ND1NG...", self.sending)
cancelbutton = QtWidgets.QPushButton("OK", self.sending)
cancelbutton.clicked.connect(self.sending.close)
2011-02-23 06:06:00 -05:00
layout.addWidget(self.sending.sendinglabel)
layout.addWidget(cancelbutton)
self.sending.setLayout(layout)
self.sending.show()
2021-03-23 17:36:43 -04:00
params = urllib.parse.urlencode({'quote': logdata, 'do': "add"})
2011-02-23 06:06:00 -05:00
headers = {"Content-type": "application/x-www-form-urlencoded",
"Accept": "text/plain"}
try:
pass
2021-03-23 17:36:43 -04:00
hconn = http.client.HTTPConnection('qdb.pesterchum.net', 80,
2011-02-23 06:06:00 -05:00
timeout=15)
hconn.request("POST", "/index.php", params, headers)
response = hconn.getresponse()
2011-02-24 13:07:37 -05:00
if response.status == 200:
2011-02-23 06:06:00 -05:00
self.sending.sendinglabel.setText("SUCC3SS!")
else:
2011-02-24 13:07:37 -05:00
self.sending.sendinglabel.setText("F41L3D: %s %s" % (response.status, response.reason))
2011-02-23 06:06:00 -05:00
hconn.close()
except Exception as e:
2011-02-23 06:06:00 -05:00
self.sending.sendinglabel.setText("F41L3D: %s" % (e))
del self.sending
2011-02-22 19:49:47 -05:00
2021-03-23 17:36:43 -04:00
class PesterInput(QtWidgets.QLineEdit):
stylesheet_path = "convo/input/style"
2011-02-04 16:17:27 -05:00
def __init__(self, theme, parent=None):
2016-12-05 10:17:03 -05:00
super(PesterInput, self).__init__(parent)
self.changeTheme(theme)
2011-02-04 16:17:27 -05:00
def changeTheme(self, theme):
self.setStyleSheet(theme[self.stylesheet_path])
2011-02-04 16:17:27 -05:00
def focusInEvent(self, event):
self.parent().clearNewMessage()
2011-02-13 04:27:12 -05:00
self.parent().textArea.textCursor().clearSelection()
2016-12-05 10:17:03 -05:00
super(PesterInput, self).focusInEvent(event)
2011-02-09 01:26:23 -05:00
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Up:
2021-03-23 17:36:43 -04:00
text = str(self.text())
2011-02-09 01:26:23 -05:00
next = self.parent().history.next(text)
if next is not None:
self.setText(next)
elif event.key() == QtCore.Qt.Key_Down:
prev = self.parent().history.prev()
if prev is not None:
self.setText(prev)
2017-01-09 02:25:49 -05:00
elif event.key() in [QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown]:
self.parent().textArea.keyPressEvent(event)
self.parent().mainwindow.idler.time = 0
2016-12-05 10:17:03 -05:00
super(PesterInput, self).keyPressEvent(event)
2011-02-09 01:26:23 -05:00
2021-03-23 17:36:43 -04:00
class PesterConvo(QtWidgets.QFrame):
2011-02-04 16:17:27 -05:00
def __init__(self, chum, initiated, mainwindow, parent=None):
super(PesterConvo, self).__init__(parent)
2011-03-02 18:36:10 -05:00
self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
2011-02-11 04:07:07 -05:00
self.setObjectName(chum.handle)
2011-02-04 16:17:27 -05:00
self.setFocusPolicy(QtCore.Qt.ClickFocus)
self.chum = chum
self.mainwindow = mainwindow
2011-02-16 06:11:09 -05:00
theme = self.mainwindow.theme
self.resize(*theme["convo/size"])
2011-02-22 19:49:47 -05:00
self.setStyleSheet("QFrame#%s { %s }" % (chum.handle, theme["convo/style"]))
2011-02-04 19:50:56 -05:00
self.setWindowIcon(self.icon())
self.setWindowTitle(self.title())
2011-02-04 16:17:27 -05:00
t = Template(self.mainwindow.theme["convo/chumlabel/text"])
2021-03-23 17:36:43 -04:00
self.chumLabel = QtWidgets.QLabel(t.safe_substitute(handle=chum.handle), self)
2011-02-04 16:17:27 -05:00
self.chumLabel.setStyleSheet(self.mainwindow.theme["convo/chumlabel/style"])
self.chumLabel.setAlignment(self.aligndict["h"][self.mainwindow.theme["convo/chumlabel/align/h"]] | self.aligndict["v"][self.mainwindow.theme["convo/chumlabel/align/v"]])
self.chumLabel.setMaximumHeight(self.mainwindow.theme["convo/chumlabel/maxheight"])
self.chumLabel.setMinimumHeight(self.mainwindow.theme["convo/chumlabel/minheight"])
2021-03-23 17:36:43 -04:00
self.chumLabel.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding))
2011-02-04 16:17:27 -05:00
self.textArea = PesterText(self.mainwindow.theme, self)
self.textInput = PesterInput(self.mainwindow.theme, self)
self.textInput.setFocus()
2021-03-23 17:36:43 -04:00
self.textInput.returnPressed.connect(self.sentMessage)
2011-02-04 16:17:27 -05:00
2021-03-23 17:36:43 -04:00
self.layout = QtWidgets.QVBoxLayout()
2011-02-04 16:17:27 -05:00
self.layout.addWidget(self.chumLabel)
self.layout.addWidget(self.textArea)
self.layout.addWidget(self.textInput)
self.layout.setSpacing(0)
margins = self.mainwindow.theme["convo/margins"]
self.layout.setContentsMargins(margins["left"], margins["top"],
margins["right"], margins["bottom"])
2011-02-04 16:17:27 -05:00
self.setLayout(self.layout)
2021-03-23 17:36:43 -04:00
self.optionsMenu = QtWidgets.QMenu(self)
2011-02-06 19:50:21 -05:00
self.optionsMenu.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
2021-03-23 17:36:43 -04:00
self.addChumAction = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
self.addChumAction.triggered.connect(self.addThisChum)
self.blockAction = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
self.blockAction.triggered.connect(self.blockThisChum)
self.quirksOff = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
2011-02-06 19:50:21 -05:00
self.quirksOff.setCheckable(True)
2021-03-23 17:36:43 -04:00
self.quirksOff.toggled[bool].connect(self.toggleQuirks)
self.oocToggle = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/ooc"], self)
self.oocToggle.setCheckable(True)
2021-03-23 17:36:43 -04:00
self.oocToggle.toggled[bool].connect(self.toggleOOC)
self.unblockchum = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
self.unblockchum.triggered.connect(self.unblockChumSlot)
self.reportchum = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self)
self.reportchum.triggered.connect(self.reportThisChum)
self.logchum = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
self.logchum.triggered.connect(self.openChumLogs)
2011-02-10 20:55:45 -05:00
# For this, we'll want to use setChecked to toggle these so they match
# the user's setting. Alternately (better), use a tristate checkbox, so
# that they start semi-checked?
# Easiest solution: Implement a 'Mute' option that overrides all
# notifications for that window, save for mentions.
# TODO: Look into setting up theme support here.
2021-03-23 17:36:43 -04:00
self._beepToggle = QtWidgets.QAction("Beep on Message", self)
self._beepToggle.setCheckable(True)
2021-03-23 17:36:43 -04:00
self._beepToggle.toggled[bool].connect(self.toggleBeep)
2021-03-23 17:36:43 -04:00
self._flashToggle = QtWidgets.QAction("Flash on Message", self)
self._flashToggle.setCheckable(True)
2021-03-23 17:36:43 -04:00
self._flashToggle.toggled[bool].connect(self.toggleFlash)
2021-03-23 17:36:43 -04:00
self._muteToggle = QtWidgets.QAction("Mute Notifications", self)
self._muteToggle.setCheckable(True)
2021-03-23 17:36:43 -04:00
self._muteToggle.toggled[bool].connect(self.toggleMute)
2011-02-06 19:50:21 -05:00
self.optionsMenu.addAction(self.quirksOff)
self.optionsMenu.addAction(self.oocToggle)
self.optionsMenu.addAction(self._beepToggle)
self.optionsMenu.addAction(self._flashToggle)
self.optionsMenu.addAction(self._muteToggle)
self.optionsMenu.addAction(self.logchum)
2011-02-06 19:50:21 -05:00
self.optionsMenu.addAction(self.addChumAction)
self.optionsMenu.addAction(self.blockAction)
2011-04-13 02:12:19 -04:00
self.optionsMenu.addAction(self.reportchum)
2011-02-06 19:50:21 -05:00
2011-02-04 16:17:27 -05:00
self.chumopen = False
2011-02-06 19:50:21 -05:00
self.applyquirks = True
self.ooc = False
2011-02-04 16:17:27 -05:00
self.always_beep = False
self.always_flash = False
self.notifications_muted = False
2011-02-04 16:17:27 -05:00
if parent:
parent.addChat(self)
if initiated:
msg = self.mainwindow.profile().pestermsg(self.chum, QtGui.QColor(self.mainwindow.theme["convo/systemMsgColor"]), self.mainwindow.theme["convo/text/beganpester"])
self.setChumOpen(True)
self.textArea.append(convertTags(msg))
2011-02-13 04:27:12 -05:00
self.mainwindow.chatlog.log(self.title(), msg)
2011-02-04 16:17:27 -05:00
self.newmessage = False
2011-02-09 01:26:23 -05:00
self.history = PesterHistory()
2011-02-04 16:17:27 -05:00
2011-02-04 19:50:56 -05:00
def title(self):
return self.chum.handle
def icon(self):
return self.chum.mood.icon(self.mainwindow.theme)
2011-02-23 06:06:00 -05:00
def myUpdateMood(self, mood):
chum = self.mainwindow.profile()
syscolor = QtGui.QColor(self.mainwindow.theme["convo/systemMsgColor"])
msg = chum.moodmsg(mood, syscolor, self.mainwindow.theme)
self.textArea.append(convertTags(msg))
self.mainwindow.chatlog.log(self.title(), msg)
2011-02-04 19:50:56 -05:00
def isBot(self, *args, **kwargs):
return self.parent().isBot(*args, **kwargs)
2011-02-08 17:47:07 -05:00
def updateMood(self, mood, unblocked=False, old=None):
syscolor = QtGui.QColor(self.mainwindow.theme["convo/systemMsgColor"])
#~ if mood.name() == "offline" and self.chumopen == True and not unblocked:
#~ self.mainwindow.ceasesound.play()
#~ msg = self.chum.pestermsg(self.mainwindow.profile(), syscolor, self.mainwindow.theme["convo/text/ceasepester"])
#~ self.textArea.append(convertTags(msg))
#~ self.mainwindow.chatlog.log(self.title(), msg)
#~ self.chumopen = False
if old and old.name() != mood.name():
2011-02-10 13:00:06 -05:00
msg = self.chum.moodmsg(mood, syscolor, self.mainwindow.theme)
2011-02-08 17:47:07 -05:00
self.textArea.append(convertTags(msg))
2011-02-13 04:27:12 -05:00
self.mainwindow.chatlog.log(self.title(), msg)
2011-02-04 16:17:27 -05:00
if self.parent():
2011-02-04 19:50:56 -05:00
self.parent().updateMood(self.title(), mood, unblocked)
2011-02-04 16:17:27 -05:00
else:
if self.chum.blocked(self.mainwindow.config) and not unblocked:
self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
2011-02-10 20:55:45 -05:00
self.optionsMenu.addAction(self.unblockchum)
self.optionsMenu.removeAction(self.blockAction)
2011-02-04 16:17:27 -05:00
else:
self.setWindowIcon(mood.icon(self.mainwindow.theme))
2011-02-10 20:55:45 -05:00
self.optionsMenu.removeAction(self.unblockchum)
self.optionsMenu.addAction(self.blockAction)
2011-02-04 16:17:27 -05:00
# print mood update?
def updateBlocked(self):
if self.parent():
2011-02-04 19:50:56 -05:00
self.parent().updateBlocked(self.title())
2011-02-04 16:17:27 -05:00
else:
self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
2011-02-10 20:55:45 -05:00
self.optionsMenu.addAction(self.unblockchum)
self.optionsMenu.removeAction(self.blockAction)
2011-02-04 16:17:27 -05:00
def updateColor(self, color):
self.chum.color = color
2011-02-13 04:27:12 -05:00
def addMessage(self, msg, me=True):
2021-03-23 17:36:43 -04:00
if type(msg) in [str, str]:
2011-02-13 04:27:12 -05:00
lexmsg = lexMessage(msg)
else:
lexmsg = msg
2011-02-04 16:17:27 -05:00
if me:
chum = self.mainwindow.profile()
else:
chum = self.chum
self.notifyNewMessage()
2011-02-13 04:27:12 -05:00
self.textArea.addMessage(lexmsg, chum)
2011-02-04 16:17:27 -05:00
def notifyNewMessage(self):
# Our imports have to be here to prevent circular import issues.
from memos import PesterMemo, MemoTabWindow
2011-02-04 16:17:27 -05:00
# first see if this conversation HASS the focus
title = self.title()
parent = self.parent()
memoblink = pesterblink = self.mainwindow.config.blink()
memoblink &= self.mainwindow.config.MBLINK
pesterblink &= self.mainwindow.config.PBLINK
mutednots = self.notifications_muted
mtsrc = self
if parent:
try:
mutednots = parent.notifications_muted
mtsrc = parent
except:
pass
if not (self.hasFocus() or self.textArea.hasFocus() or
self.textInput.hasFocus() or
(parent and parent.convoHasFocus(title))):
2011-02-04 16:17:27 -05:00
# ok if it has a tabconvo parent, send that the notify.
if parent:
# Just let the icon highlight normally.
# This function *also* highlights the tab, mind.
parent.notifyNewMessage(title)
if not mutednots:
# Remember that these two are descended from one another.
# TODO: Make these obey subclassing rules...ugh.
# They should really just use the class's function and do
# the checks there.
# PesterTabWindow -> MemoTabWindow
if isinstance(parent, MemoTabWindow):
if self.always_flash or memoblink:
self.mainwindow.gainAttention.emit(parent)
elif isinstance(parent, PesterTabWindow):
if self.always_flash or pesterblink:
self.mainwindow.gainAttention.emit(parent)
2011-02-04 16:17:27 -05:00
# if not change the window title and update system tray
else:
self.newmessage = True
self.setWindowTitle(title + "*")
# karxi: The order of execution here is a bit unclear...I'm not
# entirely sure how much of this directly affects what we see.
2011-02-04 16:17:27 -05:00
def func():
self.showChat()
self.mainwindow.waitingMessages.addMessage(title, func)
if not mutednots:
# Once again, PesterMemo inherits from PesterConvo.
if isinstance(self, PesterMemo):
if self.always_flash or memoblink:
self.mainwindow.gainAttention.emit(self)
elif isinstance(self, PesterConvo):
if self.always_flash or pesterblink:
self.mainwindow.gainAttention.emit(self)
2011-02-04 16:17:27 -05:00
def clearNewMessage(self):
if self.parent():
2011-02-04 19:50:56 -05:00
self.parent().clearNewMessage(self.title())
2011-02-04 16:17:27 -05:00
elif self.newmessage:
self.newmessage = False
2011-02-04 19:50:56 -05:00
self.setWindowTitle(self.title())
self.mainwindow.waitingMessages.messageAnswered(self.title())
2011-02-04 16:17:27 -05:00
# reset system tray
def focusInEvent(self, event):
self.clearNewMessage()
self.textInput.setFocus()
2011-02-09 01:26:23 -05:00
2011-02-04 16:17:27 -05:00
def raiseChat(self):
self.activateWindow()
self.raise_()
self.textInput.setFocus()
def showChat(self):
if self.parent():
2011-02-04 19:50:56 -05:00
self.parent().showChat(self.title())
2011-02-04 16:17:27 -05:00
self.raiseChat()
2011-02-06 19:50:21 -05:00
def contextMenuEvent(self, event):
if event.reason() == QtGui.QContextMenuEvent.Mouse:
self.optionsMenu.popup(event.globalPos())
2011-02-04 16:17:27 -05:00
def closeEvent(self, event):
2011-02-04 19:50:56 -05:00
self.mainwindow.waitingMessages.messageAnswered(self.title())
for movie in self.textArea.urls:
movie.stop()
del movie
2011-02-04 19:50:56 -05:00
self.windowClosed.emit(self.title())
2011-02-06 19:50:21 -05:00
2011-02-04 16:17:27 -05:00
def setChumOpen(self, o):
self.chumopen = o
def changeTheme(self, theme):
self.resize(*theme["convo/size"])
2011-02-25 05:41:33 -05:00
self.setStyleSheet("QFrame#%s { %s }" % (self.chum.handle, theme["convo/style"]))
2011-02-04 16:17:27 -05:00
margins = theme["convo/margins"]
self.layout.setContentsMargins(margins["left"], margins["top"],
margins["right"], margins["bottom"])
2011-02-04 19:50:56 -05:00
self.setWindowIcon(self.icon())
2011-02-04 16:17:27 -05:00
t = Template(self.mainwindow.theme["convo/chumlabel/text"])
2011-02-04 19:50:56 -05:00
self.chumLabel.setText(t.safe_substitute(handle=self.title()))
2011-02-04 16:17:27 -05:00
self.chumLabel.setStyleSheet(theme["convo/chumlabel/style"])
self.chumLabel.setAlignment(self.aligndict["h"][self.mainwindow.theme["convo/chumlabel/align/h"]] | self.aligndict["v"][self.mainwindow.theme["convo/chumlabel/align/v"]])
self.chumLabel.setMaximumHeight(self.mainwindow.theme["convo/chumlabel/maxheight"])
self.chumLabel.setMinimumHeight(self.mainwindow.theme["convo/chumlabel/minheight"])
2021-03-23 17:36:43 -04:00
self.chumLabel.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding))
2011-02-06 19:50:21 -05:00
self.quirksOff.setText(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"])
self.addChumAction.setText(self.mainwindow.theme["main/menus/rclickchumlist/addchum"])
self.blockAction.setText(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"])
2011-02-11 04:07:07 -05:00
self.unblockchum.setText(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"])
self.logchum.setText(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"])
2011-02-06 19:50:21 -05:00
2011-02-04 16:17:27 -05:00
self.textArea.changeTheme(theme)
self.textInput.changeTheme(theme)
2011-02-06 19:50:21 -05:00
2011-02-04 16:17:27 -05:00
@QtCore.pyqtSlot()
def sentMessage(self):
# Offloaded to another function, like its sisters.
# Fetch the raw text from the input box.
text = self.textInput.text()
2021-03-23 17:36:43 -04:00
text = str(self.textInput.text())
return parsetools.kxhandleInput(self, text, flavor="convo")
2011-02-04 16:17:27 -05:00
2011-02-06 19:50:21 -05:00
@QtCore.pyqtSlot()
def addThisChum(self):
self.mainwindow.addChum(self.chum)
@QtCore.pyqtSlot()
def blockThisChum(self):
self.mainwindow.blockChum(self.chum.handle)
2011-02-10 20:55:45 -05:00
@QtCore.pyqtSlot()
2011-04-13 02:12:19 -04:00
def reportThisChum(self):
self.mainwindow.reportChum(self.chum.handle)
@QtCore.pyqtSlot()
2011-02-10 20:55:45 -05:00
def unblockChumSlot(self):
self.mainwindow.unblockChum(self.chum.handle)
2011-02-06 19:50:21 -05:00
@QtCore.pyqtSlot(bool)
def toggleQuirks(self, toggled):
self.applyquirks = not toggled
@QtCore.pyqtSlot(bool)
def toggleOOC(self, toggled):
self.ooc = toggled
@QtCore.pyqtSlot()
def openChumLogs(self):
currentChum = self.chum.handle
self.mainwindow.chumList.pesterlogviewer = PesterLogViewer(currentChum, self.mainwindow.config, self.mainwindow.theme, self.mainwindow)
2021-03-23 17:36:43 -04:00
self.mainwindow.chumList.pesterlogviewer.rejected.connect(self.mainwindow.chumList.closeActiveLog)
self.mainwindow.chumList.pesterlogviewer.show()
self.mainwindow.chumList.pesterlogviewer.raise_()
self.mainwindow.chumList.pesterlogviewer.activateWindow()
2011-02-06 19:50:21 -05:00
@QtCore.pyqtSlot(bool)
def toggleBeep(self, toggled):
self.always_beep = toggled
@QtCore.pyqtSlot(bool)
def toggleFlash(self, toggled):
self.always_flash = toggled
@QtCore.pyqtSlot(bool)
def toggleMute(self, toggled):
self.notifications_muted = toggled
2021-03-23 17:36:43 -04:00
messageSent = QtCore.pyqtSignal('QString', 'QString')
windowClosed = QtCore.pyqtSignal('QString')
2011-02-04 16:17:27 -05:00
aligndict = {"h": {"center": QtCore.Qt.AlignHCenter,
"left": QtCore.Qt.AlignLeft,
"right": QtCore.Qt.AlignRight },
"v": {"center": QtCore.Qt.AlignVCenter,
"top": QtCore.Qt.AlignTop,
"bottom": QtCore.Qt.AlignBottom } }
# the import is way down here to avoid recursive imports
from logviewer import PesterLogViewer