poezio/src/roster.py

262 lines
8.3 KiB
Python
Raw Normal View History

2011-09-06 00:45:53 +00:00
# Copyright 2010-2011 Florent Le Coz <louiz@louiz.org>
2010-09-16 17:57:27 +00:00
#
# This file is part of Poezio.
#
# Poezio is free software: you can redistribute it and/or modify
2011-09-11 15:10:05 +00:00
# it under the terms of the zlib license. See the COPYING file.
2010-09-16 17:57:27 +00:00
"""
Defines the Roster and RosterGroup classes
"""
2010-11-10 21:15:08 +00:00
import logging
log = logging.getLogger(__name__)
from config import config
2011-05-24 18:33:37 +00:00
from os import path as p
from contact import Contact
2010-11-10 21:15:08 +00:00
from sleekxmpp.xmlstream.stanzabase import JID
2010-09-16 17:57:27 +00:00
class Roster(object):
def __init__(self):
self._contact_filter = None # A tuple(function, *args)
# function to filter contacts,
# on search, for example
self._contacts = {} # key = bare jid; value = Contact()
self._roster_groups = []
2011-05-24 18:33:37 +00:00
def export(self, path):
if p.isfile(path):
return
try:
f = open(path, 'w+')
f.writelines([i + "\n" for i in self._contacts])
f.close()
return True
except IOError:
return
2011-06-18 10:52:58 +00:00
def empty(self):
self._contacts = {}
self._roster_groups = []
def add_contact(self, contact, jid):
"""
Add a contact to the contact list
"""
self._contacts[jid] = contact
def remove_contact(self, jid):
"""
Remove a contact from the contact list
"""
contact = self.get_contact_by_jid(jid)
for group in contact._groups:
2011-01-12 05:49:33 +00:00
self.remove_contact_from_group(group, contact)
del self._contacts[jid]
def get_contact_len(self):
"""
Return the number of contacts in this group
"""
return len(self._contacts.keys())
def get_contact_by_jid(self, jid):
"""
Returns the contact with the given bare JID
"""
2010-11-10 21:15:08 +00:00
# Use only the bare jid
jid = JID(jid)
if jid.bare in self._contacts:
return self._contacts[jid.bare]
return None
def edit_groups_of_contact(self, contact, groups):
"""
Edit the groups the contact is in
Add or remove RosterGroup if needed
"""
# add the contact to each group he is in
# If the contact hasn't any group, we put her in
# the virtual default 'none' group
2010-11-10 21:15:08 +00:00
if not len(groups):
groups = ['none']
for group in groups:
if group not in contact._groups:
# create the group if it doesn't exist yet
contact._groups.append(group)
self.add_contact_to_group(group, contact)
# remove the contact from each group he is not in
for group in contact._groups:
if group not in groups:
# the contact is not in the group anymore
2011-10-01 12:26:19 +00:00
contact._groups.remove(group)
self.remove_contact_from_group(group, contact)
def remove_contact_from_group(self, group_name, contact):
"""
Remove the contact from the group.
Delete the group if this makes it empty
"""
for group in self._roster_groups:
if group.name == group_name:
group.remove_contact(contact)
if group.is_empty():
self._roster_groups.remove(group)
return
def add_contact_to_group(self, group_name, contact):
"""
Add the contact to the group.
Create the group if it doesn't already exist
"""
for group in self._roster_groups:
if group.name == group_name:
if not group.has_contact(contact):
group.add_contact(contact)
return
folded_groups = config.get('folded_roster_groups', '', section='var').split(':')
new_group = RosterGroup(group_name, folded=group_name in folded_groups)
self._roster_groups.append(new_group)
new_group.add_contact(contact)
def get_groups(self):
"""
Returns the list of groups
"""
return self._roster_groups
def get_contacts(self):
"""
Return a list of all the contact
"""
return [contact for contact in self._contacts.values()]
def save_to_config_file(self):
"""
Save various information to the config file
e.g. the folded groups
"""
folded_groups = ':'.join([group.name for group in self._roster_groups\
if group.folded])
log.debug('folded:%s\n' %folded_groups)
config.set_and_save('folded_roster_groups', folded_groups, 'var')
2011-02-01 23:51:34 +00:00
def get_nb_connected_contacts(self):
"""
Return the number of contacts connected
"""
length = 0
for group in self._roster_groups:
length += group.get_nb_connected_contacts()
return length
def __len__(self):
"""
Return the number of line that would be printed
for the whole roster
"""
length = 0
show_offline = config.get('roster_show_offline', 'false') == 'true'
for group in self._roster_groups:
if not show_offline and group.get_nb_connected_contacts() == 0:
continue
length += 1 # One for the group's line itself
if not group.folded:
for contact in group.get_contacts(self._contact_filter):
# We do not count the offline contacts (depending on config)
if not show_offline and\
contact.get_nb_resources() == 0:
continue
length += 1 # One for the contact's line
if not contact._folded:
# One for each resource, if the contact is unfolded
length += contact.get_nb_resources()
return length
def __repr__(self):
ret = '== Roster:\nContacts:\n'
for contact in self._contacts:
ret += '%s\n' % (contact,)
ret += 'Groups\n'
for group in self._roster_groups:
ret += '%s\n' % (group,)
return ret + '\n'
PRESENCE_PRIORITY = {'unavailable': 0,
'xa': 1,
'away': 2,
'dnd': 3,
'': 4,
'available': 4}
class RosterGroup(object):
2010-09-16 17:57:27 +00:00
"""
A RosterGroup is a group containing contacts
It can be Friends/Family etc, but also can be
Online/Offline or whatever
2010-09-16 17:57:27 +00:00
"""
def __init__(self, name, folded=False):
self._contacts = []
self.name = name
self.folded = folded # if the group content is to be shown
def is_empty(self):
return len(self._contacts) == 0
2010-09-16 17:57:27 +00:00
def has_contact(self, contact):
"""
Return a bool, telling if the contact
is already in the group
"""
if contact in self._contacts:
return True
return False
def remove_contact(self, contact):
"""
2010-12-18 18:54:55 +00:00
Remove a Contact object from the list
"""
2011-01-12 06:50:12 +00:00
try:
self._contacts.remove(contact)
except ValueError:
pass
2010-09-16 17:57:27 +00:00
def add_contact(self, contact):
2010-09-16 17:57:27 +00:00
"""
append a Contact object to the list
2010-09-16 17:57:27 +00:00
"""
assert isinstance(contact, Contact)
assert contact not in self._contacts
self._contacts.append(contact)
2010-09-16 17:57:27 +00:00
def get_contacts(self, contact_filter):
def compare_contact(a):
if not a.get_highest_priority_resource():
return 0
2011-11-09 21:00:38 +00:00
show = a.get_highest_priority_resource()
if show not in PRESENCE_PRIORITY:
return 5
return PRESENCE_PRIORITY[show]
contact_list = self._contacts if not contact_filter\
else [contact for contact in self._contacts if contact_filter[0](contact, contact_filter[1])]
return sorted(contact_list, key=compare_contact, reverse=True)
def toggle_folded(self):
self.folded = not self.folded
2010-09-16 17:57:27 +00:00
def __repr__(self):
return '<Roster_group: %s; %s>' % (self.name, self._contacts)
def __len__(self):
return len(self._contacts)
def get_nb_connected_contacts(self):
l = 0
for contact in self._contacts:
if contact.get_highest_priority_resource():
l += 1
return l
roster = Roster()