def create_widget(self, parent): from private_messages.chat_history_view import ChatHistoryWidget self._lock = loggingMutex("Private Messages", logging=get_settings().get_verbose()) from PyQt4.QtCore import QThread from private_messages.chat_messages_handler import ChatMessagesHandler if canUseBackgroundQThreads(): self._messagesThread = QThread() else: self._messagesThread = None self._messagesHandler = ChatMessagesHandler(self.logger, self, self.hidden_options[u"ack_timeout"], self.hidden_options[u"next_msgid"]) if self._messagesThread is not None: self._messagesHandler.moveToThread(self._messagesThread) self._messagesThread.start() self._messagesHandler.delayedDelivery.connect(self._delayedDelivery) self._messagesHandler.messageIDChanged.connect(self._messageIDChanged) self._messagesHandler.displayOwnMessage.connect(self._displayOwnMessage) self._messagesHandler.newMessage.connect(self._displayMessage) self._openChats = {} # mapping peer ID -> ChatDockWidget self._history = ChatHistoryWidget(self, parent, self.logger) return self._history
class private_messages(iface_gui_plugin): VERSION_INITIAL = 0 VERSION_CURRENT = VERSION_INITIAL def __init__(self): super(private_messages, self).__init__() self.options = [((u"prev_messages", u"Number of previous messages to display"), 5), ((u"enable_markdown", u"Enable Markdown annotations", self._enableMarkdownChanged), False)] self.hidden_options = {u"ack_timeout" : 3, # seconds until message delivery is marked as timed out u"next_msgid" : -1} # next free message ID. -1 = not initialized self._storage = None def get_displayed_name(self): return u"Chat" def activate(self): iface_gui_plugin.activate(self) if lunchinator_has_gui(): self._sendMessageAction = _SendMessageAction() self._openChatAction = _OpenChatAction(self._sendMessageAction) self._peerActions = [self._openChatAction, _BlockAction(self._sendMessageAction), self._sendMessageAction] else: self._peerActions = None def create_widget(self, parent): from private_messages.chat_history_view import ChatHistoryWidget self._lock = loggingMutex("Private Messages", logging=get_settings().get_verbose()) from PyQt4.QtCore import QThread from private_messages.chat_messages_handler import ChatMessagesHandler if canUseBackgroundQThreads(): self._messagesThread = QThread() else: self._messagesThread = None self._messagesHandler = ChatMessagesHandler(self.logger, self, self.hidden_options[u"ack_timeout"], self.hidden_options[u"next_msgid"]) if self._messagesThread is not None: self._messagesHandler.moveToThread(self._messagesThread) self._messagesThread.start() self._messagesHandler.delayedDelivery.connect(self._delayedDelivery) self._messagesHandler.messageIDChanged.connect(self._messageIDChanged) self._messagesHandler.displayOwnMessage.connect(self._displayOwnMessage) self._messagesHandler.newMessage.connect(self._displayMessage) self._openChats = {} # mapping peer ID -> ChatDockWidget self._history = ChatHistoryWidget(self, parent, self.logger) return self._history def destroy_widget(self): for chatWindow in self._openChats.values(): chatWindow.close() self.set_hidden_option(u"next_msgid", self._messagesHandler.getNextMessageIDForStorage(), convert=False) self._messagesHandler.deactivate() if self._messagesThread is not None: self._messagesThread.quit() self._messagesThread.wait() self._messagesThread.deleteLater() self._messagesThread = None self._messagesHandler = None self._storage = None self._lock = None iface_gui_plugin.destroy_widget(self) def _enableMarkdownChanged(self, _setting, newVal): for chatWindow in self._openChats.values(): chatWindow.getChatWidget().setMarkdownEnabled(newVal) def extendsInfoDict(self): return lunchinator_has_gui() def extendInfoDict(self, infoDict): infoDict[u"PM_v"] = self.VERSION_CURRENT def get_peer_actions(self): return self._peerActions def process_event(self, cmd, value, _ip, peerInfo, _prep): if not cmd.startswith(u"HELO_PM"): return peerID = peerInfo[u"ID"] subcmd = cmd[7:] if subcmd == u"_ACK": self._messagesHandler.processAck(peerID, value) elif subcmd == u"_TYPING": if peerID in self._openChats: self._openChats[peerID].getChatWidget().otherIsTyping() elif subcmd == u"_CLEARED": if peerID in self._openChats: self._openChats[peerID].getChatWidget().otherCleared() elif subcmd == u"_ERROR": self._messagesHandler.processAck(peerID, value, error=True) elif subcmd == u"": self._messagesHandler.processMessage(peerID, value) def getStorage(self): if self._storage == None: with self._lock: if self._storage == None: from private_messages.chat_messages_storage import ChatMessagesStorage self._storage = ChatMessagesStorage(self.logger) return self._storage @loggingFunc def _displayOwnMessage(self, otherID, msgID, recvTime, msgHTML, msgTime, status, errorMsg): otherID = convert_string(otherID) msgHTML = convert_string(msgHTML) errorMsg = convert_string(errorMsg) if recvTime == -1: recvTime = None if not errorMsg: errorMsg = None if otherID in self._openChats: chatWindow = self._openChats[otherID] chatWindow.getChatWidget().addOwnMessage(msgID, recvTime, msgHTML, msgTime, status, errorMsg) def _activateChat(self, chatWindow, forceForeground=True): chatWindow.showNormal() if forceForeground: chatWindow.raise_() chatWindow.activateWindow() return chatWindow def _openChat(self, myName, otherName, myAvatar, otherAvatar, otherID): from private_messages.chat_window import ChatWindow newWindow = ChatWindow(None, self.logger, myName, otherName, myAvatar, otherAvatar, otherID, self._sendMessageAction) newWindow.getChatWidget().setMarkdownEnabled(self.get_option(u"enable_markdown")) newWindow.windowClosing.connect(self._chatClosed) newWindow.getChatWidget().sendMessage.connect(self._messagesHandler.sendMessage) newWindow.getChatWidget().typing.connect(partial(self._messagesHandler.sendTyping, otherID)) newWindow.getChatWidget().cleared.connect(partial(self._messagesHandler.sendCleared, otherID)) self._openChats[otherID] = newWindow prevMessages = self.getStorage().getPreviousMessages(otherID, self.get_option(u"prev_messages")) from private_messages.chat_messages_storage import ChatMessagesStorage for row in reversed(prevMessages): # partner, ID, own, time, status, text isOwnMessage = row[ChatMessagesStorage.MSG_IS_OWN_MESSAGE_COL] != 0 if isOwnMessage: newWindow.getChatWidget().addOwnMessage(row[ChatMessagesStorage.MSG_ID_COL], row[ChatMessagesStorage.MSG_RECV_TIME_COL], row[ChatMessagesStorage.MSG_TEXT_COL], row[ChatMessagesStorage.MSG_TIME_COL], row[ChatMessagesStorage.MSG_STATUS_COL]) else: newWindow.getChatWidget().addOtherMessage(row[ChatMessagesStorage.MSG_TEXT_COL], row[ChatMessagesStorage.MSG_TIME_COL], row[ChatMessagesStorage.MSG_RECV_TIME_COL]) return self._activateChat(newWindow) @loggingFunc def _chatClosed(self, pID): pID = convert_string(pID) if pID in self._openChats: chatWindow = self._openChats[pID] chatWindow.deleteLater() del self._openChats[pID] else: self.logger.error("Closed chat window was not maintained: %s", pID) def getOpenChatAction(self): return self._openChatAction def openChat(self, pID, forceForeground=True): pID = convert_string(pID) if pID in self._openChats: return self._activateChat(self._openChats[pID], forceForeground) otherName = get_peers().getDisplayedPeerName(pID=pID) if otherName == None: self.logger.error("Could not get info of chat partner %s", pID) return otherAvatar = get_peers().getPeerAvatarFile(pID=pID) myName = get_settings().get_user_name() myAvatar = get_peers().getPeerAvatarFile(pID=get_settings().get_ID()) return self._openChat(myName, otherName, myAvatar, otherAvatar, pID) @loggingFunc def _delayedDelivery(self, otherID, msgID, recvTime, error, errorMessage): otherID = convert_string(otherID) errorMessage = convert_string(errorMessage) if otherID in self._openChats: chatWindow = self._openChats[otherID] chatWindow.getChatWidget().delayedDelivery(msgID, recvTime, error, errorMessage) @loggingFunc def _messageIDChanged(self, otherID, oldID, newID): otherID = convert_string(otherID) if otherID in self._openChats: chatWindow = self._openChats[otherID] chatWindow.getChatWidget().messageIDChanged(oldID, newID) @loggingFunc def _displayMessage(self, otherID, msgHTML, msgTime, msgDict): try: recvTime = time() chatWindow = self.openChat(otherID, False) chatWindow.getChatWidget().addOtherMessage(msgHTML, msgTime, recvTime) self._messagesHandler.receivedSuccessfully(otherID, msgHTML, msgTime, msgDict, recvTime) except: excType, excValue, _tb = sys.exc_info() errorMsg = u"Error processing message (%s: %s)" % (unicode(excType.__name__), unicode(excValue)) self._messagesHandler.errorReceivingMessage(otherID, msgDict, errorMsg) if not chatWindow.isActiveWindow(): from PyQt4.QtGui import QTextDocument doc = QTextDocument() doc.setHtml(msgHTML) displayNotification(chatWindow.getChatWidget().getOtherName(), convert_string(doc.toPlainText()), self.logger, chatWindow.getChatWidget().getOtherIconPath())