72
+ − 1 import wx
+ − 2 from quick_frontend.quick_contact_list import QuickContactList
+ − 3 from logging import debug , info , error
+ − 4 from cgi import escape
+ − 5 from tools.jid import JID
+ − 6
+ − 7
+ − 8 class Group ( str ):
+ − 9 """Class used to recognize groups"""
+ − 10
+ − 11 class Contact ( str ):
+ − 12 """Class used to recognize groups"""
+ − 13
+ − 14 class ContactList ( wx . SimpleHtmlListBox , QuickContactList ):
+ − 15 """Customized control to manage contacts."""
+ − 16
+ − 17 def __init__ ( self , parent , host , type = "JID" ):
+ − 18 """init the contact list
+ − 19 @param parent: WxWidgets parent of the widget
+ − 20 @param host: wix main app class
+ − 21 @param type: type of contact list: "JID" for the usual big jid contact list
+ − 22 "CUSTOM" for a customized contact list (self.__presentItem must then be overrided)
+ − 23 """
+ − 24 wx . SimpleHtmlListBox . __init__ ( self , parent , - 1 )
+ − 25 QuickContactList . __init__ ( self , host . CM )
+ − 26 self . host = host
+ − 27 self . type = type
+ − 28 self . __typeSwitch ()
+ − 29 self . groups = {} #list contacts in each groups, key = group
+ − 30 self . Bind ( wx . EVT_LISTBOX , self . onSelected )
+ − 31 self . Bind ( wx . EVT_LISTBOX_DCLICK , self . onActivated )
+ − 32
+ − 33 def __typeSwitch ( self ):
+ − 34 if self . type == "JID" :
+ − 35 self . __presentItem = self . __presentItemJID
+ − 36 elif type != "CUSTOM" :
+ − 37 self . __presentItem = self . __presentItemDefault
+ − 38
+ − 39 def __find_idx ( self , entity ):
+ − 40 """Find indexes of given contact (or groups) in contact list, manage jid
+ − 41 @return: list of indexes"""
+ − 42 result = []
+ − 43 for i in range ( self . GetCount ()):
+ − 44 if ( type ( entity ) == JID and type ( self . GetClientData ( i )) == JID and self . GetClientData ( i ) . short == entity . short ) or \
+ − 45 self . GetClientData ( i ) == entity :
+ − 46 result . append ( i )
+ − 47 return result
+ − 48
+ − 49 def replace ( self , contact , groups = None ):
+ − 50 debug ( _ ( "update %s " ) % contact )
+ − 51 if not self . __find_idx ( contact ):
+ − 52 self . add ( contact , groups )
+ − 53 else :
+ − 54 for i in self . __find_idx ( contact ):
+ − 55 self . SetString ( i , self . __presentItem ( contact ))
+ − 56
+ − 57 def disconnect ( self , contact ):
+ − 58 self . remove ( contact ) #for now, we only show online contacts
+ − 59
+ − 60 def __eraseGroup ( self , group ):
+ − 61 """Erase all contacts in group
+ − 62 @param group: group to erase
+ − 63 @return: True if something as been erased"""
+ − 64 erased = False
+ − 65 indexes = self . __find_idx ( group )
+ − 66 for idx in indexes :
+ − 67 while idx < self . GetCount () - 1 and type ( self . GetClientData ( idx + 1 )) != Group :
+ − 68 erased = True
+ − 69 self . Delete ( idx + 1 )
+ − 70 return erased
+ − 71
+ − 72
+ − 73 def __presentGroup ( self , group ):
+ − 74 """Make a nice presentation for the contact groups"""
+ − 75 html = """-- [ %s ] --""" % group
+ − 76
+ − 77 return html
+ − 78
+ − 79 def __presentItemDefault ( self , contact ):
+ − 80 """Make a basic presentation of string contacts in the list."""
+ − 81 return contact
+ − 82
+ − 83 def __presentItemJID ( self , jid ):
+ − 84 """Make a nice presentation of the contact in the list for JID contacts."""
+ − 85 name = self . CM . getAttr ( jid , 'name' )
+ − 86 nick = self . CM . getAttr ( jid , 'nick' )
+ − 87 show = filter ( lambda x : x [ 0 ] == self . CM . getAttr ( jid , 'show' ), const_STATUS )[ 0 ]
+ − 88 #show[0]==shortcut
+ − 89 #show[1]==human readable
+ − 90 #show[2]==color (or None)
+ − 91 show_html = "<font color=' %s '>[ %s ]</font>" % ( show [ 2 ], show [ 1 ]) if show [ 2 ] else ""
+ − 92 status = self . CM . getAttr ( jid , 'status' ) or ''
+ − 93 avatar = self . CM . getAttr ( jid , 'avatar' ) or IMAGE_DIR + '/empty_avatar.png'
+ − 94
+ − 95 #XXX: yes table I know :) but wxHTML* doesn't support CSS
+ − 96 html = """
+ − 97 <table border='0'>
+ − 98 <td>
+ − 99 <img height='64' width='64' src=' %s ' />
+ − 100 </td>
+ − 101 <td>
+ − 102 <b> %s </b> %s <br />
+ − 103 <i> %s </i>
+ − 104 </td>
+ − 105 </table>
+ − 106 """ % ( avatar ,
+ − 107 escape ( nick or name or jid . node or jid . short ),
+ − 108 show_html ,
+ − 109 escape ( status ))
+ − 110
+ − 111 return html
+ − 112
+ − 113 def clear_contacts ( self ):
+ − 114 """Clear all the contact list"""
+ − 115 self . Clear ()
+ − 116
+ − 117 def add ( self , contact , groups = None ):
+ − 118 """add a contact to the list"""
+ − 119 debug ( _ ( "adding %s " ), contact )
+ − 120 #gof: groups = param_groups or self.CM.getAttr(jid, 'groups')
+ − 121 if not groups :
+ − 122 idx = self . Insert ( self . __presentItem ( contact ), 0 , contact )
+ − 123 else :
+ − 124 for group in groups :
+ − 125 indexes = self . __find_idx ( group )
+ − 126 gp_idx = 0
+ − 127 if not indexes : #this is a new group, we have to create it
+ − 128 gp_idx = self . Append ( self . __presentGroup ( group ), Group ( group ))
+ − 129 else :
+ − 130 gp_idx = indexes [ 0 ]
+ − 131
+ − 132 self . Insert ( self . __presentItem ( contact ), gp_idx + 1 , contact )
+ − 133
+ − 134
+ − 135
+ − 136 def remove ( self , contact ):
+ − 137 """remove a contact from the list"""
+ − 138 debug ( _ ( "removing %s " ), contact )
+ − 139 list_idx = self . __find_idx ( contact )
75
+ − 140 list_idx . reverse () #as we make some deletions, we have to reverse the order
72
+ − 141 for i in list_idx :
+ − 142 self . Delete ( i )
+ − 143
+ − 144 def onSelected ( self , event ):
+ − 145 """Called when a contact is selected."""
+ − 146 data = self . getSelection ()
+ − 147 if data == None : #we have a group
+ − 148 group = self . GetClientData ( self . GetSelection ())
+ − 149 erased = self . __eraseGroup ( group )
+ − 150 if not erased : #the group was already erased, we can add again the contacts
+ − 151 contacts = self . CM . getContFromGroup ( group )
+ − 152 contacts . sort ()
+ − 153 id_insert = self . GetSelection () + 1
+ − 154 for contact in contacts :
+ − 155 self . Insert ( self . __presentItem ( contact ), id_insert , contact )
+ − 156 self . SetSelection ( wx . NOT_FOUND )
+ − 157 event . Skip ( False )
+ − 158 else :
+ − 159 event . Skip ()
+ − 160
+ − 161 def onActivated ( self , event ):
+ − 162 """Called when a contact is clicked or activated with keyboard."""
+ − 163 data = self . getSelection ()
+ − 164 self . onActivatedCB ( data )
+ − 165 event . Skip ()
+ − 166
+ − 167 def getSelection ( self ):
+ − 168 """Return the selected contact, or an empty string if there is not"""
+ − 169 if self . GetSelection () == wx . NOT_FOUND :
+ − 170 return None
+ − 171 data = self . GetClientData ( self . GetSelection ())
+ − 172 if type ( data ) == Group :
+ − 173 return None
+ − 174 return data
+ − 175
+ − 176 def registerActivatedCB ( self , cb ):
+ − 177 """Register a callback with manage contact activation."""
+ − 178 self . onActivatedCB = cb
+ − 179