comparison browser_side/panels.py @ 395:98cd5387d291

browser_side: new microblogs are not using the rich text editor by default: - a button allows to switch from raw to rich text, and vice versa - raw text microblogs are not submitted anymore when the focus is lost, only when <enter> is pressed
author souliane <souliane@mailoo.org>
date Mon, 10 Mar 2014 22:39:26 +0100
parents ee61b0765d6c
children 6148e9063069
comparison
equal deleted inserted replaced
394:ee61b0765d6c 395:98cd5387d291
386 self._base_item = data if isinstance(data, MicroblogItem) else MicroblogItem(data) 386 self._base_item = data if isinstance(data, MicroblogItem) else MicroblogItem(data)
387 for attr in ['id', 'type', 'empty', 'title', 'title_xhtml', 'content', 'content_xhtml', 387 for attr in ['id', 'type', 'empty', 'title', 'title_xhtml', 'content', 'content_xhtml',
388 'author', 'updated', 'published', 'comments', 'service', 'node', 388 'author', 'updated', 'published', 'comments', 'service', 'node',
389 'comments_service', 'comments_node']: 389 'comments_service', 'comments_node']:
390 getter = lambda attr: lambda inst: getattr(inst._base_item, attr) 390 getter = lambda attr: lambda inst: getattr(inst._base_item, attr)
391 setattr(MicroblogEntry, attr, property(getter(attr))) 391 setter = lambda attr: lambda inst, value: setattr(inst._base_item, attr, value)
392 setattr(MicroblogEntry, attr, property(getter(attr), setter(attr)))
392 393
393 SimplePanel.__init__(self) 394 SimplePanel.__init__(self)
394 self._blog_panel = blog_panel 395 self._blog_panel = blog_panel
395 396
396 self.panel = FlowPanel() 397 self.panel = FlowPanel()
407 entry_avatar.setStyleName('mb_entry_avatar') 408 entry_avatar.setStyleName('mb_entry_avatar')
408 self.avatar = Image(self._blog_panel.host.getAvatar(self.author)) 409 self.avatar = Image(self._blog_panel.host.getAvatar(self.author))
409 entry_avatar.add(self.avatar) 410 entry_avatar.add(self.avatar)
410 self.panel.add(entry_avatar) 411 self.panel.add(entry_avatar)
411 412
412 self.entry_dialog = SimplePanel() 413 self.entry_dialog = HorizontalPanel()
413 self.entry_dialog.setStyleName('mb_entry_dialog') 414 self.entry_dialog.setStyleName('mb_entry_dialog')
414 self.panel.add(self.entry_dialog) 415 self.panel.add(self.entry_dialog)
415 416
416 self.add(self.panel) 417 self.add(self.panel)
417 ClickHandler.__init__(self) 418 ClickHandler.__init__(self)
471 if sender == self: 472 if sender == self:
472 self._blog_panel.setSelectedEntry(self) 473 self._blog_panel.setSelectedEntry(self)
473 elif sender == self.delete_label: 474 elif sender == self.delete_label:
474 self._delete() 475 self._delete()
475 elif sender == self.update_label: 476 elif sender == self.update_label:
476 self.bubble.edit(True) 477 self.edit(True)
477 elif sender == self.comment_label: 478 elif sender == self.comment_label:
478 self._comment() 479 self._comment()
479 480
480 def __modifiedCb(self, content): 481 def __modifiedCb(self, content):
481 """Send the new content to the backend 482 """Send the new content to the backend
483 """ 484 """
484 if not content['text']: # previous content has been emptied 485 if not content['text']: # previous content has been emptied
485 self._delete(True) 486 self._delete(True)
486 return False 487 return False
487 extra = {'published': str(self.published)} 488 extra = {'published': str(self.published)}
488 if self.empty or self.content_xhtml: 489 if isinstance(self.bubble, richtext.RichTextEditor):
489 # TODO: if the user change his parameters after the message edition started, 490 # TODO: if the user change his parameters after the message edition started,
490 # the message syntax could be different then the current syntax: pass the 491 # the message syntax could be different then the current syntax: pass the
491 # message syntax in extra for the frontend to use it instead of current syntax. 492 # message syntax in extra for the frontend to use it instead of current syntax.
492 extra.update({'content_rich': content['text'], 'title': content['title']}) 493 extra.update({'content_rich': content['text'], 'title': content['title']})
493 if self.empty: 494 if self.empty:
506 self._blog_panel.removeEntry(self.type, self.id) 507 self._blog_panel.removeEntry(self.type, self.id)
507 if self.type == 'main_item': # restore the "New message" button 508 if self.type == 'main_item': # restore the "New message" button
508 self._blog_panel.refresh() 509 self._blog_panel.refresh()
509 else: # allow to create a new comment 510 else: # allow to create a new comment
510 self._parent_entry._current_comment = None 511 self._parent_entry._current_comment = None
511 512 try:
512 def __setBubble(self): 513 self.toggle_syntax_button.removeFromParent()
514 except TypeError:
515 pass
516
517 def __setBubble(self, edit=False):
513 """Set the bubble displaying the initial content.""" 518 """Set the bubble displaying the initial content."""
514 content = {'text': self.content_xhtml if self.content_xhtml else self.content, 519 content = {'text': self.content_xhtml if self.content_xhtml else self.content,
515 'title': self.title_xhtml if self.title_xhtml else self.title} 520 'title': self.title_xhtml if self.title_xhtml else self.title}
516 if self.empty or self.content_xhtml: # new message and rich text message 521 if self.content_xhtml:
517 content.update({'syntax': Const.SYNTAX_XHTML}) 522 content.update({'syntax': Const.SYNTAX_XHTML})
518 if self.author != self._blog_panel.host.whoami.bare: 523 if self.author != self._blog_panel.host.whoami.bare:
519 options = ['read_only'] 524 options = ['read_only']
520 else: 525 else:
521 options = [] if self.empty else ['update_msg'] 526 options = [] if self.empty else ['update_msg']
522 self.bubble = richtext.RichTextEditor(self._blog_panel.host, content, self.__modifiedCb, self.__afterEditCb, options) 527 self.bubble = richtext.RichTextEditor(self._blog_panel.host, content, self.__modifiedCb, self.__afterEditCb, options)
523 else: # assume raw text message have no title 528 else: # assume raw text message have no title
524 self.bubble = LightTextEditor(content, self.__modifiedCb, self.__afterEditCb, True) 529 self.bubble = LightTextEditor(content, self.__modifiedCb, self.__afterEditCb, single_line=True, listen_focus=False)
525 self.bubble.setStyleName("bubble") 530 self.bubble.setStyleName("bubble")
531 try:
532 self.toggle_syntax_button.removeFromParent()
533 except TypeError:
534 pass
526 self.entry_dialog.add(self.bubble) 535 self.entry_dialog.add(self.bubble)
527 self.bubble.edit(False) 536 self.edit(edit)
528 self.bubble.addEditListener(self.__showWarning) 537 self.bubble.addEditListener(self.__showWarning)
529 538
530 def __showWarning(self, sender, keycode): 539 def __showWarning(self, sender, keycode):
531 if keycode == KEY_ENTER: 540 if keycode == KEY_ENTER:
532 self._blog_panel.host.showWarning(None, None) 541 self._blog_panel.host.showWarning(None, None)
569 if entry is None: 578 if entry is None:
570 print "The entry of id %s can not be commented" % self.id 579 print "The entry of id %s can not be commented" % self.id
571 return 580 return
572 entry._parent_entry = self 581 entry._parent_entry = self
573 self._current_comment = entry 582 self._current_comment = entry
574 entry.bubble.edit(True) 583 self.edit(True, entry)
584
585 def edit(self, edit, entry=None):
586 """Toggle the bubble between display and edit mode
587 @edit: boolean value
588 @entry: MicroblogEntry instance, or None to use self
589 """
590 if entry is None:
591 entry = self
592 try:
593 entry.toggle_syntax_button.removeFromParent()
594 except TypeError:
595 pass
596 entry.bubble.edit(edit)
597 if edit:
598 if isinstance(entry.bubble, richtext.RichTextEditor):
599 image = '<a class="richTextIcon">A</a>'
600 title = _('Switch to raw text edition')
601 else:
602 image = '<img src="media/icons/tango/actions/32/format-text-italic.png" class="richTextIcon"/>'
603 title = _('Switch to rich text edition')
604 entry.toggle_syntax_button = Button(image, entry.toggleContentSyntax)
605 entry.toggle_syntax_button.setTitle(title)
606 entry.entry_dialog.add(entry.toggle_syntax_button)
607
608 def toggleContentSyntax(self):
609 """Toggle the editor between raw and rich text"""
610 original_content = self.bubble.getOriginalContent()
611 rich = not isinstance(self.bubble, richtext.RichTextEditor)
612
613 def setBubble(text):
614 self.content = text
615 self.content_xhtml = text if rich else ''
616 self.content_title = self.content_title_xhtml = ''
617 self.bubble.removeFromParent()
618 self.__setBubble(True)
619 self.bubble.setOriginalContent(original_content)
620
621 text = self.bubble.getContent()['text']
622 if not text:
623 setBubble(' ') # something different than empty string is needed to initialize the rich text editor
624 return
625 if not rich:
626 def confirm_cb(answer):
627 if answer:
628 self._blog_panel.host.bridge.call('syntaxConvert', setBubble, text, Const.SYNTAX_CURRENT, Const.SYNTAX_TEXT)
629 dialog.ConfirmDialog(confirm_cb, text=_("Do you really want to lose the title and text formatting?")).show()
630 else:
631 self._blog_panel.host.bridge.call('syntaxConvert', setBubble, text, Const.SYNTAX_TEXT, Const.SYNTAX_XHTML)
575 632
576 633
577 class MicroblogPanel(base_widget.LiberviaWidget): 634 class MicroblogPanel(base_widget.LiberviaWidget):
578 warning_msg_public = "This message will be PUBLIC and everybody will be able to see it, even people you don't know" 635 warning_msg_public = "This message will be PUBLIC and everybody will be able to see it, even people you don't know"
579 warning_msg_group = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>" 636 warning_msg_group = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>"
605 data = {'id': str(time()), 662 data = {'id': str(time()),
606 'new': True, 663 'new': True,
607 'author': self.host.whoami.bare, 664 'author': self.host.whoami.bare,
608 } 665 }
609 entry = self.addEntry(data) 666 entry = self.addEntry(data)
610 entry.bubble.edit(True) 667 entry.edit(True)
611 self.new_button = Button("New message", listener=addBox) 668 self.new_button = Button("New message", listener=addBox)
612 self.new_button.setStyleName("microblogNewButton") 669 self.new_button.setStyleName("microblogNewButton")
613 self.vpanel.insert(self.new_button, 0) 670 self.vpanel.insert(self.new_button, 0)
614 671
615 @classmethod 672 @classmethod
888 EMPTY_STATUS = '&lt;click to set a status&gt;' 945 EMPTY_STATUS = '&lt;click to set a status&gt;'
889 946
890 def __init__(self, host, status=''): 947 def __init__(self, host, status=''):
891 self.host = host 948 self.host = host
892 modifiedCb = lambda content: self.host.bridge.call('setStatus', None, self.host.status_panel.presence, content['text']) or True 949 modifiedCb = lambda content: self.host.bridge.call('setStatus', None, self.host.status_panel.presence, content['text']) or True
893 LightTextEditor.__init__(self, {'text': status}, modifiedCb, None, True) 950 LightTextEditor.__init__(self, {'text': status}, modifiedCb, None, single_line=True)
894 self.edit(False) 951 self.edit(False)
895 self.setStyleName('statusPanel') 952 self.setStyleName('statusPanel')
896 ClickHandler.__init__(self) 953 ClickHandler.__init__(self)
897 self.addClickListener(self) 954 self.addClickListener(self)
898 955