# HG changeset patch # User Goffi # Date 1423247490 -3600 # Node ID a6b9809b9a6818f8f53605cf52eb38bae1c127c5 # Parent ed6d8f7c60263c172029d5f0f649f28ccd4c98e6# Parent e11e34ac0f672aa81a2cd8ab19b47a37f688e42f merged souliane commits diff -r e11e34ac0f67 -r a6b9809b9a68 src/browser/libervia_main.py --- a/src/browser/libervia_main.py Fri Feb 06 17:52:26 2015 +0100 +++ b/src/browser/libervia_main.py Fri Feb 06 19:31:30 2015 +0100 @@ -505,7 +505,7 @@ mblog_entry = blog.MicroblogItem(data) for widget in self.widgets.getWidgets(blog.MicroblogPanel): - self.addBlogEntry(widget, sender, _groups, mblog_entry) + widget.addEntryIfAccepted(sender, _groups, mblog_entry) if sender == self.whoami.bare: found = False @@ -533,24 +533,15 @@ self.mblog_cache.remove(entry) break - def addBlogEntry(self, mblog_panel, sender, _groups, mblog_entry): - """Check if an entry can go in MicroblogPanel and add to it - @param mblog_panel: MicroblogPanel instance - @param sender: jid of the entry sender - @param _groups: groups which can receive this entry - @param mblog_entry: panels.MicroblogItem instance""" - if mblog_entry.type == "comment" or mblog_panel.isJidAccepted(sender) or (_groups == None and self.whoami and sender == self.whoami.bare) \ - or (_groups and _groups.intersection(mblog_panel.accepted_groups)): - mblog_panel.addEntry(mblog_entry) - def FillMicroblogPanel(self, mblog_panel): """Fill a microblog panel with entries in cache + @param mblog_panel: MicroblogPanel instance """ #XXX: only our own entries are cached for cache_entry in self.mblog_cache: _groups, mblog_entry = cache_entry - self.addBlogEntry(mblog_panel, self.whoami.bare, *cache_entry) + mblog_panel.addEntryIfAccepted(self.whoami.bare, *cache_entry) def getEntityMBlog(self, entity): log.info("geting mblog for entity [%s]" % (entity,)) diff -r e11e34ac0f67 -r a6b9809b9a68 src/browser/public/libervia.css --- a/src/browser/public/libervia.css Fri Feb 06 17:52:26 2015 +0100 +++ b/src/browser/public/libervia.css Fri Feb 06 19:31:30 2015 +0100 @@ -813,6 +813,12 @@ /* BorderWidgets */ +.borderWidgetOnDrag { + background-color: lightgray; + border: 1px dashed #000; + border-radius: 1em; +} + .bottomBorderWidget { height: 10px !important; } @@ -821,6 +827,14 @@ width: 10px !important; } +.leftBorderWidget { + float: right; +} + +.rightBorderWidget { + float: left; +} + /* Microblog */ .microblogPanel { diff -r e11e34ac0f67 -r a6b9809b9a68 src/browser/sat_browser/base_widget.py --- a/src/browser/sat_browser/base_widget.py Fri Feb 06 17:52:26 2015 +0100 +++ b/src/browser/sat_browser/base_widget.py Fri Feb 06 19:31:30 2015 +0100 @@ -20,6 +20,7 @@ import pyjd # this is dummy in pyjs from sat.core.log import getLogger log = getLogger(__name__) +from sat_frontends.quick_frontend import quick_widgets from pyjamas.ui.SimplePanel import SimplePanel from pyjamas.ui.AbsolutePanel import AbsolutePanel from pyjamas.ui.VerticalPanel import VerticalPanel @@ -47,23 +48,42 @@ class DragLabel(DragWidget): - def __init__(self, text, _type): + def __init__(self, text, type_, host=None): + """Base of Drag n Drop mecanism in Libervia + + @param text: data embedded with in drag n drop operation + @param type_: type of data that we are dragging + @param host: if not None, the host will be use to highlight BorderWidgets + """ DragWidget.__init__(self) + self.host = host self._text = text - self._type = _type + self.type_ = type_ def onDragStart(self, event): dt = event.dataTransfer - dt.setData('text/plain', "%s\n%s" % (self._text, self._type)) + dt.setData('text/plain', "%s\n%s" % (self._text, self.type_)) dt.setDragImage(self.getElement(), 15, 15) + if self.host is not None: + current_panel = self.host.tab_panel.getCurrentPanel() + for widget in current_panel.widgets: + if isinstance(widget, BorderWidget): + widget.addStyleName('borderWidgetOnDrag') + + def onDragEnd(self, event): + if self.host is not None: + current_panel = self.host.tab_panel.getCurrentPanel() + for widget in current_panel.widgets: + if isinstance(widget, BorderWidget): + widget.removeStyleName('borderWidgetOnDrag') class LiberviaDragWidget(DragLabel): """ A DragLabel which keep the widget being dragged as class value """ current = None # widget currently dragged - def __init__(self, text, _type, widget): - DragLabel.__init__(self, text, _type) + def __init__(self, text, type_, widget): + DragLabel.__init__(self, text, type_, widget.host) self.widget = widget def onDragStart(self, event): @@ -71,6 +91,7 @@ DragLabel.onDragStart(self, event) def onDragEnd(self, event): + DragLabel.onDragEnd(self, event) LiberviaDragWidget.current = None @@ -84,8 +105,14 @@ self.setStyleName('dropCell') @classmethod - def addDropKey(cls, key, callback): - DropCell.drop_keys[key] = callback + def addDropKey(cls, key, cb): + """Add a association between a key and a class to create on drop + + @param key: key to be associated (e.g. "CONTACT", "CHAT") + @param cb: either a LiberviaWidget instance, or a callback which return one + """ + DropCell.drop_keys[key] = cb + def onDragEnter(self, event): if self == LiberviaDragWidget.current: @@ -148,7 +175,7 @@ log.warning("unmanaged item type") return if isinstance(self, LiberviaWidget): - self.host.unregisterWidget(self) + # self.host.unregisterWidget(self) # FIXME self.onQuit() if not isinstance(_new_panel, LiberviaWidget): log.warning("droping an object which is not a class of LiberviaWidget") @@ -164,7 +191,8 @@ for panel in _unempty_panels: td_elt = panel.getElement().parentNode DOM.setStyleAttribute(td_elt, "width", "%s%%" % _width)""" - #FIXME: delete object ? Check the right way with pyjamas + if isinstance(self, quick_widgets.QuickWidget): + self.host.widgets.deleteWidget(self) class WidgetMenuBar(base_menu.GenericMenuBar): @@ -554,7 +582,11 @@ # dropping a widget there will add a new row td_elt = _bottom.getElement().parentNode DOM.setStyleAttribute(td_elt, "height", "1px") # needed so the cell adapt to the size of the border (specially in webkit) - self._max_cols = 1 # give the maximum number of columns i a raw + self._max_cols = 1 # give the maximum number of columns in a raw + + @property + def widgets(self): + return iter(self.flextable) def isLocked(self): return self.locked @@ -563,17 +595,16 @@ """Change the widget in the given location, add row or columns when necessary""" log.debug("changing widget: %s %s %s" % (wid.getDebugName(), row, col)) last_row = max(0, self.flextable.getRowCount() - 1) - try: - prev_wid = self.flextable.getWidget(row, col) - except: - log.error("Trying to change an unexisting widget !") - return + # try: # FIXME: except without exception specified ! + prev_wid = self.flextable.getWidget(row, col) + # except: + # log.error("Trying to change an unexisting widget !") + # return cellFormatter = self.flextable.getFlexCellFormatter() if isinstance(prev_wid, BorderWidget): # We are on a border, we must create a row and/or columns - log.debug("BORDER WIDGET") prev_wid.removeStyleName('dragover') if isinstance(prev_wid, BottomBorderWidget): diff -r e11e34ac0f67 -r a6b9809b9a68 src/browser/sat_browser/blog.py --- a/src/browser/sat_browser/blog.py Fri Feb 06 17:52:26 2015 +0100 +++ b/src/browser/sat_browser/blog.py Fri Feb 06 19:31:30 2015 +0100 @@ -215,7 +215,7 @@ self.entry_dialog.setWidth('auto') try: self.toggle_syntax_button.removeFromParent() - except TypeError: + except (AttributeError, TypeError): pass def __setBubble(self, edit=False): @@ -234,7 +234,7 @@ self.bubble.addStyleName("bubble") try: self.toggle_syntax_button.removeFromParent() - except TypeError: + except (AttributeError, TypeError): pass self.entry_dialog.add(self.bubble) self.edit(edit) @@ -297,7 +297,7 @@ entry = self try: entry.toggle_syntax_button.removeFromParent() - except TypeError: + except (AttributeError, TypeError): pass entry.bubble.edit(edit) if edit: @@ -372,6 +372,9 @@ self.vpanel.setStyleName('microblogPanel') self.setWidget(self.vpanel) + def __str__(self): + return u"Blog Widget [target: {}, profile: {}]".format(self.target, self.profile) + @property def target(self): return tuple(self.accepted_groups) @@ -411,33 +414,23 @@ assert(first.type == 'main_item') return first if first.empty else None - @classmethod - def registerClass(cls): - base_widget.LiberviaWidget.addDropKey("GROUP", cls.createPanel) - base_widget.LiberviaWidget.addDropKey("CONTACT_TITLE", cls.createMetaPanel) + @staticmethod + def onGroupDrop(host, item): + """Generic panel creation for one, several or all groups (meta). - @classmethod - def createPanel(cls, host, item): - """Generic panel creation for one, several or all groups (meta). @parem host: the SatWebFrontend instance @param item: single group as a string, list of groups (as an array) or None (for the meta group = "all groups") @return: the created MicroblogPanel """ - _items = item if isinstance(item, list) else ([] if item is None else [item]) - _type = 'ALL' if _items == [] else 'GROUP' + items_ = tuple(item) if isinstance(item, list) else (() if item is None else (item,)) + type_ = 'ALL' if items_ == () else 'GROUP' # XXX: pyjamas doesn't support use of cls directly - _new_panel = MicroblogPanel(host, _items) - host.FillMicroblogPanel(_new_panel) - host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, _type, _items, 10) - host.setSelected(_new_panel) - _new_panel.refresh() - return _new_panel - - @classmethod - def createMetaPanel(cls, host, item): - """Needed for the drop keys to not be mixed between meta panel and panel for "Contacts" group""" - return MicroblogPanel.createPanel(host, None) + widget = host.widgets.getOrCreateWidget(MicroblogPanel, items_, profile=C.PROF_KEY_NONE, on_new_widget=None, on_existing_widget=C.WIDGET_RECREATE) + host.FillMicroblogPanel(widget) + host.bridge.getMassiveLastMblogs(type_, items_, 10, profile=C.PROF_KEY_NONE, callback=widget.massiveInsert) + widget.refresh() # FIXME: needed ? + return widget @property def accepted_groups(self): @@ -544,8 +537,23 @@ vpanel.insert(entry, idx) - def addEntry(self, data): + + def addEntryIfAccepted(self, sender, groups, mblog_entry): + """Check if an entry can go in MicroblogPanel and add to it + + @param sender: jid of the entry sender + @param groups: groups which can receive this entry + @param mblog_entry: panels.MicroblogItem instance + """ + if (mblog_entry.type == "comment" + or self.isJidAccepted(sender) + or (groups == None and sender == self.host.profiles[self.profile].whoami.bare) + or (groups and groups.intersection(self.accepted_groups))): + self.addEntry(mblog_entry) + + def addEntry(self, data, ignore_invalid=False): """Add an entry to the panel + @param data: dict containing the item data @return: the added entry, or None """ @@ -686,13 +694,21 @@ self._accepted_groups = groups self._accepted_groups.sort() - def isJidAccepted(self, jid_s): - """Tell if a jid is actepted and shown in this panel - @param jid_s: jid - @return: True if the jid is accepted""" + def isJidAccepted(self, jid_): + """Tell if a jid is actepted and must be shown in this panel + + @param jid_(jid.JID): jid to check + @return: True if the jid is accepted + """ if self.accept_all(): return True for group in self._accepted_groups: - if self.host.contact_panel.isContactInGroup(group, jid_s): + if self.host.contact_lists[self.profile].isEntityInGroup(jid_, group): return True return False + + +base_widget.LiberviaWidget.addDropKey("GROUP", MicroblogPanel.onGroupDrop) + +# Needed for the drop keys to not be mixed between meta panel and panel for "Contacts" group +base_widget.LiberviaWidget.addDropKey("CONTACT_TITLE", lambda host, item: MicroblogPanel.onGroupDrop(host, None)) diff -r e11e34ac0f67 -r a6b9809b9a68 src/browser/sat_browser/chat.py --- a/src/browser/sat_browser/chat.py Fri Feb 06 17:52:26 2015 +0100 +++ b/src/browser/sat_browser/chat.py Fri Feb 06 19:31:30 2015 +0100 @@ -77,7 +77,8 @@ @param host: SatWebFrontend instance @param target: entity (jid.JID) with who we have a conversation (contact's jid for one 2 one chat, or MUC room) - @param type: one2one for simple conversation, group for MUC""" + @param type: one2one for simple conversation, group for MUC + """ QuickChat.__init__(self, host, target, type_, profiles=profiles) self.vpanel = VerticalPanel() self.vpanel.setSize('100%', '100%') @@ -127,20 +128,16 @@ assert len(self.profiles) == 1 and not self.PROFILES_MULTIPLE and not self.PROFILES_ALLOW_NONE return list(self.profiles)[0] - @classmethod - def registerClass(cls): - base_widget.LiberviaWidget.addDropKey("CONTACT", cls.createPanel) - - @classmethod - def createPanel(cls, host, item, type_=C.CHAT_ONE2ONE): - assert(item) - _contact = item if isinstance(item, jid.JID) else jid.JID(item) - host.contact_panel.setContactMessageWaiting(_contact.bare, False) - _new_panel = Chat(host, _contact, type_) # XXX: pyjamas doesn't seems to support creating with cls directly - _new_panel.historyPrint() - host.setSelected(_new_panel) - _new_panel.refresh() - return _new_panel + # @classmethod + # def createPanel(cls, host, item, type_=C.CHAT_ONE2ONE): + # assert(item) + # _contact = item if isinstance(item, jid.JID) else jid.JID(item) + # host.contact_panel.setContactMessageWaiting(_contact.bare, False) + # _new_panel = Chat(host, _contact, type_) # XXX: pyjamas doesn't seems to support creating with cls directly + # _new_panel.historyPrint() + # host.setSelected(_new_panel) + # _new_panel.refresh() + # return _new_panel def refresh(self): """Refresh the display of this widget. If the unibox is disabled, @@ -361,4 +358,6 @@ #TODO pass + quick_widgets.register(QuickChat, Chat) +base_widget.LiberviaWidget.addDropKey("CONTACT", lambda host, item: host.widgets.getOrCreateWidget(Chat, jid.JID(item), profile=C.PROF_KEY_NONE, on_new_widget=None, on_existing_widget=C.WIDGET_RECREATE)) diff -r e11e34ac0f67 -r a6b9809b9a68 src/browser/sat_browser/contact_list.py --- a/src/browser/sat_browser/contact_list.py Fri Feb 06 17:52:26 2015 +0100 +++ b/src/browser/sat_browser/contact_list.py Fri Feb 06 19:31:30 2015 +0100 @@ -73,10 +73,9 @@ class GroupLabel(base_widget.DragLabel, Label, ClickHandler): def __init__(self, host, group): self.group = group - self.host = host Label.__init__(self, group) # , Element=DOM.createElement('div') self.setStyleName('group') - base_widget.DragLabel.__init__(self, group, "GROUP") + base_widget.DragLabel.__init__(self, group, "GROUP", host) ClickHandler.__init__(self) self.addClickListener(self) @@ -125,8 +124,7 @@ def __init__(self, host, jid_, name=None, click_listener=None, handle_menu=None): VerticalPanel.__init__(self, StyleName='contactBox', VerticalAlignment='middle') - base_widget.DragLabel.__init__(self, jid_, "CONTACT") - self.host = host + base_widget.DragLabel.__init__(self, jid_, "CONTACT", host) self.jid = jid_ self.label = ContactLabel(jid_, name) self.avatar = ContactMenuBar(self, host) if handle_menu else Image() @@ -306,9 +304,8 @@ class ContactTitleLabel(base_widget.DragLabel, Label, ClickHandler): def __init__(self, host, text): Label.__init__(self, text) # , Element=DOM.createElement('div') - self.host = host self.setStyleName('contactTitle') - base_widget.DragLabel.__init__(self, text, "CONTACT_TITLE") + base_widget.DragLabel.__init__(self, text, "CONTACT_TITLE", host) ClickHandler.__init__(self) self.addClickListener(self) @@ -348,7 +345,7 @@ try: # XXX: Pyjamas doesn't do the set casting if None is present _keys.remove(None) - except KeyError: + except (KeyError, ValueError): # XXX: error raised depend on pyjama's compilation options pass current_groups = set(_keys) shown_groups = self._group_panel.getGroups() diff -r e11e34ac0f67 -r a6b9809b9a68 src/browser/sat_browser/richtext.py --- a/src/browser/sat_browser/richtext.py Fri Feb 06 17:52:26 2015 +0100 +++ b/src/browser/sat_browser/richtext.py Fri Feb 06 19:31:30 2015 +0100 @@ -51,6 +51,7 @@ @param afterEditCb: method to be called when the edition is done @param options: list of UI options (see self.readOptions) """ + FlexTable.__init__(self) # FIXME self.host = host self._debug = False # TODO: don't forget to set it False before commit self.wysiwyg = False @@ -84,7 +85,7 @@ else: self.title_offset = self.toolbar_offset = self.content_offset = y_offset self.command_offset = self.content_offset + 1 - FlexTable.__init__(self, self.command_offset + (0 if self.no_command else 1), 2) + # FlexTable.__init__(self, rowspan=self.command_offset + (0 if self.no_command else 1), colspan=2) # FIXME self.addStyleName(self.style['main']) def addEditListener(self, listener): @@ -174,14 +175,14 @@ self.wysiwyg = wysiwyg try: self.wysiwyg_button.setChecked(wysiwyg) - except TypeError: + except (AttributeError, TypeError): pass try: if wysiwyg: self.syntax_label.addStyleName('transparent') else: self.syntax_label.removeStyleName('transparent') - except TypeError: + except (AttributeError, TypeError): pass if not wysiwyg: self.display.removeStyleName('richTextWysiwyg')