def __init__(self, partnerID, rows): super(ChatHistoryModel, self).__init__() self.setHorizontalHeaderLabels([u"Sender", u"Send Time", u"Text"]) if get_peers() is not None: partnerName = get_peers().getDisplayedPeerName(pID=partnerID) else: partnerName = partnerID for row in rows: # sender item1 = self._createItem() isOwn = row[ChatMessagesStorage.MSG_IS_OWN_MESSAGE_COL] != 0 if isOwn: item1.setData(QVariant(u"You"), Qt.DisplayRole) else: item1.setData(partnerName, Qt.DisplayRole) # time item2 = self._createItem() mTime = localtime(row[ChatMessagesStorage.MSG_TIME_COL]) item2.setData(QVariant(formatTime(mTime)), Qt.DisplayRole) # message item3 = self._createItem(True) item3.setData(QVariant(row[ChatMessagesStorage.MSG_TEXT_COL]), Qt.DisplayRole) item3.setData(QVariant(isOwn), ChatMessagesModel.OWN_MESSAGE_ROLE) self.appendRow([item1, item2, item3])
def process_message(self, msg, ip, _member_info): name = u"[%s]" % get_peers().getDisplayedPeerName(pIP=ip) icon = get_peers().getPeerAvatarFile(pIP=ip) if not icon: icon = self.options[u"icon_file"] displayNotification(name, msg, self.logger, icon)
def testMemberRemovalLock(self): get_notification_center().connectMemberRemoved(self.connect_testMemberRemovalLock) print "Removing myself as Member" mIPs = get_peers().getPeerIPs(get_settings().get_ID()) print "Using IPs:", mIPs get_peers().removeMembersByIP(mIPs)
def _setCurrentFile(self, path, dispName=None): if get_peers() is not None: peerName = get_peers().getDisplayedPeerName(self._peerID) else: peerName = u"<unknown peer>" if not path: if self._down: text = u"%d %s (total %s) \u2190 %s" else: text = u"%d %s (total %s) \u2192 %s" text = text % (self._numFiles, u"file" if self._numFiles is 1 else "files", formatSize(self._totalSize), peerName) else: if self._down: text = u"%s (%stotal %s) \u2190 %s" else: text = u"%s (%stotal %s) \u2192 %s" if dispName is None: dispName = os.path.basename(path) numFilesS = u"" if self._numFiles is 1 else u"%d files, " % self._numFiles text = text % (dispName, numFilesS, formatSize(self._totalSize), peerName) self._setFileIcon(path) self._currentFile = path self._nameLabel.setText(text)
def __init__(self, parent, peerID, peerInfo): if get_peers() is not None: self._peerName = get_peers().getDisplayedPeerName(pID=peerID) else: self._peerName = "<peer name here>" self._peerInfo = peerInfo super(RemotePicturesDialog, self).__init__(parent)
def _avatarChanged(self, peerID, newFile): peerID = convert_string(peerID) newFile = convert_string(newFile) if peerID == self._otherID: self.setOtherIconPath(get_peers().getPeerAvatarFile(pID=peerID)) if peerID == get_settings().get_ID(): self.setOwnIconPath(get_peers().getPeerAvatarFile(pID=peerID))
def processMessage(self, xmsg, addr, eventTime, newPeer, fromQueue): """ process any message event, including lunch calls @type xmsg: extMessageIncoming @type addr: unicode @type eventTime: float @type newPeer: bool @type fromQueue: bool """ mtime = localtime(eventTime) t = strftime("%a, %d %b %Y %H:%M:%S", mtime).decode("utf-8") msg = xmsg.getPlainMessage() if not newPeer: with get_peers(): m = get_peers().getPeerInfo(pIP=addr, lock=False) peerName = get_peers().getDisplayedPeerName(pIP=addr, lock=False) if m is None: getCoreLogger().error("Error processing message: info dict is None") else: if peerName is None: peerName = m.get(LunchPeers.PEER_NAME_KEY, "<unknown>") getCoreLogger().info("%s: [%s (%s)] %s", t, peerName, m[LunchPeers.PEER_ID_KEY], msg) self._insertMessage(mtime, m[LunchPeers.PEER_ID_KEY], msg) get_notification_center().emitMessagePrepended(mtime, m[LunchPeers.PEER_ID_KEY], msg) else: m = {u"ID": addr} processLunchCall = False #deprecated: self.processPluginCall(addr, lambda p, ip, member_info: p.process_message(msg, ip, member_info), newPeer, fromQueue) #the next block could be one huge statement, but for readability I leave it as is if get_settings().get_lunch_trigger() in msg.lower(): # the message contains the lunch keyword if eventTime - self.last_lunch_call > get_settings().get_mute_timeout() or \ fromQueue and self.last_lunch_call == eventTime: # it has not been reported before # the call has not been during the mute_timeout or # this is a queued lunch call that previously wasn't muted diff = getTimeDifference(get_settings().get_alarm_begin_time(), get_settings().get_alarm_end_time(), getCoreLogger()) if diff == None or 0 < diff: # either the time format is invalid or we are within the alarm time processLunchCall = True else: diff = getTimeDifference(get_settings().get_next_lunch_begin(), get_settings().get_next_lunch_end(), getCoreLogger()) if diff == None or 0 < diff: # either the time format is invalid or we are within the free for lunch time processLunchCall = True if processLunchCall: self.last_lunch_call = eventTime #deprecated: self.processPluginCall(addr, lambda p, ip, member_info: p.process_lunch_call(msg, ip, member_info), newPeer, fromQueue) else: getCoreLogger().debug("messages will not trigger alarm: %s: [%s] %s until %s (unless you change the setting, that is)", t, m, msg, strftime("%H:%M:%S", localtime(eventTime + get_settings().get_mute_timeout()))) self.processPluginCall(addr, lambda p, ip, member_info: p.process_group_message(xmsg, ip, member_info, processLunchCall), newPeer, fromQueue)
def performAction(self, peerID, _peerInfo, _parent): try: from PyQt4.QtGui import QInputDialog oldName = get_peers().getDisplayedPeerName(pID=peerID) customName, ok = QInputDialog.getText(None, u"Custom Peer Name", u"Enter the displayed peer name:", text=oldName) if ok: customName = convert_string(customName) get_peers().setCustomPeerName(peerID, customName) except: getCoreLogger().exception("Error changing displayed peer name.")
def _fillPeersPopup(self, menu): menu.clear() if get_peers() is None: self.logger.warning("no lunch_peers instance available, cannot show peer actions") return with get_peers(): for peerID in get_peers(): peerInfo = get_peers().getPeerInfo(pID=peerID, lock=False) if self._delegate.getOpenChatAction().appliesToPeer(peerID, peerInfo): menu.addAction(get_peers().getDisplayedPeerName(pID=peerID, lock=False), partial(self._openChat, peerID))
def shouldProcessMessage(self, action, category, peerID, mainGUI, msgData): if category is None: category = PrivacySettings.NO_CATEGORY state = action.getPeerState(peerID, category) if state == PrivacySettings.STATE_FREE: return True if state == PrivacySettings.STATE_BLOCKED: return False if state == PrivacySettings.STATE_CONFIRM: if mainGUI is None: # no gui -> no confirmation return False from lunchinator.privacy.confirmation_dialog import PrivacyConfirmationDialog peerName = get_peers().getDisplayedPeerName(peerID) dialog = PrivacyConfirmationDialog(mainGUI, "Confirmation", peerName, peerID, action, category, msgData) dialog.exec_() return dialog.result() == PrivacyConfirmationDialog.Accepted return False
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)
def _openChat(self, peerID): peerInfo = get_peers().getPeerInfo(pID=peerID) if peerInfo is None: self.logger.error("No peer info found for peer %s", peerID) return self._delegate.getOpenChatAction().performAction(peerID, peerInfo, self)
def updateMemberInformation(self, peerID=None, peerInfo=None): if peerID != None and peerID != self.get_selected_log_member(): # only update if selected member updated return self.memberInformationTable.clear() if self.get_selected_log_member() == None: self.memberInformationTable.setColumnCount(0) self.memberInformationTable.setHeaderLabel("No member selected.") return if peerInfo == None: peerInfo = get_peers().getPeerInfo(pID=self.get_selected_log_member()) if peerInfo == None: self.memberInformationTable.setColumnCount(0) self.memberInformationTable.setHeaderLabel("No member information available.") return self.memberInformationTable.setColumnCount(len(peerInfo)) headers = sorted(peerInfo.keys(), key=lambda s: s.lower()) self.memberInformationTable.setHeaderLabels(QStringList(headers)) item = QTreeWidgetItem(self.memberInformationTable) for col, header in enumerate(headers): item.setData(col, Qt.DisplayRole, QVariant(peerInfo[header])) for col in range(self.memberInformationTable.columnCount()): self.memberInformationTable.resizeColumnToContents(col)
def _resendUndeliveredMessages(self, curTime, partner=None, force=False): if not partner and not self._hasUndelivered: return undelivered = self._getStorage().getRecentUndeliveredMessages(partner) if not partner and not undelivered: self._hasUndelivered=False for msgTuple in undelivered: msgTime = msgTuple[ChatMessagesStorage.MSG_TIME_COL] if not force: timeout = int(curTime - msgTime) if timeout > get_settings().get_peer_timeout(): continue msgID = msgTuple[ChatMessagesStorage.MSG_ID_COL] if msgID in self._waitingForAck: # already resent and waiting for ACK continue # check if partner is online otherID = msgTuple[ChatMessagesStorage.MSG_PARTNER_COL] if get_peers().isPeerID(pID=otherID): self.logger.debug("Resending undelivered message %d to peer '%s'", msgID, otherID) # partner is online, resend message msgHTML = msgTuple[ChatMessagesStorage.MSG_TEXT_COL] self.sendMessage(otherID, msgHTML, msgID, msgTime)
def displayImage(self, cat, picID, picRow, hasPrev, hasNext): cat = convert_string(cat) picURL = convert_string(picRow[RemotePicturesStorage.PIC_URL_COL]) picFile = convert_string(picRow[RemotePicturesStorage.PIC_FILE_COL]) picDesc = convert_string(picRow[RemotePicturesStorage.PIC_DESC_COL]) if picDesc is None: picDesc = u"" picSender = convert_string(picRow[RemotePicturesStorage.PIC_SENDER_COL]) picTime = picRow[RemotePicturesStorage.PIC_ADDED_COL] self.currentCategory = cat self.categoryLabel.setText(cat) self.curPicIndex = picID if picFile and os.path.exists(picFile): self.imageLabel.setImage(picFile) elif picURL: self.imageLabel.setURL(picURL) else: self.logger.warning("No image source specified") self.imageLabel.displayFallbackPic() if picSender: self.imageLabel.setToolTip(u"Sent to you by %s,\nSent %s" % (get_peers().getDisplayedPeerName(pID=picSender), formatTime(localtime(picTime)))) else: self.imageLabel.setToolTip(u"") self.descriptionLabel.setText(picDesc) self.setCurrentIndex(1) self.prevButton.setEnabled(hasPrev) self.nextButton.setEnabled(hasNext) self._categoryOpened.emit()
def _canSendFilesToOther(self): peerInfo = get_peers().getPeerInfo(pID=self._otherID) if peerInfo is None: return False action = PeerActions.get().getPeerActionByName(u"hannesrauhe.lunchinator.file_transfer", u"Send File") if action is None or not action.appliesToPeer(self._otherID, peerInfo): return False return True
def initializePeerActionsMenu(menu, peerID, filterFunc, parentWidget): menu.clear() if get_peers() == None: getCoreLogger().warning("no lunch_peers instance available, cannot show peer actions") return menu if peerID: _fillPeerActionsMenu(menu, peerID, filterFunc, parentWidget) return menu
def showPeerActionsPopup(peerID, filterFunc, parent): from PyQt4.QtGui import QMenu, QCursor if get_peers() == None: getCoreLogger().warning("no lunch_peers instance available, cannot show peer actions") return if peerID: popupMenu = _fillPeerActionsMenu(QMenu(parent), peerID, filterFunc, parent) popupMenu.exec_(QCursor.pos()) popupMenu.deleteLater()
def _getHostnames(self, _args, _argNum, prefix): with get_peers(): lunchmemberNames = set((get_peers().getRealPeerName(pID=peerID, lock=False).replace(u" ", u"\\ ")\ for peerID in get_peers()\ if get_peers().getRealPeerName(pID=peerID, lock=False).replace(u" ", u"\\ ").startswith(prefix))) for peerID in get_peers(): lunchmemberNames.union((ip for ip in get_peers().getPeerIPs(pID=peerID, lock=False) if ip.startswith(prefix))) lunchmembers = list(lunchmemberNames.union((peerID for peerID in get_peers() if peerID.startswith(prefix)))) return lunchmembers if lunchmembers != None else []
def _updatePeer(self, peerID, infoDict=None): peerID = convert_string(peerID) if infoDict == None: infoDict = get_peers().getPeerInfo(pID=peerID) if infoDict == None: #this happens when a peer that is also a member is removed #-> the peer is not there anymore when the member removed signal arrives return self.membersModel.externalRowUpdated(peerID, infoDict)
def process_event(self, cmd, value, ip, member_info, _prep): if cmd == "HELO_VOTE": if self.w is None: self.logger.error("Voter: Vote cannot be processed") return vote = json.loads(value) if vote.has_key("time") and vote.has_key("place"): self.add_vote(member_info[u"ID"], vote["place"], vote["time"]) displayNotification("New Vote", "%s voted" % get_peers().getDisplayedPeerName(pIP=ip), self.logger) else: self.logger.error("Voter: Vote does not look valid: %s", value)
def getHostList(self, args): hosts = [] for member in args: if len(member) == 0: continue ids = get_peers().getPeerIDsByName(member) if ids: hosts.extend(ids) else: # assume IP or host name hosts.append(member) return hosts
def _updatePeers(self): if get_peers() is None: return selectedBefore = self._getSelectedPeer() rows = self._delegate.getStorage().getPartners() newPeers = {} with get_peers(): for row in rows: pID = row[0] newPeers[pID] = get_peers().getPeerInfo(pID=pID, lock=False) self._peerModel.removeMissingKeys(newPeers.keys()) for pID, peerInfo in newPeers.iteritems(): if self._peerModel.hasKey(pID): self._peerModel.externalRowUpdated(pID, peerInfo) else: self._peerModel.externalRowAppended(pID, peerInfo) selectedAfter = self._getSelectedPeer() if selectedAfter is not None and selectedBefore == selectedAfter: self._createHistoryModel(selectedAfter)
def processEvent(self, xmsg, addr, _eventTime, newPeer, fromQueue): """ process any non-message event @type xmsg: extMessageIncoming @type addr: unicode @type _eventTime: float @type newPeer: bool @type fromQueue: bool """ msgData = None cmd = xmsg.getCommand() value = xmsg.getCommandPayload() action = PeerActions.get().getPeerAction(cmd) peerID = get_peers().getPeerID(pIP=addr) if action is not None: if peerID is None: getCoreLogger().error(u"Could not get peer ID for IP %s", addr) return try: msgData = action.preProcessMessageData(value) except: getCoreLogger().error("Error preprocessing data for peer action %s: %s", action.getName(), formatException()) return if action.willIgnorePeerAction(msgData): getCoreLogger().debug("Ignore peer action %s.%s from peer %s (message: %s)", action.getPluginName(), action.getName(), peerID, value) if action.hasCategories(): category = action.getCategoryFromMessage(msgData) else: category = None shouldProcess = PeerActions.get().shouldProcessMessage(action, category, peerID, self.getMainGUI(), msgData) getCoreLogger().debug(u"%s peer action %s.%s from peer %s%s", "Accept" if shouldProcess else "Reject", action.getPluginName(), action.getName(), peerID, ("" if category is None else " category " + category)) if not shouldProcess: return self.processPluginCall(addr, lambda p, ip, member_info: p.process_command(xmsg, ip, member_info, msgData), newPeer, fromQueue, action) #deprecated: self.processPluginCall(addr, lambda p, ip, member_info: p.process_event("HELO_"+cmd, value, ip, member_info, msgData), newPeer, fromQueue, action)
def data(self, index, role=Qt.DisplayRole): if role == Qt.DisplayRole: message = self._getMessage(index.row()) if index.column() == self.TIME_COL: # time mTime = message[0] return QVariant(formatTime(mTime)) elif index.column() == self.SENDER_COL: # sender peerID = message[1] # look in peers first, it's always up to date name = get_peers().getDisplayedPeerName(pID=peerID, lock=False) if not name: # look up in stored peer names name = get_peers().getDisplayedPeerName(pID=peerID) if not name: # check if peerID is IP (from old version) name = get_peers().getDisplayedPeerName(pIP=peerID, lock=False) if not name: name = peerID return QVariant(name) else: return QVariant(message[2]) elif role == Qt.SizeHintRole: return QSize(0, 20) elif role == self.SORT_ROLE: if index.column() == self.TIME_COL: mTime = self._getMessage(index.row())[0] return QVariant(time.mktime(mTime)) else: # return display role as fallback return self.data(index) elif role == Qt.ToolTipRole: if index.column() == self.MESSAGE_COL: return self.data(index, Qt.DisplayRole) return QVariant()
def __init__(self, data, tristate, logger): columns = [(u"Peer Name", self._updateNameItem)] super(PeerModel, self).__init__(get_peers(), columns, logger) if data is None: raise ValueError("data cannot be None") self._data = data self._tristate = tristate if self.dataSource is not None: peers = self.dataSource.getAllKnownPeerIDs() for pID in peers: self.appendContentRow(pID, None) else: for i in range(20): self.appendContentRow("test %d" % i, None)
def __printExceptions(self, action, category, policy): exceptions = action.getExceptions(policy, category) if not exceptions: print "No exceptions." else: print "Exceptions:" self.appendOutput(u"Peer", u"State") self.appendSeparator() for peerID, state in exceptions.iteritems(): peerName = get_peers().getDisplayedPeerName(pID=peerID) if peerName is None: peerName = peerID allow = (state == 0) if policy == PrivacySettings.POLICY_EVERYBODY_EX else (state == 1) self.appendOutput(peerName, u"allow" if allow else u"deny") self.flushOutput()
def _updateMemberStatus(self, _pID=None, _pInfo=None): peers = get_server().getLunchPeers() readyMembers = peers.getReadyMembers() notReadyMembers = peers.getMembers() - readyMembers # don't display members with unknown status as ready readyMembers = [pID for pID in readyMembers if peers.isPeerReadinessKnown(pID=pID)] everybodyReady = False if not readyMembers and not notReadyMembers: status = u"No members." elif not readyMembers: status = u"Nobody is ready for lunch." elif not notReadyMembers: everybodyReady = True status = u"Everybody is ready for lunch." else: if len(readyMembers) == 1: ready = u"1 member" else: ready = u"%d members" % len(readyMembers) if len(notReadyMembers) == 1: notReady = u"1 member" else: notReady = u"%d members" % len(notReadyMembers) status = u"%s ready, %s not ready for lunch." % (ready, notReady) if everybodyReady and not self._highlightPeersReady: # don't highlight if I am the only member if len(readyMembers) > 1 or not get_peers().isMe(pID=iter(readyMembers).next()): self._highlightPeersReady = True if get_settings().get_notification_if_everybody_ready(): displayNotification("Lunch Time", "Everybody is ready for lunch now", getCoreLogger(), get_settings().get_resource("images", "lunchinator.png")) self._highlightIcon() else: status = u"You are the only member." elif not everybodyReady and self._highlightPeersReady: self._highlightPeersReady = False self._highlightIcon() self._memberStatusAction.setText(status)
def create_info_table_widget(self, parent): self.info_table = QTreeView(parent) self.info_table.setSortingEnabled(True) self.info_table.setHeaderHidden(False) self.info_table.setAlternatingRowColors(True) self.info_table.setIndentation(0) self.info_table_model = ExtendedMembersModel(get_peers(), self.logger) proxyModel = QSortFilterProxyModel(self.info_table) proxyModel.setSortCaseSensitivity(Qt.CaseInsensitive) proxyModel.setDynamicSortFilter(True) proxyModel.setSourceModel(self.info_table_model) self.info_table.setModel(proxyModel) get_notification_center().connectPeerAppended(self.info_table_model.externalRowAppended) get_notification_center().connectPeerUpdated(self.info_table_model.externalRowUpdated) get_notification_center().connectPeerRemoved(self.info_table_model.externalRowRemoved) return self.info_table
def updateWidgets(self, _=None, __=None, ___=None): if not self.isVisible(): return True peers = get_peers() if peers is not None: members = peers.getMembers() readyMembers = peers.getReadyMembers() notReadyMembers = peers.getMembers() - readyMembers else: members = [] readyMembers = [] notReadyMembers = [] memText = "%d group members online<br />" % len(members) memToolTip = "" # don't display members with unknown status as ready readyMembers = [pID for pID in readyMembers if peers.isPeerReadinessKnown(pID=pID)] readyText = ", ".join([peers.getDisplayedPeerName(pID=x) for x in readyMembers]) notReadyText = ", ".join([peers.getDisplayedPeerName(pID=x) for x in notReadyMembers]) memToolTip += "<span style='color:green'>%s</span><br />" % readyText if len(readyMembers) else "" memToolTip += "<span style='color:red'>%s</span>" % notReadyText if len(notReadyMembers) else "" memText += "<span style='color:green'>%d ready for lunch</span>" % len(readyMembers) if len(readyMembers) else "no one ready for lunch" self.memberView.setText(memText) self.memberView.setToolTip(memToolTip) msgTexts = "" with get_server().get_messages(): messages = get_server().get_messages().getAll(time() - (180 * 60)) for timest, peerID, msg in messages: member = peers.getDisplayedPeerName(pID=peerID) color = self.getMemberColor(peerID) msgTexts += "<span style='color:#%s'><b>%s</b> \ <i>[%s]</i>: %s</span><br />\n" % (color, member,strftime("%H:%M",timest), msg) self.msgview.setHtml(msgTexts)