# HG changeset patch # User Goffi # Date 1306628033 -7200 # Node ID d5266c41ca2419fe8dfc0f002e86fa5cebe80a0f # Parent f25c4077f6b937325697fdea0c12a25b84d01a4a Roster list update, contact deletion + some refactoring diff -r f25c4077f6b9 -r d5266c41ca24 browser_side/card_game.py --- a/browser_side/card_game.py Sat May 28 20:18:14 2011 +0200 +++ b/browser_side/card_game.py Sun May 29 02:13:53 2011 +0200 @@ -39,7 +39,7 @@ from pyjamas.dnd import makeDraggable from pyjamas.ui.DragWidget import DragWidget, DragContainer from jid import JID -from dialog import ConfirmDialog, SimpleDialog +from dialog import ConfirmDialog, InfoDialog from tools import html_sanitize from datetime import datetime from time import time @@ -414,4 +414,4 @@ else: title = "You loose :(" body = re.sub(r'<.*?>',lambda x:'
' if '/elem' in x.group(0) else '', xml_data) #Q&D conversion to simple HTML text - SimpleDialog(title, body, _new_game).show() + InfoDialog(title, body, _new_game).show() diff -r f25c4077f6b9 -r d5266c41ca24 browser_side/contact.py --- a/browser_side/contact.py Sat May 28 20:18:14 2011 +0200 +++ b/browser_side/contact.py Sun May 29 02:13:53 2011 +0200 @@ -90,31 +90,53 @@ _item.addMouseListener(self._parent) DOM.setStyleAttribute(_item.getElement(), "cursor", "pointer") VerticalPanel.add(self, _item) + + def remove(self, group): + for wid in self: + if isinstance(wid, GroupLabel) and wid.group == group: + VerticalPanel.remove(self, wid) class ContactList(VerticalPanel): def __init__(self): VerticalPanel.__init__(self) - self.contacts=[] + self.contacts = set() - def __iter__(self): - return self.contacts.__iter__() - def add(self, jid, name=None): + if jid in self.contacts: + return + self.contacts.add(jid) _item = ContactLabel(jid, name) DOM.setStyleAttribute(_item.getElement(), "cursor", "pointer") VerticalPanel.add(self, _item) - self.contacts.append(_item) + + def remove(self, jid): + wid = self.getContactLabel(jid) + if not wid: + return + VerticalPanel.remove(self, wid) + self.contacts.remove(jid) + + def isContactPresent(self, contact_jid): + """Return True if a contact is present in the panel""" + return contact_jid in self.contacts + + def getContacts(self): + return self.contacts + + def getContactLabel(self, contact_jid): + """get contactList widget of a contact + @return: ContactLabel item if present, else None""" + for wid in self: + if isinstance(wid, ContactLabel) and wid.jid == contact_jid: + return wid + return None def setState(self, jid, state): """Change the appearance of the contact, according to the state @param jid: jid which need to change state @param state: 'unavailable' if not connected, else presence like RFC6121 #4.7.2.1""" - _item = None - for contact in self.contacts: - if contact.jid == jid: - _item = contact - break + _item = self.getContactLabel(jid) if _item: if state == 'unavailable': _item.removeStyleName('contactConnected') @@ -151,19 +173,40 @@ self.add(self.vPanel) self.setStyleName('contactBox') - def addContact(self, jid, attributes, groups): - """Add a contact to the panel + def updateContact(self, jid, attributes, groups): + """Add a contact to the panel if it doesn't exist, update it else @param jid: jid @attributes: cf SàT Bridge API's newContact @param groups: list of groups""" - for group in groups: + _current_groups = self.getContactGroups(jid) + _new_groups = set(groups) + _key = "@%s: " + + for group in _current_groups.difference(_new_groups): + #We remove the contact from the groups where he isn't anymore + self.groups[group].remove(jid) + if not self.groups[group]: + #The group is now empty, we must remove it + del self.groups[group] + self._groupList.remove(group) + self.host.uni_box.removeKey(_key % group) + + for group in _new_groups.difference(_current_groups): + #We add the contact to the groups he joined if not self.groups.has_key(group): self.groups[group] = set() self._groupList.add(group) - self.host.uni_box.addKey("@%s: " % group) + self.host.uni_box.addKey(_key % group) self.groups[group].add(jid) + + #We add the contact to contact list, it will check if contact already exists self._contact_list.add(jid) + def removeContact(self, jid): + """Remove contacts from groups where he is and contact list""" + self.updateContact(jid, {}, []) #we remove contact from every group + self._contact_list.remove(jid) + def setConnected(self, jid, resource, availability, priority, statuses): """Set connection status""" if availability=='unavailable': @@ -182,12 +225,23 @@ """return a list of all jid (bare jid) connected""" return self.connected.keys() + def getContactGroups(self, contact_jid): + """Get groups where contact is + @param group: string of single group, or list of string + @param contact_jid: jid to test + """ + result=set() + for group in self.groups: + if self.isContactInGroup(group, contact_jid): + result.add(group) + return result + def isContactInGroup(self, group, contact_jid): """Test if the contact_jid is in the group @param group: string of single group, or list of string @param contact_jid: jid to test @return: True if contact_jid is in on of the groups""" - if self.groups.has_key(group) and contact_jid in self.groups[group]: + if group in self.groups and contact_jid in self.groups[group]: return True return False @@ -198,6 +252,9 @@ return True return False + def getContacts(self): + return self._contact_list.getContacts() + def getGroups(self): return self.groups.keys() diff -r f25c4077f6b9 -r d5266c41ca24 browser_side/dialog.py --- a/browser_side/dialog.py Sat May 28 20:18:14 2011 +0200 +++ b/browser_side/dialog.py Sun May 29 02:13:53 2011 +0200 @@ -87,9 +87,9 @@ def onCancel(self): self.hide() -class ConfirmDialog(DialogBox): +class GenericConfirmDialog(DialogBox): - def __init__(self, callback, text='Are you sure ?'): + def __init__(self, widgets, callback, title='Confirmation'): """ Dialog to confirm an action @param callback: method to call when contacts have been choosed @@ -99,12 +99,14 @@ content = VerticalPanel() content.setWidth('100%') + for wid in widgets: + content.add(wid) button_panel = HorizontalPanel() self.confirm_button = Button("OK", self.onConfirm) button_panel.add(self.confirm_button) button_panel.add(Button("Cancel", self.onCancel)) content.add(button_panel) - self.setHTML(text) + self.setHTML(title) self.setWidget(content) def onConfirm(self): @@ -115,7 +117,12 @@ self.hide() self.callback(False) -class InfoDialog(DialogBox): +class ConfirmDialog(GenericConfirmDialog): + + def __init__(self, callback, text='Are you sure ?', title='Confirmation'): + GenericConfirmDialog.__init__(self,[HTML(text)], callback, title) + +class GenericDialog(DialogBox): """Dialog which just show a widget and a close button""" def __init__(self, title, widget, callback = None): @@ -141,10 +148,10 @@ if self.callback: self.callback() -class SimpleDialog(InfoDialog): +class InfoDialog(GenericDialog): def __init__(self, title, body, callback = None): - InfoDialog.__init__(self, title, HTML(body), callback) + GenericDialog.__init__(self, title, HTML(body), callback) class PopupPanelWrapper(PopupPanel): """This wrapper catch Escape event to avoid request cancellation by Firefox""" diff -r f25c4077f6b9 -r d5266c41ca24 browser_side/panels.py --- a/browser_side/panels.py Sat May 28 20:18:14 2011 +0200 +++ b/browser_side/panels.py Sun May 29 02:13:53 2011 +0200 @@ -79,6 +79,8 @@ menu_contacts = MenuBar(vertical=True) menu_contacts.addItem("add contact", MenuCmd(self, "onAddContact")) + menu_contacts.addItem("update contact", MenuCmd(self, "onUpdateContact")) + menu_contacts.addItem("remove contact", MenuCmd(self, "onRemoveContact")) menu_group = MenuBar(vertical=True) menu_group.addItem("join room", MenuCmd(self, "onJoinRoom")) @@ -134,6 +136,31 @@ _dialog.setHTML('Adding contact') _dialog.show() + def onUpdateContact(self): + pass + + def onRemoveContact(self): + _dialog = None + _contacts_list = ListBox() + + def secondConfirmCb(confirm): + if confirm: + for contact in _contacts_list.getSelectedValues(): + self.host.bridge.call('delContact', None, contact) + else: + _dialog.show() + + def dialogCb(confirm): + if confirm: + html_list = ''.join(['
  • %s
  • ' % html_sanitize(contact) for contact in _contacts_list.getSelectedValues()]) + html_body = "Are you sure to remove the following contacts from your contact list ?" % html_list + dialog.ConfirmDialog(secondConfirmCb, html_body).show() + + for contact in self.host.contact_panel.getContacts(): + _contacts_list.addItem(contact) + _dialog = dialog.GenericConfirmDialog([_contacts_list], dialogCb, "Who do you want to remove from your contacts ?") + _dialog.show() + #Group menu def onJoinRoom(self): _dialog = None @@ -313,6 +340,13 @@ def addKey(self, key): self.getCompletionItems().completions.append(key) + def removeKey(self, key): + try: + self.getCompletionItems().completions.remove(key) + except KeyError: + print "WARNING: trying to remove an unknown key" + + def showWarning(self, target_data): type, target = target_data if type == "PUBLIC": diff -r f25c4077f6b9 -r d5266c41ca24 libervia.py --- a/libervia.py Sat May 28 20:18:14 2011 +0200 +++ b/libervia.py Sun May 29 02:13:53 2011 +0200 @@ -68,7 +68,7 @@ LiberviaJsonProxy.__init__(self, "/json_api", ["getContacts", "addContact", "sendMessage", "sendMblog", "getMblogNodes", "getProfileJid", "getHistory", "getPresenceStatus", "joinMUC", "getRoomJoined", "launchTarotGame", "getTarotCardsPaths", "tarotGameReady", "tarotGameContratChoosed", - "tarotGamePlayCards", "getWaitingSub", "subscription"]) + "tarotGamePlayCards", "getWaitingSub", "subscription", "delContact"]) class BridgeSignals(LiberviaJsonProxy): def __init__(self): @@ -160,7 +160,7 @@ def _getContactsCB(self, contacts_data): for contact in contacts_data: jid, attributes, groups = contact - self.contact_panel.addContact(jid, attributes, groups) + self._newContactCb(jid, attributes, groups) def _getSignalsCB(self, signal_data): bridge_signals = BridgeSignals() @@ -191,6 +191,10 @@ self._tarotGameGenericCb(name, args[0], args[1:]) elif name == 'subscribe': self._subscribeCb(*args) + elif name == 'contactDeleted': + self._contactDeletedCb(*args) + elif name == 'newContact': + self._newContactCb(*args) def _getProfileJidCB(self, jid): self.whoami = JID(jid) @@ -283,10 +287,10 @@ def _subscribeCb(self, sub_type, entity): if sub_type == 'subscribed': - dialog.SimpleDialog('Subscription confirmation', 'The contact %s has added you to his/her contact list' % html_sanitize(entity)).show() + dialog.InfoDialog('Subscription confirmation', 'The contact %s has added you to his/her contact list' % html_sanitize(entity)).show() elif sub_type == 'unsubscribed': - dialog.SimpleDialog('Subscription refusal', 'The contact %s has refused to add you in his/her contact list' % html_sanitize(entity)).show() + dialog.InfoDialog('Subscription refusal', 'The contact %s has refused to add you in his/her contact list' % html_sanitize(entity)).show() elif sub_type == 'subscribe': #The user want to subscribe to our presence @@ -302,7 +306,11 @@ _dialog.setHTML('Add contact request') _dialog.show() - + def _contactDeletedCb(self, entity): + self.contact_panel.removeContact(entity) + + def _newContactCb(self, contact, attributes, groups): + self.contact_panel.updateContact(contact, attributes, groups) if __name__ == '__main__': pyjd.setup("http://localhost:8080/libervia.html") diff -r f25c4077f6b9 -r d5266c41ca24 libervia.tac --- a/libervia.tac Sat May 28 20:18:14 2011 +0200 +++ b/libervia.tac Sun May 29 02:13:53 2011 +0200 @@ -148,6 +148,11 @@ self.sat_host.bridge.addContact(entity, profile) self.sat_host.bridge.updateContact(entity, name, groups, profile) + def jsonrpc_delContact(self, entity): + """Remove contact from contacts list""" + profile = ISATSession(self.session).profile + self.sat_host.bridge.delContact(entity, profile) + def jsonrpc_subscription(self, sub_type, entity, name, groups): """Confirm (or infirm) subscription, and setup user roster in case of subscription""" @@ -579,7 +584,7 @@ self.bridge.register("actionResult", self.action_handler.actionResultCb, "request") for signal_name in ['presenceUpdate', 'personalEvent', 'newMessage', 'roomJoined', 'roomUserJoined', 'roomUserLeft', 'tarotGameStarted', 'tarotGameNew', 'tarotGameChooseContrat', 'tarotGameShowCards', 'tarotGameInvalidCards', 'tarotGameCardsPlayed', 'tarotGameYourTurn', 'tarotGameScore', - 'subscribe']: + 'subscribe', 'contactDeleted', 'newContact']: self.bridge.register(signal_name, self.signal_handler.getGenericCb(signal_name)) root.putChild('json_signal_api', self.signal_handler) root.putChild('json_api', MethodHandler(self))