comparison sat_frontends/primitivus/chat.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 26edcf3a30eb
children df2bc2e704bc
comparison
equal deleted inserted replaced
2623:49533de4540b 2624:56f94936df1e
17 # You should have received a copy of the GNU Affero General Public License 17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 from sat.core.i18n import _ 20 from sat.core.i18n import _
21 from sat.core import log as logging 21 from sat.core import log as logging
22
22 log = logging.getLogger(__name__) 23 log = logging.getLogger(__name__)
23 import urwid 24 import urwid
24 from urwid_satext import sat_widgets 25 from urwid_satext import sat_widgets
25 from sat_frontends.quick_frontend import quick_widgets 26 from sat_frontends.quick_frontend import quick_widgets
26 from sat_frontends.quick_frontend import quick_chat 27 from sat_frontends.quick_frontend import quick_chat
34 import bisect 35 import bisect
35 36
36 37
37 OCCUPANTS_FOOTER = _(u"{} occupants") 38 OCCUPANTS_FOOTER = _(u"{} occupants")
38 39
40
39 class MessageWidget(urwid.WidgetWrap): 41 class MessageWidget(urwid.WidgetWrap):
40
41 def __init__(self, mess_data): 42 def __init__(self, mess_data):
42 """ 43 """
43 @param mess_data(quick_chat.Message, None): message data 44 @param mess_data(quick_chat.Message, None): message data
44 None: used only for non text widgets (e.g.: focus separator) 45 None: used only for non text widgets (e.g.: focus separator)
45 """ 46 """
47 mess_data.widgets.add(self) 48 mess_data.widgets.add(self)
48 super(MessageWidget, self).__init__(urwid.Text(self.markup)) 49 super(MessageWidget, self).__init__(urwid.Text(self.markup))
49 50
50 @property 51 @property
51 def markup(self): 52 def markup(self):
52 return self._generateInfoMarkup() if self.mess_data.type == C.MESS_TYPE_INFO else self._generateMarkup() 53 return (
54 self._generateInfoMarkup()
55 if self.mess_data.type == C.MESS_TYPE_INFO
56 else self._generateMarkup()
57 )
53 58
54 @property 59 @property
55 def info_type(self): 60 def info_type(self):
56 return self.mess_data.info_type 61 return self.mess_data.info_type
57 62
64 """Return currently displayed message""" 69 """Return currently displayed message"""
65 return self.mess_data.main_message 70 return self.mess_data.main_message
66 71
67 @message.setter 72 @message.setter
68 def message(self, value): 73 def message(self, value):
69 self.mess_data.message = {'':value} 74 self.mess_data.message = {"": value}
70 self.redraw() 75 self.redraw()
71 76
72 @property 77 @property
73 def type(self): 78 def type(self):
74 try: 79 try:
96 if focus: 101 if focus:
97 canvas.set_cursor(self.get_cursor_coords(size)) 102 canvas.set_cursor(self.get_cursor_coords(size))
98 return canvas 103 return canvas
99 104
100 def _generateInfoMarkup(self): 105 def _generateInfoMarkup(self):
101 return ('info_msg', self.message) 106 return ("info_msg", self.message)
102 107
103 def _generateMarkup(self): 108 def _generateMarkup(self):
104 """Generate text markup according to message data and Widget options""" 109 """Generate text markup according to message data and Widget options"""
105 markup = [] 110 markup = []
106 d = self.mess_data 111 d = self.mess_data
107 mention = d.mention 112 mention = d.mention
108 113
109 # message status 114 # message status
110 if d.status is None: 115 if d.status is None:
111 markup.append(u' ') 116 markup.append(u" ")
112 elif d.status == "delivered": 117 elif d.status == "delivered":
113 markup.append(('msg_status_received', u'✔')) 118 markup.append(("msg_status_received", u"✔"))
114 else: 119 else:
115 log.warning(u"Unknown status: {}".format(d.status)) 120 log.warning(u"Unknown status: {}".format(d.status))
116 121
117 # timestamp 122 # timestamp
118 if self.parent.show_timestamp: 123 if self.parent.show_timestamp:
119 attr = 'msg_mention' if mention else 'date' 124 attr = "msg_mention" if mention else "date"
120 markup.append((attr, u"[{}]".format(d.time_text))) 125 markup.append((attr, u"[{}]".format(d.time_text)))
121 else: 126 else:
122 if mention: 127 if mention:
123 markup.append(('msg_mention', '[*]')) 128 markup.append(("msg_mention", "[*]"))
124 129
125 # nickname 130 # nickname
126 if self.parent.show_short_nick: 131 if self.parent.show_short_nick:
127 markup.append(('my_nick' if d.own_mess else 'other_nick', "**" if d.own_mess else "*")) 132 markup.append(
133 ("my_nick" if d.own_mess else "other_nick", "**" if d.own_mess else "*")
134 )
128 else: 135 else:
129 markup.append(('my_nick' if d.own_mess else 'other_nick', u"[{}] ".format(d.nick or ''))) 136 markup.append(
137 ("my_nick" if d.own_mess else "other_nick", u"[{}] ".format(d.nick or ""))
138 )
130 139
131 msg = self.message # needed to generate self.selected_lang 140 msg = self.message # needed to generate self.selected_lang
132 141
133 if d.selected_lang: 142 if d.selected_lang:
134 markup.append(("msg_lang", u"[{}] ".format(d.selected_lang))) 143 markup.append(("msg_lang", u"[{}] ".format(d.selected_lang)))
144 153
145 @param update_dict(dict, None): key=attribute updated value=new_value 154 @param update_dict(dict, None): key=attribute updated value=new_value
146 """ 155 """
147 self.redraw() 156 self.redraw()
148 157
158
149 @total_ordering 159 @total_ordering
150 class OccupantWidget(urwid.WidgetWrap): 160 class OccupantWidget(urwid.WidgetWrap):
151
152 def __init__(self, occupant_data): 161 def __init__(self, occupant_data):
153 self.occupant_data = occupant_data 162 self.occupant_data = occupant_data
154 occupant_data.widgets.add(self) 163 occupant_data.widgets.add(self)
155 markup = self._generateMarkup() 164 markup = self._generateMarkup()
156 text = sat_widgets.ClickableText(markup) 165 text = sat_widgets.ClickableText(markup)
157 urwid.connect_signal(text, 166 urwid.connect_signal(
158 'click', 167 text,
168 "click",
159 self.occupant_data.parent._occupantsClicked, 169 self.occupant_data.parent._occupantsClicked,
160 user_args=[self.occupant_data]) 170 user_args=[self.occupant_data],
171 )
161 super(OccupantWidget, self).__init__(text) 172 super(OccupantWidget, self).__init__(text)
162 173
163 def __eq__(self, other): 174 def __eq__(self, other):
164 if other is None: 175 if other is None:
165 return False 176 return False
204 def _generateMarkup(self): 215 def _generateMarkup(self):
205 # TODO: role and affiliation are shown in a Q&D way 216 # TODO: role and affiliation are shown in a Q&D way
206 # should be more intuitive and themable 217 # should be more intuitive and themable
207 o = self.occupant_data 218 o = self.occupant_data
208 markup = [] 219 markup = []
209 markup.append(('info_msg', u'{}{} '.format( 220 markup.append(
210 o.role[0].upper(), 221 ("info_msg", u"{}{} ".format(o.role[0].upper(), o.affiliation[0].upper()))
211 o.affiliation[0].upper(), 222 )
212 )))
213 markup.append(o.nick) 223 markup.append(o.nick)
214 if o.state is not None: 224 if o.state is not None:
215 markup.append(u' {}'.format(C.CHAT_STATE_ICON[o.state])) 225 markup.append(u" {}".format(C.CHAT_STATE_ICON[o.state]))
216 return markup 226 return markup
217 227
218 # events 228 # events
219 def update(self, update_dict=None): 229 def update(self, update_dict=None):
220 self.redraw() 230 self.redraw()
221 231
222 232
223 class OccupantsWidget(urwid.WidgetWrap): 233 class OccupantsWidget(urwid.WidgetWrap):
224
225 def __init__(self, parent): 234 def __init__(self, parent):
226 self.parent = parent 235 self.parent = parent
227 self.occupants_walker = urwid.SimpleListWalker([]) 236 self.occupants_walker = urwid.SimpleListWalker([])
228 self.occupants_footer = urwid.Text('', align='center') 237 self.occupants_footer = urwid.Text("", align="center")
229 self.updateFooter() 238 self.updateFooter()
230 occupants_widget = urwid.Frame(urwid.ListBox(self.occupants_walker), footer=self.occupants_footer) 239 occupants_widget = urwid.Frame(
240 urwid.ListBox(self.occupants_walker), footer=self.occupants_footer
241 )
231 super(OccupantsWidget, self).__init__(occupants_widget) 242 super(OccupantsWidget, self).__init__(occupants_widget)
232 occupants_list = sorted(self.parent.occupants.keys(), key=lambda o:o.lower()) 243 occupants_list = sorted(self.parent.occupants.keys(), key=lambda o: o.lower())
233 for occupant in occupants_list: 244 for occupant in occupants_list:
234 occupant_data = self.parent.occupants[occupant] 245 occupant_data = self.parent.occupants[occupant]
235 self.occupants_walker.append(OccupantWidget(occupant_data)) 246 self.occupants_walker.append(OccupantWidget(occupant_data))
236 247
237 def updateFooter(self): 248 def updateFooter(self):
238 """update footer widget""" 249 """update footer widget"""
239 txt = OCCUPANTS_FOOTER.format(len(self.parent.occupants)) 250 txt = OCCUPANTS_FOOTER.format(len(self.parent.occupants))
240 self.occupants_footer.set_text(txt) 251 self.occupants_footer.set_text(txt)
241 252
242 def getNicks(self, start=u''): 253 def getNicks(self, start=u""):
243 """Return nicks of all occupants 254 """Return nicks of all occupants
244 255
245 @param start(unicode): only return nicknames which start with this text 256 @param start(unicode): only return nicknames which start with this text
246 """ 257 """
247 return [w.nick for w in self.occupants_walker if isinstance(w, OccupantWidget) and w.nick.startswith(start)] 258 return [
259 w.nick
260 for w in self.occupants_walker
261 if isinstance(w, OccupantWidget) and w.nick.startswith(start)
262 ]
248 263
249 def addUser(self, occupant_data): 264 def addUser(self, occupant_data):
250 """add a user to the list""" 265 """add a user to the list"""
251 bisect.insort(self.occupants_walker, OccupantWidget(occupant_data)) 266 bisect.insort(self.occupants_walker, OccupantWidget(occupant_data))
252 self.updateFooter() 267 self.updateFooter()
259 self.updateFooter() 274 self.updateFooter()
260 self.parent.host.redraw() # FIXME: should not be necessary 275 self.parent.host.redraw() # FIXME: should not be necessary
261 276
262 277
263 class Chat(PrimitivusWidget, quick_chat.QuickChat): 278 class Chat(PrimitivusWidget, quick_chat.QuickChat):
264 279 def __init__(
265 def __init__(self, host, target, type_=C.CHAT_ONE2ONE, nick=None, occupants=None, subject=None, profiles=None): 280 self,
266 quick_chat.QuickChat.__init__(self, host, target, type_, nick, occupants, subject, profiles=profiles) 281 host,
282 target,
283 type_=C.CHAT_ONE2ONE,
284 nick=None,
285 occupants=None,
286 subject=None,
287 profiles=None,
288 ):
289 quick_chat.QuickChat.__init__(
290 self, host, target, type_, nick, occupants, subject, profiles=profiles
291 )
267 self.filters = [] # list of filter callbacks to apply 292 self.filters = [] # list of filter callbacks to apply
268 self.mess_walker = urwid.SimpleListWalker([]) 293 self.mess_walker = urwid.SimpleListWalker([])
269 self.mess_widgets = urwid.ListBox(self.mess_walker) 294 self.mess_widgets = urwid.ListBox(self.mess_walker)
270 self.chat_widget = urwid.Frame(self.mess_widgets) 295 self.chat_widget = urwid.Frame(self.mess_widgets)
271 self.chat_colums = urwid.Columns([('weight', 8, self.chat_widget)]) 296 self.chat_colums = urwid.Columns([("weight", 8, self.chat_widget)])
272 self.pile = urwid.Pile([self.chat_colums]) 297 self.pile = urwid.Pile([self.chat_colums])
273 PrimitivusWidget.__init__(self, self.pile, self.target) 298 PrimitivusWidget.__init__(self, self.pile, self.target)
274 299
275 # we must adapt the behaviour with the type 300 # we must adapt the behaviour with the type
276 if type_ == C.CHAT_GROUP: 301 if type_ == C.CHAT_GROUP:
277 if len(self.chat_colums.contents) == 1: 302 if len(self.chat_colums.contents) == 1:
278 self.occupants_widget = OccupantsWidget(self) 303 self.occupants_widget = OccupantsWidget(self)
279 self.occupants_panel = sat_widgets.VerticalSeparator(self.occupants_widget) 304 self.occupants_panel = sat_widgets.VerticalSeparator(
305 self.occupants_widget
306 )
280 self._appendOccupantsPanel() 307 self._appendOccupantsPanel()
281 self.host.addListener('presence', self.presenceListener, [profiles]) 308 self.host.addListener("presence", self.presenceListener, [profiles])
282 309
283 # focus marker is a separator indicated last visible message before focus was lost 310 # focus marker is a separator indicated last visible message before focus was lost
284 self.focus_marker = None # link to current marker 311 self.focus_marker = None # link to current marker
285 self.focus_marker_set = None # True if a new marker has been inserted 312 self.focus_marker_set = None # True if a new marker has been inserted
286 self.show_timestamp = True 313 self.show_timestamp = True
287 self.show_short_nick = False 314 self.show_short_nick = False
288 self.show_title = 1 # 0: clip title; 1: full title; 2: no title 315 self.show_title = 1 # 0: clip title; 1: full title; 2: no title
289 self.postInit() 316 self.postInit()
290 317
291 def keypress(self, size, key): 318 def keypress(self, size, key):
292 if key == a_key['OCCUPANTS_HIDE']: # user wants to (un)hide the occupants panel 319 if key == a_key["OCCUPANTS_HIDE"]: # user wants to (un)hide the occupants panel
293 if self.type == C.CHAT_GROUP: 320 if self.type == C.CHAT_GROUP:
294 widgets = [widget for (widget, options) in self.chat_colums.contents] 321 widgets = [widget for (widget, options) in self.chat_colums.contents]
295 if self.occupants_panel in widgets: 322 if self.occupants_panel in widgets:
296 self._removeOccupantsPanel() 323 self._removeOccupantsPanel()
297 else: 324 else:
298 self._appendOccupantsPanel() 325 self._appendOccupantsPanel()
299 elif key == a_key['TIMESTAMP_HIDE']: # user wants to (un)hide timestamp 326 elif key == a_key["TIMESTAMP_HIDE"]: # user wants to (un)hide timestamp
300 self.show_timestamp = not self.show_timestamp 327 self.show_timestamp = not self.show_timestamp
301 self.redraw() 328 self.redraw()
302 elif key == a_key['SHORT_NICKNAME']: # user wants to (not) use short nick 329 elif key == a_key["SHORT_NICKNAME"]: # user wants to (not) use short nick
303 self.show_short_nick = not self.show_short_nick 330 self.show_short_nick = not self.show_short_nick
304 self.redraw() 331 self.redraw()
305 elif key == a_key['SUBJECT_SWITCH']: # user wants to (un)hide group's subject or change its apperance 332 elif (
333 key == a_key["SUBJECT_SWITCH"]
334 ): # user wants to (un)hide group's subject or change its apperance
306 if self.subject: 335 if self.subject:
307 self.show_title = (self.show_title + 1) % 3 336 self.show_title = (self.show_title + 1) % 3
308 if self.show_title == 0: 337 if self.show_title == 0:
309 self.setSubject(self.subject, 'clip') 338 self.setSubject(self.subject, "clip")
310 elif self.show_title == 1: 339 elif self.show_title == 1:
311 self.setSubject(self.subject, 'space') 340 self.setSubject(self.subject, "space")
312 elif self.show_title == 2: 341 elif self.show_title == 2:
313 self.chat_widget.header = None 342 self.chat_widget.header = None
314 self._invalidate() 343 self._invalidate()
315 elif key == a_key['GOTO_BOTTOM']: # user wants to focus last message 344 elif key == a_key["GOTO_BOTTOM"]: # user wants to focus last message
316 self.mess_widgets.focus_position = len(self.mess_walker) - 1 345 self.mess_widgets.focus_position = len(self.mess_walker) - 1
317 346
318 return super(Chat, self).keypress(size, key) 347 return super(Chat, self).keypress(size, key)
319 348
320 def completion(self, text, completion_data): 349 def completion(self, text, completion_data):
324 """ 353 """
325 if self.type != C.CHAT_GROUP: 354 if self.type != C.CHAT_GROUP:
326 return text 355 return text
327 356
328 space = text.rfind(" ") 357 space = text.rfind(" ")
329 start = text[space + 1:] 358 start = text[space + 1 :]
330 words = self.occupants_widget.getNicks(start) 359 words = self.occupants_widget.getNicks(start)
331 if not words: 360 if not words:
332 return text 361 return text
333 try: 362 try:
334 word_idx = words.index(completion_data['last_word']) + 1 363 word_idx = words.index(completion_data["last_word"]) + 1
335 except (KeyError, ValueError): 364 except (KeyError, ValueError):
336 word_idx = 0 365 word_idx = 0
337 else: 366 else:
338 if word_idx == len(words): 367 if word_idx == len(words):
339 word_idx = 0 368 word_idx = 0
340 word = completion_data['last_word'] = words[word_idx] 369 word = completion_data["last_word"] = words[word_idx]
341 return u"{}{}{}".format(text[:space + 1], word, ': ' if space < 0 else '') 370 return u"{}{}{}".format(text[: space + 1], word, ": " if space < 0 else "")
342 371
343 def getMenu(self): 372 def getMenu(self):
344 """Return Menu bar""" 373 """Return Menu bar"""
345 menu = sat_widgets.Menu(self.host.loop) 374 menu = sat_widgets.Menu(self.host.loop)
346 if self.type == C.CHAT_GROUP: 375 if self.type == C.CHAT_GROUP:
347 self.host.addMenus(menu, C.MENU_ROOM, {'room_jid': self.target.bare}) 376 self.host.addMenus(menu, C.MENU_ROOM, {"room_jid": self.target.bare})
348 game = _("Game") 377 game = _("Game")
349 menu.addMenu(game, "Tarot", self.onTarotRequest) 378 menu.addMenu(game, "Tarot", self.onTarotRequest)
350 elif self.type == C.CHAT_ONE2ONE: 379 elif self.type == C.CHAT_ONE2ONE:
351 # FIXME: self.target is a bare jid, we need to check that 380 # FIXME: self.target is a bare jid, we need to check that
352 contact_list = self.host.contact_lists[self.profile] 381 contact_list = self.host.contact_lists[self.profile]
353 if not self.target.resource: 382 if not self.target.resource:
354 full_jid = contact_list.getFullJid(self.target) 383 full_jid = contact_list.getFullJid(self.target)
355 else: 384 else:
356 full_jid = self.target 385 full_jid = self.target
357 self.host.addMenus(menu, C.MENU_SINGLE, {'jid': full_jid}) 386 self.host.addMenus(menu, C.MENU_SINGLE, {"jid": full_jid})
358 return menu 387 return menu
359 388
360 def setFilter(self, args): 389 def setFilter(self, args):
361 """set filtering of messages 390 """set filtering of messages
362 391
397 @param message(quick_chat.Message): message to add 426 @param message(quick_chat.Message): message to add
398 """ 427 """
399 if message.type != C.MESS_TYPE_INFO: 428 if message.type != C.MESS_TYPE_INFO:
400 return False 429 return False
401 try: 430 try:
402 info_type = message.extra['info_type'] 431 info_type = message.extra["info_type"]
403 except KeyError: 432 except KeyError:
404 return False 433 return False
405 else: 434 else:
406 return info_type in quick_chat.ROOM_USER_MOVED 435 return info_type in quick_chat.ROOM_USER_MOVED
407 436
427 # we merge in/out messages if no message was sent meanwhile 456 # we merge in/out messages if no message was sent meanwhile
428 if not isinstance(wid, MessageWidget): 457 if not isinstance(wid, MessageWidget):
429 continue 458 continue
430 if wid.mess_data.type != C.MESS_TYPE_INFO: 459 if wid.mess_data.type != C.MESS_TYPE_INFO:
431 break 460 break
432 if wid.info_type in quick_chat.ROOM_USER_MOVED and wid.mess_data.nick == message.nick: 461 if (
462 wid.info_type in quick_chat.ROOM_USER_MOVED
463 and wid.mess_data.nick == message.nick
464 ):
433 try: 465 try:
434 count = wid.reentered_count 466 count = wid.reentered_count
435 except AttributeError: 467 except AttributeError:
436 count = wid.reentered_count = 1 468 count = wid.reentered_count = 1
437 nick = wid.mess_data.nick 469 nick = wid.mess_data.nick
438 if message.info_type == quick_chat.ROOM_USER_LEFT: 470 if message.info_type == quick_chat.ROOM_USER_LEFT:
439 wid.message = _(u"<= {nick} has left the room ({count})").format(nick=nick, count=count) 471 wid.message = _(u"<= {nick} has left the room ({count})").format(
472 nick=nick, count=count
473 )
440 else: 474 else:
441 wid.message = _(u"<=> {nick} re-entered the room ({count})") .format(nick=nick, count=count) 475 wid.message = _(
442 wid.reentered_count+=1 476 u"<=> {nick} re-entered the room ({count})"
477 ).format(nick=nick, count=count)
478 wid.reentered_count += 1
443 return 479 return
444 480
445 if ((self.host.selected_widget != self or not self.host.x_notify.hasFocus()) 481 if (
446 and self.focus_marker_set is not None): 482 self.host.selected_widget != self or not self.host.x_notify.hasFocus()
483 ) and self.focus_marker_set is not None:
447 if not self.focus_marker_set and not self._locked and self.mess_walker: 484 if not self.focus_marker_set and not self._locked and self.mess_walker:
448 if self.focus_marker is not None: 485 if self.focus_marker is not None:
449 self.mess_walker.remove(self.focus_marker) 486 self.mess_walker.remove(self.focus_marker)
450 self.focus_marker = urwid.Divider('—') 487 self.focus_marker = urwid.Divider("—")
451 self.mess_walker.append(self.focus_marker) 488 self.mess_walker.append(self.focus_marker)
452 self.focus_marker_set = True 489 self.focus_marker_set = True
453 self._scrollDown() 490 self._scrollDown()
454 else: 491 else:
455 if self.focus_marker_set: 492 if self.focus_marker_set:
471 # because that's history messages 508 # because that's history messages
472 return 509 return
473 510
474 if wid.mess_data.mention: 511 if wid.mess_data.mention:
475 from_jid = wid.mess_data.from_jid 512 from_jid = wid.mess_data.from_jid
476 msg = _(u'You have been mentioned by {nick} in {room}'.format( 513 msg = _(
477 nick=wid.mess_data.nick, 514 u"You have been mentioned by {nick} in {room}".format(
478 room=self.target, 515 nick=wid.mess_data.nick, room=self.target
479 )) 516 )
480 self.host.notify(C.NOTIFY_MENTION, from_jid, msg, widget=self, profile=self.profile) 517 )
518 self.host.notify(
519 C.NOTIFY_MENTION, from_jid, msg, widget=self, profile=self.profile
520 )
481 elif self.type == C.CHAT_ONE2ONE: 521 elif self.type == C.CHAT_ONE2ONE:
482 from_jid = wid.mess_data.from_jid 522 from_jid = wid.mess_data.from_jid
483 msg = _(u'{entity} is talking to you'.format( 523 msg = _(u"{entity} is talking to you".format(entity=from_jid))
484 entity=from_jid, 524 self.host.notify(
485 )) 525 C.NOTIFY_MESSAGE, from_jid, msg, widget=self, profile=self.profile
486 self.host.notify(C.NOTIFY_MESSAGE, from_jid, msg, widget=self, profile=self.profile) 526 )
487 else: 527 else:
488 self.host.notify(C.NOTIFY_MESSAGE, self.target, widget=self, profile=self.profile) 528 self.host.notify(
489 529 C.NOTIFY_MESSAGE, self.target, widget=self, profile=self.profile
530 )
490 531
491 def addUser(self, nick): 532 def addUser(self, nick):
492 occupant = super(Chat, self).addUser(nick) 533 occupant = super(Chat, self).addUser(nick)
493 self.occupants_widget.addUser(occupant) 534 self.occupants_widget.addUser(occupant)
494 535
503 544
504 # we have a click on a nick, we need to create the widget if it doesn't exists 545 # we have a click on a nick, we need to create the widget if it doesn't exists
505 self.getOrCreatePrivateWidget(occupant.jid) 546 self.getOrCreatePrivateWidget(occupant.jid)
506 547
507 # now we select the new window 548 # now we select the new window
508 for contact_list in self.host.widgets.getWidgets(ContactList, profiles=(self.profile,)): 549 for contact_list in self.host.widgets.getWidgets(
550 ContactList, profiles=(self.profile,)
551 ):
509 contact_list.setFocus(occupant.jid, True) 552 contact_list.setFocus(occupant.jid, True)
510 553
511 def _appendOccupantsPanel(self): 554 def _appendOccupantsPanel(self):
512 self.chat_colums.contents.append((self.occupants_panel, ('weight', 2, False))) 555 self.chat_colums.contents.append((self.occupants_panel, ("weight", 2, False)))
513 556
514 def _removeOccupantsPanel(self): 557 def _removeOccupantsPanel(self):
515 for widget, options in self.chat_colums.contents: 558 for widget, options in self.chat_colums.contents:
516 if widget is self.occupants_panel: 559 if widget is self.occupants_panel:
517 self.chat_colums.contents.remove((widget, options)) 560 self.chat_colums.contents.remove((widget, options))
520 def addGamePanel(self, widget): 563 def addGamePanel(self, widget):
521 """Insert a game panel to this Chat dialog. 564 """Insert a game panel to this Chat dialog.
522 565
523 @param widget (Widget): the game panel 566 @param widget (Widget): the game panel
524 """ 567 """
525 assert (len(self.pile.contents) == 1) 568 assert len(self.pile.contents) == 1
526 self.pile.contents.insert(0, (widget, ('weight', 1))) 569 self.pile.contents.insert(0, (widget, ("weight", 1)))
527 self.pile.contents.insert(1, (urwid.Filler(urwid.Divider('-'), ('fixed', 1)))) 570 self.pile.contents.insert(1, (urwid.Filler(urwid.Divider("-"), ("fixed", 1))))
528 self.host.redraw() 571 self.host.redraw()
529 572
530 def removeGamePanel(self, widget): 573 def removeGamePanel(self, widget):
531 """Remove the game panel from this Chat dialog. 574 """Remove the game panel from this Chat dialog.
532 575
533 @param widget (Widget): the game panel 576 @param widget (Widget): the game panel
534 """ 577 """
535 assert (len(self.pile.contents) == 3) 578 assert len(self.pile.contents) == 3
536 del self.pile.contents[0] 579 del self.pile.contents[0]
537 self.host.redraw() 580 self.host.redraw()
538 581
539 def setSubject(self, subject, wrap='space'): 582 def setSubject(self, subject, wrap="space"):
540 """Set title for a group chat""" 583 """Set title for a group chat"""
541 quick_chat.QuickChat.setSubject(self, subject) 584 quick_chat.QuickChat.setSubject(self, subject)
542 self.subj_wid = urwid.Text(unicode(subject.replace('\n', '|') if wrap == 'clip' else subject), 585 self.subj_wid = urwid.Text(
543 align='left' if wrap == 'clip' else 'center', wrap=wrap) 586 unicode(subject.replace("\n", "|") if wrap == "clip" else subject),
544 self.chat_widget.header = urwid.AttrMap(self.subj_wid, 'title') 587 align="left" if wrap == "clip" else "center",
588 wrap=wrap,
589 )
590 self.chat_widget.header = urwid.AttrMap(self.subj_wid, "title")
545 self.host.redraw() 591 self.host.redraw()
546 592
547 ## Messages 593 ## Messages
548 594
549 def printMessages(self, clear=True): 595 def printMessages(self, clear=True):
562 try: 608 try:
563 w.redraw() 609 w.redraw()
564 except AttributeError: 610 except AttributeError:
565 pass 611 pass
566 612
567 def updateHistory(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, profile='@NONE@'): 613 def updateHistory(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, profile="@NONE@"):
568 del self.mess_walker[:] 614 del self.mess_walker[:]
569 if filters and 'search' in filters: 615 if filters and "search" in filters:
570 self.mess_walker.append(urwid.Text(_(u"Results for searching the globbing pattern: {}").format(filters['search']))) 616 self.mess_walker.append(
571 self.mess_walker.append(urwid.Text(_(u"Type ':history <lines>' to reset the chat history"))) 617 urwid.Text(
618 _(u"Results for searching the globbing pattern: {}").format(
619 filters["search"]
620 )
621 )
622 )
623 self.mess_walker.append(
624 urwid.Text(_(u"Type ':history <lines>' to reset the chat history"))
625 )
572 super(Chat, self).updateHistory(size, filters, profile) 626 super(Chat, self).updateHistory(size, filters, profile)
573 627
574 def _onHistoryPrinted(self): 628 def _onHistoryPrinted(self):
575 """Refresh or scroll down the focus after the history is printed""" 629 """Refresh or scroll down the focus after the history is printed"""
576 self.printMessages(clear=False) 630 self.printMessages(clear=False)
577 super(Chat, self)._onHistoryPrinted() 631 super(Chat, self)._onHistoryPrinted()
578 632
579 def onPrivateCreated(self, widget): 633 def onPrivateCreated(self, widget):
580 self.host.contact_lists[widget.profile].setSpecial(widget.target, C.CONTACT_SPECIAL_GROUP) 634 self.host.contact_lists[widget.profile].setSpecial(
635 widget.target, C.CONTACT_SPECIAL_GROUP
636 )
581 637
582 def onSelected(self): 638 def onSelected(self):
583 self.focus_marker_set = False 639 self.focus_marker_set = False
584 640
585 def notify(self, contact="somebody", msg=""): 641 def notify(self, contact="somebody", msg=""):
596 # as that mean that he is probably watching discussion history 652 # as that mean that he is probably watching discussion history
597 self.mess_widgets.focus_position = len(self.mess_walker) - 1 653 self.mess_widgets.focus_position = len(self.mess_walker) - 1
598 self.host.redraw() 654 self.host.redraw()
599 if not self.host.x_notify.hasFocus(): 655 if not self.host.x_notify.hasFocus():
600 if self.type == C.CHAT_ONE2ONE: 656 if self.type == C.CHAT_ONE2ONE:
601 self.host.x_notify.sendNotification(_("Primitivus: %s is talking to you") % contact) 657 self.host.x_notify.sendNotification(
658 _("Primitivus: %s is talking to you") % contact
659 )
602 elif self.nick is not None and self.nick.lower() in msg.lower(): 660 elif self.nick is not None and self.nick.lower() in msg.lower():
603 self.host.x_notify.sendNotification(_("Primitivus: %(user)s mentioned you in room '%(room)s'") % {'user': contact, 'room': self.target}) 661 self.host.x_notify.sendNotification(
662 _("Primitivus: %(user)s mentioned you in room '%(room)s'")
663 % {"user": contact, "room": self.target}
664 )
604 665
605 # MENU EVENTS # 666 # MENU EVENTS #
606 def onTarotRequest(self, menu): 667 def onTarotRequest(self, menu):
607 # TODO: move this to plugin_misc_tarot with dynamic menu 668 # TODO: move this to plugin_misc_tarot with dynamic menu
608 if len(self.occupants) != 4: 669 if len(self.occupants) != 4:
609 self.host.showPopUp(sat_widgets.Alert(_("Can't start game"), _("You need to be exactly 4 peoples in the room to start a Tarot game"), ok_cb=self.host.removePopUp)) 670 self.host.showPopUp(
671 sat_widgets.Alert(
672 _("Can't start game"),
673 _(
674 "You need to be exactly 4 peoples in the room to start a Tarot game"
675 ),
676 ok_cb=self.host.removePopUp,
677 )
678 )
610 else: 679 else:
611 self.host.bridge.tarotGameCreate(self.target, list(self.occupants), self.profile) 680 self.host.bridge.tarotGameCreate(
681 self.target, list(self.occupants), self.profile
682 )
612 683
613 # MISC EVENTS # 684 # MISC EVENTS #
614 685
615 def onDelete(self): 686 def onDelete(self):
616 # FIXME: to be checked after refactoring 687 # FIXME: to be checked after refactoring
617 super(Chat, self).onDelete() 688 super(Chat, self).onDelete()
618 if self.type == C.CHAT_GROUP: 689 if self.type == C.CHAT_GROUP:
619 self.host.removeListener('presence', self.presenceListener) 690 self.host.removeListener("presence", self.presenceListener)
620 691
621 def onChatState(self, from_jid, state, profile): 692 def onChatState(self, from_jid, state, profile):
622 super(Chat, self).onChatState(from_jid, state, profile) 693 super(Chat, self).onChatState(from_jid, state, profile)
623 if self.type == C.CHAT_ONE2ONE: 694 if self.type == C.CHAT_ONE2ONE:
624 self.title_dynamic = C.CHAT_STATE_ICON[state] 695 self.title_dynamic = C.CHAT_STATE_ICON[state]
628 self.changeSubject(dialog.text) 699 self.changeSubject(dialog.text)
629 self.host.removePopUp(dialog) 700 self.host.removePopUp(dialog)
630 701
631 def onSubjectDialog(self, new_subject=None): 702 def onSubjectDialog(self, new_subject=None):
632 dialog = sat_widgets.InputDialog( 703 dialog = sat_widgets.InputDialog(
633 _(u'Change title'), 704 _(u"Change title"),
634 _(u'Enter the new title'), 705 _(u"Enter the new title"),
635 default_txt=new_subject if new_subject is not None else self.subject) 706 default_txt=new_subject if new_subject is not None else self.subject,
636 dialog.setCallback('ok', self._onSubjectDialogCb, dialog) 707 )
637 dialog.setCallback('cancel', lambda dummy: self.host.removePopUp(dialog)) 708 dialog.setCallback("ok", self._onSubjectDialogCb, dialog)
709 dialog.setCallback("cancel", lambda dummy: self.host.removePopUp(dialog))
638 self.host.showPopUp(dialog) 710 self.host.showPopUp(dialog)
711
639 712
640 quick_widgets.register(quick_chat.QuickChat, Chat) 713 quick_widgets.register(quick_chat.QuickChat, Chat)
641 quick_widgets.register(quick_games.Tarot, game_tarot.TarotGame) 714 quick_widgets.register(quick_games.Tarot, game_tarot.TarotGame)