• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10.1/pyobjc-45/2.6/pyobjc/pyobjc-framework-InstantMessage/Examples/ABPresence/
1from Cocoa import *
2from AddressBook import *
3from InstantMessage import *
4
5from ServiceWatcher import *
6
7class PeopleDataSource (NSObject):
8    _abPeople = objc.ivar()
9    _imPersonStatus = objc.ivar() # Parallel array to abPeople
10    _table = objc.IBOutlet()
11
12    def awakeFromNib(self):
13	self._imPersonStatus = NSMutableArray.alloc().init()
14
15	# We don't need to query the staus of everyone, we will wait for
16        # notifications of their status to arrive, so we just set them all up
17        # as offline.
18	self.setupABPeople()
19
20	NSNotificationCenter.defaultCenter().addObserver_selector_name_object_(
21                self, 'abDatabaseChangedExternallyNotification:',
22                kABDatabaseChangedExternallyNotification, None)
23
24	NSNotificationCenter.defaultCenter().addObserver_selector_name_object_(
25                self, 'addressBookPersonStatusChanged:',
26                kAddressBookPersonStatusChanged, None)
27
28	NSNotificationCenter.defaultCenter().addObserver_selector_name_object_(
29                self, 'statusImagesChanged:',
30                kStatusImagesChanged, None)
31
32    # This dumps all the status information and rebuilds the array against
33    # the current _abPeople
34    # Fairly expensive, so this is only done when necessary
35    def rebuildStatusInformation(self):
36	# Now scan through all the people, adding their status to the status
37        # cache array
38        for i, person in enumerate(self._abPeople):
39                # Let's assume they're offline to start
40		bestStatus = IMPersonStatusOffline
41
42                for service in IMService.allServices():
43			screenNames = service.screenNamesForPerson_(person)
44
45                        for screenName in screenNames:
46				dictionary = service.infoForScreenName_(
47                                        screenName)
48				status = dictionary.get(IMPersonStatusKey)
49                                if status is not None:
50					thisStatus = status
51                                        if IMComparePersonStatus(bestStatus, thisStatus) != NSOrderedAscending:
52						bestStatus = thisStatus;
53
54		self._imPersonStatus[i] = bestStatus
55
56	self._table.reloadData()
57
58    # Rebuild status information for a given person, much faster than a full
59    # rebuild
60    def rebuildStatusInformationForPerson_(self, forPerson):
61        for i, person in enumerate(self._abPeople):
62            if person is forPerson:
63                bestStatus = IMPersonStatusOffline
64
65                # Scan through all the services, taking the 'best' status we
66                # can find
67                for service in IMService.allServices():
68                    screenNames = service.screenNamesForPerson_(person)
69
70                    # Ask for the status on each of their screen names
71                    for screenName in screenNames:
72                        dictionary = service.infoForScreenName_(screenName)
73                        status = dictionary.get(IMPersonStatusKey)
74                        if status is not None:
75                            thisStatus = status
76                            if IMComparePersonStatus(bestStatus, thisStatus) != NSOrderedAscending:
77                                bestStatus = thisStatus
78
79                self._imPersonStatus[i] = bestStatus
80                self._table.reloadData()
81                break
82
83    # Sets up all our internal data
84    def setupABPeople(self):
85	# Keep around a copy of all the people in the AB now
86	self._abPeople = ABAddressBook.sharedAddressBook().people().mutableCopy()
87
88	# Sort them by display name
89        self._abPeople.sortUsingSelector_('compareDisplayNames:')
90
91	# Assume everyone is offline.
92	self._imPersonStatus.removeAllObjects()
93	offlineNumber =  IMPersonStatusOffline
94        for i in range(len(self._abPeople)):
95            self._imPersonStatus.append(offlineNumber)
96
97    # This will do a full flush of people in our AB Cache, along with
98    # rebuilding their status */
99    def reloadABPeople(self):
100	self.setupABPeople()
101
102	# Now recache all the status info, this will spawn a reload of the table
103	self.rebuildStatusInformation()
104
105    def numberOfRowsInTableView_(self, tableView):
106        if self._abPeople is None:
107            return 0
108        return len(self._abPeople)
109
110    def tableView_objectValueForTableColumn_row_(self, tableView, tableColumn, row):
111	identifier = tableColumn.identifier()
112        if identifier == u"image":
113            status = self._imPersonStatus[row]
114            return NSImage.imageNamed_(IMService.imageNameForStatus_(status))
115
116        elif identifier == u"name":
117            return self._abPeople[row].displayName()
118
119	return None
120
121
122    # Posted from ServiceWatcher
123    # The object of this notification is an ABPerson who's status has
124    # Changed
125    def addressBookPersonStatusChanged_(self, notification):
126	self.rebuildStatusInformationForPerson_(notification.object())
127
128    # Posted from ServiceWatcher
129    # We should reload the tableview, because the user has changed the
130    # status images that Messages is using.
131    def statusImagesChanged_(self, notification):
132	self._table.reloadData()
133
134    # If the AB database changes, force a reload of everyone
135    # We could look in the notification to catch differential updates, but
136    # for now this is fine.
137    def abDatabaseChangedExternallyNotification_(self, notification):
138	self.reloadABPeople()
139