• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10.1/pyobjc-45/pyobjc/pyobjc-framework-InstantMessage-2.5.1/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