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
This commit is contained in:
Goffi 2010-01-07 00:17:27 +11:00
commit 3b2d29b632
7 changed files with 293 additions and 203 deletions

View file

@ -22,23 +22,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
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 @@ class QuickApp():
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 @@ class QuickApp():
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 @@ class QuickApp():
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

View file

@ -30,12 +30,12 @@ class QuickChatList(dict):
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

View file

@ -24,19 +24,27 @@ from tools.jid import JID
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

View file

@ -19,29 +19,68 @@ You should have received a copy of the GNU General Public License
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]

View file

@ -52,6 +52,9 @@ class DBusBridgeFrontend(BridgeFrontend):
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 @@ class DBusBridgeFrontend(BridgeFrontend):
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)

View file

@ -43,6 +43,7 @@ from boxsizer import BoxSizer
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 ChatList(QuickChatList):
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 @@ class ContactList(Window, QuickContactList):
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 @@ class ContactList(Window, QuickContactList):
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 @@ class ContactList(Window, QuickContactList):
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 @@ class ContactList(Window, QuickContactList):
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 @@ class SortilegeApp(QuickApp):
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 @@ class SortilegeApp(QuickApp):
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 @@ class SortilegeApp(QuickApp):
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 @@ class SortilegeApp(QuickApp):
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()

View file

@ -34,24 +34,28 @@ from logging import debug, info, error
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 @@ class ChatList(QuickChatList):
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 __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 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)
def replace(self, jid):
debug("update %s" % jid)
if not self.__find_idx(jid):
self.add(jid)
else:
debug ("updating %s",jid)
self.__presentItem(jid, name, show, status, group)
for i in self.__find_idx(jid):
self.SetString(i, self.__presentItem(jid))
def __presentItem(self, jid, name, show, status, group):
def disconnect(self, jid):
self.remove(jid) #for now, we only show online contacts
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 @@ class MainWindow(wx.Frame, QuickApp):
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 @@ class MainWindow(wx.Frame, QuickApp):
#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 @@ class MainWindow(wx.Frame, QuickApp):
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 @@ class MainWindow(wx.Frame, QuickApp):
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 @@ class MainWindow(wx.Frame, QuickApp):
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 @@ class MainWindow(wx.Frame, QuickApp):
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 @@ class MainWindow(wx.Frame, QuickApp):
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 @@ class MainWindow(wx.Frame, QuickApp):
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 @@ class MainWindow(wx.Frame, QuickApp):
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 @@ class MainWindow(wx.Frame, QuickApp):
)
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 @@ class MainWindow(wx.Frame, QuickApp):
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"""