Mercurial > libervia-backend
comparison sat_frontends/primitivus/contact_list.py @ 2624:56f94936df1e
code style reformatting using black
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Jun 2018 20:14:46 +0200 |
parents | 81b70eeb710f |
children | 003b8b4b56a7 |
comparison
equal
deleted
inserted
replaced
2623:49533de4540b | 2624:56f94936df1e |
---|---|
25 from sat_frontends.primitivus.constants import Const as C | 25 from sat_frontends.primitivus.constants import Const as C |
26 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 | 27 from sat_frontends.primitivus.widget import PrimitivusWidget |
28 from sat_frontends.tools import jid | 28 from sat_frontends.tools import jid |
29 from sat.core import log as logging | 29 from sat.core import log as logging |
30 | |
30 log = logging.getLogger(__name__) | 31 log = logging.getLogger(__name__) |
31 from sat_frontends.quick_frontend import quick_widgets | 32 from sat_frontends.quick_frontend import quick_widgets |
32 | 33 |
33 | 34 |
34 class ContactList(PrimitivusWidget, QuickContactList): | 35 class ContactList(PrimitivusWidget, QuickContactList): |
35 PROFILES_MULTIPLE=False | 36 PROFILES_MULTIPLE = False |
36 PROFILES_ALLOW_NONE=False | 37 PROFILES_ALLOW_NONE = False |
37 signals = ['click','change'] | 38 signals = ["click", "change"] |
38 # FIXME: Only single profile is managed so far | 39 # FIXME: Only single profile is managed so far |
39 | 40 |
40 def __init__(self, host, target, on_click=None, on_change=None, user_data=None, profiles=None): | 41 def __init__( |
42 self, host, target, on_click=None, on_change=None, user_data=None, profiles=None | |
43 ): | |
41 QuickContactList.__init__(self, host, profiles) | 44 QuickContactList.__init__(self, host, profiles) |
42 self.contact_list = self.host.contact_lists[self.profile] | 45 self.contact_list = self.host.contact_lists[self.profile] |
43 | 46 |
44 #we now build the widget | 47 # we now build the widget |
45 self.status_bar = StatusBar(host) | 48 self.status_bar = StatusBar(host) |
46 self.frame = sat_widgets.FocusFrame(self._buildList(), None, self.status_bar) | 49 self.frame = sat_widgets.FocusFrame(self._buildList(), None, self.status_bar) |
47 PrimitivusWidget.__init__(self, self.frame, _(u'Contacts')) | 50 PrimitivusWidget.__init__(self, self.frame, _(u"Contacts")) |
48 if on_click: | 51 if on_click: |
49 urwid.connect_signal(self, 'click', on_click, user_data) | 52 urwid.connect_signal(self, "click", on_click, user_data) |
50 if on_change: | 53 if on_change: |
51 urwid.connect_signal(self, 'change', on_change, user_data) | 54 urwid.connect_signal(self, "change", on_change, user_data) |
52 self.host.addListener('notification', self.onNotification, [self.profile]) | 55 self.host.addListener("notification", self.onNotification, [self.profile]) |
53 self.host.addListener('notificationsClear', self.onNotification, [self.profile]) | 56 self.host.addListener("notificationsClear", self.onNotification, [self.profile]) |
54 self.postInit() | 57 self.postInit() |
55 | 58 |
56 def update(self, entities=None, type_=None, profile=None): | 59 def update(self, entities=None, type_=None, profile=None): |
57 """Update display, keep focus""" | 60 """Update display, keep focus""" |
58 # FIXME: full update is done each time, must handle entities, type_ and profile | 61 # FIXME: full update is done each time, must handle entities, type_ and profile |
62 try: | 65 try: |
63 self.frame.body.focus_position = position | 66 self.frame.body.focus_position = position |
64 except IndexError: | 67 except IndexError: |
65 pass | 68 pass |
66 self._invalidate() | 69 self._invalidate() |
67 self.host.redraw() # FIXME: check if can be avoided | 70 self.host.redraw() # FIXME: check if can be avoided |
68 | 71 |
69 def keypress(self, size, key): | 72 def keypress(self, size, key): |
70 # FIXME: we have a temporary behaviour here: FOCUS_SWITCH change focus globally in the parent, | 73 # FIXME: we have a temporary behaviour here: FOCUS_SWITCH change focus globally in the parent, |
71 # and FOCUS_UP/DOWN is transwmitter to parent if we are respectively on the first or last element | 74 # and FOCUS_UP/DOWN is transwmitter to parent if we are respectively on the first or last element |
72 if key in sat_widgets.FOCUS_KEYS: | 75 if key in sat_widgets.FOCUS_KEYS: |
73 if (key == a_key['FOCUS_SWITCH'] or (key == a_key['FOCUS_UP'] and self.frame.focus_position == 'body') or | 76 if ( |
74 (key == a_key['FOCUS_DOWN'] and self.frame.focus_position == 'footer')): | 77 key == a_key["FOCUS_SWITCH"] |
78 or (key == a_key["FOCUS_UP"] and self.frame.focus_position == "body") | |
79 or (key == a_key["FOCUS_DOWN"] and self.frame.focus_position == "footer") | |
80 ): | |
75 return key | 81 return key |
76 if key == a_key['STATUS_HIDE']: #user wants to (un)hide contacts' statuses | 82 if key == a_key["STATUS_HIDE"]: # user wants to (un)hide contacts' statuses |
77 self.contact_list.show_status = not self.contact_list.show_status | 83 self.contact_list.show_status = not self.contact_list.show_status |
78 self.update() | 84 self.update() |
79 elif key == a_key['DISCONNECTED_HIDE']: #user wants to (un)hide disconnected contacts | 85 elif ( |
80 self.host.bridge.setParam(C.SHOW_OFFLINE_CONTACTS, C.boolConst(not self.contact_list.show_disconnected), "General", profile_key=self.profile) | 86 key == a_key["DISCONNECTED_HIDE"] |
81 elif key == a_key['RESOURCES_HIDE']: #user wants to (un)hide contacts resources | 87 ): # user wants to (un)hide disconnected contacts |
88 self.host.bridge.setParam( | |
89 C.SHOW_OFFLINE_CONTACTS, | |
90 C.boolConst(not self.contact_list.show_disconnected), | |
91 "General", | |
92 profile_key=self.profile, | |
93 ) | |
94 elif key == a_key["RESOURCES_HIDE"]: # user wants to (un)hide contacts resources | |
82 self.contact_list.showResources(not self.contact_list.show_resources) | 95 self.contact_list.showResources(not self.contact_list.show_resources) |
83 self.update() | 96 self.update() |
84 return super(ContactList, self).keypress(size, key) | 97 return super(ContactList, self).keypress(size, key) |
85 | 98 |
86 # QuickWidget methods | 99 # QuickWidget methods |
126 # events | 139 # events |
127 | 140 |
128 def _groupClicked(self, group_wid): | 141 def _groupClicked(self, group_wid): |
129 group = group_wid.getValue() | 142 group = group_wid.getValue() |
130 data = self.contact_list.getGroupData(group) | 143 data = self.contact_list.getGroupData(group) |
131 data[C.GROUP_DATA_FOLDED] = not data.setdefault(C.GROUP_DATA_FOLDED, False) | 144 data[C.GROUP_DATA_FOLDED] = not data.setdefault(C.GROUP_DATA_FOLDED, False) |
132 self.setFocus(group) | 145 self.setFocus(group) |
133 self.update() | 146 self.update() |
134 | 147 |
135 def _contactClicked(self, use_bare_jid, contact_wid, selected): | 148 def _contactClicked(self, use_bare_jid, contact_wid, selected): |
136 """Method called when a contact is clicked | 149 """Method called when a contact is clicked |
139 @param contact_wid: widget of the contact, must have the entity set in data attribute | 152 @param contact_wid: widget of the contact, must have the entity set in data attribute |
140 @param selected: boolean returned by the widget, telling if it is selected | 153 @param selected: boolean returned by the widget, telling if it is selected |
141 """ | 154 """ |
142 entity = contact_wid.data | 155 entity = contact_wid.data |
143 self.host.modeHint(C.MODE_INSERTION) | 156 self.host.modeHint(C.MODE_INSERTION) |
144 self._emit('click', entity) | 157 self._emit("click", entity) |
145 | 158 |
146 def onNotification(self, entity, notif, profile): | 159 def onNotification(self, entity, notif, profile): |
147 notifs = list(self.host.getNotifs(C.ENTITY_ALL, profile=self.profile)) | 160 notifs = list(self.host.getNotifs(C.ENTITY_ALL, profile=self.profile)) |
148 if notifs: | 161 if notifs: |
149 self.title_dynamic = u"({})".format(len(notifs)) | 162 self.title_dynamic = u"({})".format(len(notifs)) |
151 self.title_dynamic = None | 164 self.title_dynamic = None |
152 self.host.redraw() # FIXME: should not be necessary | 165 self.host.redraw() # FIXME: should not be necessary |
153 | 166 |
154 # Methods to build the widget | 167 # Methods to build the widget |
155 | 168 |
156 def _buildEntityWidget(self, entity, keys=None, use_bare_jid=False, with_notifs=True, with_show_attr=True, markup_prepend=None, markup_append=None, special=False): | 169 def _buildEntityWidget( |
170 self, | |
171 entity, | |
172 keys=None, | |
173 use_bare_jid=False, | |
174 with_notifs=True, | |
175 with_show_attr=True, | |
176 markup_prepend=None, | |
177 markup_append=None, | |
178 special=False, | |
179 ): | |
157 """Build one contact markup data | 180 """Build one contact markup data |
158 | 181 |
159 @param entity (jid.JID): entity to build | 182 @param entity (jid.JID): entity to build |
160 @param keys (iterable): value to markup, in preferred order. | 183 @param keys (iterable): value to markup, in preferred order. |
161 The first available key will be used. | 184 The first available key will be used. |
178 if keys is None: | 201 if keys is None: |
179 entity_txt = entity | 202 entity_txt = entity |
180 else: | 203 else: |
181 cache = self.contact_list.getCache(entity) | 204 cache = self.contact_list.getCache(entity) |
182 for key in keys: | 205 for key in keys: |
183 if key.startswith('cache_'): | 206 if key.startswith("cache_"): |
184 entity_txt = cache.get(key[6:]) | 207 entity_txt = cache.get(key[6:]) |
185 else: | 208 else: |
186 entity_txt = getattr(entity, key) | 209 entity_txt = getattr(entity, key) |
187 if entity_txt: | 210 if entity_txt: |
188 break | 211 break |
191 | 214 |
192 if with_show_attr: | 215 if with_show_attr: |
193 show = self.contact_list.getCache(entity, C.PRESENCE_SHOW) | 216 show = self.contact_list.getCache(entity, C.PRESENCE_SHOW) |
194 if show is None: | 217 if show is None: |
195 show = C.PRESENCE_UNAVAILABLE | 218 show = C.PRESENCE_UNAVAILABLE |
196 show_icon, entity_attr = C.PRESENCE.get(show, ('', 'default')) | 219 show_icon, entity_attr = C.PRESENCE.get(show, ("", "default")) |
197 markup.insert(0, u"{} ".format(show_icon)) | 220 markup.insert(0, u"{} ".format(show_icon)) |
198 else: | 221 else: |
199 entity_attr = 'default' | 222 entity_attr = "default" |
200 | 223 |
201 notifs = list(self.host.getNotifs(entity, exact_jid=special, profile=self.profile)) | 224 notifs = list( |
225 self.host.getNotifs(entity, exact_jid=special, profile=self.profile) | |
226 ) | |
202 if notifs: | 227 if notifs: |
203 header = [('cl_notifs', u'({})'.format(len(notifs))), u' '] | 228 header = [("cl_notifs", u"({})".format(len(notifs))), u" "] |
204 if list(self.host.getNotifs(entity.bare, C.NOTIFY_MENTION, profile=self.profile)): | 229 if list( |
205 header = ('cl_mention', header) | 230 self.host.getNotifs(entity.bare, C.NOTIFY_MENTION, profile=self.profile) |
206 else: | 231 ): |
207 header = u'' | 232 header = ("cl_mention", header) |
233 else: | |
234 header = u"" | |
208 | 235 |
209 markup.append((entity_attr, entity_txt)) | 236 markup.append((entity_attr, entity_txt)) |
210 if markup_prepend: | 237 if markup_prepend: |
211 markup.insert(0, markup_prepend) | 238 markup.insert(0, markup_prepend) |
212 if markup_append: | 239 if markup_append: |
213 markup.extend(markup_append) | 240 markup.extend(markup_append) |
214 | 241 |
215 widget = sat_widgets.SelectableText(markup, | 242 widget = sat_widgets.SelectableText( |
216 selected = entity in selected, | 243 markup, selected=entity in selected, header=header |
217 header = header) | 244 ) |
218 widget.data = entity | 245 widget.data = entity |
219 widget.comp = entity_txt.lower() # value to use for sorting | 246 widget.comp = entity_txt.lower() # value to use for sorting |
220 urwid.connect_signal(widget, 'change', self._contactClicked, user_args=[use_bare_jid]) | 247 urwid.connect_signal( |
248 widget, "change", self._contactClicked, user_args=[use_bare_jid] | |
249 ) | |
221 return widget | 250 return widget |
222 | 251 |
223 def _buildEntities(self, content, entities): | 252 def _buildEntities(self, content, entities): |
224 """Add entity representation in widget list | 253 """Add entity representation in widget list |
225 | 254 |
229 if not entities: | 258 if not entities: |
230 return | 259 return |
231 widgets = [] # list of built widgets | 260 widgets = [] # list of built widgets |
232 | 261 |
233 for entity in entities: | 262 for entity in entities: |
234 if entity in self.contact_list._specials or not self.contact_list.entityVisible(entity): | 263 if ( |
264 entity in self.contact_list._specials | |
265 or not self.contact_list.entityVisible(entity) | |
266 ): | |
235 continue | 267 continue |
236 markup_extra = [] | 268 markup_extra = [] |
237 if self.contact_list.show_resources: | 269 if self.contact_list.show_resources: |
238 for resource in self.contact_list.getCache(entity, C.CONTACT_RESOURCES): | 270 for resource in self.contact_list.getCache(entity, C.CONTACT_RESOURCES): |
239 resource_disp = ('resource_main' if resource == self.contact_list.getCache(entity, C.CONTACT_MAIN_RESOURCE) else 'resource', "\n " + resource) | 271 resource_disp = ( |
272 "resource_main" | |
273 if resource | |
274 == self.contact_list.getCache(entity, C.CONTACT_MAIN_RESOURCE) | |
275 else "resource", | |
276 "\n " + resource, | |
277 ) | |
240 markup_extra.append(resource_disp) | 278 markup_extra.append(resource_disp) |
241 if self.contact_list.show_status: | 279 if self.contact_list.show_status: |
242 status = self.contact_list.getCache(jid.JID('%s/%s' % (entity, resource)), 'status') | 280 status = self.contact_list.getCache( |
243 status_disp = ('status', "\n " + status) if status else "" | 281 jid.JID("%s/%s" % (entity, resource)), "status" |
282 ) | |
283 status_disp = ("status", "\n " + status) if status else "" | |
244 markup_extra.append(status_disp) | 284 markup_extra.append(status_disp) |
245 | |
246 | 285 |
247 else: | 286 else: |
248 if self.contact_list.show_status: | 287 if self.contact_list.show_status: |
249 status = self.contact_list.getCache(entity, 'status') | 288 status = self.contact_list.getCache(entity, "status") |
250 status_disp = ('status', "\n " + status) if status else "" | 289 status_disp = ("status", "\n " + status) if status else "" |
251 markup_extra.append(status_disp) | 290 markup_extra.append(status_disp) |
252 widget = self._buildEntityWidget(entity, ('cache_nick', 'cache_name', 'node'), use_bare_jid=True, markup_append=markup_extra) | 291 widget = self._buildEntityWidget( |
292 entity, | |
293 ("cache_nick", "cache_name", "node"), | |
294 use_bare_jid=True, | |
295 markup_append=markup_extra, | |
296 ) | |
253 widgets.append(widget) | 297 widgets.append(widget) |
254 | 298 |
255 widgets.sort(key=lambda widget: widget.comp) | 299 widgets.sort(key=lambda widget: widget.comp) |
256 | 300 |
257 for widget in widgets: | 301 for widget in widgets: |
262 specials = sorted(self.contact_list.getSpecials()) | 306 specials = sorted(self.contact_list.getSpecials()) |
263 current = None | 307 current = None |
264 for entity in specials: | 308 for entity in specials: |
265 if current is not None and current.bare == entity.bare: | 309 if current is not None and current.bare == entity.bare: |
266 # nested entity (e.g. MUC private conversations) | 310 # nested entity (e.g. MUC private conversations) |
267 widget = self._buildEntityWidget(entity, ('resource',), markup_prepend=' ', special=True) | 311 widget = self._buildEntityWidget( |
312 entity, ("resource",), markup_prepend=" ", special=True | |
313 ) | |
268 else: | 314 else: |
269 # the special widgets | 315 # the special widgets |
270 if entity.resource: | 316 if entity.resource: |
271 widget = self._buildEntityWidget(entity, ('resource',), special=True) | 317 widget = self._buildEntityWidget(entity, ("resource",), special=True) |
272 else: | 318 else: |
273 widget = self._buildEntityWidget(entity, ('cache_nick', 'cache_name', 'node'), with_show_attr=False, special=True) | 319 widget = self._buildEntityWidget( |
320 entity, | |
321 ("cache_nick", "cache_name", "node"), | |
322 with_show_attr=False, | |
323 special=True, | |
324 ) | |
274 content.append(widget) | 325 content.append(widget) |
275 | 326 |
276 def _buildList(self): | 327 def _buildList(self): |
277 """Build the main contact list widget""" | 328 """Build the main contact list widget""" |
278 content = urwid.SimpleListWalker([]) | 329 content = urwid.SimpleListWalker([]) |
279 | 330 |
280 self._buildSpecials(content) | 331 self._buildSpecials(content) |
281 if self.contact_list._specials: | 332 if self.contact_list._specials: |
282 content.append(urwid.Divider('=')) | 333 content.append(urwid.Divider("=")) |
283 | 334 |
284 groups = list(self.contact_list._groups) | 335 groups = list(self.contact_list._groups) |
285 groups.sort(key=lambda x: x.lower() if x else x) | 336 groups.sort(key=lambda x: x.lower() if x else x) |
286 for group in groups: | 337 for group in groups: |
287 data = self.contact_list.getGroupData(group) | 338 data = self.contact_list.getGroupData(group) |
288 folded = data.get(C.GROUP_DATA_FOLDED, False) | 339 folded = data.get(C.GROUP_DATA_FOLDED, False) |
289 jids = list(data['jids']) | 340 jids = list(data["jids"]) |
290 if group is not None and (self.contact_list.anyEntityVisible(jids) or self.contact_list.show_empty_groups): | 341 if group is not None and ( |
291 header = '[-]' if not folded else '[+]' | 342 self.contact_list.anyEntityVisible(jids) |
292 widget = sat_widgets.ClickableText(group, header=header + ' ') | 343 or self.contact_list.show_empty_groups |
344 ): | |
345 header = "[-]" if not folded else "[+]" | |
346 widget = sat_widgets.ClickableText(group, header=header + " ") | |
293 content.append(widget) | 347 content.append(widget) |
294 urwid.connect_signal(widget, 'click', self._groupClicked) | 348 urwid.connect_signal(widget, "click", self._groupClicked) |
295 if not folded: | 349 if not folded: |
296 self._buildEntities(content, jids) | 350 self._buildEntities(content, jids) |
297 not_in_roster = set(self.contact_list._cache).difference(self.contact_list._roster).difference(self.contact_list._specials).difference((self.contact_list.whoami.bare,)) | 351 not_in_roster = ( |
352 set(self.contact_list._cache) | |
353 .difference(self.contact_list._roster) | |
354 .difference(self.contact_list._specials) | |
355 .difference((self.contact_list.whoami.bare,)) | |
356 ) | |
298 if not_in_roster: | 357 if not_in_roster: |
299 content.append(urwid.Divider('-')) | 358 content.append(urwid.Divider("-")) |
300 self._buildEntities(content, not_in_roster) | 359 self._buildEntities(content, not_in_roster) |
301 | 360 |
302 return urwid.ListBox(content) | 361 return urwid.ListBox(content) |
303 | 362 |
363 | |
304 quick_widgets.register(QuickContactList, ContactList) | 364 quick_widgets.register(QuickContactList, ContactList) |