Merge lp:~keirangtp/cardapio/pidgin-offline-buddies into lp:cardapio

Proposed by Paweł Bara
Status: Merged
Merge reported by: Thiago Teixeira
Merged at revision: not available
Proposed branch: lp:~keirangtp/cardapio/pidgin-offline-buddies
Merge into: lp:cardapio
Diff against target: 187 lines (+74/-27)
1 file modified
src/plugins/pidgin.py (+74/-27)
To merge this branch: bzr merge lp:~keirangtp/cardapio/pidgin-offline-buddies
Reviewer Review Type Date Requested Status
Thiago Teixeira Approve
Review via email: mp+37643@code.launchpad.net

Description of the change

Pidgin plugin now looks for offline buddies too! it sorts the results by status and shows icon representing buddy's status next to his alias

To post a comment you must log in.
Revision history for this message
Paweł Bara (keirangtp) wrote :

before you merge - what about weird statuses (like mood or tune vel now-playing)? do you think I should translate them to their gnome look alikes to avoid fallback icon?

Revision history for this message
Thiago Teixeira (tvst) wrote :

If it's not much trouble, I guess using the closest Gnome or XDG equivalent icons seems like a good idea. I can't see any reason not to do it, but since I don't use Pidgin very often, I'm not in the best position to judge. So it's up to you.

- Thiago

> To: <email address hidden>
> From: <email address hidden>
> Subject: Re: [Merge] lp:~keirangtp/cardapio/pidgin-offline-buddies into lp:cardapio
> Date: Tue, 5 Oct 2010 17:46:42 +0000
>
> before you merge - what about weird statuses (like mood or tune vel now-playing)? do you think I should translate them to their gnome look alikes to avoid fallback icon?
> --
> https://code.launchpad.net/~keirangtp/cardapio/pidgin-offline-buddies/+merge/37643
> You are requested to review the proposed merge of lp:~keirangtp/cardapio/pidgin-offline-buddies into lp:cardapio.

433. By Pawel Bara

we avoid missing status icons by proper translation of Pidgin's status CATEGORY to standard icon name

434. By Pawel Bara

correction of plugin description

Revision history for this message
Paweł Bara (keirangtp) wrote :

it was not as easy as I thought but it's done - you can merge this now

Revision history for this message
Thiago Teixeira (tvst) wrote :

Nice code! Good commenting and docstrings.

review: Approve
Revision history for this message
Paweł Bara (keirangtp) wrote :

Thank you! ;)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/plugins/pidgin.py'
2--- src/plugins/pidgin.py 2010-08-22 05:03:45 +0000
3+++ src/plugins/pidgin.py 2010-10-07 16:33:43 +0000
4@@ -1,3 +1,5 @@
5+from operator import itemgetter
6+
7 from dbus.exceptions import DBusException
8
9 class CardapioPlugin(CardapioPluginInterface):
10@@ -6,11 +8,17 @@
11 Pidgin plugin based on it's D-Bus interface. Documentation:
12 http://developer.pidgin.im/wiki/DbusHowto
13
14- The plugin looks for online buddies and provides the user with
15+ The plugin looks for Pidgin buddies and provides the user with
16 possibility to start a conversation with any of them. All active
17 accounts are considered. We match buddies by their alias (case
18 insensitive).
19
20+ Each buddy is marked with icon representing his or her current
21+ status. We try to avoid nonexistent status icons by translating
22+ the categories of statuses to three standard icons (user-available,
23+ user-away or user-offline). Results are categorized and sorted
24+ according to their status too.
25+
26 Please note that the plugin only works when Pidgin is on. You don't
27 need to turn Pidgin on before starting Cardapio or before initializing
28 the plugin. You just need to turn it on before performing a Cardapio
29@@ -36,7 +44,7 @@
30 category_tooltip = _('Your online Pidgin buddies')
31
32 category_icon = 'pidgin'
33- fallback_icon = ''
34+ fallback_icon = 'pidgin'
35
36 hide_from_sidebar = True
37
38@@ -60,19 +68,41 @@
39 self.cardapio.write_to_log(self, 'Pidgin plugin initialization error: {0}'.format(str(ex)), is_error = True)
40 self.loaded = False
41
42+ # Pidgin's status primitives (constants)
43+ status_primitives = ['offline', 'available', 'unavailable', 'invisible', 'away',
44+ 'extended_away', 'mobile', 'tune', 'mood']
45+
46+ # mappings of Pidgin's status primitives to standard icon names
47+ status_icons = { 'offline' : 'user-offline', 'available' : 'user-available',
48+ 'unavailable' : 'user-offline', 'invisible' : 'user-offline',
49+ 'away' : 'user-away', 'extended_away' : 'user-away',
50+ 'mobile' : 'user-available', 'tune' : 'user-available',
51+ 'mood' : 'user-available' }
52+
53 def on_dbus_name_change(self, connection_name):
54 """
55 This method effectively tracks down the events of Pidgin app starting
56 and shutting down. When the app shuts down, this callback nullifies our
57- Pidgin's proxy and when the app starts, this callback sets the valid
58- proxy again.
59+ Pidgin's proxy. When the app starts, this callback sets the valid
60+ proxy, then refreshes the constants that represent possible Pidgin's
61+ status primitives.
62 """
63
64 if len(connection_name) == 0:
65+ # clear the state
66+ self.statuses = {}
67 self.pidgin = None
68 else:
69 bus_object = self.bus.get_object(connection_name, self.dpidgin_object_path)
70- self.pidgin = dbus.Interface(bus_object, self.dpidgin_iface_name)
71+ pidgin = dbus.Interface(bus_object, self.dpidgin_iface_name)
72+
73+ # remember the unique id of each status primitive
74+ self.statuses = {}
75+ for primitive in self.status_primitives:
76+ self.statuses[primitive] = pidgin.PurplePrimitiveGetTypeFromId(primitive)
77+
78+ # ready
79+ self.pidgin = pidgin
80
81 def search(self, text, result_limit):
82 if len(text) == 0:
83@@ -87,12 +117,11 @@
84
85 # prepare a parametrized callback that remembers the current search text and
86 # the result limit
87- callback = DBusGatherBuddiesCallback(self.pidgin, self.finalize_search,
88- text, result_limit)
89+ callback = DBusGatherBuddiesCallback(self, text, result_limit)
90
91 # let's start by getting all of the user's active accounts
92 self.pidgin.PurpleAccountsGetAllActive(reply_handler = callback.handle_search_result,
93- error_handler = self.handle_search_error)
94+ error_handler = self.handle_search_error)
95
96 def finalize_search(self, buddies, text):
97 """
98@@ -113,7 +142,7 @@
99 items.append({
100 'name' : buddy[2] + ' ({0})'.format(buddy[1]),
101 'tooltip' : _('Talk to this buddy'),
102- 'icon name' : 'pidgin',
103+ 'icon name' : buddy[3],
104 'type' : 'callback',
105 'command' : conversation_callback.start_conversation,
106 'context menu' : None
107@@ -135,9 +164,10 @@
108 call.
109 """
110
111- def __init__(self, pidgin, result_callback, text, result_limit):
112- self.pidgin = pidgin
113- self.result_callback = result_callback
114+ def __init__(self, parent, text, result_limit):
115+ self.parent = parent
116+ self.pidgin = parent.pidgin
117+ self.result_callback = parent.finalize_search
118
119 self.text = text
120 self.result_limit = result_limit
121@@ -147,10 +177,17 @@
122 Callback to asynchronous Pidgin's PurpleAccountsGetAllActive
123 call. It gathers results and then passes those back to the
124 main plugin class through the result_callback method.
125+
126+ Results are prepared in certain way:
127+ - sorted by status, then alias
128+ - limited to at most result_limit entries
129 """
130
131 # gather all online buddies
132- self.result_callback(self.gather_buddies(accounts), self.text)
133+ buddies = self.gather_buddies(accounts)
134+ # sort (we rely on alphabetical order of icon names) and crop
135+ # the results before triggering further processing of them
136+ self.result_callback(sorted(buddies, key=itemgetter(3, 2))[:self.result_limit], self.text)
137
138 def gather_buddies(self, accounts):
139 """
140@@ -170,23 +207,33 @@
141 # and every buddy associated with this active account...
142 for buddy in self.pidgin.PurpleFindBuddies(account, ''):
143
144- # obey the result limit!
145- if len(buddies) == self.result_limit:
146- return buddies
147-
148- # we remember only those buddies who are online now
149- if self.pidgin.PurpleBuddyIsOnline(buddy):
150-
151- buddy_alias = self.pidgin.PurpleBuddyGetAlias(buddy)
152+ buddy_alias = self.pidgin.PurpleBuddyGetAlias(buddy)
153+
154+ # if buddy's alias contains (case insensitive) the search
155+ # keyword, add him to the result list
156+ if buddy_alias.lower().count(self.text.lower()) > 0:
157+
158+ # but gather rest of his data first...
159 buddy_name = self.pidgin.PurpleBuddyGetName(buddy)
160-
161- # if buddies alias contains (case insensitive) the search
162- # keyword, add him to the result list
163- if buddy_alias.lower().count(self.text.lower()) > 0:
164- buddies.append((account, buddy_name, buddy_alias))
165-
166+ presence = self.pidgin.PurpleBuddyGetPresence(buddy)
167+
168+ buddies.append((account, buddy_name, buddy_alias, self.get_icon_name(presence)))
169+
170 return buddies
171
172+ def get_icon_name(self, presence):
173+ """
174+ Returns standard icon name for given presence of user.
175+ """
176+
177+ # look for active status primitive...
178+ for primitive in self.parent.status_primitives:
179+ status_const = self.parent.statuses[primitive]
180+ if(self.pidgin.PurplePresenceIsStatusPrimitiveActive(presence, status_const)):
181+ return self.parent.status_icons[primitive]
182+
183+ # couldn't find it - fallback icon...
184+ return 'user-offline'
185
186 class DBusTalkToBuddyCallback:
187 """

Subscribers

People subscribed via source and target branches