Mercurial > libervia-backend
changeset 51:8c67ea98ab91
frontend improved to take into account new SàT features
- quick_frontend: better use of contact management, it now manages nicks, avatars, and connected status
- quick_frontend: disconnect and remove are now 2 separate methods for contact list
- wix: new contact list using HTML items, and showing avatars. Groups are not showed for now
- wix: contact status now use tuples, to keep order, human readable status and color of contact
- wix: contact list is updated when avatar or nick is found
- wix: fixed 'question' dialog, which is renamed in 'yes/no'
- wix: action result are now ignored for unkwnown id
- sortilege refactored to work again
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 07 Jan 2010 00:17:27 +1100 |
parents | daa1f01a5332 |
children | 6455fb62ff83 |
files | frontends/quick_frontend/quick_app.py frontends/quick_frontend/quick_chat_list.py frontends/quick_frontend/quick_contact_list.py frontends/quick_frontend/quick_contact_management.py frontends/sat_bridge_frontend/DBus.py frontends/sortilege/sortilege frontends/wix/main_window.py |
diffstat | 7 files changed, 286 insertions(+), 196 deletions(-) [+] |
line wrap: on
line diff
--- a/frontends/quick_frontend/quick_app.py Thu Jan 07 00:05:15 2010 +1100 +++ b/frontends/quick_frontend/quick_app.py Thu Jan 07 00:17:27 2010 +1100 @@ -22,23 +22,23 @@ from logging import debug, info, error from tools.jid import JID from sat_bridge_frontend.DBus import DBusBridgeFrontend -from quick_frontend.quick_contact_management import QuickContactManagement - +import pdb class QuickApp(): """This class contain the main methods needed for the frontend""" def __init__(self): self.rosterList = {} - self.CM = QuickContactManagement() #a short name if more handy ## bridge ## self.bridge=DBusBridgeFrontend() self.bridge.register("newContact", self.newContact) self.bridge.register("newMessage", self.newMessage) self.bridge.register("presenceUpdate", self.presenceUpdate) + self.bridge.register("subscribe", self.subscribe) self.bridge.register("paramUpdate", self.paramUpdate) self.bridge.register("contactDeleted", self.contactDeleted) + self.bridge.register("updatedValue", self.updatedValue, "request") self.bridge.register("askConfirmation", self.askConfirmation, "request") self.bridge.register("actionResult", self.actionResult, "request") self.bridge.register("actionResultExt", self.actionResult, "request") @@ -59,13 +59,23 @@ for contact in self.bridge.getContacts(): self.newContact(contact[0], contact[1], contact[2]) - for status in self.bridge.getPresenceStatus(): - self.presenceUpdate(status[0], status[1], status[2], status[3], status[4]) + presences = self.bridge.getPresenceStatus() + for contact in presences: + for res in presences[contact]: + jabber_id = contact+('/'+res if res else '') + show = presences[contact][res][0] + priority = presences[contact][res][1] + statuses = presences[contact][res][2] + self.presenceUpdate(jabber_id, show, priority, statuses) + + waitingSub = self.bridge.getWaitingSub() + for sub in waitingSub: + self.subscribe(waitingSub[sub], sub) def newContact(self, JabberId, attributes, groups): - jid=JID(JabberId) - self.rosterList[jid.short]=(dict(attributes), list(groups)) + entity=JID(JabberId) + self.rosterList[entity.short]=(dict(attributes), list(groups)) def newMessage(self, from_jid, msg, type, to_jid): sender=JID(from_jid) @@ -76,64 +86,66 @@ def setStatusOnline(self, online=True): pass - def presenceUpdate(self, jabber_id, type, show, status, priority): - debug ("presence update for %s (type=%s, show=%s, status=%s)", jabber_id, type, show, status); - jid=JID(jabber_id) - debug ("jid.short=%s whoami.short=%s", jid.short, self.whoami.short) + def presenceUpdate(self, jabber_id, show, priority, statuses): + debug ("presence update for %s (show=%s, statuses=%s)", jabber_id, show, statuses); + from_jid=JID(jabber_id) + debug ("from_jid.short=%s whoami.short=%s", from_jid.short, self.whoami.short) - ### subscription management ### - if type=="subscribed": - # this is a subscription confirmation, we just have to inform user - self.showDialog("The contact %s has accepted your subscription" % jid.short, 'Subscription confirmation') - return - elif type=="unsubscribed": - # this is a subscription refusal, we just have to inform user - self.showDialog("The contact %s has refused your subscription" % jid.short, 'Subscription refusal', 'error') - return - elif type=="subscribe": - # this is a subscrition request, we have to ask for user confirmation - answer = self.showDialog("The contact %s wants to subscribe to your presence.\nDo you accept ?" % jid.short, 'Subscription confirmation', 'question') - if answer: - self.bridge.setPresence(type="subscribed", to=jid.short) - else: - self.bridge.setPresence(type="unsubscribed", to=jid.short) - return - ### subscription management end ### - - if jid.short==self.whoami.short: + if from_jid.short==self.whoami.short: if not type: self.setStatusOnline(True) elif type=="unavailable": self.setStatusOnline(False) return - if not type: + if show != 'unavailable': name="" group="" - if self.rosterList.has_key(jid.short): - if self.rosterList[jid.short][0].has_key("name"): - name=self.rosterList[jid.short][0]["name"] - if self.rosterList[jid.short][0].has_key("show"): - name=self.rosterList[jid.short][0]["show"] - if self.rosterList[jid.short][0].has_key("status"): - name=self.rosterList[jid.short][0]["status"] - if len(self.rosterList[jid.short][1]): - group=self.rosterList[jid.short][1][0] + if self.rosterList.has_key(from_jid.short): + if self.rosterList[from_jid.short][0].has_key("name"): + name=self.rosterList[from_jid.short][0]["name"] + if len(self.rosterList[from_jid.short][1]): + group=self.rosterList[from_jid.short][1][0] #FIXME: must be moved in a plugin - if jid.short in self.watched and not jid.short in self.onlineContact: - self.showAlert("Watched jid [%s] is connected !" % jid.short) + if from_jid.short in self.watched and not from_jid.short in self.onlineContact: + self.showAlert("Watched jid [%s] is connected !" % from_jid.short) - self.onlineContact.add(jid) #FIXME onlineContact is useless with CM, must be removed - self.CM.add(jid) - self.contactList.replace(jid, show=show, status=status, name=name, group=group) + self.onlineContact.add(from_jid) #FIXME onlineContact is useless with CM, must be removed + self.CM.add(from_jid) + self.CM.update(from_jid, 'name', name) + self.CM.update(from_jid, 'show', show) + self.CM.update(from_jid, 'statuses', statuses) + self.CM.update(from_jid, 'group', group) + cache = self.bridge.getProfileCache(from_jid) + if cache.has_key('nick'): + self.CM.update(from_jid, 'nick', cache['nick']) + if cache.has_key('avatar'): + self.CM.update(from_jid, 'avatar', self.bridge.getAvatarFile(cache['avatar'])) + self.contactList.replace(from_jid) + if show=="unavailable" and from_jid in self.onlineContact: + self.onlineContact.remove(from_jid) + self.CM.remove(from_jid) + if not self.CM.isConnected(from_jid): + self.contactList.disconnect(from_jid) - if type=="unavailable" and jid in self.onlineContact: - self.onlineContact.remove(jid) - self.CM.remove(jid) - self.contactList.remove(jid) - + def subscribe(self, type, raw_jid): + """Called when a subsciption maangement signal is received""" + entity = JID(raw_jid) + if type=="subscribed": + # this is a subscription confirmation, we just have to inform user + self.showDialog("The contact %s has accepted your subscription" % entity.short, 'Subscription confirmation') + elif type=="unsubscribed": + # this is a subscription refusal, we just have to inform user + self.showDialog("The contact %s has refused your subscription" % entity.short, 'Subscription refusal', 'error') + elif type=="subscribe": + # this is a subscriptionn request, we have to ask for user confirmation + answer = self.showDialog("The contact %s wants to subscribe to your presence.\nDo you accept ?" % entity.short, 'Subscription confirmation', 'yes/no') + if answer: + self.bridge.subscription("subscribed", entity.short) + else: + self.bridge.subscribed("unsubscribed", entity.short) def showDialog(self, message, title, type="info"): raise NotImplementedError @@ -151,13 +163,26 @@ def contactDeleted(self, jid): target = JID(jid) + self.CM.remove(target) + self.contactList.remove(self.CM.get_full(target)) try: self.onlineContact.remove(target.short) except KeyError: pass - self.contactList.remove(self.CM.get_full(jid)) - self.CM.remove(target) - + + def updatedValue(self, name, data): + print "toto" + print "updatedValue", name, data + if name == "profile_nick": + target = JID(data['jid']) + self.CM.update(target, 'nick', data['nick']) + self.contactList.replace(target) + elif name == "profile_avatar": + target = JID(data['jid']) + filename = self.bridge.getAvatarFile(data['avatar']) + self.CM.update(target, 'avatar', filename) + self.contactList.replace(target) + def askConfirmation(self, type, id, data): raise NotImplementedError
--- a/frontends/quick_frontend/quick_chat_list.py Thu Jan 07 00:05:15 2010 +1100 +++ b/frontends/quick_frontend/quick_chat_list.py Thu Jan 07 00:17:27 2010 +1100 @@ -30,12 +30,12 @@ dict.__init__(self) self.host = host - def __getitem__(self,name_param): - name=JID(name_param).short - if not self.has_key(name): + def __getitem__(self,to_jid): + target=JID(to_jid) + if not self.has_key(target.short): #we have to create the chat win - self[name] = self.createChat(name) - return dict.__getitem__(self,name) + self[target.short] = self.createChat(target) + return dict.__getitem__(self,target.short) - def createChat(self, name): + def createChat(self, target): raise NotImplementedError
--- a/frontends/quick_frontend/quick_contact_list.py Thu Jan 07 00:05:15 2010 +1100 +++ b/frontends/quick_frontend/quick_contact_list.py Thu Jan 07 00:17:27 2010 +1100 @@ -24,19 +24,27 @@ class QuickContactList(): + """This class manage the visual representation of contacts""" - def __init__(self): + def __init__(self, CM): + """ + @param CM: instance of QuickContactManagement + """ debug("Contact List init") - self.jid_ids={} + self.CM = CM - def replace(self, jid, name="", show="", status="", group=""): - """add a contact to the list""" + def replace(self, jid): + """add a contact to the list if doesn't exist, else update it""" + raise NotImplementedError + + def disconnect(self, jid): + """mark a contact disconnected""" raise NotImplementedError def remove(self, jid): """remove a contact from the list""" raise NotImplementedError - def add(self, jid, name="", show="", status="", group=""): + def add(self, jid): """add a contact to the list""" raise NotImplementedError
--- a/frontends/quick_frontend/quick_contact_management.py Thu Jan 07 00:05:15 2010 +1100 +++ b/frontends/quick_frontend/quick_contact_management.py Thu Jan 07 00:17:27 2010 +1100 @@ -19,29 +19,68 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. """ -from logging import debug, info, error +from logging import debug, info, warning, error from tools.jid import JID import pdb class QuickContactManagement(): """This helper class manage the contacts and ease the use of nicknames and shortcuts""" + ### FIXME: is SàT a better place for all this stuff ??? ### def __init__(self): self.__contactlist = {} - def add(self, jid_param): - jid=JID(jid_param) - self.__contactlist[jid.short] = {'name':jid, 'last_resource':jid.resource} + def add(self, entity): + """Add contact to the list, update resources""" + if not self.__contactlist.has_key(entity.short): + self.__contactlist[entity.short] = {'resources':[]} + if entity.resource in self.__contactlist[entity.short]['resources']: + self.__contactlist[entity.short]['resources'].remove(entity.resource) + self.__contactlist[entity.short]['resources'].append(entity.resource) - def remove(self, jid_param): - jid=JID(jid_param) + def getAttr(self, entity, name): + """Return a specific attribute of contact, or all attributes + @param entity: jid of the contact + @param name: name of the attribute + @return: asked attribute""" + if self.__contactlist.has_key(entity.short): + if name == 'status': #FIXME: for the moment, we only use the first status + if self.__contactlist[entity.short]['statuses']: + return self.__contactlist[entity.short]['statuses'].values()[0] + if self.__contactlist[entity.short].has_key(name): + return self.__contactlist[entity.short][name] + else: + debug('Trying to get attribute for an unknown contact') + return None + + def isConnected(self, entity): + """Tell if the contact is online""" + print "is connected (%s): %s" %(entity, str(self.__contactlist.has_key(entity.short))) #gof + return self.__contactlist.has_key(entity.short) + + def remove(self, entity): + """remove resource. If no more resource is online or is no resource is specified, contact is deleted""" try: - del self.__contactlist[jid.short] + if entity.resource: + self.__contactlist[entity.short]['resources'].remove(entity.resource) + if not entity.resource or not self.__contactlist[entity.short]['resources']: + #no more resource available: the contact seems really disconnected + del self.__contactlist[entity.short] except KeyError: pass - def get_full(self, jid_param): - jid=JID(jid_param) - return jid.short+'/'+self.__contactlist[jid.short]['last_resource'] + def update(self, entity, key, value): + """Update attribute of contact + @param entity: jid of the contact + @param key: name of the attribute + @param value: value of the attribute + """ + if self.__contactlist.has_key(entity.short): + self.__contactlist[entity.short][key] = value + else: + debug ('Trying to update an uknown contact: %s', entity.short) + + def get_full(self, entity): + return entity.short+'/'+self.__contactlist[entity.short]['resources'][-1]
--- a/frontends/sat_bridge_frontend/DBus.py Thu Jan 07 00:05:15 2010 +1100 +++ b/frontends/sat_bridge_frontend/DBus.py Thu Jan 07 00:17:27 2010 +1100 @@ -52,6 +52,9 @@ def getPresenceStatus(self): return self.db_comm_iface.getPresenceStatus() + def getWaitingSub(self): + return self.db_comm_iface.getWaitingSub() + def sendMessage(self, to, message): return self.db_comm_iface.sendMessage(to, message) @@ -64,14 +67,20 @@ def getProfile(self, target): return self.db_comm_iface.getProfile(target) + def getProfileCache(self, target): + return self.db_comm_iface.getProfileCache(target) + def getAvatarFile(self, hash): return self.db_comm_iface.getAvatarFile(hash) def in_band_register(self, target): return self.db_comm_iface.in_band_register(target) - def setPresence(self, to="", type="", show="", status="", priority=0): - return self.db_comm_iface.setPresence(to, type, show, status, priority) + def setPresence(self, to="", show="", priority=0, statuses={}): + return self.db_comm_iface.setPresence(to, show, priority, statuses) + + def subscription(self, type, entity): + return self.db_comm_iface.subscription(type, entity) def setParam(self, name, value, category): return self.db_comm_iface.setParam(name, value, category)
--- a/frontends/sortilege/sortilege Thu Jan 07 00:05:15 2010 +1100 +++ b/frontends/sortilege/sortilege Thu Jan 07 00:17:27 2010 +1100 @@ -43,6 +43,7 @@ from quick_frontend.quick_chat_list import QuickChatList from quick_frontend.quick_contact_list import QuickContactList from quick_frontend.quick_app import QuickApp +from quick_frontend.quick_contact_management import QuickContactManagement ### logging configuration FIXME: put this elsewhere ### logging.basicConfig(level=logging.CRITICAL, #TODO: configure it top put messages in a log file @@ -80,8 +81,10 @@ class ContactList(Window, QuickContactList): - def __init__(self): - QuickContactList.__init__(self) + def __init__(self, host, CM): + QuickContactList.__init__(self, CM) + self.host = host + self.jid_list = [] self.__index=0 #indicate which contact is selected (ie: where we are) Window.__init__(self, stdscr, stdscr.getmaxyx()[0]-2,const_CONTACT_WIDTH,0,0, True, "Contact List", code=code) @@ -98,14 +101,15 @@ def registerEnterCB(self, CB): self.__enterCB=CB - def replace(self, jid, name="", show="", status="", group=""): + def replace(self, jid): """add a contact to the list""" - self.jid_ids[jid] = name or jid + name = self.CM.getAttr(jid,'name') + self.jid_list.append(jid.short) self.update() def indexUp(self): """increment select contact index""" - if self.__index < len(self.jid_ids)-1: #we dont want to select a missing contact + if self.__index < len(self.jid_list)-1: #we dont want to select a missing contact self.__index = self.__index + 1 self.update() @@ -115,11 +119,15 @@ self.__index = self.__index - 1 self.update() + def disconnect(self, jid): + """for now, we just remove the contact""" + self.remove(jid) + def remove(self, jid): """remove a contact from the list""" - del self.jid_ids[jid] - if self.__index >= len(self.jid_ids) and self.__index > 0: #if select index is out of border, we put it on the last contact - self.__index = len(self.jid_ids)-1 + self.jid_list.remove(jid.short) + if self.__index >= len(self.jid_list) and self.__index > 0: #if select index is out of border, we put it on the last contact + self.__index = len(self.jid_list)-1 self.update() def update(self): @@ -127,13 +135,10 @@ if self.isHidden(): return Window.update(self) - viewList=[] - for jid in self.jid_ids: - viewList.append(self.jid_ids[jid]) - viewList.sort() + self.jid_list.sort() begin=0 if self.__index<self.rHeight else self.__index-self.rHeight+1 idx=0 - for item in viewList[begin:self.rHeight+begin]: + for item in self.jid_list[begin:self.rHeight+begin]: attr = curses.A_REVERSE if ( self.isActive() and (idx+begin) == self.__index ) else 0 centered = item.center(self.rWidth) ## it's nicer in the center :) self.addYXStr(idx, 0, centered, attr) @@ -147,10 +152,10 @@ elif k == curses.KEY_DOWN: self.indexUp() elif k == ascii.NL: - if not self.jid_ids: + if not self.jid_list: return try: - self.__enterCB(self.jid_ids.keys()[self.__index]) + self.__enterCB(self.jid_list[self.__index]) except NameError: pass # TODO: thrown an error here @@ -170,6 +175,7 @@ gobject.io_add_watch(0, gobject.IO_IN, self.loopCB) ## misc init stuff ## + self.CM = QuickContactManagement() self.listWins=[] self.chatParams={'timestamp':True, 'color':True, @@ -190,7 +196,7 @@ self.color(True) ## windows ## - self.contactList = ContactList() + self.contactList = ContactList(self, self.CM) self.editBar = EditBox(stdscr, "> ", self.code) self.editBar.activate(False) self.statusBar = StatusBar(stdscr, self.code) @@ -237,10 +243,10 @@ def showChat(self, chat): debug ("show chat") if self.currentChat: - debug ("hide de %s", self.currentChat) + debug ("hiding %s", self.currentChat) self.chat_wins[self.currentChat].hide() self.currentChat=chat - debug ("show de %s", self.currentChat) + debug ("showing %s", self.currentChat) self.chat_wins[self.currentChat].show() self.chat_wins[self.currentChat].update() @@ -268,8 +274,8 @@ pass - def presenceUpdate(self, jabber_id, type, show, status, priority): - QuickApp.presenceUpdate(self, jabber_id, type, show, status, priority) + def presenceUpdate(self, jabber_id, show, priority, statuses): + QuickApp.presenceUpdate(self, jabber_id, show, priority, statuses) self.editBar.replace_cur() curses.doupdate()
--- a/frontends/wix/main_window.py Thu Jan 07 00:05:15 2010 +1100 +++ b/frontends/wix/main_window.py Thu Jan 07 00:17:27 2010 +1100 @@ -34,24 +34,28 @@ from quick_frontend.quick_chat_list import QuickChatList from quick_frontend.quick_contact_list import QuickContactList from quick_frontend.quick_app import QuickApp +from quick_frontend.quick_contact_management import QuickContactManagement +from cgi import escape +import sys +IMAGE_DIR = sys.path[0]+'/images' msgOFFLINE = "offline" msgONLINE = "online" -idCONNECT = 1 -idDISCONNECT = 2 -idEXIT = 3 -idPARAM = 4 -idADD_CONTACT = 5 -idREMOVE_CONTACT = 6 -idSHOW_PROFILE = 7 -idFIND_GATEWAYS = 8 +idCONNECT,\ +idDISCONNECT,\ +idEXIT,\ +idPARAM,\ +idADD_CONTACT,\ +idREMOVE_CONTACT,\ +idSHOW_PROFILE,\ +idFIND_GATEWAYS = range(8) const_DEFAULT_GROUP = "Unclassed" -const_STATUS = {"Online":"", - "Want to discuss":"chat", - "AFK":"away", - "Do Not Disturb":"dnd", - "Away":"xa"} +const_STATUS = [("", "Online", None), + ("chat", "Free for chat", "green"), + ("away", "AFK", "brown"), + ("dnd", "DND", "red"), + ("xa", "Away", "red")] class ChatList(QuickChatList): """This class manage the list of chat windows""" @@ -59,100 +63,96 @@ def __init__(self, host): QuickChatList.__init__(self, host) - def createChat(self, name): - return Chat(name, self.host) + def createChat(self, target): + return Chat(target, self.host) - -class ContactList(wx.TreeCtrl, QuickContactList): +class ContactList(wx.SimpleHtmlListBox, QuickContactList): """Customized control to manage contacts.""" - def __init__(self, parent): - wx.TreeCtrl.__init__(self, parent, style = wx.TR_HIDE_ROOT | wx.TR_HAS_BUTTONS) - QuickContactList.__init__(self) - self.jid_ids={} - self.groups={} - self.root=self.AddRoot("") - self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.onActivated, self) + def __init__(self, parent, CM): + wx.SimpleHtmlListBox.__init__(self, parent, -1) + QuickContactList.__init__(self, CM) + self.host = parent + self.Bind(wx.EVT_LISTBOX_DCLICK, self.onActivated) - #icons - isz = (16,16) - il = wx.ImageList(isz[0], isz[1]) - self.icon_online = il.Add(wx.ArtProvider_GetBitmap(wx.ART_TICK_MARK, wx.ART_OTHER, isz)) - self.icon_unavailable = il.Add(wx.ArtProvider_GetBitmap(wx.ART_CROSS_MARK, wx.ART_OTHER, isz)) - self.AssignImageList(il) + def __find_idx(self, jid, reverse=False): + """Find indexes of given jid in contact list + @return: list of indexes""" + result=[] + for i in range(self.GetCount()): + if self.GetClientData(i).short == jid.short: + result.append(i) + return result - self.__addNode(const_DEFAULT_GROUP) + def replace(self, jid): + debug("update %s" % jid) + if not self.__find_idx(jid): + self.add(jid) + else: + for i in self.__find_idx(jid): + self.SetString(i, self.__presentItem(jid)) - def __addNode(self, label): - """Add an item container""" - ret=self.AppendItem(self.root, label) - self.SetPyData(ret, "[node]") - self.SetItemBold(ret) - self.groups[label]=ret + def disconnect(self, jid): + self.remove(jid) #for now, we only show online contacts - def replace(self, jid, name="", show="", status="", group=""): - debug("status = %s show = %s",status, show) - if not self.jid_ids.has_key(jid): - self.add(jid, name, show, status, group) - else: - debug ("updating %s",jid) - self.__presentItem(jid, name, show, status, group) - - def __presentItem(self, jid, name, show, status, group): + def __presentItem(self, jid): """Make a nice presentation of the contact in the list.""" - id=self.jid_ids[jid] - label= "%s [%s] \n %s" % ((name or jid), (show or "online"), status) - self.SetItemText(id, label) + name = self.CM.getAttr(jid,'name') + nick = self.CM.getAttr(jid,'nick') + show = filter(lambda x:x[0]==self.CM.getAttr(jid,'show'), const_STATUS)[0] + #show[0]==shortcut + #show[1]==human readable + #show[2]==color (or None) + show_html = "<font color='%s'>[%s]</font>" % (show[2], show[1]) if show[2] else "" + status = self.CM.getAttr(jid,'status') or '' + avatar = self.CM.getAttr(jid,'avatar') or IMAGE_DIR+'/empty_avatar.png' + + #XXX: yes table I know :) but wxHTML* doesn't support CSS + html = """ + <table border='0'> + <td> + <img height='64' width='64' src='%s' /> + </td> + <td> + <b>%s</b> %s<br /> + <i>%s</i> + </td> + </table> + """ % (avatar, + escape(nick or name or jid.node or jid.short), + show_html, + escape(status)) - # icon - if not show or show=="chat": - self.SetItemImage(id, self.icon_online) - else: - self.SetItemImage(id, self.icon_unavailable) + return html - #colour - if not show: - self.SetItemTextColour(id, wx.BLACK) - elif show=="chat": - self.SetItemTextColour(id, wx.GREEN) - elif show=="away": - self.SetItemTextColour(id, wx.BLUE) - else: - self.SetItemTextColour(id, wx.RED) - - def add(self, jid, name="", show="", status="", group=""): + def add(self, jid): """add a contact to the list""" debug ("adding %s",jid) - dest_group=group or const_DEFAULT_GROUP - if not self.groups.has_key(dest_group): - self.__addNode(dest_group) - self.jid_ids[jid]=self.AppendItem(self.groups[dest_group], "") - self.__presentItem(jid, name, show, status, group) - self.SetPyData(self.jid_ids[jid], "[contact]"+jid) - self.EnsureVisible(self.jid_ids[jid]) - self.Refresh() #FIXME: Best way ? + idx = self.Append(self.__presentItem(jid)) + + self.SetClientData(idx, jid) def remove(self, jid): """remove a contact from the list""" debug ("removing %s",jid) - self.Delete(self.jid_ids[jid]) - del self.jid_ids[jid] - self.Refresh() #FIXME: Best way ? + list_idx = self.__find_idx(jid) + list_idx.reverse() #we me make some deletions, we have to reverse the order + for i in list_idx: + self.Delete(i) def onActivated(self, event): """Called when a contact is clicked or activated with keyboard.""" - if self.GetPyData(event.GetItem()).startswith("[contact]"): - self.onActivatedCB(self.GetPyData(event.GetItem())[9:]) - else: - event.Skip() + data = self.getSelection() + self.onActivatedCB(data) + event.Skip() def getSelection(self): """Return the selected contact, or an empty string if there is not""" - data = self.GetPyData(self.GetSelection()) - if not data or not data.startswith("[contact]"): - return "" - return JID(data[9:]) + if self.GetSelection() == wx.NOT_FOUND: + return "" #FIXME: gof: à améliorer + data = self.GetClientData(self.GetSelection()) + return data def registerActivatedCB(self, cb): """Register a callback with manage contact activation.""" @@ -163,10 +163,11 @@ def __init__(self): wx.Frame.__init__(self,None, title="SAT Wix", size=(400,200)) + self.CM = QuickContactManagement() #gof: #Frame elements - self.contactList = ContactList(self) + self.contactList = ContactList(self, self.CM) self.contactList.registerActivatedCB(self.onContactActivated) self.chat_wins=ChatList(self) self.CreateStatusBar() @@ -175,7 +176,7 @@ #ToolBar self.tools=self.CreateToolBar() - self.statusBox = wx.ComboBox(self.tools, -1, "Online", choices=const_STATUS.keys(), + self.statusBox = wx.ComboBox(self.tools, -1, "Online", choices=[status[1] for status in const_STATUS], style=wx.CB_DROPDOWN | wx.CB_READONLY) self.tools.AddControl(self.statusBox) self.tools.AddSeparator() @@ -186,7 +187,7 @@ self.tools.Disable() #tray icon - ticon = wx.Icon("images/tray_icon.xpm", wx.BITMAP_TYPE_XPM) + ticon = wx.Icon(IMAGE_DIR+'/crystal/tray_icon.xpm', wx.BITMAP_TYPE_XPM) self.tray_icon = wx.TaskBarIcon() self.tray_icon.SetIcon(ticon, "Wix jabber client") wx.EVT_TASKBAR_LEFT_UP(self.tray_icon, self.onTrayClick) @@ -252,10 +253,11 @@ flags = wx.OK | wx.ICON_INFORMATION elif type == 'error': flags = wx.OK | wx.ICON_ERROR - elif type == 'question': - flags = wx.OK | wx.ICON_QUESTION + elif type == 'yes/no': + flags = wx.YES_NO | wx.ICON_QUESTION else: flags = wx.OK | wx.ICON_INFORMATION + error('unmanaged dialog type: %s', type) dlg = wx.MessageDialog(self, message, title, flags) answer = dlg.ShowModal() dlg.Destroy() @@ -272,8 +274,8 @@ return - def presenceUpdate(self, jabber_id, type, show, status, priority): - QuickApp.presenceUpdate(self, jabber_id, type, show, status, priority) + def presenceUpdate(self, jabber_id, show, priority, statuses): + QuickApp.presenceUpdate(self, jabber_id, show, priority, statuses) def askConfirmation(self, type, id, data): #TODO: refactor this in QuickApp @@ -315,6 +317,9 @@ def actionResult(self, type, id, data): debug ("actionResult: type = [%s] id = [%s] data = [%s]" % (type, id, data)) + if not id in self.current_action_ids: + debug ('unknown id, ignoring') + return if type == "SUPPRESS": self.current_action_ids.remove(id) elif type == "SUCCESS": @@ -349,7 +354,6 @@ callback = self.current_action_ids_cb[id] del self.current_action_ids_cb[id] callback(data) - print ("Dict of dict found as result") else: error ("FIXME FIXME FIXME: type [%s] not implemented" % type) raise NotImplementedError @@ -384,10 +388,10 @@ def onContactActivated(self, jid): debug ("onContactActivated: %s", jid) - if self.chat_wins[jid].IsShown(): - self.chat_wins[jid].Hide() + if self.chat_wins[jid.short].IsShown(): + self.chat_wins[jid.short].Hide() else: - self.chat_wins[jid].Show() + self.chat_wins[jid.short].Show() def onConnectRequest(self, e): self.bridge.connect() @@ -396,9 +400,9 @@ self.bridge.disconnect() def __updateStatus(self): - show = const_STATUS[self.statusBox.GetValue()] + show = filter(lambda x:x[1] == self.statusBox.GetValue(), const_STATUS)[0][0] status = self.statusTxt.GetValue() - self.bridge.setPresence(show=show, status=status) + self.bridge.setPresence(show=show, statuses={'default':status}) #FIXME: manage multilingual statuses def onStatusChange(self, e): debug("Status change request") @@ -445,7 +449,7 @@ ) if dlg.ShowModal() == wx.ID_YES: - info("Unsubsribing %s presence", target.short) + info("Unsubscribing %s presence", target.short) self.bridge.delContact(target.short) dlg.Destroy() @@ -476,7 +480,6 @@ id = self.bridge.findGateways(self.whoami.domain) self.current_action_ids.add(id) self.current_action_ids_cb[id] = self.onGatewaysFound - print "Find Gateways id=", id def onGatewaysFound(self, data): """Called when SàT has found the server gateways"""