Mercurial > libervia-backend
comparison frontends/src/primitivus/contact_list.py @ 1367:f71a0fc26886
merged branch frontends_multi_profiles
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 18 Mar 2015 10:52:28 +0100 |
parents | 1679ac59f701 |
children | 017270e6eea4 |
comparison
equal
deleted
inserted
replaced
1295:1e3b1f9ad6e2 | 1367:f71a0fc26886 |
---|---|
19 | 19 |
20 from sat.core.i18n import _ | 20 from sat.core.i18n import _ |
21 import urwid | 21 import urwid |
22 from urwid_satext import sat_widgets | 22 from urwid_satext import sat_widgets |
23 from sat_frontends.quick_frontend.quick_contact_list import QuickContactList | 23 from sat_frontends.quick_frontend.quick_contact_list import QuickContactList |
24 from sat_frontends.quick_frontend.quick_utils import unescapePrivate | |
25 from sat_frontends.tools.jid import JID | |
26 from sat_frontends.primitivus.status import StatusBar | 24 from sat_frontends.primitivus.status import StatusBar |
27 from sat_frontends.primitivus.constants import Const as C | 25 from sat_frontends.primitivus.constants import Const as C |
28 from sat_frontends.primitivus.keys import action_key_map as a_key | 26 from sat_frontends.primitivus.keys import action_key_map as a_key |
27 from sat_frontends.primitivus.widget import PrimitivusWidget | |
28 from sat_frontends.tools import jid | |
29 from sat.core import log as logging | 29 from sat.core import log as logging |
30 log = logging.getLogger(__name__) | 30 log = logging.getLogger(__name__) |
31 | 31 |
32 | 32 |
33 class ContactList(urwid.WidgetWrap, QuickContactList): | 33 class ContactList(PrimitivusWidget, QuickContactList): |
34 signals = ['click','change'] | 34 signals = ['click','change'] |
35 | 35 |
36 def __init__(self, host, on_click=None, on_change=None, user_data=None): | 36 def __init__(self, host, on_click=None, on_change=None, user_data=None, profile=None): |
37 QuickContactList.__init__(self) | 37 QuickContactList.__init__(self, host, profile) |
38 self.host = host | |
39 self.selected = None | |
40 self.groups={} | |
41 self.alert_jid=set() | |
42 self.show_status = False | |
43 self.show_disconnected = False | |
44 self.show_empty_groups = True | |
45 # TODO: this may lead to two successive UI refresh and needs an optimization | |
46 self.host.bridge.asyncGetParamA(C.SHOW_EMPTY_GROUPS, "General", profile_key=host.profile, callback=self.showEmptyGroups) | |
47 self.host.bridge.asyncGetParamA(C.SHOW_OFFLINE_CONTACTS, "General", profile_key=host.profile, callback=self.showOfflineContacts) | |
48 | 38 |
49 #we now build the widget | 39 #we now build the widget |
50 self.host.status_bar = StatusBar(host) | 40 self.status_bar = StatusBar(host) |
51 self.frame = sat_widgets.FocusFrame(self.__buildList(), None, self.host.status_bar) | 41 self.frame = sat_widgets.FocusFrame(self._buildList(), None, self.status_bar) |
52 self.main_widget = sat_widgets.LabelLine(self.frame, sat_widgets.SurroundedText(_("Contacts"))) | 42 PrimitivusWidget.__init__(self, self.frame, _(u'Contacts')) |
53 urwid.WidgetWrap.__init__(self, self.main_widget) | |
54 if on_click: | 43 if on_click: |
55 urwid.connect_signal(self, 'click', on_click, user_data) | 44 urwid.connect_signal(self, 'click', on_click, user_data) |
56 if on_change: | 45 if on_change: |
57 urwid.connect_signal(self, 'change', on_change, user_data) | 46 urwid.connect_signal(self, 'change', on_change, user_data) |
58 | 47 |
59 def update(self): | 48 def update(self): |
60 """Update display, keep focus""" | 49 """Update display, keep focus""" |
61 widget, position = self.frame.body.get_focus() | 50 widget, position = self.frame.body.get_focus() |
62 self.frame.body = self.__buildList() | 51 self.frame.body = self._buildList() |
63 if position: | 52 if position: |
64 try: | 53 try: |
65 self.frame.body.focus_position = position | 54 self.frame.body.focus_position = position |
66 except IndexError: | 55 except IndexError: |
67 pass | 56 pass |
68 self.host.redraw() | 57 self._invalidate() |
69 | 58 self.host.redraw() # FIXME: check if can be avoided |
70 def update_jid(self, jid): | |
71 self.update() | |
72 | 59 |
73 def keypress(self, size, key): | 60 def keypress(self, size, key): |
74 # FIXME: we have a temporary behaviour here: FOCUS_SWITCH change focus globally in the parent, | 61 # FIXME: we have a temporary behaviour here: FOCUS_SWITCH change focus globally in the parent, |
75 # and FOCUS_UP/DOWN is transwmitter to parent if we are respectively on the first or last element | 62 # and FOCUS_UP/DOWN is transwmitter to parent if we are respectively on the first or last element |
76 if key in sat_widgets.FOCUS_KEYS: | 63 if key in sat_widgets.FOCUS_KEYS: |
79 return key | 66 return key |
80 if key == a_key['STATUS_HIDE']: #user wants to (un)hide contacts' statuses | 67 if key == a_key['STATUS_HIDE']: #user wants to (un)hide contacts' statuses |
81 self.show_status = not self.show_status | 68 self.show_status = not self.show_status |
82 self.update() | 69 self.update() |
83 elif key == a_key['DISCONNECTED_HIDE']: #user wants to (un)hide disconnected contacts | 70 elif key == a_key['DISCONNECTED_HIDE']: #user wants to (un)hide disconnected contacts |
84 self.host.bridge.setParam(C.SHOW_OFFLINE_CONTACTS, C.str(not self.show_disconnected), "General", profile_key=self.host.profile) | 71 self.host.bridge.setParam(C.SHOW_OFFLINE_CONTACTS, C.str(not self.show_disconnected), "General", profile_key=self.profile) |
72 elif key == a_key['RESOURCES_HIDE']: #user wants to (un)hide contacts resources | |
73 self.showResources(not self.show_resources) | |
74 self.update() | |
85 return super(ContactList, self).keypress(size, key) | 75 return super(ContactList, self).keypress(size, key) |
86 | 76 |
87 def __contains__(self, jid): | 77 # modify the contact list |
88 for group in self.groups: | |
89 if jid.bare in self.groups[group][1]: | |
90 return True | |
91 return False | |
92 | 78 |
93 def setFocus(self, text, select=False): | 79 def setFocus(self, text, select=False): |
94 """give focus to the first element that matches the given text. You can also | 80 """give focus to the first element that matches the given text. You can also |
95 pass in text a sat_frontends.tools.jid.JID (it's a subclass of unicode). | 81 pass in text a sat_frontends.tools.jid.JID (it's a subclass of unicode). |
82 | |
96 @param text: contact group name, contact or muc userhost, muc private dialog jid | 83 @param text: contact group name, contact or muc userhost, muc private dialog jid |
97 @param select: if True, the element is also clicked | 84 @param select: if True, the element is also clicked |
98 """ | 85 """ |
99 idx = 0 | 86 idx = 0 |
100 for widget in self.frame.body.body: | 87 for widget in self.frame.body.body: |
101 try: | 88 try: |
102 if isinstance(widget, sat_widgets.ClickableText): | 89 if isinstance(widget, sat_widgets.ClickableText): |
103 # contact group | 90 # contact group |
104 value = widget.getValue() | 91 value = widget.getValue() |
105 elif isinstance(widget, sat_widgets.SelectableText): | 92 elif isinstance(widget, sat_widgets.SelectableText): |
106 if widget.data.startswith(C.PRIVATE_PREFIX): | 93 # contact or muc |
107 # muc private dialog | 94 value = widget.data |
108 value = widget.getValue() | |
109 else: | |
110 # contact or muc | |
111 value = widget.data | |
112 else: | 95 else: |
113 # Divider instance | 96 # Divider instance |
114 continue | 97 continue |
115 # there's sometimes a leading space | 98 # there's sometimes a leading space |
116 if text.strip() == value.strip(): | 99 if text.strip() == value.strip(): |
117 self.frame.body.focus_position = idx | 100 self.frame.body.focus_position = idx |
118 if select: | 101 if select: |
119 self.__contactClicked(widget, True) | 102 self._contactClicked(False, widget, True) |
120 return | 103 return |
121 except AttributeError: | 104 except AttributeError: |
122 pass | 105 pass |
123 idx += 1 | 106 idx += 1 |
124 | 107 |
125 def putAlert(self, jid): | 108 log.debug(u"Not element found for {} in setFocus".format(text)) |
126 """Put an alert on the jid to get attention from user (e.g. for new message)""" | 109 |
127 self.alert_jid.add(jid.bare) | 110 def specialResourceVisible(self, entity): |
111 """Assure a resource of a special entity is visible and clickable | |
112 | |
113 Mainly used to display private conversation in MUC rooms | |
114 @param entity: full jid of the resource to show | |
115 """ | |
116 assert isinstance(entity, jid.JID) | |
117 if entity not in self._special_extras: | |
118 self._special_extras.add(entity) | |
119 self.update() | |
120 | |
121 # events | |
122 | |
123 def _groupClicked(self, group_wid): | |
124 group = group_wid.getValue() | |
125 data = self.getGroupData(group) | |
126 data[C.GROUP_DATA_FOLDED] = not data.setdefault(C.GROUP_DATA_FOLDED, False) | |
127 self.setFocus(group) | |
128 self.update() | 128 self.update() |
129 | 129 |
130 def __groupClicked(self, group_wid): | 130 def _contactClicked(self, use_bare_jid, contact_wid, selected): |
131 group = self.groups[group_wid.getValue()] | 131 """Method called when a contact is clicked |
132 group[0] = not group[0] | 132 |
133 @param use_bare_jid: True if use_bare_jid is set in self._buildEntityWidget. | |
134 If True, all jids in self._alerts with the same bare jid has contact_wid.data will be removed | |
135 @param contact_wid: widget of the contact, must have the entity set in data attribute | |
136 @param selected: boolean returned by the widget, telling if it is selected | |
137 """ | |
138 entity = contact_wid.data | |
139 if use_bare_jid: | |
140 to_remove = set() | |
141 for alert_entity in self._alerts: | |
142 if alert_entity.bare == entity.bare: | |
143 to_remove.add(alert_entity) | |
144 self._alerts.difference_update(to_remove) | |
145 else: | |
146 self._alerts.discard(entity) | |
147 self.host.modeHint(C.MODE_INSERTION) | |
133 self.update() | 148 self.update() |
134 self.setFocus(group_wid.getValue()) | 149 self._emit('click', entity) |
135 | 150 |
136 def __contactClicked(self, contact_wid, selected): | 151 def onPresenceUpdate(self, entity, show, priority, statuses, profile): |
137 self.selected = contact_wid.data | 152 super(ContactList, self).onPresenceUpdate(entity, show, priority, statuses, profile) |
138 for widget in self.frame.body.body: | |
139 if widget.__class__ == sat_widgets.SelectableText: | |
140 widget.setState(widget.data == self.selected, invisible=True) | |
141 if self.selected in self.alert_jid: | |
142 self.alert_jid.remove(self.selected) | |
143 self.host.modeHint('INSERTION') | |
144 self.update() | 153 self.update() |
145 self._emit('click') | 154 |
146 | 155 def onNickUpdate(self, entity, new_nick, profile): |
147 def __buildContact(self, content, contacts): | 156 self.update() |
148 """Add contact representation in widget list | 157 |
158 # Methods to build the widget | |
159 | |
160 def _buildEntityWidget(self, entity, keys=None, use_bare_jid=False, with_alert=True, with_show_attr=True, markup_prepend=None, markup_append = None): | |
161 """Build one contact markup data | |
162 | |
163 @param entity (jid.JID): entity to build | |
164 @param keys (iterable): value to markup, in preferred order. | |
165 The first available key will be used. | |
166 If key starts with "cache_", it will be checked in cache, | |
167 else, getattr will be done on entity with the key (e.g. getattr(entity, 'node')). | |
168 If nothing full or keys is None, full entity is used. | |
169 @param use_bare_jid (bool): if True, use bare jid for alerts and selected comparisons | |
170 @param with_alert (bool): if True, show alert if entity is in self._alerts | |
171 @param with_show_attr (bool): if True, show color corresponding to presence status | |
172 @param markup_prepend (list): markup to prepend to the generated one before building the widget | |
173 @param markup_append (list): markup to append to the generated one before building the widget | |
174 @return (list): markup data are expected by Urwid text widgets | |
175 """ | |
176 markup = [] | |
177 if use_bare_jid: | |
178 alerts = {entity.bare for entity in self._alerts} | |
179 selected = {entity.bare for entity in self._selected} | |
180 else: | |
181 alerts = self._alerts | |
182 selected = self._selected | |
183 if keys is None: | |
184 entity_txt = entity | |
185 else: | |
186 cache = self.getCache(entity) | |
187 for key in keys: | |
188 if key.startswith('cache_'): | |
189 entity_txt = cache.get(key[6:]) | |
190 else: | |
191 entity_txt = getattr(entity, key) | |
192 if entity_txt: | |
193 break | |
194 if not entity_txt: | |
195 entity_txt = entity | |
196 | |
197 if with_show_attr: | |
198 show = self.getCache(entity, C.PRESENCE_SHOW) | |
199 if show is None: | |
200 show = C.PRESENCE_UNAVAILABLE | |
201 show_icon, entity_attr = C.PRESENCE.get(show, ('', 'default')) | |
202 markup.insert(0, u"{} ".format(show_icon)) | |
203 else: | |
204 entity_attr = 'default' | |
205 | |
206 if with_alert and entity in alerts: | |
207 entity_attr = 'alert' | |
208 header = C.ALERT_HEADER | |
209 else: | |
210 header = '' | |
211 | |
212 markup.append((entity_attr, entity_txt)) | |
213 if markup_prepend: | |
214 markup.insert(0, markup_prepend) | |
215 if markup_append: | |
216 markup.extend(markup_append) | |
217 | |
218 widget = sat_widgets.SelectableText(markup, | |
219 selected = entity in selected, | |
220 header = header) | |
221 widget.data = entity | |
222 widget.comp = entity_txt.lower() # value to use for sorting | |
223 urwid.connect_signal(widget, 'change', self._contactClicked, user_args=[use_bare_jid]) | |
224 return widget | |
225 | |
226 def _buildEntities(self, content, entities): | |
227 """Add entity representation in widget list | |
228 | |
149 @param content: widget list, e.g. SimpleListWalker | 229 @param content: widget list, e.g. SimpleListWalker |
150 @param contacts (list): list of JID userhosts""" | 230 @param entities (iterable): iterable of JID to display |
151 if not contacts: | 231 """ |
232 if not entities: | |
152 return | 233 return |
153 widgets = [] # list of built widgets | 234 widgets = [] # list of built widgets |
154 | 235 |
155 for contact in contacts: | 236 for entity in entities: |
156 if contact.startswith(C.PRIVATE_PREFIX): | 237 if entity in self._specials or not self.entityToShow(entity): |
157 contact_disp = ('alert' if contact in self.alert_jid else "show_normal", unescapePrivate(contact)) | 238 continue |
158 show_icon = '' | 239 markup_extra = [] |
159 status = '' | 240 if self.show_resources: |
241 for resource in self.getCache(entity, C.CONTACT_RESOURCES): | |
242 resource_disp = ('resource_main' if resource == self.getCache(entity, C.CONTACT_MAIN_RESOURCE) else 'resource', "\n " + resource) | |
243 markup_extra.append(resource_disp) | |
244 if self.show_status: | |
245 status = self.getCache(jid.JID('%s/%s' % (entity, resource)), 'status') | |
246 status_disp = ('status', "\n " + status) if status else "" | |
247 markup_extra.append(status_disp) | |
248 | |
249 | |
160 else: | 250 else: |
161 jid = JID(contact) | 251 if self.show_status: |
162 name = self.getCache(jid, 'name') | 252 status = self.getCache(entity, 'status') |
163 nick = self.getCache(jid, 'nick') | 253 status_disp = ('status', "\n " + status) if status else "" |
164 status = self.getCache(jid, 'status') | 254 markup_extra.append(status_disp) |
165 show = self.getCache(jid, 'show') | 255 widget = self._buildEntityWidget(entity, ('cache_nick', 'cache_name', 'node'), use_bare_jid=True, markup_append=markup_extra) |
166 if show is None: | |
167 show = "unavailable" | |
168 if not self.contactToShow(contact): | |
169 continue | |
170 show_icon, show_attr = C.PRESENCE.get(show, ('', 'default')) | |
171 contact_disp = ('alert' if contact in self.alert_jid else show_attr, nick or name or jid.node or jid.bare) | |
172 display = [show_icon + " ", contact_disp] | |
173 if self.show_status: | |
174 status_disp = ('status', "\n " + status) if status else "" | |
175 display.append(status_disp) | |
176 header = '(*) ' if contact in self.alert_jid else '' | |
177 widget = sat_widgets.SelectableText(display, | |
178 selected=contact == self.selected, | |
179 header=header) | |
180 widget.data = contact | |
181 widget.comp = contact_disp[1].lower() # value to use for sorting | |
182 widgets.append(widget) | 256 widgets.append(widget) |
183 | 257 |
184 widgets.sort(key=lambda widget: widget.comp) | 258 widgets.sort(key=lambda widget: widget.comp) |
185 | 259 |
186 for widget in widgets: | 260 for widget in widgets: |
187 content.append(widget) | 261 content.append(widget) |
188 urwid.connect_signal(widget, 'change', self.__contactClicked) | 262 |
189 | 263 def _buildSpecials(self, content): |
190 def __buildSpecials(self, content): | |
191 """Build the special entities""" | 264 """Build the special entities""" |
192 specials = self.specials.keys() | 265 specials = list(self._specials) |
193 specials.sort() | 266 specials.sort() |
194 for special in specials: | 267 extra_shown = set() |
195 jid=JID(special) | 268 for entity in specials: |
196 name = self.getCache(jid, 'name') | 269 # the special widgets |
197 nick = self.getCache(jid, 'nick') | 270 widget = self._buildEntityWidget(entity, ('cache_nick', 'cache_name', 'node'), with_show_attr=False) |
198 special_disp = ('alert' if special in self.alert_jid else 'default', nick or name or jid.node or jid.bare) | |
199 display = [ " " , special_disp] | |
200 header = '(*) ' if special in self.alert_jid else '' | |
201 widget = sat_widgets.SelectableText(display, | |
202 selected = special==self.selected, | |
203 header=header) | |
204 widget.data = special | |
205 content.append(widget) | 271 content.append(widget) |
206 urwid.connect_signal(widget, 'change', self.__contactClicked) | 272 |
207 | 273 # resources which must be displayed (e.g. MUC private conversations) |
208 def __buildList(self): | 274 extras = [extra for extra in self._special_extras if extra.bare == entity.bare] |
275 extras.sort() | |
276 for extra in extras: | |
277 widget = self._buildEntityWidget(extra, ('resource',), markup_prepend = ' ') | |
278 content.append(widget) | |
279 extra_shown.add(extra) | |
280 | |
281 # entities which must be visible but not resource of current special entities | |
282 for extra in self._special_extras.difference(extra_shown): | |
283 widget = self._buildEntityWidget(extra, ('resource',)) | |
284 content.append(widget) | |
285 | |
286 def _buildList(self): | |
209 """Build the main contact list widget""" | 287 """Build the main contact list widget""" |
210 content = urwid.SimpleListWalker([]) | 288 content = urwid.SimpleListWalker([]) |
211 | 289 |
212 self.__buildSpecials(content) | 290 self._buildSpecials(content) |
213 if self.specials: | 291 if self._specials: |
214 content.append(urwid.Divider('=')) | 292 content.append(urwid.Divider('=')) |
215 | 293 |
216 group_keys = self.groups.keys() | 294 groups = list(self._groups) |
217 group_keys.sort(key=lambda x: x.lower() if x else x) | 295 groups.sort(key=lambda x: x.lower() if x else x) |
218 for key in group_keys: | 296 for group in groups: |
219 unfolded = self.groups[key][0] | 297 data = self.getGroupData(group) |
220 contacts = list(self.groups[key][1]) | 298 folded = data.get(C.GROUP_DATA_FOLDED, False) |
221 if key is not None and (self.nonEmptyGroup(contacts) or self.show_empty_groups): | 299 jids = list(data['jids']) |
222 header = '[-]' if unfolded else '[+]' | 300 if group is not None and (self.anyEntityToShow(jids) or self.show_empty_groups): |
223 widget = sat_widgets.ClickableText(key, header=header + ' ') | 301 header = '[-]' if not folded else '[+]' |
302 widget = sat_widgets.ClickableText(group, header=header + ' ') | |
224 content.append(widget) | 303 content.append(widget) |
225 urwid.connect_signal(widget, 'click', self.__groupClicked) | 304 urwid.connect_signal(widget, 'click', self._groupClicked) |
226 if unfolded: | 305 if not folded: |
227 self.__buildContact(content, contacts) | 306 self._buildEntities(content, jids) |
307 not_in_roster = set(self._cache).difference(self._roster).difference(self._specials).difference((self.whoami.bare,)) | |
308 if not_in_roster: | |
309 content.append(urwid.Divider('-')) | |
310 self._buildEntities(content, not_in_roster) | |
311 | |
228 return urwid.ListBox(content) | 312 return urwid.ListBox(content) |
229 | |
230 def contactToShow(self, contact): | |
231 """Tell if the contact should be showed or hidden. | |
232 | |
233 @param contact (str): JID userhost of the contact | |
234 @return: True if that contact should be showed in the list""" | |
235 show = self.getCache(JID(contact), 'show') | |
236 return (show is not None and show != "unavailable") or \ | |
237 self.show_disconnected or contact in self.alert_jid or contact == self.selected | |
238 | |
239 def nonEmptyGroup(self, contacts): | |
240 """Tell if a contact group contains some contacts to show. | |
241 | |
242 @param contacts (list[str]): list of JID userhosts | |
243 @return: bool | |
244 """ | |
245 for contact in contacts: | |
246 if self.contactToShow(contact): | |
247 return True | |
248 return False | |
249 | |
250 def unselectAll(self): | |
251 """Unselect all contacts""" | |
252 self.selected = None | |
253 for widget in self.frame.body.body: | |
254 if widget.__class__ == sat_widgets.SelectableText: | |
255 widget.setState(False, invisible=True) | |
256 | |
257 def getContact(self): | |
258 """Return contact currently selected""" | |
259 return self.selected | |
260 | |
261 def clearContacts(self): | |
262 """clear all the contact list""" | |
263 QuickContactList.clearContacts(self) | |
264 self.groups={} | |
265 self.selected = None | |
266 self.unselectAll() | |
267 self.update() | |
268 | |
269 def replace(self, jid, groups=None, attributes=None): | |
270 """Add a contact to the list if doesn't exist, else update it. | |
271 | |
272 This method can be called with groups=None for the purpose of updating | |
273 the contact's attributes (e.g. nickname). In that case, the groups | |
274 attribute must not be set to the default group but ignored. If not, | |
275 you may move your contact from its actual group(s) to the default one. | |
276 | |
277 None value for 'groups' has a different meaning than [None] which is for the default group. | |
278 | |
279 @param jid (JID) | |
280 @param groups (list): list of groups or None to ignore the groups membership. | |
281 @param attributes (dict) | |
282 """ | |
283 QuickContactList.replace(self, jid, groups, attributes) # eventually change the nickname | |
284 if jid.bare in self.specials: | |
285 return | |
286 if groups is None: | |
287 self.update() | |
288 return | |
289 assert isinstance(jid, JID) | |
290 assert isinstance(groups, list) | |
291 if groups == []: | |
292 groups = [None] # [None] is the default group | |
293 for group in [group for group in self.groups if group not in groups]: | |
294 try: # remove the contact from a previous group | |
295 self.groups[group][1].remove(jid.bare) | |
296 except KeyError: | |
297 pass | |
298 for group in groups: | |
299 if group not in self.groups: | |
300 self.groups[group] = [True, set()] # [unfold, list_of_contacts] | |
301 self.groups[group][1].add(jid.bare) | |
302 self.update() | |
303 | |
304 def remove(self, jid): | |
305 """remove a contact from the list""" | |
306 QuickContactList.remove(self, jid) | |
307 groups_to_remove = [] | |
308 for group in self.groups: | |
309 contacts = self.groups[group][1] | |
310 if jid.bare in contacts: | |
311 contacts.remove(jid.bare) | |
312 if not len(contacts): | |
313 groups_to_remove.append(group) | |
314 for group in groups_to_remove: | |
315 del self.groups[group] | |
316 self.update() | |
317 | |
318 def add(self, jid, param_groups=None): | |
319 """add a contact to the list""" | |
320 self.replace(jid, param_groups if param_groups else [None]) | |
321 | |
322 def setSpecial(self, special_jid, special_type, show=False): | |
323 """Set entity as a special | |
324 @param special_jid: jid of the entity | |
325 @param special_type: special type (e.g.: "MUC") | |
326 @param show: True to display the dialog to chat with this entity | |
327 """ | |
328 QuickContactList.setSpecial(self, special_jid, special_type, show) | |
329 if None in self.groups: | |
330 folded, group_jids = self.groups[None] | |
331 for group_jid in group_jids: | |
332 if JID(group_jid).bare == special_jid.bare: | |
333 group_jids.remove(group_jid) | |
334 break | |
335 self.update() | |
336 if show: | |
337 # also display the dialog for this room | |
338 self.setFocus(special_jid, True) | |
339 self.host.redraw() | |
340 | |
341 def updatePresence(self, jid, show, priority, statuses): | |
342 #XXX: for the moment, we ignore presence updates for special entities | |
343 if jid.bare not in self.specials: | |
344 QuickContactList.updatePresence(self, jid, show, priority, statuses) | |
345 | |
346 def showOfflineContacts(self, show): | |
347 show = C.bool(show) | |
348 if self.show_disconnected == show: | |
349 return | |
350 self.show_disconnected = show | |
351 self.update() | |
352 | |
353 def showEmptyGroups(self, show): | |
354 show = C.bool(show) | |
355 if self.show_empty_groups == show: | |
356 return | |
357 self.show_empty_groups = show | |
358 self.update() |