view frontends/src/primitivus/contact_list.py @ 411:b109a79ac72f

primitivus: urwid 1.0.0 update (crash was caused by using non unicode caption)
author Goffi <goffi@goffi.org>
date Sat, 08 Oct 2011 21:03:02 +0200
parents b1794cbb88e5
children cf005701624b
line wrap: on
line source

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

"""
Primitivus: 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 urwid
from urwid_satext import sat_widgets
from sat_frontends.quick_frontend.quick_contact_list import QuickContactList
from sat.tools.jid import JID


class ContactList(urwid.WidgetWrap, QuickContactList):
    signals = ['click','change']

    def __init__(self, host, CM, on_click=None, on_change=None, user_data=None):
        self.host = host
        self.selected = None
        self.groups={}
        self.alert_jid=set()
        
        #we now build the widget
        self.frame = urwid.Frame(self.__buildList())
        self.main_widget = sat_widgets.LabelLine(self.frame, sat_widgets.SurroundedText(_("Contacts")))
        urwid.WidgetWrap.__init__(self, self.main_widget)
        if on_click:
            urwid.connect_signal(self, 'click', on_click, user_data)
        if on_change:
            urwid.connect_signal(self, 'change', on_change, user_data)
        QuickContactList.__init__(self, CM)

    def __contains__(self, jid):
        for group in self.groups:
            if jid.short in self.groups[group][1]:
                return True
        return False

    def setFocus(self, name):
        """give focus to the first group or contact with the given name"""
        idx = 0
        for widget in self.frame.body.body:
            if widget.getValue() == name:
                self.frame.body.set_focus(idx)
                return
            idx+=1

    def putAlert(self, jid):
        """Put an alert on the jid to get attention from user (e.g. for new message)"""
        self.alert_jid.add(jid.short)
        self.frame.body = self.__buildList()
        self.host.redraw()

    def __groupClicked(self, group_wid):
        group = self.groups[group_wid.getValue()]
        group[0] = not group[0]
        self.frame.body = self.__buildList()
        self.host.redraw()
        self.setFocus(group_wid.getValue())

    def __contactClicked(self, contact_wid, selected):
        self.selected = contact_wid.data
        for widget in self.frame.body.body:
            if widget.__class__ == sat_widgets.SelectableText:
                widget.setState(widget.data == self.selected, invisible=True)
        if self.selected in self.alert_jid:
            self.alert_jid.remove(self.selected)
            self.frame.body = self.__buildList()
            self.host.redraw()
        self._emit('click')

    def __buildContact(self, content, param_contacts):
        """Add contact representation in widget list
        @param content: widget list, e.g. SimpleListWalker
        @param contacts: list of JID"""
        contacts = list(param_contacts)
        contacts.sort()
        for contact in contacts:
            jid=JID(contact) 
            name = self.CM.getAttr(jid,'name')
            nick = self.CM.getAttr(jid,'nick')
            display = nick or name or jid.node or jid.short
            header = '(*) ' if contact in self.alert_jid else ''
            widget = sat_widgets.SelectableText(('alert' if contact in self.alert_jid else 'default',display),
                                                    selected = contact==self.selected, header=header)
            widget.data = contact
            content.append(widget)
            urwid.connect_signal(widget, 'change', self.__contactClicked)

    def __buildList(self):
        """Build the main contact list widget"""
        content = urwid.SimpleListWalker([])
        group_keys = self.groups.keys()
        group_keys.sort()
        for key in group_keys:
            unfolded = self.groups[key][0]
            if key!=None:
                header = '[-]' if unfolded else '[+]'
                widget = sat_widgets.ClickableText(key,header=header+' ')
                content.append(widget)
                urwid.connect_signal(widget, 'click', self.__groupClicked)
            if unfolded:
                self.__buildContact(content, self.groups[key][1])
        return urwid.ListBox(content)

    def unselectAll(self):
        """Unselect all contacts"""
        self.selected = None
        for widget in self.frame.body.body:
            if widget.__class__ == sat_widgets.SelectableText:
                widget.setState(False, invisible=True)


    def get_contact(self):
        """Return contact currently selected"""
        return self.selected
            
    def clear_contacts(self):
        """clear all the contact list"""
        self.groups={}
        self.selected = None
        self.unselectAll()
        self.frame.body = self.__buildList()
        self.host.redraw()

    def replace(self, jid, groups=[None]):
        """add a contact to the list if doesn't exist, else update it"""
        assert isinstance(groups, list)
        assert isinstance(jid, JID)
        if not groups:
            groups=[None]
        for group in groups:
            if not self.groups.has_key(group):
                self.groups[group] = [True,set()]  #[unfold,list_of_contacts]
            self.groups[group][1].add(jid.short)
        self.frame.body = self.__buildList()
        self.host.redraw()


        """contacts = self.list_wid.getAllValues()
        if jid.short not in contacts:
            contacts.append(jid.short)
            contacts.sort()
            self.list_wid.changeValues(contacts)
            self._emit('change')"""
    
    def disconnect(self, jid):
        """mark a contact disconnected"""
        self.remove(jid.short)
    
    def remove(self, param_jid):
        """remove a contact from the list"""
        groups_to_remove = []
        jid = JID(param_jid)
        for group in self.groups:
            contacts = self.groups[group][1]
            if jid.short in contacts:
                contacts.remove(jid.short)
                if not len(contacts):
                    groups_to_remove.append(group)
        for group in groups_to_remove:
            del self.groups[group]
        self.frame.body = self.__buildList()
        self.host.redraw()
    
    def add(self, jid, param_groups=[None]):
        """add a contact to the list"""
        self.replace(jid,param_groups)