- plugin XEP-0045: user joined./left signal is sended - wix: user are adder/removed when these signals are catched
179 lines
6.3 KiB
Python
179 lines
6.3 KiB
Python
import wx
|
|
from quick_frontend.quick_contact_list import QuickContactList
|
|
from logging import debug, info, error
|
|
from cgi import escape
|
|
from tools.jid import JID
|
|
|
|
|
|
class Group(str):
|
|
"""Class used to recognize groups"""
|
|
|
|
class Contact(str):
|
|
"""Class used to recognize groups"""
|
|
|
|
class ContactList(wx.SimpleHtmlListBox, QuickContactList):
|
|
"""Customized control to manage contacts."""
|
|
|
|
def __init__(self, parent, host, type="JID"):
|
|
"""init the contact list
|
|
@param parent: WxWidgets parent of the widget
|
|
@param host: wix main app class
|
|
@param type: type of contact list: "JID" for the usual big jid contact list
|
|
"CUSTOM" for a customized contact list (self.__presentItem must then be overrided)
|
|
"""
|
|
wx.SimpleHtmlListBox.__init__(self, parent, -1)
|
|
QuickContactList.__init__(self, host.CM)
|
|
self.host = host
|
|
self.type = type
|
|
self.__typeSwitch()
|
|
self.groups = {} #list contacts in each groups, key = group
|
|
self.Bind(wx.EVT_LISTBOX, self.onSelected)
|
|
self.Bind(wx.EVT_LISTBOX_DCLICK, self.onActivated)
|
|
|
|
def __typeSwitch(self):
|
|
if self.type == "JID":
|
|
self.__presentItem = self.__presentItemJID
|
|
elif type != "CUSTOM":
|
|
self.__presentItem = self.__presentItemDefault
|
|
|
|
def __find_idx(self, entity):
|
|
"""Find indexes of given contact (or groups) in contact list, manage jid
|
|
@return: list of indexes"""
|
|
result=[]
|
|
for i in range(self.GetCount()):
|
|
if (type(entity) == JID and type(self.GetClientData(i)) == JID and self.GetClientData(i).short == entity.short) or\
|
|
self.GetClientData(i) == entity:
|
|
result.append(i)
|
|
return result
|
|
|
|
def replace(self, contact, groups=None):
|
|
debug(_("update %s") % contact)
|
|
if not self.__find_idx(contact):
|
|
self.add(contact, groups)
|
|
else:
|
|
for i in self.__find_idx(contact):
|
|
self.SetString(i, self.__presentItem(contact))
|
|
|
|
def disconnect(self, contact):
|
|
self.remove(contact) #for now, we only show online contacts
|
|
|
|
def __eraseGroup(self, group):
|
|
"""Erase all contacts in group
|
|
@param group: group to erase
|
|
@return: True if something as been erased"""
|
|
erased = False
|
|
indexes = self.__find_idx(group)
|
|
for idx in indexes:
|
|
while idx<self.GetCount()-1 and type(self.GetClientData(idx+1)) != Group:
|
|
erased = True
|
|
self.Delete(idx+1)
|
|
return erased
|
|
|
|
|
|
def __presentGroup(self, group):
|
|
"""Make a nice presentation for the contact groups"""
|
|
html = """-- [%s] --""" % group
|
|
|
|
return html
|
|
|
|
def __presentItemDefault(self, contact):
|
|
"""Make a basic presentation of string contacts in the list."""
|
|
return contact
|
|
|
|
def __presentItemJID(self, jid):
|
|
"""Make a nice presentation of the contact in the list for JID contacts."""
|
|
name = self.CM.getAttr(jid,'name')
|
|
nick = self.CM.getAttr(jid,'nick')
|
|
show = filter(lambda x:x[0]==self.CM.getAttr(jid,'show'), const_STATUS)[0]
|
|
#show[0]==shortcut
|
|
#show[1]==human readable
|
|
#show[2]==color (or None)
|
|
show_html = "<font color='%s'>[%s]</font>" % (show[2], show[1]) if show[2] else ""
|
|
status = self.CM.getAttr(jid,'status') or ''
|
|
avatar = self.CM.getAttr(jid,'avatar') or IMAGE_DIR+'/empty_avatar.png'
|
|
|
|
#XXX: yes table I know :) but wxHTML* doesn't support CSS
|
|
html = """
|
|
<table border='0'>
|
|
<td>
|
|
<img height='64' width='64' src='%s' />
|
|
</td>
|
|
<td>
|
|
<b>%s</b> %s<br />
|
|
<i>%s</i>
|
|
</td>
|
|
</table>
|
|
""" % (avatar,
|
|
escape(nick or name or jid.node or jid.short),
|
|
show_html,
|
|
escape(status))
|
|
|
|
return html
|
|
|
|
def clear_contacts(self):
|
|
"""Clear all the contact list"""
|
|
self.Clear()
|
|
|
|
def add(self, contact, groups = None):
|
|
"""add a contact to the list"""
|
|
debug (_("adding %s"),contact)
|
|
#gof: groups = param_groups or self.CM.getAttr(jid, 'groups')
|
|
if not groups:
|
|
idx = self.Insert(self.__presentItem(contact), 0, contact)
|
|
else:
|
|
for group in groups:
|
|
indexes = self.__find_idx(group)
|
|
gp_idx = 0
|
|
if not indexes: #this is a new group, we have to create it
|
|
gp_idx = self.Append(self.__presentGroup(group), Group(group))
|
|
else:
|
|
gp_idx = indexes[0]
|
|
|
|
self.Insert(self.__presentItem(contact), gp_idx+1, contact)
|
|
|
|
|
|
|
|
def remove(self, contact):
|
|
"""remove a contact from the list"""
|
|
debug (_("removing %s"), contact)
|
|
list_idx = self.__find_idx(contact)
|
|
list_idx.reverse() #as we make some deletions, we have to reverse the order
|
|
for i in list_idx:
|
|
self.Delete(i)
|
|
|
|
def onSelected(self, event):
|
|
"""Called when a contact is selected."""
|
|
data = self.getSelection()
|
|
if data == None: #we have a group
|
|
group = self.GetClientData(self.GetSelection())
|
|
erased = self.__eraseGroup(group)
|
|
if not erased: #the group was already erased, we can add again the contacts
|
|
contacts = self.CM.getContFromGroup(group)
|
|
contacts.sort()
|
|
id_insert = self.GetSelection()+1
|
|
for contact in contacts:
|
|
self.Insert(self.__presentItem(contact), id_insert, contact)
|
|
self.SetSelection(wx.NOT_FOUND)
|
|
event.Skip(False)
|
|
else:
|
|
event.Skip()
|
|
|
|
def onActivated(self, event):
|
|
"""Called when a contact is clicked or activated with keyboard."""
|
|
data = self.getSelection()
|
|
self.onActivatedCB(data)
|
|
event.Skip()
|
|
|
|
def getSelection(self):
|
|
"""Return the selected contact, or an empty string if there is not"""
|
|
if self.GetSelection() == wx.NOT_FOUND:
|
|
return None
|
|
data = self.GetClientData(self.GetSelection())
|
|
if type(data) == Group:
|
|
return None
|
|
return data
|
|
|
|
def registerActivatedCB(self, cb):
|
|
"""Register a callback with manage contact activation."""
|
|
self.onActivatedCB=cb
|
|
|