1# 2# PeopleDataSource.rb 3# ABPresence 4# 5# Created by Laurent Sansonetti on 1/4/07. 6# Copyright (c) 2007 Apple Computer. All rights reserved. 7# 8 9class PeopleDataSource < NSObject 10 ib_outlet :table 11 12 # Initialize and register for AddressBook notifications 13 def awakeFromNib 14 @imPersonStatus = [] 15 @abPeople = [] 16 17 nCenter = NSNotificationCenter.defaultCenter 18 nCenter.objc_send :addObserver, self, 19 :selector, 'abDatabaseChangedExternallyNotification:', 20 :name, KABDatabaseChangedExternallyNotification, 21 :object, nil 22 nCenter.objc_send :addObserver, self, 23 :selector, 'addressBookPersonStatusChanged:', 24 :name, KAddressBookPersonStatusChanged, 25 :object, nil 26 27 reloadABPeople 28 end 29 30 # Data Loading 31 32 def bestStatusForPerson(person) 33 bestStatus = IMPersonStatusOffline # Let's assume they're offline to start 34 IMService.allServices.to_a.each do |service| 35 service.screenNamesForPerson(person).to_a.each do |screenName| 36 dict = service.infoForScreenName(screenName) 37 next if dict.nil? 38 status = dict.objectForKey(IMPersonStatusKey) 39 next if status.nil? 40 thisStatus = status.intValue 41 if thisStatus > bestStatus 42 bestStatus = thisStatus 43 end 44 end 45 end 46 return bestStatus 47 end 48 49 # This dumps all the status information and rebuilds the array against the current _abPeople 50 # Fairly expensive, so this is only done when necessary 51 def rebuildStatusInformation 52 @imPersonStatus = @abPeople.map { |person| bestStatusForPerson(person) } 53 @table.reloadData 54 end 55 56 57 # Rebuild status information for a given person, much faster than a full rebuild 58 def rebuildStatusInformationForPerson(forPerson) 59 @abPeople.each_with_index do |person, i| 60 next unless person == forPerson 61 @imPersonStatus[i] = bestStatusForPerson(person) 62 end 63 @table.reloadData 64 end 65 66 # This will do a full flush of people in our AB Cache, along with rebuilding their status 67 def reloadABPeople 68 @abPeople = ABAddressBook.sharedAddressBook.people.to_a.sort do |x, y| 69 x.displayName.to_s <=> y.displayName.to_s 70 end 71 rebuildStatusInformation 72 end 73 74 # NSTableView Data Source 75 76 def numberOfRowsInTableView(tableView) 77 @abPeople ? @abPeople.size : 0 78 end 79 80 def tableView_objectValueForTableColumn_row(tableView, tableColumn, row) 81 case tableColumn.identifier.to_s 82 when 'image' 83 case @imPersonStatus[row] 84 when IMPersonStatusAvailable, IMPersonStatusIdle 85 NSImage.imageNamed('online') 86 when IMPersonStatusAway 87 NSImage.imageNamed('offline') 88 end 89 when 'name' 90 @abPeople[row].displayName 91 end 92 end 93 94 # Notifications 95 96 # Posted from ServiceWatcher 97 # The object of this notification is an ABPerson who's status has changed 98 def addressBookPersonStatusChanged(notification) 99 rebuildStatusInformationForPerson(notification.object) 100 end 101 102 # If the AB database changes, force a reload of everyone 103 # We could look in the notification to catch differential updates, but for now 104 # this is fine. 105 def abDatabaseChangedExternallyNotification(notification) 106 reloadABPeople 107 end 108 109end 110