Mercurial > libervia-web
comparison browser_side/panels.py @ 202:2bc6cf004e61
browser, server: comments handling:
- banner in unibar show a specific message when the message will be a comment
- comments are inserted in a subpanel, in chronological order
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 20 Jun 2013 12:16:46 +0200 |
parents | aa76793da353 |
children | 4d7054542751 |
comparison
equal
deleted
inserted
replaced
201:aa76793da353 | 202:2bc6cf004e61 |
---|---|
62 """This text box is used as a main typing point, for message, microblog, etc""" | 62 """This text box is used as a main typing point, for message, microblog, etc""" |
63 | 63 |
64 def __init__(self, host): | 64 def __init__(self, host): |
65 TextArea.__init__(self) | 65 TextArea.__init__(self) |
66 #AutoCompleteTextBox.__init__(self) | 66 #AutoCompleteTextBox.__init__(self) |
67 self.__size = (0,0) | 67 self.__size = (0,0) |
68 self._popup = None | 68 self._popup = None |
69 self._timer = Timer(notify=self._timeCb) | 69 self._timer = Timer(notify=self._timeCb) |
70 self.host = host | 70 self.host = host |
71 self.setStyleName('uniBox') | 71 self.setStyleName('uniBox') |
72 self.addKeyboardListener(self) | 72 self.addKeyboardListener(self) |
82 def removeKey(self, key): | 82 def removeKey(self, key): |
83 try: | 83 try: |
84 self.getCompletionItems().completions.remove(key) | 84 self.getCompletionItems().completions.remove(key) |
85 except KeyError: | 85 except KeyError: |
86 print "WARNING: trying to remove an unknown key" | 86 print "WARNING: trying to remove an unknown key" |
87 | 87 |
88 | 88 |
89 def showWarning(self, target_data): | 89 def showWarning(self, target_data): |
90 target_hook, _type, msg = target_data | 90 target_hook, _type, msg = target_data |
91 if _type == "NONE": | 91 if _type == "NONE": |
92 return | 92 return |
113 self._popup.setStyleName("warningPopup") | 113 self._popup.setStyleName("warningPopup") |
114 if style: | 114 if style: |
115 self._popup.addStyleName(style) | 115 self._popup.addStyleName(style) |
116 | 116 |
117 left = 0 | 117 left = 0 |
118 top = 0 #max(0, self.getAbsoluteTop() - contents.getOffsetHeight() - 2) | 118 top = 0 #max(0, self.getAbsoluteTop() - contents.getOffsetHeight() - 2) |
119 self._popup.setPopupPosition(left, top) | 119 self._popup.setPopupPosition(left, top) |
120 self._popup.show() | 120 self._popup.show() |
121 | 121 |
122 def _timeCb(self, timer): | 122 def _timeCb(self, timer): |
123 if self._popup: | 123 if self._popup: |
130 @return: a tuple (selected, target_type, target info) with: | 130 @return: a tuple (selected, target_type, target info) with: |
131 - target_hook: None if we use the selected widget, (msg, data) if we have a hook (e.g. "@@: " for a public blog), where msg is the parsed message (i.e. without the "hook key: "@@: bla" become ("bla", None)) | 131 - target_hook: None if we use the selected widget, (msg, data) if we have a hook (e.g. "@@: " for a public blog), where msg is the parsed message (i.e. without the "hook key: "@@: bla" become ("bla", None)) |
132 - target_type: one of PUBLIC, GROUP, ONE2ONE, STATUS, MISC | 132 - target_type: one of PUBLIC, GROUP, ONE2ONE, STATUS, MISC |
133 - msg: HTML message which will appear in the privacy warning banner """ | 133 - msg: HTML message which will appear in the privacy warning banner """ |
134 target = self._selected_cache | 134 target = self._selected_cache |
135 | 135 |
136 def getSelectedOrStatus(): | 136 def getSelectedOrStatus(): |
137 if target: | 137 if target: |
138 _type, msg = target.getWarningData() | 138 _type, msg = target.getWarningData() |
139 target_hook = None # we use the selected widget, not a hook | 139 target_hook = None # we use the selected widget, not a hook |
140 else: | 140 else: |
145 if not txt.startswith('@'): | 145 if not txt.startswith('@'): |
146 target_hook, _type, msg = getSelectedOrStatus() | 146 target_hook, _type, msg = getSelectedOrStatus() |
147 elif txt.startswith('@@: '): | 147 elif txt.startswith('@@: '): |
148 _type = "PUBLIC" | 148 _type = "PUBLIC" |
149 msg = MicroblogPanel.warning_msg_public | 149 msg = MicroblogPanel.warning_msg_public |
150 target_hook = (txt[4:], None) | 150 target_hook = (txt[4:], None) |
151 elif txt.startswith('@'): | 151 elif txt.startswith('@'): |
152 _end = txt.find(': ') | 152 _end = txt.find(': ') |
153 if _end == -1: | 153 if _end == -1: |
154 target_hook, _type, msg = getSelectedOrStatus() | 154 target_hook, _type, msg = getSelectedOrStatus() |
155 else: | 155 else: |
163 msg = MicroblogPanel.warning_msg_group % group | 163 msg = MicroblogPanel.warning_msg_group % group |
164 target_hook = (txt[_end+2:], group) | 164 target_hook = (txt[_end+2:], group) |
165 else: | 165 else: |
166 print "ERROR: Unknown target" | 166 print "ERROR: Unknown target" |
167 target_hook, _type, msg = getSelectedOrStatus() | 167 target_hook, _type, msg = getSelectedOrStatus() |
168 | 168 |
169 return (target_hook, _type, msg) | 169 return (target_hook, _type, msg) |
170 | 170 |
171 def onBrowserEvent(self, event): | 171 def onBrowserEvent(self, event): |
172 #XXX: woraroung a pyjamas bug: self.currentEvent is not set | 172 #XXX: woraroung a pyjamas bug: self.currentEvent is not set |
173 # so the TextBox's cancelKey doens't work. This is a workaround | 173 # so the TextBox's cancelKey doens't work. This is a workaround |
214 | 214 |
215 def onSelectedChange(self, selected): | 215 def onSelectedChange(self, selected): |
216 self._selected_cache = selected | 216 self._selected_cache = selected |
217 | 217 |
218 """def complete(self): | 218 """def complete(self): |
219 | 219 |
220 #self.visible=False #XXX: self.visible is not unset in pyjamas when ENTER is pressed and a completion is done | 220 #self.visible=False #XXX: self.visible is not unset in pyjamas when ENTER is pressed and a completion is done |
221 #XXX: fixed directly on pyjamas, if the patch is accepted, no need to walk around this | 221 #XXX: fixed directly on pyjamas, if the patch is accepted, no need to walk around this |
222 return AutoCompleteTextBox.complete(self)""" | 222 return AutoCompleteTextBox.complete(self)""" |
223 | 223 |
224 class MicroblogItem(): | 224 class MicroblogItem(): |
225 #XXX: should be moved in a separated module | 225 #XXX: should be moved in a separated module |
226 | 226 |
227 def __init__(self, data): | 227 def __init__(self, data): |
228 self.id = data['id'] | 228 self.id = data['id'] |
229 self.type = data.get('type','main_item') | |
229 self.content = data['content'] | 230 self.content = data['content'] |
230 self.author = data['author'] | 231 self.author = data['author'] |
231 self.timestamp = float(data.get('timestamp',0)) #XXX: int doesn't work here | 232 self.timestamp = float(data.get('timestamp',0)) #XXX: int doesn't work here |
232 | 233 self.comments = data.get('comments', False) |
234 if self.comments: | |
235 try: | |
236 self.comments_hash = (data['comments_service'], data['comments_node']) | |
237 self.comments_service = data['comments_service'] | |
238 self.comments_node = data['comments_node'] | |
239 except KeyError: | |
240 print "Warning: can't manage comment [%s], some keys are missing in microblog data (%s)" % (data["comments"], data.keys()) | |
241 self.comments = False | |
242 if set(("service","node")).issubset(data.keys()): | |
243 self.service = data["service"] | |
244 self.node = data["node"] | |
245 self.hash = (self.service, self.node) | |
246 | |
233 class MicroblogEntry(SimplePanel, ClickHandler): | 247 class MicroblogEntry(SimplePanel, ClickHandler): |
234 | 248 |
235 def __init__(self, blog_panel, mblog_entry): | 249 def __init__(self, blog_panel, mblog_entry): |
236 SimplePanel.__init__(self) | 250 SimplePanel.__init__(self) |
237 self._blog_panel = blog_panel | 251 self._blog_panel = blog_panel |
238 | 252 |
239 self.author = mblog_entry.author | 253 self.author = mblog_entry.author |
240 self.timestamp = mblog_entry.timestamp | 254 self.timestamp = mblog_entry.timestamp |
241 _datetime = datetime.fromtimestamp(mblog_entry.timestamp) | 255 _datetime = datetime.fromtimestamp(mblog_entry.timestamp) |
256 self.comments = mblog_entry.comments | |
242 | 257 |
243 self.panel = HTMLPanel(""" | 258 self.panel = HTMLPanel(""" |
244 <div class='mb_entry_header'><span class='mb_entry_author'>%(author)s</span> on <span class='mb_entry_timestamp'>%(timestamp)s</span></div> | 259 <div class='mb_entry_header'><span class='mb_entry_author'>%(author)s</span> on <span class='mb_entry_timestamp'>%(timestamp)s</span></div> |
245 <div class="mb_entry_avatar" id='id_avatar'></div> | 260 <div class="mb_entry_avatar" id='id_avatar'></div> |
246 <div class="mb_entry_dialog"> | 261 <div class="mb_entry_dialog"> |
259 | 274 |
260 def updateAvatar(self, new_avatar): | 275 def updateAvatar(self, new_avatar): |
261 """Change the avatar of the entry | 276 """Change the avatar of the entry |
262 @param new_avatar: path to the new image""" | 277 @param new_avatar: path to the new image""" |
263 self.avatar.setUrl(new_avatar) | 278 self.avatar.setUrl(new_avatar) |
264 | 279 |
265 def onClick(self, sender): | 280 def onClick(self, sender): |
266 print "microblog entry selected (author=%s)" % self.author | 281 print "microblog entry selected (author=%s)" % self.author |
267 self._blog_panel.setSelectedEntry(self) | 282 self._blog_panel.setSelectedEntry(self if self.comments else None) |
268 | 283 |
269 | 284 |
270 class MicroblogPanel(base_widget.LiberviaWidget): | 285 class MicroblogPanel(base_widget.LiberviaWidget): |
271 warning_msg_public = "This message will be PUBLIC and everybody will be able to see it, even people you don't know" | 286 warning_msg_public = "This message will be PUBLIC and everybody will be able to see it, even people you don't know" |
272 warning_msg_group = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>" | 287 warning_msg_group = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>" |
278 base_widget.LiberviaWidget.__init__(self, host, ", ".join(accepted_groups), selectable = True) | 293 base_widget.LiberviaWidget.__init__(self, host, ", ".join(accepted_groups), selectable = True) |
279 #base_widget.ScrollPanelWrapper.__init__(self) | 294 #base_widget.ScrollPanelWrapper.__init__(self) |
280 #DropCell.__init__(self) | 295 #DropCell.__init__(self) |
281 self.accepted_groups = accepted_groups | 296 self.accepted_groups = accepted_groups |
282 self.entries = {} | 297 self.entries = {} |
298 self.comments = {} | |
283 self.selected_entry = None | 299 self.selected_entry = None |
284 self.vpanel = VerticalPanel() | 300 self.vpanel = VerticalPanel() |
285 self.vpanel.setStyleName('microblogPanel') | 301 self.vpanel.setStyleName('microblogPanel') |
286 self.setWidget(self.vpanel) | 302 self.setWidget(self.vpanel) |
287 | 303 |
304 host.FillMicroblogPanel(_new_panel) | 320 host.FillMicroblogPanel(_new_panel) |
305 host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, 'ALL', [], 10) | 321 host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, 'ALL', [], 10) |
306 return _new_panel | 322 return _new_panel |
307 | 323 |
308 def getWarningData(self): | 324 def getWarningData(self): |
309 if not self.accepted_groups: | 325 if self.selected_entry: |
326 if not self.selected_entry.comments: | |
327 print ("ERROR: an item without comment is selected") | |
328 return ("NONE", None) | |
329 return ("PUBLIC", "This is a <span class='warningTarget'>comment</span> and keep the initial post visibility, so it is potentialy public") | |
330 | |
331 elif not self.accepted_groups: | |
310 # we have a meta MicroblogPanel, we publish publicly | 332 # we have a meta MicroblogPanel, we publish publicly |
311 return ("PUBLIC", self.warning_msg_public) | 333 return ("PUBLIC", self.warning_msg_public) |
312 else: | 334 else: |
313 # we only accept one group at the moment | 335 # we only accept one group at the moment |
314 # FIXME: manage several groups | 336 # FIXME: manage several groups |
315 return ("GROUP", self.warning_msg_group % self.accepted_groups[0]) | 337 return ("GROUP", self.warning_msg_group % self.accepted_groups[0]) |
316 | 338 |
317 def onTextEntered(self, text): | 339 def onTextEntered(self, text): |
318 if not self.accepted_groups: | 340 if self.selected_entry: |
341 # we are entering a comment | |
342 comments_node = self.selected_entry.comments | |
343 if not comments_node: | |
344 raise Exception("ERROR: comments node is empty") | |
345 self.host.bridge.call("sendMblogComment", None, comments_node, text) | |
346 elif not self.accepted_groups: | |
347 # we are entering a public microblog | |
319 self.host.bridge.call("sendMblog", None, "PUBLIC", None, text) | 348 self.host.bridge.call("sendMblog", None, "PUBLIC", None, text) |
320 else: | 349 else: |
350 # we are entering a microblog restricted to a group | |
321 # FIXME: manage several groups | 351 # FIXME: manage several groups |
322 self.host.bridge.call("sendMblog", None, "GROUP", self.accepted_groups[0], text) | 352 self.host.bridge.call("sendMblog", None, "GROUP", self.accepted_groups[0], text) |
323 | 353 |
324 def accept_all(self): | 354 def accept_all(self): |
325 return not self.accepted_groups #we accept every microblog only if we are not filtering by groups | 355 return not self.accepted_groups #we accept every microblog only if we are not filtering by groups |
326 | 356 |
327 def getEntries(self): | 357 def getEntries(self): |
328 """Ask all the entries for the currenly accepted groups, | 358 """Ask all the entries for the currenly accepted groups, |
329 and fill the panel""" | 359 and fill the panel""" |
330 | 360 |
331 def massiveInsert(self, mblogs): | 361 def massiveInsert(self, mblogs): |
332 """Insert several microblogs at once | 362 """Insert several microblogs at once |
333 @param mblogs: dictionary of microblogs, as the result of getMassiveLastGroupBlogs | 363 @param mblogs: dictionary of microblogs, as the result of getMassiveLastGroupBlogs |
334 """ | 364 """ |
335 print "Massive insertion of microblogs" | 365 print "Massive insertion of microblogs" |
336 for publisher in mblogs: | 366 for publisher in mblogs: |
337 print "adding blogs for [%s]" % publisher | 367 print "adding blogs for [%s]" % publisher |
338 for mblog in mblogs[publisher]: | 368 for mblog in mblogs[publisher]: |
339 if not mblog.has_key('content'): | 369 if not "content" in mblog: |
340 print ("WARNING: No content found in microblog [%s]", mblog) | 370 print ("WARNING: No content found in microblog [%s]", mblog) |
341 continue | 371 continue |
342 mblog_entry = MicroblogItem(mblog) | 372 mblog_item = MicroblogItem(mblog) |
343 self.addEntry(mblog_entry) | 373 self.addEntry(mblog_item) |
344 | 374 |
345 def addEntry(self, mblog_entry): | 375 def mblogsInsert(self, mblogs): |
346 """Add an entry to the panel | 376 """ Insert several microblogs at once |
347 @param mblog_entry: MicroblogItem instance | 377 @param mblogs: list of microblogs |
348 """ | 378 """ |
349 if mblog_entry.id in self.entries: | 379 for mblog in mblogs: |
350 return | 380 if not "content" in mblog: |
351 _entry = MicroblogEntry(self, mblog_entry) | 381 print ("WARNING: No content found in microblog [%s]", mblog) |
352 self.entries[mblog_entry.id] = _entry | 382 continue |
353 | 383 mblog_item = MicroblogItem(mblog) |
384 self.addEntry(mblog_item) | |
385 | |
386 def _chronoInsert(self, vpanel, entry, reverse = True): | |
387 """ Insert an entry in chronological order | |
388 @param vpanel: VerticalPanel instance | |
389 @param entry: MicroblogEntry | |
390 @param reverse: more recent entry on top if True, chronological order else""" | |
354 # we look for the right index to insert our entry: | 391 # we look for the right index to insert our entry: |
355 # we insert the entry above the first entry | 392 # if reversed, we insert the entry above the first entry |
356 # in the past | 393 # in the past |
357 idx = 0 | 394 idx = 0 |
358 for child in self.vpanel.children: | 395 |
396 for child in vpanel.children: | |
359 if not isinstance(child, MicroblogEntry): | 397 if not isinstance(child, MicroblogEntry): |
360 break | 398 idx+=1 |
361 if child.timestamp < mblog_entry.timestamp: | 399 continue |
362 break | 400 if reverse: |
401 if child.timestamp < entry.timestamp: | |
402 break | |
403 else: | |
404 if child.timestamp > entry.timestamp: | |
405 break | |
363 idx+=1 | 406 idx+=1 |
364 self.vpanel.insert(_entry,idx) | 407 |
408 vpanel.insert(entry, idx) | |
409 | |
410 def addEntry(self, mblog_item): | |
411 """Add an entry to the panel | |
412 @param mblog_item: MicroblogItem instance | |
413 """ | |
414 if mblog_item.type == "comment": | |
415 if not mblog_item.hash in self.comments: | |
416 # The comments node is not known in this panel | |
417 return | |
418 _entry = MicroblogEntry(self, mblog_item) | |
419 parent = self.comments[mblog_item.hash] | |
420 parent_idx = self.vpanel.getWidgetIndex(parent) | |
421 # we find or create the panel where the comment must be inserted | |
422 try: | |
423 sub_panel = self.vpanel.getWidget(parent_idx+1) | |
424 except IndexError: | |
425 sub_panel = None | |
426 if not sub_panel or not isinstance(sub_panel, VerticalPanel): | |
427 sub_panel = VerticalPanel() | |
428 sub_panel.setStyleName('microblogPanel') | |
429 sub_panel.addStyleName('subPanel') | |
430 self.vpanel.insert(sub_panel, parent_idx+1) | |
431 | |
432 # we want comments to be inserted in chronological order | |
433 self._chronoInsert(sub_panel, _entry, reverse=False) | |
434 return | |
435 | |
436 if mblog_item.id in self.entries: | |
437 return | |
438 _entry = MicroblogEntry(self, mblog_item) | |
439 | |
440 self.entries[mblog_item.id] = _entry | |
441 | |
442 self._chronoInsert(self.vpanel, _entry) | |
443 | |
444 if mblog_item.comments: | |
445 # entry has comments, we keep the comment node as a reference | |
446 self.comments[mblog_item.comments_hash] = _entry | |
447 self.host.bridge.call('getMblogComments', self.mblogsInsert, mblog_item.comments_service, mblog_item.comments_node) | |
365 | 448 |
366 def setSelectedEntry(self, entry): | 449 def setSelectedEntry(self, entry): |
367 if self.selected_entry == entry: | 450 if self.selected_entry == entry: |
368 entry = None | 451 entry = None |
369 if self.selected_entry: | 452 if self.selected_entry: |
376 def updateValue(self, type, jid, value): | 459 def updateValue(self, type, jid, value): |
377 """Update a jid value in entries | 460 """Update a jid value in entries |
378 @param type: one of 'avatar', 'nick' | 461 @param type: one of 'avatar', 'nick' |
379 @param jid: jid concerned | 462 @param jid: jid concerned |
380 @param value: new value""" | 463 @param value: new value""" |
464 def updateVPanel(vpanel): | |
465 for child in vpanel.children: | |
466 if isinstance(child, MicroblogEntry) and child.author == jid: | |
467 child.updateAvatar(value) | |
468 elif isinstance(child, VerticalPanel): | |
469 updateVPanel(child) | |
381 if type=='avatar': | 470 if type=='avatar': |
382 for entry in self.entries.values(): | 471 updateVPanel(self.vpanel) |
383 if entry.author == jid: | |
384 entry.updateAvatar(value) | |
385 | 472 |
386 def setAcceptedGroup(self, group): | 473 def setAcceptedGroup(self, group): |
387 """Set the group which can be displayed in this panel | 474 """Set the group which can be displayed in this panel |
388 @param group: string of the group, or list of string | 475 @param group: string of the group, or list of string |
389 """ | 476 """ |
464 def removeOccupant(self, nick): | 551 def removeOccupant(self, nick): |
465 try: | 552 try: |
466 self.remove(self.occupants_list[nick]) | 553 self.remove(self.occupants_list[nick]) |
467 except KeyError: | 554 except KeyError: |
468 print "ERROR: trying to remove an unexisting nick" | 555 print "ERROR: trying to remove an unexisting nick" |
469 | 556 |
470 def clear(self): | 557 def clear(self): |
471 self.occupants_list.clear() | 558 self.occupants_list.clear() |
472 AbsolutePanel.clear(self) | 559 AbsolutePanel.clear(self) |
473 | 560 |
474 class ChatPanel(base_widget.LiberviaWidget): | 561 class ChatPanel(base_widget.LiberviaWidget): |
541 | 628 |
542 def onQuit(self): | 629 def onQuit(self): |
543 base_widget.LiberviaWidget.onQuit(self) | 630 base_widget.LiberviaWidget.onQuit(self) |
544 if self.type == 'group': | 631 if self.type == 'group': |
545 self.host.bridge.call('mucLeave', None, self.target.bare) | 632 self.host.bridge.call('mucLeave', None, self.target.bare) |
546 | 633 |
547 | 634 |
548 def setUserNick(self, nick): | 635 def setUserNick(self, nick): |
549 """Set the nick of the user, usefull for e.g. change the color of the user""" | 636 """Set the nick of the user, usefull for e.g. change the color of the user""" |
550 self.nick = nick | 637 self.nick = nick |
551 | 638 |
552 def setPresents(self, nicks): | 639 def setPresents(self, nicks): |
553 """Set the users presents in this room | 640 """Set the users presents in this room |
554 @param occupants: list of nicks (string)""" | 641 @param occupants: list of nicks (string)""" |
555 self.occupants_list.clear() | 642 self.occupants_list.clear() |
556 for nick in nicks: | 643 for nick in nicks: |
569 def getHistoryCB(history): | 656 def getHistoryCB(history): |
570 for line in history: | 657 for line in history: |
571 timestamp, from_jid, to_jid, message, mess_type = line | 658 timestamp, from_jid, to_jid, message, mess_type = line |
572 self.printMessage(from_jid, message, timestamp) | 659 self.printMessage(from_jid, message, timestamp) |
573 self.host.bridge.call('getHistory', getHistoryCB, self.host.whoami.bare, self.target.bare, size, True) | 660 self.host.bridge.call('getHistory', getHistoryCB, self.host.whoami.bare, self.target.bare, size, True) |
574 | 661 |
575 def printInfo(self, msg, type='normal'): | 662 def printInfo(self, msg, type='normal'): |
576 """Print general info | 663 """Print general info |
577 @param msg: message to print | 664 @param msg: message to print |
578 @type: one of: | 665 @type: one of: |
579 normal: general info like "toto has joined the room" | 666 normal: general info like "toto has joined the room" |
585 elif type == 'me': | 672 elif type == 'me': |
586 _wid.setStyleName('chatTextMe') | 673 _wid.setStyleName('chatTextMe') |
587 else: | 674 else: |
588 _wid.setStyleName('chatTextInfo') | 675 _wid.setStyleName('chatTextInfo') |
589 self.content.add(_wid) | 676 self.content.add(_wid) |
590 | 677 |
591 | 678 |
592 def printMessage(self, from_jid, msg, timestamp=None): | 679 def printMessage(self, from_jid, msg, timestamp=None): |
593 """Print message in chat window. Must be implemented by child class""" | 680 """Print message in chat window. Must be implemented by child class""" |
594 _jid=JID(from_jid) | 681 _jid=JID(from_jid) |
595 nick = _jid.node if self.type=='one2one' else _jid.resource | 682 nick = _jid.node if self.type=='one2one' else _jid.resource |
596 mymess = _jid.resource == self.nick if self.type == "group" else _jid.bare == self.host.whoami.bare #mymess = True if message comes from local user | 683 mymess = _jid.resource == self.nick if self.type == "group" else _jid.bare == self.host.whoami.bare #mymess = True if message comes from local user |
597 if msg.startswith('/me '): | 684 if msg.startswith('/me '): |
598 self.printInfo('* %s %s' % (nick, msg[4:]),type='me') | 685 self.printInfo('* %s %s' % (nick, msg[4:]),type='me') |
599 return | 686 return |
600 self.content.add(ChatText(timestamp, nick, mymess, msg)) | 687 self.content.add(ChatText(timestamp, nick, mymess, msg)) |
601 self.content_scroll.scrollToBottom() | 688 self.content_scroll.scrollToBottom() |
602 | 689 |
603 def startGame(self, game_type, referee, players): | 690 def startGame(self, game_type, referee, players): |
604 """Configure the chat window to start a game""" | 691 """Configure the chat window to start a game""" |
605 if game_type=="Tarot": | 692 if game_type=="Tarot": |
606 if hasattr(self, "tarot_panel"): | 693 if hasattr(self, "tarot_panel"): |
607 return | 694 return |
610 self.vpanel.setCellHeight(self.tarot_panel, self.tarot_panel.getHeight()) | 697 self.vpanel.setCellHeight(self.tarot_panel, self.tarot_panel.getHeight()) |
611 elif game_type=="RadioCol": | 698 elif game_type=="RadioCol": |
612 #XXX: We can have double panel if we join quickly enough to have the group chat start signal | 699 #XXX: We can have double panel if we join quickly enough to have the group chat start signal |
613 # on invitation + the one triggered on room join | 700 # on invitation + the one triggered on room join |
614 if hasattr(self, "radiocol_panel"): | 701 if hasattr(self, "radiocol_panel"): |
615 return | 702 return |
616 self.radiocol_panel = RadioColPanel(self, referee, self.nick) | 703 self.radiocol_panel = RadioColPanel(self, referee, self.nick) |
617 self.vpanel.insert(self.radiocol_panel, 0) | 704 self.vpanel.insert(self.radiocol_panel, 0) |
618 self.vpanel.setCellHeight(self.radiocol_panel, self.radiocol_panel.getHeight()) | 705 self.vpanel.setCellHeight(self.radiocol_panel, self.radiocol_panel.getHeight()) |
619 | 706 |
620 def getGame(self, game_type): | 707 def getGame(self, game_type): |
621 """Return class managing the game type""" | 708 """Return class managing the game type""" |
622 #TODO: check that the game is launched, and manage errors | 709 #TODO: check that the game is launched, and manage errors |
623 if game_type=="Tarot": | 710 if game_type=="Tarot": |
624 return self.tarot_panel | 711 return self.tarot_panel |
625 elif game_type=="RadioCol": | 712 elif game_type=="RadioCol": |
626 return self.radiocol_panel | 713 return self.radiocol_panel |
627 | 714 |
628 class WebPanel(base_widget.LiberviaWidget): | 715 class WebPanel(base_widget.LiberviaWidget): |
629 """ (mini)browser like widget """ | 716 """ (mini)browser like widget """ |
630 | 717 |
631 def __init__(self, host, url=None): | 718 def __init__(self, host, url=None): |
632 """ | 719 """ |
633 @param host: SatWebFrontend instance | 720 @param host: SatWebFrontend instance |
634 """ | 721 """ |
635 base_widget.LiberviaWidget.__init__(self, host) | 722 base_widget.LiberviaWidget.__init__(self, host) |
656 def onUrlClick(self, sender): | 743 def onUrlClick(self, sender): |
657 self._frame.setUrl(self._url.getText()) | 744 self._frame.setUrl(self._url.getText()) |
658 | 745 |
659 class ContactTabPanel(HorizontalPanel): | 746 class ContactTabPanel(HorizontalPanel): |
660 """ TabPanel with a contacts list which can be hidden """ | 747 """ TabPanel with a contacts list which can be hidden """ |
661 | 748 |
662 def __init__(self, host, locked = False): | 749 def __init__(self, host, locked = False): |
663 self.host=host | 750 self.host=host |
664 HorizontalPanel.__init__(self) | 751 HorizontalPanel.__init__(self) |
665 self._left = VerticalPanel() | 752 self._left = VerticalPanel() |
666 contacts_switch = Button('<<', self._contactsSwitch) | 753 contacts_switch = Button('<<', self._contactsSwitch) |
689 menu = Menu(host) | 776 menu = Menu(host) |
690 | 777 |
691 #unibox | 778 #unibox |
692 unibox_panel = UniBoxPanel(host) | 779 unibox_panel = UniBoxPanel(host) |
693 self.host.setUniBox(unibox_panel.unibox) | 780 self.host.setUniBox(unibox_panel.unibox) |
694 | 781 |
695 #status bar | 782 #status bar |
696 status = host.status_panel | 783 status = host.status_panel |
697 | 784 |
698 #contacts | 785 #contacts |
699 _contacts = VerticalPanel() | 786 _contacts = VerticalPanel() |
700 contacts_switch = Button('<<', self._contactsSwitch) | 787 contacts_switch = Button('<<', self._contactsSwitch) |
701 contacts_switch.addStyleName('contactsSwitch') | 788 contacts_switch.addStyleName('contactsSwitch') |
702 _contacts.add(contacts_switch) | 789 _contacts.add(contacts_switch) |
717 | 804 |
718 _hpanel = HorizontalPanel() | 805 _hpanel = HorizontalPanel() |
719 _hpanel.add(_contacts) | 806 _hpanel.add(_contacts) |
720 _hpanel.add(self.tab_panel) | 807 _hpanel.add(self.tab_panel) |
721 self.add(_hpanel) | 808 self.add(_hpanel) |
722 | 809 |
723 self.setWidth("100%") | 810 self.setWidth("100%") |
724 Window.addWindowResizeListener(self) | 811 Window.addWindowResizeListener(self) |
725 | 812 |
726 def _contactsSwitch(self, btn): | 813 def _contactsSwitch(self, btn): |
727 """ (Un)hide contacts panel """ | 814 """ (Un)hide contacts panel """ |