view frontends/src/wix/contact_list.py @ 297:c5554e2939dd

plugin XEP 0277: author for in request + author, updated management for out request - a workaround is now used to parse "nick" tag (Jappix behaviour) - author and updated can now be used in data when sendind microblog. Is no author is given, user jid is used, if no updated is given, current timestamp is used
author Goffi <goffi@goffi.org>
date Fri, 18 Feb 2011 22:32:02 +0100
parents b1794cbb88e5
children 3a21d586dae4
line wrap: on
line source

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
wix: a SAT frontend
Copyright (C) 2009, 2010, 2011  Jérôme Poisson (goffi@goffi.org)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

import wx
from sat_frontends.quick_frontend.quick_contact_list import QuickContactList
from logging import debug, info, error
from cgi import escape
from sat.tools.jid  import JID


class Group(unicode):
    """Class used to recognize groups"""

class Contact(unicode):
    """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 __contains__(self, jid):
        return bool(self.__find_idx(jid))

    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 = u"""-- [%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'
        
        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)
        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
            first_visible = self.GetVisibleBegin()
            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)
            self.ScrollToLine(first_visible)
            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