Пример #1
0
class PesterConvo(QtGui.QFrame):
    def __init__(self, chum, initiated, mainwindow, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
        self.setObjectName(chum.handle)
        self.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.chum = chum
        self.mainwindow = mainwindow
        theme = self.mainwindow.theme
        self.resize(*theme["convo/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (chum.handle, theme["convo/style"]))
        self.setWindowIcon(self.icon())
        self.setWindowTitle(self.title())

        t = Template(self.mainwindow.theme["convo/chumlabel/text"])

        self.chumLabel = QtGui.QLabel(t.safe_substitute(handle=chum.handle), self)
        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"])
        self.chumLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding))
        self.textArea = PesterText(self.mainwindow.theme, self)
        self.textInput = PesterInput(self.mainwindow.theme, self)
        self.textInput.setFocus()

        self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
                     self, QtCore.SLOT('sentMessage()'))

        self.layout = QtGui.QVBoxLayout()
        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"])

        self.setLayout(self.layout)

        self.optionsMenu = QtGui.QMenu(self)
        self.optionsMenu.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
        self.addChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
        self.connect(self.addChumAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('addThisChum()'))
        self.blockAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
        self.connect(self.blockAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('blockThisChum()'))
        self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
        self.quirksOff.setCheckable(True)
        self.connect(self.quirksOff, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('toggleQuirks(bool)'))
        self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
        self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('unblockChumSlot()'))
        self.reportchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self)
        self.connect(self.reportchum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('reportThisChum()'))
        self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
        self.connect(self.logchum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('openChumLogs()'))

        self.optionsMenu.addAction(self.quirksOff)
        self.optionsMenu.addAction(self.logchum)
        self.optionsMenu.addAction(self.addChumAction)
        self.optionsMenu.addAction(self.blockAction)
        self.optionsMenu.addAction(self.reportchum)

        self.chumopen = False
        self.applyquirks = True

        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))
            self.mainwindow.chatlog.log(self.title(), msg)
        self.newmessage = False
        self.history = PesterHistory()

    def title(self):
        return self.chum.handle
    def icon(self):
        return self.chum.mood.icon(self.mainwindow.theme)
    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)

    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():
            msg = self.chum.moodmsg(mood, syscolor, self.mainwindow.theme)
            self.textArea.append(convertTags(msg))
            self.mainwindow.chatlog.log(self.title(), msg)
        if self.parent():
            self.parent().updateMood(self.title(), mood, unblocked)
        else:
            if self.chum.blocked(self.mainwindow.config) and not unblocked:
                self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
                self.optionsMenu.addAction(self.unblockchum)
                self.optionsMenu.removeAction(self.blockAction)
            else:
                self.setWindowIcon(mood.icon(self.mainwindow.theme))
                self.optionsMenu.removeAction(self.unblockchum)
                self.optionsMenu.addAction(self.blockAction)
        # print mood update?
    def updateBlocked(self):
        if self.parent():
            self.parent().updateBlocked(self.title())
        else:
            self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
        self.optionsMenu.addAction(self.unblockchum)
        self.optionsMenu.removeAction(self.blockAction)

    def updateColor(self, color):
        self.chum.color = color
    def addMessage(self, msg, me=True):
        if type(msg) in [str, unicode]:
            lexmsg = lexMessage(msg)
        else:
            lexmsg = msg
        if me:
            chum = self.mainwindow.profile()
        else:
            chum = self.chum
            self.notifyNewMessage()
        self.textArea.addMessage(lexmsg, 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.title()))):
            # ok if it has a tabconvo parent, send that the notify.
            if self.parent():
                self.parent().notifyNewMessage(self.title())
                if type(self.parent()).__name__ == "PesterTabWindow":
                  if self.mainwindow.config.blink() & self.mainwindow.config.PBLINK:
                    self.mainwindow.gainAttention.emit(self.parent())
                elif type(self.parent()).__name__ == "MemoTabWindow":
                  if self.mainwindow.config.blink() & self.mainwindow.config.MBLINK:
                    self.mainwindow.gainAttention.emit(self.parent())
            # if not change the window title and update system tray
            else:
                self.newmessage = True
                self.setWindowTitle(self.title()+"*")
                def func():
                    self.showChat()
                self.mainwindow.waitingMessages.addMessage(self.title(), func)
                if type(self).__name__ == "PesterConvo":
                  if self.mainwindow.config.blink() & self.mainwindow.config.PBLINK:
                    self.mainwindow.gainAttention.emit(self)
                elif type(self).__name__ == "PesterMemo":
                  if self.mainwindow.config.blink() & self.mainwindow.config.MBLINK:
                    self.mainwindow.gainAttention.emit(self)

    def clearNewMessage(self):
        if self.parent():
            self.parent().clearNewMessage(self.title())
        elif self.newmessage:
            self.newmessage = False
            self.setWindowTitle(self.title())
            self.mainwindow.waitingMessages.messageAnswered(self.title())
            # reset system tray
    def focusInEvent(self, event):
        self.clearNewMessage()
        self.textInput.setFocus()

    def raiseChat(self):
        self.activateWindow()
        self.raise_()
        self.textInput.setFocus()

    def showChat(self):
        if self.parent():
            self.parent().showChat(self.title())
        self.raiseChat()
    def contextMenuEvent(self, event):
        if event.reason() == QtGui.QContextMenuEvent.Mouse:
            self.optionsMenu.popup(event.globalPos())
    def closeEvent(self, event):
        self.mainwindow.waitingMessages.messageAnswered(self.title())
        self.windowClosed.emit(self.title())

    def setChumOpen(self, o):
        self.chumopen = o
    def changeTheme(self, theme):
        self.resize(*theme["convo/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (self.chum.handle, theme["convo/style"]))

        margins = theme["convo/margins"]
        self.layout.setContentsMargins(margins["left"], margins["top"],
                                       margins["right"], margins["bottom"])

        self.setWindowIcon(self.icon())
        t = Template(self.mainwindow.theme["convo/chumlabel/text"])
        self.chumLabel.setText(t.safe_substitute(handle=self.title()))
        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"])
        self.chumLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding))
        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"])
        self.unblockchum.setText(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"])
        self.logchum.setText(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"])

        self.textArea.changeTheme(theme)
        self.textInput.changeTheme(theme)


    @QtCore.pyqtSlot()
    def sentMessage(self):
        text = unicode(self.textInput.text())
        if text == "" or text[0:11] == "PESTERCHUM:":
            return
        self.history.add(text)
        quirks = self.mainwindow.userprofile.quirks
        lexmsg = lexMessage(text)
        if type(lexmsg[0]) is not mecmd and self.applyquirks:
            try:
                lexmsg = quirks.apply(lexmsg)
            except:
                msgbox = QtGui.QMessageBox()
                msgbox.setText("Whoa there! There seems to be a problem.")
                msgbox.setInformativeText("A quirk seems to be having a problem. (Possibly you're trying to capture a non-existant group?)")
                msgbox.exec_()
                return
        lexmsgs = splitMessage(lexmsg)

        for lm in lexmsgs:
            serverMsg = copy(lm)
            self.addMessage(lm, True)
            # if ceased, rebegin
            if hasattr(self, 'chumopen') and not self.chumopen:
                self.mainwindow.newConvoStarted.emit(QtCore.QString(self.title()), True)
                self.setChumOpen(True)
            text = convertTags(serverMsg, "ctag")
            self.messageSent.emit(text, self.title())
        self.textInput.setText("")

    @QtCore.pyqtSlot()
    def addThisChum(self):
        self.mainwindow.addChum(self.chum)
    @QtCore.pyqtSlot()
    def blockThisChum(self):
        self.mainwindow.blockChum(self.chum.handle)
    @QtCore.pyqtSlot()
    def reportThisChum(self):
        self.mainwindow.reportChum(self.chum.handle)
    @QtCore.pyqtSlot()
    def unblockChumSlot(self):
        self.mainwindow.unblockChum(self.chum.handle)
    @QtCore.pyqtSlot(bool)
    def toggleQuirks(self, toggled):
        self.applyquirks = not toggled
    @QtCore.pyqtSlot()
    def openChumLogs(self):
        currentChum = self.chum.handle
        self.mainwindow.chumList.pesterlogviewer = PesterLogViewer(currentChum, self.mainwindow.config, self.mainwindow.theme, self.mainwindow)
        self.connect(self.mainwindow.chumList.pesterlogviewer, QtCore.SIGNAL('rejected()'),
                     self.mainwindow.chumList, QtCore.SLOT('closeActiveLog()'))
        self.mainwindow.chumList.pesterlogviewer.show()
        self.mainwindow.chumList.pesterlogviewer.raise_()
        self.mainwindow.chumList.pesterlogviewer.activateWindow()

    messageSent = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
    windowClosed = QtCore.pyqtSignal(QtCore.QString)

    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 } }
Пример #2
0
    def __init__(self, chum, initiated, mainwindow, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
        self.setObjectName(chum.handle)
        self.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.chum = chum
        self.mainwindow = mainwindow
        theme = self.mainwindow.theme
        self.resize(*theme["convo/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (chum.handle, theme["convo/style"]))
        self.setWindowIcon(self.icon())
        self.setWindowTitle(self.title())

        t = Template(self.mainwindow.theme["convo/chumlabel/text"])

        self.chumLabel = QtGui.QLabel(t.safe_substitute(handle=chum.handle), self)
        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"])
        self.chumLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding))
        self.textArea = PesterText(self.mainwindow.theme, self)
        self.textInput = PesterInput(self.mainwindow.theme, self)
        self.textInput.setFocus()

        self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
                     self, QtCore.SLOT('sentMessage()'))

        self.layout = QtGui.QVBoxLayout()
        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"])

        self.setLayout(self.layout)

        self.optionsMenu = QtGui.QMenu(self)
        self.optionsMenu.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
        self.addChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
        self.connect(self.addChumAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('addThisChum()'))
        self.blockAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
        self.connect(self.blockAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('blockThisChum()'))
        self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
        self.quirksOff.setCheckable(True)
        self.connect(self.quirksOff, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('toggleQuirks(bool)'))
        self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
        self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('unblockChumSlot()'))
        self.reportchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self)
        self.connect(self.reportchum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('reportThisChum()'))
        self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
        self.connect(self.logchum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('openChumLogs()'))

        self.optionsMenu.addAction(self.quirksOff)
        self.optionsMenu.addAction(self.logchum)
        self.optionsMenu.addAction(self.addChumAction)
        self.optionsMenu.addAction(self.blockAction)
        self.optionsMenu.addAction(self.reportchum)

        self.chumopen = False
        self.applyquirks = True

        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))
            self.mainwindow.chatlog.log(self.title(), msg)
        self.newmessage = False
        self.history = PesterHistory()
Пример #3
0
    def __init__(self, chum, initiated, mainwindow, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
        self.setObjectName(chum.handle)
        self.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.chum = chum
        self.mainwindow = mainwindow
        theme = self.mainwindow.theme
        self.resize(*theme["convo/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (chum.handle, theme["convo/style"]))
        self.setWindowIcon(self.icon())
        self.setWindowTitle(self.title())

        t = Template(self.mainwindow.theme["convo/chumlabel/text"])
        
        self.chumLabel = QtGui.QLabel(t.safe_substitute(handle=chum.handle), self)
        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"])
        self.chumLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding))
        self.textArea = PesterText(self.mainwindow.theme, self)
        self.textInput = PesterInput(self.mainwindow.theme, self)
        self.textInput.setFocus()

        self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
                     self, QtCore.SLOT('sentMessage()'))

        self.layout = QtGui.QVBoxLayout()
        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"])
        
        self.setLayout(self.layout)

        self.optionsMenu = QtGui.QMenu(self)
        self.optionsMenu.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
        self.addChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
        self.connect(self.addChumAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('addThisChum()'))
        self.blockAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
        self.connect(self.blockAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('blockThisChum()'))
        self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
        self.quirksOff.setCheckable(True)
        self.connect(self.quirksOff, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('toggleQuirks(bool)'))
        self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
        self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('unblockChumSlot()'))

        self.optionsMenu.addAction(self.quirksOff)
        self.optionsMenu.addAction(self.addChumAction)
        self.optionsMenu.addAction(self.blockAction)

        self.chumopen = False
        self.applyquirks = True

        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))
            self.mainwindow.chatlog.log(self.title(), msg)
        self.newmessage = False
        self.history = PesterHistory()
Пример #4
0
    def __init__(self, chum, initiated, mainwindow, parent=None):
        super(PesterConvo, self).__init__(parent)
        self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
        self.setObjectName(chum.handle)
        self.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.chum = chum
        self.mainwindow = mainwindow
        theme = self.mainwindow.theme
        self.resize(*theme["convo/size"])
        self.setStyleSheet("QFrame#%s { %s }" %
                           (chum.handle, theme["convo/style"]))
        self.setWindowIcon(self.icon())
        self.setWindowTitle(self.title())

        t = Template(self.mainwindow.theme["convo/chumlabel/text"])

        self.chumLabel = QtGui.QLabel(t.safe_substitute(handle=chum.handle),
                                      self)
        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"])
        self.chumLabel.setSizePolicy(
            QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding,
                              QtGui.QSizePolicy.MinimumExpanding))
        self.textArea = PesterText(self.mainwindow.theme, self)
        self.textInput = PesterInput(self.mainwindow.theme, self)
        self.textInput.setFocus()

        self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'), self,
                     QtCore.SLOT('sentMessage()'))

        self.layout = QtGui.QVBoxLayout()
        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"])

        self.setLayout(self.layout)

        self.optionsMenu = QtGui.QMenu(self)
        self.optionsMenu.setStyleSheet(
            self.mainwindow.theme["main/defaultwindow/style"])
        self.addChumAction = QtGui.QAction(
            self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
        self.connect(self.addChumAction, QtCore.SIGNAL('triggered()'), self,
                     QtCore.SLOT('addThisChum()'))
        self.blockAction = QtGui.QAction(
            self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
        self.connect(self.blockAction, QtCore.SIGNAL('triggered()'), self,
                     QtCore.SLOT('blockThisChum()'))
        self.quirksOff = QtGui.QAction(
            self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
        self.quirksOff.setCheckable(True)
        self.connect(self.quirksOff, QtCore.SIGNAL('toggled(bool)'), self,
                     QtCore.SLOT('toggleQuirks(bool)'))
        self.oocToggle = QtGui.QAction(
            self.mainwindow.theme["main/menus/rclickchumlist/ooc"], self)
        self.oocToggle.setCheckable(True)
        self.connect(self.oocToggle, QtCore.SIGNAL('toggled(bool)'), self,
                     QtCore.SLOT('toggleOOC(bool)'))
        self.unblockchum = QtGui.QAction(
            self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"],
            self)
        self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'), self,
                     QtCore.SLOT('unblockChumSlot()'))
        self.reportchum = QtGui.QAction(
            self.mainwindow.theme["main/menus/rclickchumlist/report"], self)
        self.connect(self.reportchum, QtCore.SIGNAL('triggered()'), self,
                     QtCore.SLOT('reportThisChum()'))
        self.logchum = QtGui.QAction(
            self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
        self.connect(self.logchum, QtCore.SIGNAL('triggered()'), self,
                     QtCore.SLOT('openChumLogs()'))

        # 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.
        self._beepToggle = QtGui.QAction("Beep on Message", self)
        self._beepToggle.setCheckable(True)
        self.connect(self._beepToggle, QtCore.SIGNAL('toggled(bool)'), self,
                     QtCore.SLOT('toggleBeep(bool)'))

        self._flashToggle = QtGui.QAction("Flash on Message", self)
        self._flashToggle.setCheckable(True)
        self.connect(self._flashToggle, QtCore.SIGNAL('toggled(bool)'), self,
                     QtCore.SLOT('toggleFlash(bool)'))

        self._muteToggle = QtGui.QAction("Mute Notifications", self)
        self._muteToggle.setCheckable(True)
        self.connect(self._muteToggle, QtCore.SIGNAL('toggled(bool)'), self,
                     QtCore.SLOT('toggleMute(bool)'))

        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)
        self.optionsMenu.addAction(self.addChumAction)
        self.optionsMenu.addAction(self.blockAction)
        self.optionsMenu.addAction(self.reportchum)

        self.chumopen = False
        self.applyquirks = True
        self.ooc = False

        self.always_beep = False
        self.always_flash = False
        self.notifications_muted = False

        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))
            self.mainwindow.chatlog.log(self.title(), msg)
        self.newmessage = False
        self.history = PesterHistory()
Пример #5
0
class PesterConvo(QtGui.QFrame):
    def __init__(self, chum, initiated, mainwindow, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
        self.setObjectName(chum.handle)
        self.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.chum = chum
        self.mainwindow = mainwindow
        theme = self.mainwindow.theme
        self.resize(*theme["convo/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (chum.handle, theme["convo/style"]))
        self.setWindowIcon(self.icon())
        self.setWindowTitle(self.title())

        t = Template(self.mainwindow.theme["convo/chumlabel/text"])
        
        self.chumLabel = QtGui.QLabel(t.safe_substitute(handle=chum.handle), self)
        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"])
        self.chumLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding))
        self.textArea = PesterText(self.mainwindow.theme, self)
        self.textInput = PesterInput(self.mainwindow.theme, self)
        self.textInput.setFocus()

        self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
                     self, QtCore.SLOT('sentMessage()'))

        self.layout = QtGui.QVBoxLayout()
        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"])
        
        self.setLayout(self.layout)

        self.optionsMenu = QtGui.QMenu(self)
        self.optionsMenu.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
        self.addChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
        self.connect(self.addChumAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('addThisChum()'))
        self.blockAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
        self.connect(self.blockAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('blockThisChum()'))
        self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
        self.quirksOff.setCheckable(True)
        self.connect(self.quirksOff, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('toggleQuirks(bool)'))
        self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
        self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('unblockChumSlot()'))

        self.optionsMenu.addAction(self.quirksOff)
        self.optionsMenu.addAction(self.addChumAction)
        self.optionsMenu.addAction(self.blockAction)

        self.chumopen = False
        self.applyquirks = True

        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))
            self.mainwindow.chatlog.log(self.title(), msg)
        self.newmessage = False
        self.history = PesterHistory()

    def title(self):
        return self.chum.handle
    def icon(self):
        return self.chum.mood.icon(self.mainwindow.theme)
    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)

    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
        elif old and old.name() != mood.name():
            msg = self.chum.moodmsg(mood, syscolor, self.mainwindow.theme)
            self.textArea.append(convertTags(msg))
            self.mainwindow.chatlog.log(self.title(), msg)
        if self.parent():
            self.parent().updateMood(self.title(), mood, unblocked)
        else:
            if self.chum.blocked(self.mainwindow.config) and not unblocked:
                self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
                self.optionsMenu.addAction(self.unblockchum)
                self.optionsMenu.removeAction(self.blockAction)
            else:
                self.setWindowIcon(mood.icon(self.mainwindow.theme))
                self.optionsMenu.removeAction(self.unblockchum)
                self.optionsMenu.addAction(self.blockAction)
        # print mood update?
    def updateBlocked(self):
        if self.parent():
            self.parent().updateBlocked(self.title())
        else:
            self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
        self.optionsMenu.addAction(self.unblockchum)
        self.optionsMenu.removeAction(self.blockAction)

    def updateColor(self, color):
        self.chum.color = color
    def addMessage(self, msg, me=True):
        if type(msg) in [str, unicode]:
            lexmsg = lexMessage(msg)
        else:
            lexmsg = msg
        if me:
            chum = self.mainwindow.profile()
        else:
            chum = self.chum
            self.notifyNewMessage()
        self.textArea.addMessage(lexmsg, 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.title()))):
            # ok if it has a tabconvo parent, send that the notify.
            if self.parent():
                self.parent().notifyNewMessage(self.title())
            # if not change the window title and update system tray
            else:
                self.newmessage = True
                self.setWindowTitle(self.title()+"*")
                def func():
                    self.showChat()
                self.mainwindow.waitingMessages.addMessage(self.title(), func)
                
    def clearNewMessage(self):
        if self.parent():
            self.parent().clearNewMessage(self.title())
        elif self.newmessage:
            self.newmessage = False
            self.setWindowTitle(self.title())
            self.mainwindow.waitingMessages.messageAnswered(self.title())
            # reset system tray
    def focusInEvent(self, event):
        self.clearNewMessage()
        self.textInput.setFocus()

    def raiseChat(self):
        self.activateWindow()
        self.raise_()
        self.textInput.setFocus()

    def showChat(self):
        if self.parent():
            self.parent().showChat(self.title())
        self.raiseChat()
    def contextMenuEvent(self, event):
        if event.reason() == QtGui.QContextMenuEvent.Mouse:
            self.optionsMenu.popup(event.globalPos())
    def closeEvent(self, event):
        self.mainwindow.waitingMessages.messageAnswered(self.title())
        self.windowClosed.emit(self.title())

    def setChumOpen(self, o):
        self.chumopen = o
    def changeTheme(self, theme):
        self.resize(*theme["convo/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (self.chum.handle, theme["convo/style"]))
            
        margins = theme["convo/margins"]
        self.layout.setContentsMargins(margins["left"], margins["top"],
                                       margins["right"], margins["bottom"])

        self.setWindowIcon(self.icon())
        t = Template(self.mainwindow.theme["convo/chumlabel/text"])
        self.chumLabel.setText(t.safe_substitute(handle=self.title()))
        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"])
        self.chumLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding))
        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"])
        self.unblockchum.setText(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"])

        self.textArea.changeTheme(theme)
        self.textInput.changeTheme(theme)


    @QtCore.pyqtSlot()
    def sentMessage(self):
        text = unicode(self.textInput.text())
        if text == "" or text[0:11] == "PESTERCHUM:":
            return
        self.history.add(text)
        quirks = self.mainwindow.userprofile.quirks
        lexmsg = lexMessage(text)
        if type(lexmsg[0]) is not mecmd and self.applyquirks:
            lexmsg = quirks.apply(lexmsg)
        serverMsg = copy(lexmsg)
        self.addMessage(lexmsg, True)
        # if ceased, rebegin
        if hasattr(self, 'chumopen') and not self.chumopen:
            self.mainwindow.newConvoStarted.emit(QtCore.QString(self.title()), True)
        text = convertTags(serverMsg, "ctag")
        self.messageSent.emit(text, self.title())
        self.textInput.setText("")

    @QtCore.pyqtSlot()
    def addThisChum(self):
        self.mainwindow.addChum(self.chum)
    @QtCore.pyqtSlot()
    def blockThisChum(self):
        self.mainwindow.blockChum(self.chum.handle)
    @QtCore.pyqtSlot()
    def unblockChumSlot(self):
        self.mainwindow.unblockChum(self.chum.handle)
    @QtCore.pyqtSlot(bool)
    def toggleQuirks(self, toggled):
        self.applyquirks = not toggled

    messageSent = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
    windowClosed = QtCore.pyqtSignal(QtCore.QString)

    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 } }
Пример #6
0
class PesterConvo(QtWidgets.QFrame):
    def __init__(self, chum, initiated, mainwindow, parent=None):
        QtWidgets.QFrame.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
        self.setObjectName(chum.handle)
        self.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.chum = chum
        self.mainwindow = mainwindow
        theme = self.mainwindow.theme
        self.resize(*theme["convo/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (chum.handle, theme["convo/style"]))
        self.setWindowIcon(self.icon())
        self.setWindowTitle(self.title())

        t = Template(self.mainwindow.theme["convo/chumlabel/text"])

        self.chumLabel = QtWidgets.QLabel(t.safe_substitute(handle=chum.handle), self)
        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"])
        self.chumLabel.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding))
        self.textArea = PesterText(self.mainwindow.theme, self)
        self.textInput = PesterInput(self.mainwindow.theme, self)
        self.textInput.setFocus()

        self.textInput.returnPressed.connect(self.sentMessage)

        self.layout = QtWidgets.QVBoxLayout()
        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"])

        self.setLayout(self.layout)

        self.optionsMenu = QtWidgets.QMenu(self)
        self.optionsMenu.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
        self.addChumAction = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self, triggered=self.addThisChum)
        self.blockAction = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self, triggered=self.blockThisChum)
        self.quirksOff = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self, toggled=self.toggleQuirks)
        self.quirksOff.setCheckable(True)
        self.oocToggle = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/ooc"], self, toggled=self.toggleOOC)
        self.oocToggle.setCheckable(True)
        self.unblockchum = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self, triggered=self.unblockChumSlot)
        self.reportchum = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self, triggered=self.reportThisChum)
        self.logchum = QtWidgets.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self, triggered=self.openChumLogs)

        self.optionsMenu.addAction(self.quirksOff)
        self.optionsMenu.addAction(self.oocToggle)
        self.optionsMenu.addAction(self.logchum)
        self.optionsMenu.addAction(self.addChumAction)
        self.optionsMenu.addAction(self.blockAction)
        self.optionsMenu.addAction(self.reportchum)

        self.chumopen = False
        self.applyquirks = True
        self.ooc = False

        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))
            self.mainwindow.chatlog.log(self.title(), msg)
        self.newmessage = False
        self.history = PesterHistory()

    def title(self):
        return self.chum.handle
    def icon(self):
        return self.chum.mood.icon(self.mainwindow.theme)
    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)

    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():
            msg = self.chum.moodmsg(mood, syscolor, self.mainwindow.theme)
            self.textArea.append(convertTags(msg))
            self.mainwindow.chatlog.log(self.title(), msg)
        if self.parent():
            self.parent().updateMood(self.title(), mood, unblocked)
        else:
            if self.chum.blocked(self.mainwindow.config) and not unblocked:
                self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
                self.optionsMenu.addAction(self.unblockchum)
                self.optionsMenu.removeAction(self.blockAction)
            else:
                self.setWindowIcon(mood.icon(self.mainwindow.theme))
                self.optionsMenu.removeAction(self.unblockchum)
                self.optionsMenu.addAction(self.blockAction)
        # print mood update?
    def updateBlocked(self):
        if self.parent():
            self.parent().updateBlocked(self.title())
        else:
            self.setWindowIcon(QtGui.QIcon(self.mainwindow.theme["main/chums/moods/blocked/icon"]))
        self.optionsMenu.addAction(self.unblockchum)
        self.optionsMenu.removeAction(self.blockAction)

    def updateColor(self, color):
        self.chum.color = color
    def addMessage(self, msg, me=True):
        if type(msg) is str:
            lexmsg = lexMessage(msg)
        else:
            lexmsg = msg
        if me:
            chum = self.mainwindow.profile()
        else:
            chum = self.chum
            self.notifyNewMessage()
        self.textArea.addMessage(lexmsg, 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.title()))):
            # ok if it has a tabconvo parent, send that the notify.
            if self.parent():
                self.parent().notifyNewMessage(self.title())
                if type(self.parent()).__name__ == "PesterTabWindow":
                  if self.mainwindow.config.blink() & self.mainwindow.config.PBLINK:
                    self.mainwindow.gainAttention.emit(self.parent())
                elif type(self.parent()).__name__ == "MemoTabWindow":
                  if self.mainwindow.config.blink() & self.mainwindow.config.MBLINK:
                    self.mainwindow.gainAttention.emit(self.parent())
            # if not change the window title and update system tray
            else:
                self.newmessage = True
                self.setWindowTitle(self.title()+"*")
                def func():
                    self.showChat()
                self.mainwindow.waitingMessages.addMessage(self.title(), func)
                if type(self).__name__ == "PesterConvo":
                  if self.mainwindow.config.blink() & self.mainwindow.config.PBLINK:
                    self.mainwindow.gainAttention.emit(self)
                elif type(self).__name__ == "PesterMemo":
                  if self.mainwindow.config.blink() & self.mainwindow.config.MBLINK:
                    self.mainwindow.gainAttention.emit(self)

    def clearNewMessage(self):
        if self.parent():
            self.parent().clearNewMessage(self.title())
        elif self.newmessage:
            self.newmessage = False
            self.setWindowTitle(self.title())
            self.mainwindow.waitingMessages.messageAnswered(self.title())
            # reset system tray
    def focusInEvent(self, event):
        self.clearNewMessage()
        self.textInput.setFocus()

    def raiseChat(self):
        self.activateWindow()
        self.raise_()
        self.textInput.setFocus()

    def showChat(self):
        if self.parent():
            self.parent().showChat(self.title())
        self.raiseChat()
    def contextMenuEvent(self, event):
        if event.reason() == QtGui.QContextMenuEvent.Mouse:
            self.optionsMenu.popup(event.globalPos())
    def closeEvent(self, event):
        self.mainwindow.waitingMessages.messageAnswered(self.title())
        for movie in self.textArea.urls:
            movie.stop()
            del movie
        self.windowClosed.emit(self.title())

    def setChumOpen(self, o):
        self.chumopen = o
    def changeTheme(self, theme):
        self.resize(*theme["convo/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (self.chum.handle, theme["convo/style"]))

        margins = theme["convo/margins"]
        self.layout.setContentsMargins(margins["left"], margins["top"],
                                       margins["right"], margins["bottom"])

        self.setWindowIcon(self.icon())
        t = Template(self.mainwindow.theme["convo/chumlabel/text"])
        self.chumLabel.setText(t.safe_substitute(handle=self.title()))
        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"])
        self.chumLabel.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding))
        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"])
        self.unblockchum.setText(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"])
        self.logchum.setText(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"])

        self.textArea.changeTheme(theme)
        self.textInput.changeTheme(theme)


    @QtCore.pyqtSlot()
    def sentMessage(self):
        text = str(self.textInput.text())
        if text == "" or text[0:11] == "PESTERCHUM:":
            return
        oocDetected = oocre.match(text.strip())
        if self.ooc and not oocDetected:
            text = "(( %s ))" % (text)
        self.history.add(text)
        quirks = self.mainwindow.userprofile.quirks
        lexmsg = lexMessage(text)
        if type(lexmsg[0]) is not mecmd and self.applyquirks and not (self.ooc or oocDetected):
            try:
                lexmsg = quirks.apply(lexmsg)
            except:
                msgbox = QtWidgets.QMessageBox()
                msgbox.setText("Whoa there! There seems to be a problem.")
                msgbox.setInformativeText("A quirk seems to be having a problem. (Possibly you're trying to capture a non-existant group?)")
                msgbox.exec_()
                return
        lexmsgs = splitMessage(lexmsg)

        for lm in lexmsgs:
            serverMsg = copy(lm)
            self.addMessage(lm, True)
            # if ceased, rebegin
            if hasattr(self, 'chumopen') and not self.chumopen:
                self.mainwindow.newConvoStarted.emit(self.title(), True)
                self.setChumOpen(True)
            text = convertTags(serverMsg, "ctag")
            self.messageSent.emit(text, self.title())
        self.textInput.setText("")

    @QtCore.pyqtSlot()
    def addThisChum(self):
        self.mainwindow.addChum(self.chum)
    @QtCore.pyqtSlot()
    def blockThisChum(self):
        self.mainwindow.blockChum(self.chum.handle)
    @QtCore.pyqtSlot()
    def reportThisChum(self):
        self.mainwindow.reportChum(self.chum.handle)
    @QtCore.pyqtSlot()
    def unblockChumSlot(self):
        self.mainwindow.unblockChum(self.chum.handle)
    @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)
        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()

    messageSent = QtCore.pyqtSignal('QString', 'QString')
    windowClosed = QtCore.pyqtSignal('QString')

    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 } }
Пример #7
0
    def __init__(self, channel, timestr, mainwindow, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
        self.channel = channel
        self.setObjectName(self.channel)
        self.mainwindow = mainwindow
        self.time = TimeTracker(txt2delta(timestr))
        self.setWindowTitle(channel)
        self.channelLabel = QtGui.QLabel(self)
        self.channelLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding))

        self.textArea = MemoText(self.mainwindow.theme, self)
        self.textInput = MemoInput(self.mainwindow.theme, self)
        self.textInput.setFocus()

        self.userlist = RightClickList(self)
        self.userlist.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding))
        self.userlist.optionsMenu = QtGui.QMenu(self)
        self.addchumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
        self.connect(self.addchumAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('addChumSlot()'))
        self.banuserAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/banuser"], self)
        self.connect(self.banuserAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('banSelectedUser()'))
        self.opAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/opuser"], self)
        self.connect(self.opAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('opSelectedUser()'))
        self.userlist.optionsMenu.addAction(self.addchumAction)
        # ban & op list added if we are op

        self.optionsMenu = QtGui.QMenu(self)
        self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
        self.quirksOff.setCheckable(True)
        self.connect(self.quirksOff, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('toggleQuirks(bool)'))
        self.optionsMenu.addAction(self.quirksOff)

        self.timeslider = TimeSlider(QtCore.Qt.Horizontal, self)
        self.timeinput = TimeInput(self.timeslider, self)
        self.timeinput.setText(timestr)
        self.timeinput.setSlider()
        self.timetravel = QtGui.QPushButton("GO", self)
        self.timeclose = QtGui.QPushButton("CLOSE", self)
        self.timeswitchl = QtGui.QPushButton(self)
        self.timeswitchr = QtGui.QPushButton(self)

        self.connect(self.timetravel, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('sendtime()'))
        self.connect(self.timeclose, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('smashclock()'))
        self.connect(self.timeswitchl, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('prevtime()'))
        self.connect(self.timeswitchr, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('nexttime()'))

        self.times = {}

        self.initTheme(self.mainwindow.theme)

        # connect
        self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
                     self, QtCore.SLOT('sentMessage()'))

        layout_0 = QtGui.QVBoxLayout()
        layout_0.addWidget(self.textArea)
        layout_0.addWidget(self.textInput)

        layout_1 = QtGui.QHBoxLayout()
        layout_1.addLayout(layout_0)
        layout_1.addWidget(self.userlist)

#        layout_1 = QtGui.QGridLayout()
#        layout_1.addWidget(self.timeslider, 0, 1, QtCore.Qt.AlignHCenter)
#        layout_1.addWidget(self.timeinput, 1, 0, 1, 3)
        layout_2 = QtGui.QHBoxLayout()
        layout_2.addWidget(self.timeslider)
        layout_2.addWidget(self.timeinput)
        layout_2.addWidget(self.timetravel)
        layout_2.addWidget(self.timeclose)
        layout_2.addWidget(self.timeswitchl)
        layout_2.addWidget(self.timeswitchr)
        self.layout = QtGui.QVBoxLayout()

        self.layout.addWidget(self.channelLabel)
        self.layout.addLayout(layout_1)
        self.layout.addLayout(layout_2)
        self.layout.setSpacing(0)
        margins = self.mainwindow.theme["memos/margins"]
        self.layout.setContentsMargins(margins["left"], margins["top"],
                                  margins["right"], margins["bottom"])
        
        self.setLayout(self.layout)

        if parent:
            parent.addChat(self)

        p = self.mainwindow.profile()
        timeGrammar = self.time.getGrammar()
        systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
        msg = p.memoopenmsg(systemColor, self.time.getTime(), timeGrammar, self.mainwindow.theme["convo/text/openmemo"], self.channel)
        self.time.openCurrentTime()
        self.textArea.append(convertTags(msg))
        self.mainwindow.chatlog.log(self.channel, msg)

        self.op = False
        self.newmessage = False
        self.history = PesterHistory()
        self.applyquirks = True
Пример #8
0
class PesterMemo(PesterConvo):
    def __init__(self, channel, timestr, mainwindow, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
        self.channel = channel
        self.setObjectName(self.channel)
        self.mainwindow = mainwindow
        self.time = TimeTracker(txt2delta(timestr))
        self.setWindowTitle(channel)
        self.channelLabel = QtGui.QLabel(self)
        self.channelLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding))

        self.textArea = MemoText(self.mainwindow.theme, self)
        self.textInput = MemoInput(self.mainwindow.theme, self)
        self.textInput.setFocus()

        self.userlist = RightClickList(self)
        self.userlist.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding))
        self.userlist.optionsMenu = QtGui.QMenu(self)
        self.addchumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
        self.connect(self.addchumAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('addChumSlot()'))
        self.banuserAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/banuser"], self)
        self.connect(self.banuserAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('banSelectedUser()'))
        self.opAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/opuser"], self)
        self.connect(self.opAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('opSelectedUser()'))
        self.userlist.optionsMenu.addAction(self.addchumAction)
        # ban & op list added if we are op

        self.optionsMenu = QtGui.QMenu(self)
        self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
        self.quirksOff.setCheckable(True)
        self.connect(self.quirksOff, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('toggleQuirks(bool)'))
        self.optionsMenu.addAction(self.quirksOff)

        self.timeslider = TimeSlider(QtCore.Qt.Horizontal, self)
        self.timeinput = TimeInput(self.timeslider, self)
        self.timeinput.setText(timestr)
        self.timeinput.setSlider()
        self.timetravel = QtGui.QPushButton("GO", self)
        self.timeclose = QtGui.QPushButton("CLOSE", self)
        self.timeswitchl = QtGui.QPushButton(self)
        self.timeswitchr = QtGui.QPushButton(self)

        self.connect(self.timetravel, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('sendtime()'))
        self.connect(self.timeclose, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('smashclock()'))
        self.connect(self.timeswitchl, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('prevtime()'))
        self.connect(self.timeswitchr, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('nexttime()'))

        self.times = {}

        self.initTheme(self.mainwindow.theme)

        # connect
        self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
                     self, QtCore.SLOT('sentMessage()'))

        layout_0 = QtGui.QVBoxLayout()
        layout_0.addWidget(self.textArea)
        layout_0.addWidget(self.textInput)

        layout_1 = QtGui.QHBoxLayout()
        layout_1.addLayout(layout_0)
        layout_1.addWidget(self.userlist)

#        layout_1 = QtGui.QGridLayout()
#        layout_1.addWidget(self.timeslider, 0, 1, QtCore.Qt.AlignHCenter)
#        layout_1.addWidget(self.timeinput, 1, 0, 1, 3)
        layout_2 = QtGui.QHBoxLayout()
        layout_2.addWidget(self.timeslider)
        layout_2.addWidget(self.timeinput)
        layout_2.addWidget(self.timetravel)
        layout_2.addWidget(self.timeclose)
        layout_2.addWidget(self.timeswitchl)
        layout_2.addWidget(self.timeswitchr)
        self.layout = QtGui.QVBoxLayout()

        self.layout.addWidget(self.channelLabel)
        self.layout.addLayout(layout_1)
        self.layout.addLayout(layout_2)
        self.layout.setSpacing(0)
        margins = self.mainwindow.theme["memos/margins"]
        self.layout.setContentsMargins(margins["left"], margins["top"],
                                  margins["right"], margins["bottom"])
        
        self.setLayout(self.layout)

        if parent:
            parent.addChat(self)

        p = self.mainwindow.profile()
        timeGrammar = self.time.getGrammar()
        systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
        msg = p.memoopenmsg(systemColor, self.time.getTime(), timeGrammar, self.mainwindow.theme["convo/text/openmemo"], self.channel)
        self.time.openCurrentTime()
        self.textArea.append(convertTags(msg))
        self.mainwindow.chatlog.log(self.channel, msg)

        self.op = False
        self.newmessage = False
        self.history = PesterHistory()
        self.applyquirks = True

    def title(self):
        return self.channel
    def icon(self):
        return PesterIcon(self.mainwindow.theme["memos/memoicon"])

    def sendTimeInfo(self, newChum=False):
        if newChum:
            self.messageSent.emit("PESTERCHUM:TIME>%s" % (delta2txt(self.time.getTime(), "server")+"i"),
                                  self.title())
        else:
            self.messageSent.emit("PESTERCHUM:TIME>%s" % (delta2txt(self.time.getTime(), "server")),
                                  self.title())

    def updateMood(self):
        pass
    def updateBlocked(self):
        pass
    def updateColor(self, handle, color):
        chums = self.userlist.findItems(handle, QtCore.Qt.MatchFlags(0))
        for c in chums:
            c.setTextColor(color)
    def addMessage(self, text, handle):
        if type(handle) is bool:
            chum = self.mainwindow.profile()
        else:
            chum = PesterProfile(handle)
            self.notifyNewMessage()
        self.textArea.addMessage(text, chum)

    def initTheme(self, theme):
        self.resize(*theme["memos/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (self.channel, theme["memos/style"]))
        self.setWindowIcon(PesterIcon(theme["memos/memoicon"]))

        t = Template(theme["memos/label/text"])
        self.channelLabel.setText(t.safe_substitute(channel=self.channel))
        self.channelLabel.setStyleSheet(theme["memos/label/style"])
        self.channelLabel.setAlignment(self.aligndict["h"][theme["memos/label/align/h"]] | self.aligndict["v"][theme["memos/label/align/v"]])
        self.channelLabel.setMaximumHeight(theme["memos/label/maxheight"])
        self.channelLabel.setMinimumHeight(theme["memos/label/minheight"])

        self.userlist.optionsMenu.setStyleSheet(theme["main/defaultwindow/style"])
        self.userlist.setStyleSheet(theme["memos/userlist/style"])
        self.userlist.setFixedWidth(theme["memos/userlist/width"])
        self.addchumAction.setText(theme["main/menus/rclickchumlist/addchum"])
        self.banuserAction.setText(theme["main/menus/rclickchumlist/banuser"])
        self.opAction.setText(theme["main/menus/rclickchumlist/opuser"])

        self.timeinput.setFixedWidth(theme["memos/time/text/width"])
        self.timeinput.setStyleSheet(theme["memos/time/text/style"])
        slidercss = "QSlider { %s } QSlider::groove { %s } QSlider::handle { %s }" % (theme["memos/time/slider/style"], theme["memos/time/slider/groove"], theme["memos/time/slider/handle"])
        self.timeslider.setStyleSheet(slidercss) 

        larrow = PesterIcon(self.mainwindow.theme["memos/time/arrows/left"])
        self.timeswitchl.setIcon(larrow)
        self.timeswitchl.setIconSize(larrow.realsize())
        self.timeswitchl.setStyleSheet(self.mainwindow.theme["memos/time/arrows/style"])
        self.timetravel.setStyleSheet(self.mainwindow.theme["memos/time/buttons/style"])
        self.timeclose.setStyleSheet(self.mainwindow.theme["memos/time/buttons/style"])

        rarrow = PesterIcon(self.mainwindow.theme["memos/time/arrows/right"])
        self.timeswitchr.setIcon(rarrow)
        self.timeswitchr.setIconSize(rarrow.realsize())
        self.timeswitchr.setStyleSheet(self.mainwindow.theme["memos/time/arrows/style"])


    def changeTheme(self, theme):
        self.initTheme(theme)
        self.textArea.changeTheme(theme)
        self.textInput.changeTheme(theme)
        margins = theme["memos/margins"]
        self.layout.setContentsMargins(margins["left"], margins["top"],
                                  margins["right"], margins["bottom"])
        for item in [self.userlist.item(i) for i in range(0,self.userlist.count())]:
            if item.op:
                icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
                item.setIcon(icon)

    def addUser(self, handle):
        chumdb = self.mainwindow.chumdb
        defaultcolor = QtGui.QColor("black")
        op = False
        if handle[0] == '@':
            op = True
            handle = handle[1:]
            if handle == self.mainwindow.profile().handle:
                self.userlist.optionsMenu.addAction(self.opAction)
                self.userlist.optionsMenu.addAction(self.banuserAction)
                self.op = True
        item = QtGui.QListWidgetItem(handle)
        if handle == self.mainwindow.profile().handle:
            color = self.mainwindow.profile().color
        else:
            color = chumdb.getColor(handle, defaultcolor)
        item.setTextColor(color)
        item.op = op
        if op:
            icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
            item.setIcon(icon)
        self.userlist.addItem(item)

    def timeUpdate(self, handle, cmd):
        window = self.mainwindow
        chum = PesterProfile(handle)
        systemColor = QtGui.QColor(window.theme["memos/systemMsgColor"])
        close = None
        # old TC command?
        try:
            secs = int(cmd)
            time = datetime.fromtimestamp(secs)
            timed = time - datetime.now()
            s = (timed.seconds // 60)*60
            timed = timedelta(timed.days, s)
        except ValueError:
            if cmd == "i":
                timed = timedelta(0)
            else:
                if cmd[len(cmd)-1] == 'c':
                    close = timeProtocol(cmd)
                    timed = None
                else:
                    timed = timeProtocol(cmd)

        if self.times.has_key(handle):
            if close is not None:
                if close in self.times[handle]:
                    self.times[handle].setCurrent(close)
                    grammar = self.times[handle].getGrammar()
                    self.times[handle].removeTime(close)
                    msg = chum.memoclosemsg(systemColor, grammar, window.theme["convo/text/closememo"])
                    self.textArea.append(convertTags(msg))
                    self.mainwindow.chatlog.log(self.channel, msg)
            elif timed not in self.times[handle]:
                self.times[handle].addTime(timed)
            else:
                self.times[handle].setCurrent(timed)
        else:
            if timed is not None:
                ttracker = TimeTracker(timed)
                self.times[handle] = ttracker

    @QtCore.pyqtSlot()
    def sentMessage(self):
        text = unicode(self.textInput.text())
        if text == "" or text[0:11] == "PESTERCHUM:":
            return
        self.history.add(text)
        if self.time.getTime() == None:
            self.sendtime()
        grammar = self.time.getGrammar()
        quirks = self.mainwindow.userprofile.quirks
        lexmsg = lexMessage(text)
        if type(lexmsg[0]) is not mecmd:
            if self.applyquirks:
                lexmsg = quirks.apply(lexmsg)
            initials = self.mainwindow.profile().initials()
            colorcmd = self.mainwindow.profile().colorcmd()
            clientMsg = [colorBegin("<c=%s>" % (colorcmd), colorcmd),
                         "%s%s%s: " % (grammar.pcf, initials, grammar.number)] + lexmsg + [colorEnd("</c>")]
            # account for TC's parsing error
            serverMsg = [colorBegin("<c=%s>" % (colorcmd), colorcmd),
                         "%s: " % (initials)] + lexmsg + [colorEnd("</c>"), " "]
        else:
            clientMsg = copy(lexmsg)
            serverMsg = copy(lexmsg)

        self.addMessage(clientMsg, True)
        serverText = convertTags(serverMsg, "ctag")
        self.messageSent.emit(serverText, self.title())

        self.textInput.setText("")
    @QtCore.pyqtSlot()
    def namesUpdated(self):
        # get namesdb
        namesdb = self.mainwindow.namesdb
        # reload names
        self.userlist.clear()
        for n in self.mainwindow.namesdb[self.channel]:
            self.addUser(n)

    @QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
    def userPresentChange(self, handle, channel, update):
        h = unicode(handle)
        c = unicode(channel)
        update = unicode(update)
        if update[0:4] == "kick": # yeah, i'm lazy.
            l = update.split(":")
            update = l[0]
            op = l[1]
        if update == "nick":
            l = h.split(":")
            oldnick = l[0]
            newnick = l[1]
            h = oldnick
        if (update in ["join","left", "kick", "+o"]) \
                and channel != self.channel:
            return
        chums = self.userlist.findItems(h, QtCore.Qt.MatchFlags(0))
        systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
        # print exit
        if update == "quit" or update == "left" or update == "nick":
            for c in chums:
                chum = PesterProfile(h)
                self.userlist.takeItem(self.userlist.row(c))
                if not self.times.has_key(h):
                    self.times[h] = TimeTracker(timedelta(0))
                while self.times[h].getTime() is not None:
                    t = self.times[h]
                    grammar = t.getGrammar()
                    msg = chum.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"])
                    self.textArea.append(convertTags(msg))
                    self.mainwindow.chatlog.log(self.channel, msg)
                    self.times[h].removeTime(t.getTime())
                if update == "nick":
                    self.addUser(newnick)
        elif update == "kick":
            if len(chums) == 0:
                return
            c = chums[0]
            chum = PesterProfile(h)
            if h == self.mainwindow.profile().handle:
                chum = self.mainwindow.profile()
                ttracker = self.time
                curtime = self.time.getTime()
            elif self.times.has_key(h):
                ttracker = self.times[h]
            else:
                ttracker = TimeTracker(timedelta(0))
            while ttracker.getTime() is not None:
                grammar = ttracker.getGrammar()
                opchum = PesterProfile(op)
                if self.times.has_key(op):
                    opgrammar = self.times[op].getGrammar()
                elif op == self.mainwindow.profile().handle:
                    opgrammar = self.time.getGrammar()
                else:
                    opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW")
                msg = chum.memobanmsg(opchum, opgrammar, systemColor, grammar)
                self.textArea.append(convertTags(msg))
                self.mainwindow.chatlog.log(self.channel, msg)
                ttracker.removeTime(ttracker.getTime())

            if chum is self.mainwindow.profile():
                # are you next?
                msgbox = QtGui.QMessageBox()
                msgbox.setText(self.mainwindow.theme["convo/text/kickedmemo"])
                msgbox.setInformativeText("press 0k to rec0nnect or cancel to absc0nd")
                msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
                ret = msgbox.exec_()
                if ret == QtGui.QMessageBox.Ok:
                    self.userlist.clear()
                    self.time = TimeTracker(curtime)
                    self.resetSlider(curtime)
                    self.mainwindow.joinChannel.emit(self.channel)
                    me = self.mainwindow.profile()
                    self.time.openCurrentTime()
                    msg = me.memoopenmsg(systemColor, self.time.getTime(), self.time.getGrammar(), self.mainwindow.theme["convo/text/openmemo"], self.channel)
                    self.textArea.append(convertTags(msg))
                    self.mainwindow.chatlog.log(self.channel, msg)
                elif ret == QtGui.QMessageBox.Cancel:
                    if self.parent():
                        i = self.parent().tabIndices[self.channel]
                        self.parent().tabClose(i)
                    else:
                        self.close()
            else:
                # i warned you about those stairs bro
                self.userlist.takeItem(self.userlist.row(c))
        elif update == "join":
            self.addUser(h)
            time = self.time.getTime()
            serverText = "PESTERCHUM:TIME>"+delta2txt(time, "server")
            self.messageSent.emit(serverText, self.title())
        elif update == "+o":
            chums = self.userlist.findItems(h, QtCore.Qt.MatchFlags(0))
            for c in chums:
                icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
                c.setIcon(icon)
                if unicode(c.text()) == self.mainwindow.profile().handle:
                    self.userlist.optionsMenu.addAction(self.opAction)
                    self.userlist.optionsMenu.addAction(self.banuserAction)

    @QtCore.pyqtSlot()
    def addChumSlot(self):
        if not self.userlist.currentItem():
            return
        currentChum = PesterProfile(unicode(self.userlist.currentItem().text()))
        self.mainwindow.addChum(currentChum)
    @QtCore.pyqtSlot()
    def banSelectedUser(self):
        if not self.userlist.currentItem():
            return
        currentHandle = unicode(self.userlist.currentItem().text())
        self.mainwindow.kickUser.emit(currentHandle, self.channel)
    @QtCore.pyqtSlot()
    def opSelectedUser(self):
        if not self.userlist.currentItem():
            return
        currentHandle = unicode(self.userlist.currentItem().text())
        self.mainwindow.setChannelMode.emit(self.channel, "+o", currentHandle)
    def resetSlider(self, time, send=True):
        self.timeinput.setText(delta2txt(time))
        self.timeinput.setSlider()
        if send:
            self.sendtime()

    @QtCore.pyqtSlot()
    def sendtime(self):
        me = self.mainwindow.profile()
        systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
        time = txt2delta(self.timeinput.text())
        present = self.time.addTime(time)

        serverText = "PESTERCHUM:TIME>"+delta2txt(time, "server")
        self.messageSent.emit(serverText, self.title())
    @QtCore.pyqtSlot()
    def smashclock(self):
        me = self.mainwindow.profile()
        time = txt2delta(self.timeinput.text())
        removed = self.time.removeTime(time)
        if removed:
            grammar = self.time.getGrammarTime(time)
            systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
            msg = me.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"])
            self.textArea.append(convertTags(msg))
            self.mainwindow.chatlog.log(self.channel, msg)

        newtime = self.time.getTime()
        if newtime is None:
            newtime = timedelta(0)
            self.resetSlider(newtime, send=False)
        else:
            self.resetSlider(newtime)
    @QtCore.pyqtSlot()
    def prevtime(self):
        time = self.time.prevTime()
        self.time.setCurrent(time)
        self.resetSlider(time)
        self.textInput.setFocus()
    @QtCore.pyqtSlot()
    def nexttime(self):
        time = self.time.nextTime()
        self.time.setCurrent(time)
        self.resetSlider(time)
        self.textInput.setFocus()
    def closeEvent(self, event):
        self.mainwindow.waitingMessages.messageAnswered(self.channel)
        self.windowClosed.emit(self.title())

    windowClosed = QtCore.pyqtSignal(QtCore.QString)
Пример #9
0
class PesterMemo(PesterConvo):
    def __init__(self, channel, timestr, mainwindow, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
        self.channel = channel
        self.setObjectName(self.channel)
        self.mainwindow = mainwindow
        self.time = TimeTracker(txt2delta(timestr))
        self.setWindowTitle(channel)
        self.channelLabel = QtGui.QLabel(self)
        self.channelLabel.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding))

        self.textArea = MemoText(self.mainwindow.theme, self)
        self.textInput = MemoInput(self.mainwindow.theme, self)
        self.textInput.setFocus()

        self.userlist = RightClickList(self)
        self.userlist.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding))
        self.userlist.optionsMenu = QtGui.QMenu(self)
        self.addchumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
        self.connect(self.addchumAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('addChumSlot()'))
        self.banuserAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/banuser"], self)
        self.connect(self.banuserAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('banSelectedUser()'))
        self.opAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/opuser"], self)
        self.connect(self.opAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('opSelectedUser()'))
        self.voiceAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/voiceuser"], self)
        self.connect(self.voiceAction, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('voiceSelectedUser()'))
        self.userlist.optionsMenu.addAction(self.addchumAction)
        # ban & op list added if we are op

        self.optionsMenu = QtGui.QMenu(self)
        self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self)
        self.quirksOff.setCheckable(True)
        self.connect(self.quirksOff, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('toggleQuirks(bool)'))
        self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
        self.connect(self.logchum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('openChumLogs()'))
        self.invitechum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/invitechum"], self)
        self.connect(self.invitechum, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('inviteChums()'))
        self.optionsMenu.addAction(self.quirksOff)
        self.optionsMenu.addAction(self.logchum)
        self.optionsMenu.addAction(self.invitechum)

        self.chanModeMenu = QtGui.QMenu("Memo Settings", self)
        self.chanHide = QtGui.QAction("Hidden", self)
        self.chanHide.setCheckable(True)
        self.connect(self.chanHide, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('hideChan(bool)'))
        self.chanInvite = QtGui.QAction("Invite-Only", self)
        self.chanInvite.setCheckable(True)
        self.connect(self.chanInvite, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('inviteChan(bool)'))
        self.chanMod = QtGui.QAction("Mute", self)
        self.chanMod.setCheckable(True)
        self.connect(self.chanMod, QtCore.SIGNAL('toggled(bool)'),
                     self, QtCore.SLOT('modChan(bool)'))
        self.chanModeMenu.addAction(self.chanHide)
        self.chanModeMenu.addAction(self.chanInvite)
        self.chanModeMenu.addAction(self.chanMod)

        self.timeslider = TimeSlider(QtCore.Qt.Horizontal, self)
        self.timeinput = TimeInput(self.timeslider, self)
        self.timeinput.setText(timestr)
        self.timeinput.setSlider()
        self.timetravel = QtGui.QPushButton("GO", self)
        self.timeclose = QtGui.QPushButton("CLOSE", self)
        self.timeswitchl = QtGui.QPushButton(self)
        self.timeswitchr = QtGui.QPushButton(self)

        self.connect(self.timetravel, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('sendtime()'))
        self.connect(self.timeclose, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('smashclock()'))
        self.connect(self.timeswitchl, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('prevtime()'))
        self.connect(self.timeswitchr, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('nexttime()'))

        self.times = {}

        self.initTheme(self.mainwindow.theme)

        # connect
        self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
                     self, QtCore.SLOT('sentMessage()'))

        layout_0 = QtGui.QVBoxLayout()
        layout_0.addWidget(self.textArea)
        layout_0.addWidget(self.textInput)

        layout_1 = QtGui.QHBoxLayout()
        layout_1.addLayout(layout_0)
        layout_1.addWidget(self.userlist)

#        layout_1 = QtGui.QGridLayout()
#        layout_1.addWidget(self.timeslider, 0, 1, QtCore.Qt.AlignHCenter)
#        layout_1.addWidget(self.timeinput, 1, 0, 1, 3)
        layout_2 = QtGui.QHBoxLayout()
        layout_2.addWidget(self.timeslider)
        layout_2.addWidget(self.timeinput)
        layout_2.addWidget(self.timetravel)
        layout_2.addWidget(self.timeclose)
        layout_2.addWidget(self.timeswitchl)
        layout_2.addWidget(self.timeswitchr)
        self.layout = QtGui.QVBoxLayout()

        self.layout.addWidget(self.channelLabel)
        self.layout.addLayout(layout_1)
        self.layout.addLayout(layout_2)
        self.layout.setSpacing(0)
        margins = self.mainwindow.theme["memos/margins"]
        self.layout.setContentsMargins(margins["left"], margins["top"],
                                  margins["right"], margins["bottom"])

        self.setLayout(self.layout)

        if parent:
            parent.addChat(self)

        p = self.mainwindow.profile()
        timeGrammar = self.time.getGrammar()
        systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
        msg = p.memoopenmsg(systemColor, self.time.getTime(), timeGrammar, self.mainwindow.theme["convo/text/openmemo"], self.channel)
        self.time.openCurrentTime()
        self.textArea.append(convertTags(msg))
        self.mainwindow.chatlog.log(self.channel, msg)

        self.op = False
        self.newmessage = False
        self.history = PesterHistory()
        self.applyquirks = True

    def title(self):
        return self.channel
    def icon(self):
        return PesterIcon(self.mainwindow.theme["memos/memoicon"])

    def sendTimeInfo(self, newChum=False):
        if newChum:
            self.messageSent.emit("PESTERCHUM:TIME>%s" % (delta2txt(self.time.getTime(), "server")+"i"),
                                  self.title())
        else:
            self.messageSent.emit("PESTERCHUM:TIME>%s" % (delta2txt(self.time.getTime(), "server")),
                                  self.title())

    def updateMood(self):
        pass
    def updateBlocked(self):
        pass
    def updateColor(self, handle, color):
        chums = self.userlist.findItems(handle, QtCore.Qt.MatchFlags(0))
        for c in chums:
            c.setTextColor(color)
    def addMessage(self, text, handle):
        if type(handle) is bool:
            chum = self.mainwindow.profile()
        else:
            chum = PesterProfile(handle)
            self.notifyNewMessage()
        self.textArea.addMessage(text, chum)

    def initTheme(self, theme):
        self.resize(*theme["memos/size"])
        self.setStyleSheet("QFrame#%s { %s }" % (self.channel, theme["memos/style"]))
        self.setWindowIcon(PesterIcon(theme["memos/memoicon"]))

        t = Template(theme["memos/label/text"])
        if self.mainwindow.advanced and hasattr(self, 'modes'):
            self.channelLabel.setText(t.safe_substitute(channel=self.channel) + "(%s)" % (self.modes))
        else:
            self.channelLabel.setText(t.safe_substitute(channel=self.channel))
        self.channelLabel.setStyleSheet(theme["memos/label/style"])
        self.channelLabel.setAlignment(self.aligndict["h"][theme["memos/label/align/h"]] | self.aligndict["v"][theme["memos/label/align/v"]])
        self.channelLabel.setMaximumHeight(theme["memos/label/maxheight"])
        self.channelLabel.setMinimumHeight(theme["memos/label/minheight"])

        self.userlist.optionsMenu.setStyleSheet(theme["main/defaultwindow/style"])
        scrolls = "width: 12px; height: 12px; border: 0; padding: 0;"
        if theme.has_key("main/chums/scrollbar"):
            self.userlist.setStyleSheet("QListWidget { %s } QScrollBar { %s } QScrollBar::handle { %s } QScrollBar::add-line { %s } QScrollBar::sub-line { %s } QScrollBar:up-arrow { %s } QScrollBar:down-arrow { %s }" % (theme["memos/userlist/style"], theme["main/chums/scrollbar/style"] + scrolls, theme["main/chums/scrollbar/handle"], theme["main/chums/scrollbar/downarrow"], theme["main/chums/scrollbar/uparrow"], theme["main/chums/scrollbar/uarrowstyle"], theme["main/chums/scrollbar/darrowstyle"] ))
        elif theme.has_key("convo/scrollbar"):
            self.userlist.setStyleSheet("QListWidget { %s } QScrollBar { %s } QScrollBar::handle { %s } QScrollBar::add-line { %s } QScrollBar::sub-line { %s } QScrollBar:up-arrow { %s } QScrollBar:down-arrow { %s }" % (theme["memos/userlist/style"], theme["convo/scrollbar/style"] + scrolls, theme["convo/scrollbar/handle"], "display:none;", "display:none;", "display:none;", "display:none;" ))
        else:
            self.userlist.setStyleSheet("QListWidget { %s } QScrollBar { %s } QScrollBar::handle { %s }" % (theme["memos/userlist/style"], scrolls, "background-color: black;"))
        self.userlist.setFixedWidth(theme["memos/userlist/width"])
        self.addchumAction.setText(theme["main/menus/rclickchumlist/addchum"])
        self.banuserAction.setText(theme["main/menus/rclickchumlist/banuser"])
        self.opAction.setText(theme["main/menus/rclickchumlist/opuser"])
        self.voiceAction.setText(theme["main/menus/rclickchumlist/voiceuser"])
        self.quirksOff.setText(theme["main/menus/rclickchumlist/quirksoff"])
        self.logchum.setText(theme["main/menus/rclickchumlist/viewlog"])

        self.timeinput.setFixedWidth(theme["memos/time/text/width"])
        self.timeinput.setStyleSheet(theme["memos/time/text/style"])
        slidercss = "QSlider { %s } QSlider::groove { %s } QSlider::handle { %s }" % (theme["memos/time/slider/style"], theme["memos/time/slider/groove"], theme["memos/time/slider/handle"])
        self.timeslider.setStyleSheet(slidercss)

        larrow = PesterIcon(self.mainwindow.theme["memos/time/arrows/left"])
        self.timeswitchl.setIcon(larrow)
        self.timeswitchl.setIconSize(larrow.realsize())
        self.timeswitchl.setStyleSheet(self.mainwindow.theme["memos/time/arrows/style"])
        self.timetravel.setStyleSheet(self.mainwindow.theme["memos/time/buttons/style"])
        self.timeclose.setStyleSheet(self.mainwindow.theme["memos/time/buttons/style"])

        rarrow = PesterIcon(self.mainwindow.theme["memos/time/arrows/right"])
        self.timeswitchr.setIcon(rarrow)
        self.timeswitchr.setIconSize(rarrow.realsize())
        self.timeswitchr.setStyleSheet(self.mainwindow.theme["memos/time/arrows/style"])


    def changeTheme(self, theme):
        self.initTheme(theme)
        self.textArea.changeTheme(theme)
        self.textInput.changeTheme(theme)
        margins = theme["memos/margins"]
        self.layout.setContentsMargins(margins["left"], margins["top"],
                                  margins["right"], margins["bottom"])
        for item in [self.userlist.item(i) for i in range(0,self.userlist.count())]:
            if item.op:
                icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
                item.setIcon(icon)
            elif item.voice:
                icon = PesterIcon(self.mainwindow.theme["memos/voice/icon"])
                item.setIcon(icon)

    def addUser(self, handle):
        chumdb = self.mainwindow.chumdb
        defaultcolor = QtGui.QColor("black")
        op = False
        voice = False
        if handle[0] == '@':
            op = True
            handle = handle[1:]
            if handle == self.mainwindow.profile().handle:
                self.userlist.optionsMenu.addAction(self.opAction)
                self.userlist.optionsMenu.addAction(self.banuserAction)
                self.optionsMenu.addMenu(self.chanModeMenu)
                self.op = True
        elif handle[0] == '+':
            voice = True
            handle = handle[1:]
        item = QtGui.QListWidgetItem(handle)
        if handle == self.mainwindow.profile().handle:
            color = self.mainwindow.profile().color
        else:
            color = chumdb.getColor(handle, defaultcolor)
        item.setTextColor(color)
        item.op = op
        item.voice = voice
        if op:
            icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
            item.setIcon(icon)
        elif voice:
            icon = PesterIcon(self.mainwindow.theme["memos/voice/icon"])
            item.setIcon(icon)
        self.userlist.addItem(item)
        self.sortUsers()

    def sortUsers(self):
        users = []
        listing = self.userlist.item(0)
        while listing is not None:
            users.append(self.userlist.takeItem(0))
            listing = self.userlist.item(0)
        users.sort(key=lambda x: ((0 if x.op else 1), (0 if x.voice else 1), x.text()))
        for u in users:
            self.userlist.addItem(u)

    def updateChanModes(self, modes):
        if not hasattr(self, 'modes'): self.modes = ""
        chanmodes = list(str(self.modes))
        if chanmodes and chanmodes[0] == "+": chanmodes = chanmodes[1:]
        modes = str(modes)
        if modes[0] == "+":
            for m in modes[1:]:
                if m not in chanmodes:
                    chanmodes.extend(m)
            if modes.find("s") >= 0: self.chanHide.setChecked(True)
            if modes.find("i") >= 0: self.chanInvite.setChecked(True)
            if modes.find("m") >= 0: self.chanMod.setChecked(True)
        elif modes[0] == "-":
            for i in modes[1:]:
                try:
                    chanmodes.remove(i)
                except ValueError:
                    pass
            if modes.find("s") >= 0: self.chanHide.setChecked(False)
            if modes.find("i") >= 0: self.chanInvite.setChecked(False)
            if modes.find("m") >= 0: self.chanMod.setChecked(False)
        chanmodes.sort()
        self.modes = "+" + "".join(chanmodes)
        if self.mainwindow.advanced:
            t = Template(self.mainwindow.theme["memos/label/text"])
            self.channelLabel.setText(t.safe_substitute(channel=self.channel) + "(%s)" % (self.modes))

    def timeUpdate(self, handle, cmd):
        window = self.mainwindow
        chum = PesterProfile(handle)
        systemColor = QtGui.QColor(window.theme["memos/systemMsgColor"])
        close = None
        # old TC command?
        try:
            secs = int(cmd)
            time = datetime.fromtimestamp(secs)
            timed = time - datetime.now()
            s = (timed.seconds // 60)*60
            timed = timedelta(timed.days, s)
        except ValueError:
            if cmd == "i":
                timed = timedelta(0)
            else:
                if cmd[len(cmd)-1] == 'c':
                    close = timeProtocol(cmd)
                    timed = None
                else:
                    timed = timeProtocol(cmd)

        if self.times.has_key(handle):
            if close is not None:
                if close in self.times[handle]:
                    self.times[handle].setCurrent(close)
                    grammar = self.times[handle].getGrammar()
                    self.times[handle].removeTime(close)
                    msg = chum.memoclosemsg(systemColor, grammar, window.theme["convo/text/closememo"])
                    self.textArea.append(convertTags(msg))
                    self.mainwindow.chatlog.log(self.channel, msg)
            elif timed not in self.times[handle]:
                self.times[handle].addTime(timed)
            else:
                self.times[handle].setCurrent(timed)
        else:
            if timed is not None:
                ttracker = TimeTracker(timed)
                self.times[handle] = ttracker

    @QtCore.pyqtSlot()
    def sentMessage(self):
        text = unicode(self.textInput.text())
        if text == "" or text[0:11] == "PESTERCHUM:":
            return
        self.history.add(text)
        if self.time.getTime() == None:
            self.sendtime()
        grammar = self.time.getGrammar()
        quirks = self.mainwindow.userprofile.quirks
        lexmsg = lexMessage(text)
        if type(lexmsg[0]) is not mecmd:
            if self.applyquirks:
                lexmsg = quirks.apply(lexmsg)
            initials = self.mainwindow.profile().initials()
            colorcmd = self.mainwindow.profile().colorcmd()
            clientMsg = [colorBegin("<c=%s>" % (colorcmd), colorcmd),
                         "%s%s%s: " % (grammar.pcf, initials, grammar.number)] + lexmsg + [colorEnd("</c>")]
            # account for TC's parsing error
            serverMsg = [colorBegin("<c=%s>" % (colorcmd), colorcmd),
                         "%s: " % (initials)] + lexmsg + [colorEnd("</c>"), " "]
        else:
            clientMsg = copy(lexmsg)
            serverMsg = copy(lexmsg)

        self.addMessage(clientMsg, True)
        serverText = convertTags(serverMsg, "ctag")
        self.messageSent.emit(serverText, self.title())

        self.textInput.setText("")
    @QtCore.pyqtSlot()
    def namesUpdated(self):
        # get namesdb
        namesdb = self.mainwindow.namesdb
        # reload names
        self.userlist.clear()
        for n in self.mainwindow.namesdb[self.channel]:
            self.addUser(n)
    @QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
    def modesUpdated(self, channel, modes):
        c = unicode(channel)
        if c == self.channel:
            self.updateChanModes(modes)

    @QtCore.pyqtSlot(QtCore.QString)
    def closeInviteOnly(self, channel):
        c = unicode(channel)
        if c == self.channel:
            self.disconnect(self.mainwindow, QtCore.SIGNAL('inviteOnlyChan(QString)'),
                     self, QtCore.SLOT('closeInviteOnly(QString)'))
            if self.parent():
                print self.channel
                i = self.parent().tabIndices[self.channel]
                self.parent().tabClose(i)
            else:
                self.close()
            msgbox = QtGui.QMessageBox()
            msgbox.setText("%s: Invites only!" % (c))
            msgbox.setInformativeText("This channel is invite-only. You must get an invitation from someone on the inside before entering.")
            msgbox.setStandardButtons(QtGui.QMessageBox.Ok)
            ret = msgbox.exec_()

    @QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
    def userPresentChange(self, handle, channel, update):
        h = unicode(handle)
        c = unicode(channel)
        update = unicode(update)
        if update[0:4] == "kick": # yeah, i'm lazy.
            l = update.split(":")
            update = l[0]
            op = l[1]
            reason = l[2]
        if update == "nick":
            l = h.split(":")
            oldnick = l[0]
            newnick = l[1]
            h = oldnick
        if update[0:1] in ["+", "-"]:
            l = update.split(":")
            update = l[0]
            op = l[1]
        if (update in ["join","left", "kick", "+o", "-o", "+v", "-v"]) \
                and channel != self.channel:
            return
        chums = self.userlist.findItems(h, QtCore.Qt.MatchFlags(0))
        systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
        # print exit
        if update == "quit" or update == "left" or update == "nick":
            for c in chums:
                chum = PesterProfile(h)
                self.userlist.takeItem(self.userlist.row(c))
                if not self.times.has_key(h):
                    self.times[h] = TimeTracker(timedelta(0))
                while self.times[h].getTime() is not None:
                    t = self.times[h]
                    grammar = t.getGrammar()
                    msg = chum.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"])
                    self.textArea.append(convertTags(msg))
                    self.mainwindow.chatlog.log(self.channel, msg)
                    self.times[h].removeTime(t.getTime())
                if update == "nick":
                    self.addUser(newnick)
                    newchums = self.userlist.findItems(newnick, QtCore.Qt.MatchFlags(0))
                    for nc in newchums:
                        for c in chums:
                            if c.op:
                                nc.op = True
                                icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
                                nc.setIcon(icon)
                            if c.voice:
                                nc.voice = True
                                icon = PesterIcon(self.mainwindow.theme["memos/voice/icon"])
                                nc.setIcon(icon)
                    self.sortUsers()
        elif update == "kick":
            if len(chums) == 0:
                return
            c = chums[0]
            chum = PesterProfile(h)
            if h == self.mainwindow.profile().handle:
                chum = self.mainwindow.profile()
                ttracker = self.time
                curtime = self.time.getTime()
            elif self.times.has_key(h):
                ttracker = self.times[h]
            else:
                ttracker = TimeTracker(timedelta(0))
            while ttracker.getTime() is not None:
                grammar = ttracker.getGrammar()
                opchum = PesterProfile(op)
                if self.times.has_key(op):
                    opgrammar = self.times[op].getGrammar()
                elif op == self.mainwindow.profile().handle:
                    opgrammar = self.time.getGrammar()
                else:
                    opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW")
                msg = chum.memobanmsg(opchum, opgrammar, systemColor, grammar, reason)
                self.textArea.append(convertTags(msg))
                self.mainwindow.chatlog.log(self.channel, msg)
                ttracker.removeTime(ttracker.getTime())

            if chum is self.mainwindow.profile():
                # are you next?
                msgbox = QtGui.QMessageBox()
                msgbox.setText(self.mainwindow.theme["convo/text/kickedmemo"])
                msgbox.setInformativeText("press 0k to rec0nnect or cancel to absc0nd")
                msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
                ret = msgbox.exec_()
                if ret == QtGui.QMessageBox.Ok:
                    self.userlist.clear()
                    self.time = TimeTracker(curtime)
                    self.resetSlider(curtime)
                    self.mainwindow.joinChannel.emit(self.channel)
                    me = self.mainwindow.profile()
                    self.time.openCurrentTime()
                    msg = me.memoopenmsg(systemColor, self.time.getTime(), self.time.getGrammar(), self.mainwindow.theme["convo/text/openmemo"], self.channel)
                    self.textArea.append(convertTags(msg))
                    self.mainwindow.chatlog.log(self.channel, msg)
                elif ret == QtGui.QMessageBox.Cancel:
                    if self.parent():
                        i = self.parent().tabIndices[self.channel]
                        self.parent().tabClose(i)
                    else:
                        self.close()
            else:
                # i warned you about those stairs bro
                self.userlist.takeItem(self.userlist.row(c))
        elif update == "join":
            self.addUser(h)
            time = self.time.getTime()
            serverText = "PESTERCHUM:TIME>"+delta2txt(time, "server")
            self.messageSent.emit(serverText, self.title())
        elif update == "+o":
            if self.mainwindow.config.opvoiceMessages():
                chum = PesterProfile(h)
                if h == self.mainwindow.profile().handle:
                    chum = self.mainwindow.profile()
                    ttracker = self.time
                    curtime = self.time.getTime()
                elif self.times.has_key(h):
                    ttracker = self.times[h]
                else:
                    ttracker = TimeTracker(timedelta(0))
                opchum = PesterProfile(op)
                if self.times.has_key(op):
                    opgrammar = self.times[op].getGrammar()
                elif op == self.mainwindow.profile().handle:
                    opgrammar = self.time.getGrammar()
                else:
                    opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW")
                msg = chum.memoopmsg(opchum, opgrammar, systemColor)
                self.textArea.append(convertTags(msg))
                self.mainwindow.chatlog.log(self.channel, msg)
            for c in chums:
                c.op = True
                icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
                c.setIcon(icon)
                if unicode(c.text()) == self.mainwindow.profile().handle:
                    self.userlist.optionsMenu.addAction(self.opAction)
                    self.userlist.optionsMenu.addAction(self.voiceAction)
                    self.userlist.optionsMenu.addAction(self.banuserAction)
                    self.optionsMenu.addMenu(self.chanModeMenu)
            self.sortUsers()
        elif update == "-o":
            self.mainwindow.channelNames.emit(self.channel)
            if self.mainwindow.config.opvoiceMessages():
                chum = PesterProfile(h)
                if h == self.mainwindow.profile().handle:
                    chum = self.mainwindow.profile()
                    ttracker = self.time
                    curtime = self.time.getTime()
                elif self.times.has_key(h):
                    ttracker = self.times[h]
                else:
                    ttracker = TimeTracker(timedelta(0))
                opchum = PesterProfile(op)
                if self.times.has_key(op):
                    opgrammar = self.times[op].getGrammar()
                elif op == self.mainwindow.profile().handle:
                    opgrammar = self.time.getGrammar()
                else:
                    opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW")
                msg = chum.memodeopmsg(opchum, opgrammar, systemColor)
                self.textArea.append(convertTags(msg))
                self.mainwindow.chatlog.log(self.channel, msg)
            for c in chums:
                c.op = False
                if c.voice:
                    icon = PesterIcon(self.mainwindow.theme["memos/voice/icon"])
                    c.setIcon(icon)
                else:
                    icon = QtGui.QIcon()
                    c.setIcon(icon)
                if unicode(c.text()) == self.mainwindow.profile().handle:
                    self.userlist.optionsMenu.removeAction(self.opAction)
                    self.userlist.optionsMenu.removeAction(self.voiceAction)
                    self.userlist.optionsMenu.removeAction(self.banuserAction)
                    self.optionsMenu.removeAction(self.chanModeMenu.menuAction())
            self.sortUsers()
        elif update == "+v":
            if self.mainwindow.config.opvoiceMessages():
                chum = PesterProfile(h)
                if h == self.mainwindow.profile().handle:
                    chum = self.mainwindow.profile()
                    ttracker = self.time
                    curtime = self.time.getTime()
                elif self.times.has_key(h):
                    ttracker = self.times[h]
                else:
                    ttracker = TimeTracker(timedelta(0))
                opchum = PesterProfile(op)
                if self.times.has_key(op):
                    opgrammar = self.times[op].getGrammar()
                elif op == self.mainwindow.profile().handle:
                    opgrammar = self.time.getGrammar()
                else:
                    opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW")
                msg = chum.memovoicemsg(opchum, opgrammar, systemColor)
                self.textArea.append(convertTags(msg))
                self.mainwindow.chatlog.log(self.channel, msg)
            for c in chums:
                c.voice = True
                if not c.op:
                    icon = PesterIcon(self.mainwindow.theme["memos/voice/icon"])
                    c.setIcon(icon)
            self.sortUsers()
        elif update == "-v":
            if self.mainwindow.config.opvoiceMessages():
                chum = PesterProfile(h)
                if h == self.mainwindow.profile().handle:
                    chum = self.mainwindow.profile()
                    ttracker = self.time
                    curtime = self.time.getTime()
                elif self.times.has_key(h):
                    ttracker = self.times[h]
                else:
                    ttracker = TimeTracker(timedelta(0))
                opchum = PesterProfile(op)
                if self.times.has_key(op):
                    opgrammar = self.times[op].getGrammar()
                elif op == self.mainwindow.profile().handle:
                    opgrammar = self.time.getGrammar()
                else:
                    opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW")
                msg = chum.memodevoicemsg(opchum, opgrammar, systemColor)
                self.textArea.append(convertTags(msg))
                self.mainwindow.chatlog.log(self.channel, msg)
            for c in chums:
                c.voice = False
                if c.op:
                    icon = PesterIcon(self.mainwindow.theme["memos/op/icon"])
                    c.setIcon(icon)
                else:
                    icon = QtGui.QIcon()
                    c.setIcon(icon)
            self.sortUsers()
        elif c == self.channel and h == "" and update[0] in ["+","-"]:
            self.updateChanModes(update)

    @QtCore.pyqtSlot()
    def addChumSlot(self):
        if not self.userlist.currentItem():
            return
        currentChum = PesterProfile(unicode(self.userlist.currentItem().text()))
        self.mainwindow.addChum(currentChum)
    @QtCore.pyqtSlot()
    def banSelectedUser(self):
        if not self.userlist.currentItem():
            return
        currentHandle = unicode(self.userlist.currentItem().text())
        (reason, ok) = QtGui.QInputDialog.getText(self, "Ban User", "Enter the reason you are banning this user (optional):")
        if ok:
            self.mainwindow.kickUser.emit("%s:%s" % (currentHandle, reason), self.channel)
    @QtCore.pyqtSlot()
    def opSelectedUser(self):
        if not self.userlist.currentItem():
            return
        currentHandle = unicode(self.userlist.currentItem().text())
        self.mainwindow.setChannelMode.emit(self.channel, "+o", currentHandle)
    @QtCore.pyqtSlot()
    def voiceSelectedUser(self):
        if not self.userlist.currentItem():
            return
        currentHandle = unicode(self.userlist.currentItem().text())
        self.mainwindow.setChannelMode.emit(self.channel, "+v", currentHandle)
    def resetSlider(self, time, send=True):
        self.timeinput.setText(delta2txt(time))
        self.timeinput.setSlider()
        if send:
            self.sendtime()

    @QtCore.pyqtSlot()
    def openChumLogs(self):
        currentChum = self.channel
        self.mainwindow.chumList.pesterlogviewer = PesterLogViewer(currentChum, self.mainwindow.config, self.mainwindow.theme, self.mainwindow)
        self.connect(self.mainwindow.chumList.pesterlogviewer, QtCore.SIGNAL('rejected()'),
                     self.mainwindow.chumList, QtCore.SLOT('closeActiveLog()'))
        self.mainwindow.chumList.pesterlogviewer.show()
        self.mainwindow.chumList.pesterlogviewer.raise_()
        self.mainwindow.chumList.pesterlogviewer.activateWindow()

    @QtCore.pyqtSlot()
    def inviteChums(self):
        if not hasattr(self, 'invitechums'):
            self.invitechums = None
        if not self.invitechums:
            (chum, ok) = QtGui.QInputDialog.getText(self, "Invite to Chat", "Enter the chumhandle of the user you'd like to invite:")
            if ok:
                chum = unicode(chum)
                self.mainwindow.inviteChum.emit(chum, self.channel)
            self.invitechums = None

    @QtCore.pyqtSlot(bool)
    def hideChan(self, on):
        x = ["-","+"][on]
        self.mainwindow.setChannelMode.emit(self.channel, x+"s", "")
    @QtCore.pyqtSlot(bool)
    def inviteChan(self, on):
        x = ["-","+"][on]
        self.mainwindow.setChannelMode.emit(self.channel, x+"i", "")
    @QtCore.pyqtSlot(bool)
    def modChan(self, on):
        x = ["-","+"][on]
        self.mainwindow.setChannelMode.emit(self.channel, x+"m", "")

    @QtCore.pyqtSlot()
    def sendtime(self):
        me = self.mainwindow.profile()
        systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
        time = txt2delta(self.timeinput.text())
        present = self.time.addTime(time)

        serverText = "PESTERCHUM:TIME>"+delta2txt(time, "server")
        self.messageSent.emit(serverText, self.title())
    @QtCore.pyqtSlot()
    def smashclock(self):
        me = self.mainwindow.profile()
        time = txt2delta(self.timeinput.text())
        removed = self.time.removeTime(time)
        if removed:
            grammar = self.time.getGrammarTime(time)
            systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"])
            msg = me.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"])
            self.textArea.append(convertTags(msg))
            self.mainwindow.chatlog.log(self.channel, msg)

        newtime = self.time.getTime()
        if newtime is None:
            newtime = timedelta(0)
            self.resetSlider(newtime, send=False)
        else:
            self.resetSlider(newtime)
    @QtCore.pyqtSlot()
    def prevtime(self):
        time = self.time.prevTime()
        self.time.setCurrent(time)
        self.resetSlider(time)
        self.textInput.setFocus()
    @QtCore.pyqtSlot()
    def nexttime(self):
        time = self.time.nextTime()
        self.time.setCurrent(time)
        self.resetSlider(time)
        self.textInput.setFocus()
    def closeEvent(self, event):
        self.mainwindow.waitingMessages.messageAnswered(self.channel)
        self.windowClosed.emit(self.title())

    windowClosed = QtCore.pyqtSignal(QtCore.QString)