Merge lp:~vinod-khare/pithos/appindicator into lp:~kevin-mehall/pithos/trunk

Proposed by Vinod Khare
Status: Superseded
Proposed branch: lp:~vinod-khare/pithos/appindicator
Merge into: lp:~kevin-mehall/pithos/trunk
Diff against target: 303 lines (+129/-9)
4 files modified
bin/PithosAppIndicator.py (+58/-0)
bin/pithos (+10/-2)
pithos/notification_icon.py (+58/-7)
pithos/pithosconfig.py (+3/-0)
To merge this branch: bzr merge lp:~vinod-khare/pithos/appindicator
Reviewer Review Type Date Requested Status
Kevin Mehall Needs Resubmitting
Review via email: mp+30720@code.launchpad.net

This proposal has been superseded by a proposal from 2010-07-22.

Description of the change

Adds appindicator support for Ubuntu. Also adds a monochrome icon for the same.

To post a comment you must log in.
Revision history for this message
Kevin Mehall (kevin-mehall) wrote :

Can this share any code with the recently-merged notification area icon patch? Sorry to merge that just as you were about to submit...

See http://bazaar.launchpad.net/~gtg/gtg/trunk/annotate/head:/GTG/plugins/notification_area/notification_area.py
for an example of a notification area plugin that combines appindicator and the legacy notification area

Then it can use the same enable/disable mechanism I implemented for the existing icon.

Also, it looks like this branch sets the execute bit on every file in the repository. Is there anything you can do about this?

review: Needs Resubmitting
Revision history for this message
Vinod Khare (vinod-khare) wrote :

> Can this share any code with the recently-merged notification area icon patch?
> Sorry to merge that just as you were about to submit...
>
> See http://bazaar.launchpad.net/~gtg/gtg/trunk/annotate/head:/GTG/plugins/noti
> fication_area/notification_area.py
> for an example of a notification area plugin that combines appindicator and
> the legacy notification area
>
> Then it can use the same enable/disable mechanism I implemented for the
> existing icon.
>
> Also, it looks like this branch sets the execute bit on every file in the
> repository. Is there anything you can do about this?

Yeah, just saw the merge, I'm pulling the changes to see if I can merge the two things.

lp:~vinod-khare/pithos/appindicator updated
69. By Vinod Khare <email address hidden>

Merging appindicator with notification area icon

70. By Vinod Khare <email address hidden>

This will hopefully resolve the execute bit problem :(

71. By Vinod Khare <email address hidden>

Code cleanup

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore' (properties changed: -x to +x)
2=== modified file '.quickly' (properties changed: -x to +x)
3=== added file 'bin/PithosAppIndicator.py'
4--- bin/PithosAppIndicator.py 1970-01-01 00:00:00 +0000
5+++ bin/PithosAppIndicator.py 2010-07-22 22:24:47 +0000
6@@ -0,0 +1,58 @@
7+import appindicator
8+import os
9+import sys
10+import gtk
11+
12+# Check if we are working in the source tree or from the installed
13+# package and mangle the python path accordingly
14+if os.path.dirname(sys.argv[0]) != ".":
15+ if sys.argv[0][0] == "/":
16+ fullPath = os.path.dirname(sys.argv[0])
17+ else:
18+ fullPath = os.getcwd() + "/" + os.path.dirname(sys.argv[0])
19+else:
20+ fullPath = os.getcwd()
21+sys.path.insert(0, os.path.dirname(fullPath))
22+
23+from pithos import AboutPithosDialog, PreferencesPithosDialog, StationsDialog
24+from pithos.pithosconfig import getdatapath, getmediapath
25+from pithos.gobject_worker import GObjectWorker
26+
27+class PithosAppIndicator:
28+ def __init__(self,window):
29+ # App Indicator
30+ self.ind = appindicator.Indicator("example-simple-client","pithos-mono",appindicator.CATEGORY_APPLICATION_STATUS,getmediapath())
31+ self.ind.set_status (appindicator.STATUS_ACTIVE)
32+
33+ # create a menu
34+ menu = gtk.Menu()
35+
36+ # Play/Pause menu item
37+ PlayPauseMenuItem = gtk.ImageMenuItem("Play/Pause")
38+ PlayPauseMenuItem.connect("activate",window.playpause)
39+ PlayPauseMenuItem.show()
40+
41+ skipMenuItem = gtk.MenuItem("Skip")
42+ skipMenuItem.connect("activate",window.next_song)
43+ skipMenuItem.show();
44+
45+ showhideMenuItem = gtk.MenuItem("Show/Hide")
46+ showhideMenuItem.connect("activate",window.showhide)
47+ showhideMenuItem.show();
48+
49+ quitMenuItem = gtk.MenuItem("Quit")
50+ quitMenuItem.connect("activate",window.quit)
51+ quitMenuItem.show()
52+
53+ menu.append(PlayPauseMenuItem)
54+ menu.append(skipMenuItem)
55+ menu.append(showhideMenuItem)
56+ menu.append(quitMenuItem)
57+
58+ # this is where you would connect your menu item up with a function:
59+
60+ # menu_items.connect("activate", self.menuitem_response, buf)
61+
62+ # show the items
63+
64+ self.ind.set_menu(menu)
65
66=== modified file 'bin/pithos'
67--- bin/pithos 2010-07-22 22:00:40 +0000
68+++ bin/pithos 2010-07-22 22:24:47 +0000
69@@ -35,6 +35,8 @@
70 import dbus
71 from dbus.mainloop.glib import DBusGMainLoop
72 DBusGMainLoop(set_as_default=True)
73+import appindicator
74+from PithosAppIndicator import PithosAppIndicator
75
76 # Check if we are working in the source tree or from the installed
77 # package and mangle the python path accordingly
78@@ -48,7 +50,7 @@
79 sys.path.insert(0, os.path.dirname(fullPath))
80
81 from pithos import AboutPithosDialog, PreferencesPithosDialog, StationsDialog
82-from pithos.pithosconfig import getdatapath
83+from pithos.pithosconfig import getdatapath, getmediapath
84 from pithos.gobject_worker import GObjectWorker
85 from pithos.notification_icon import PithosNotificationIcon
86
87@@ -234,6 +236,8 @@
88
89 aa = gtk.gdk.pixbuf_new_from_file(os.path.join(getdatapath(), 'media', 'album_default.png'))
90 self.default_album_art = aa.scale_simple(ALBUM_ART_SIZE, ALBUM_ART_SIZE, gtk.gdk.INTERP_BILINEAR)
91+
92+ self.showing = True
93
94 if self.preferences.get('show_icon', False):
95 self.notification_icon = PithosNotificationIcon(self)
96@@ -241,6 +245,7 @@
97 self.notification_icon = None
98
99 self.piano_connect()
100+
101
102 def worker_run(self, fn, args=(), callback=None, context=None, message=None):
103 if context: self.statusbar.push(self.statusbar.get_context_id(context), message)
104@@ -630,6 +635,7 @@
105 self.preferences['last_station_id'] = self.current_station_id
106 self.prefs_dlg.save()
107 gtk.main_quit()
108+
109
110 def NewPithosWindow(pandora_class):
111 """NewPithosWindow - returns a fully instantiated
112@@ -648,6 +654,7 @@
113 window.finish_initializing(builder, pandora_class)
114 return window
115
116+
117 if __name__ == "__main__":
118 #support for command line options
119 import logging, optparse
120@@ -669,5 +676,6 @@
121 #run the application
122 window = NewPithosWindow(PianoPandora)
123 window.show()
124- gtk.main()
125+
126+ gtk.main()
127
128
129=== modified file 'data/media/album_default.png' (properties changed: -x to +x)
130=== modified file 'data/media/album_default.svg' (properties changed: -x to +x)
131=== modified file 'data/media/icon.png' (properties changed: -x to +x)
132=== modified file 'data/media/icon.svg' (properties changed: -x to +x)
133=== added file 'data/media/pithos-mono.png'
134Binary files data/media/pithos-mono.png 1970-01-01 00:00:00 +0000 and data/media/pithos-mono.png 2010-07-22 22:24:47 +0000 differ
135=== modified file 'data/media/rate_bg.png' (properties changed: -x to +x)
136=== modified file 'data/media/rate_bg.svg' (properties changed: -x to +x)
137=== modified file 'data/ui/AboutPithosDialog.ui' (properties changed: -x to +x)
138=== modified file 'data/ui/PithosWindow.ui' (properties changed: -x to +x)
139=== modified file 'data/ui/PreferencesPithosDialog.ui' (properties changed: -x to +x)
140=== modified file 'data/ui/SearchDialog.ui' (properties changed: -x to +x)
141=== modified file 'data/ui/StationsDialog.ui' (properties changed: -x to +x)
142=== modified file 'data/ui/about_pithos_dialog.xml' (properties changed: -x to +x)
143=== modified file 'data/ui/pithos_window.xml' (properties changed: -x to +x)
144=== modified file 'data/ui/preferences_pithos_dialog.xml' (properties changed: -x to +x)
145=== modified file 'data/ui/search_dialog.xml' (properties changed: -x to +x)
146=== modified file 'data/ui/stations_dialog.xml' (properties changed: -x to +x)
147=== modified file 'debian/changelog' (properties changed: -x to +x)
148=== modified file 'debian/compat' (properties changed: -x to +x)
149=== modified file 'debian/control' (properties changed: -x to +x)
150=== modified file 'debian/copyright' (properties changed: -x to +x)
151=== modified file 'pithos.desktop.in' (properties changed: -x to +x)
152=== modified file 'pithos/AboutPithosDialog.py' (properties changed: -x to +x)
153=== modified file 'pithos/PreferencesPithosDialog.py' (properties changed: -x to +x)
154=== modified file 'pithos/SearchDialog.py' (properties changed: -x to +x)
155=== modified file 'pithos/StationsDialog.py' (properties changed: -x to +x)
156=== modified file 'pithos/__init__.py' (properties changed: -x to +x)
157=== modified file 'pithos/fakepiano.py' (properties changed: -x to +x)
158=== modified file 'pithos/gobject_worker.py' (properties changed: -x to +x)
159=== modified file 'pithos/libpiano/Makefile' (properties changed: -x to +x)
160=== modified file 'pithos/libpiano/README' (properties changed: -x to +x)
161=== modified file 'pithos/libpiano/__init__.py' (properties changed: -x to +x)
162=== modified file 'pithos/libpiano/config.h' (properties changed: -x to +x)
163=== modified file 'pithos/libpiano/crypt.c' (properties changed: -x to +x)
164=== modified file 'pithos/libpiano/crypt.h' (properties changed: -x to +x)
165=== modified file 'pithos/libpiano/crypt_key_input.h' (properties changed: -x to +x)
166=== modified file 'pithos/libpiano/crypt_key_output.h' (properties changed: -x to +x)
167=== modified file 'pithos/libpiano/ezxml.c' (properties changed: -x to +x)
168=== modified file 'pithos/libpiano/ezxml.h' (properties changed: -x to +x)
169=== modified file 'pithos/libpiano/http.c' (properties changed: -x to +x)
170=== modified file 'pithos/libpiano/http.h' (properties changed: -x to +x)
171=== modified file 'pithos/libpiano/piano.c' (properties changed: -x to +x)
172=== modified file 'pithos/libpiano/piano.h' (properties changed: -x to +x)
173=== modified file 'pithos/libpiano/piano.i' (properties changed: -x to +x)
174=== modified file 'pithos/libpiano/piano_private.h' (properties changed: -x to +x)
175=== modified file 'pithos/libpiano/waitress.c' (properties changed: -x to +x)
176=== modified file 'pithos/libpiano/waitress.h' (properties changed: -x to +x)
177=== modified file 'pithos/libpiano/xml.c' (properties changed: -x to +x)
178=== modified file 'pithos/libpiano/xml.h' (properties changed: -x to +x)
179=== modified file 'pithos/notification_icon.py' (properties changed: -x to +x)
180--- pithos/notification_icon.py 2010-07-22 20:46:37 +0000
181+++ pithos/notification_icon.py 2010-07-22 22:24:47 +0000
182@@ -18,20 +18,53 @@
183 import gtk
184 import pithosconfig
185
186+# Check if appindicator is available on the system
187+try:
188+ import appindicator
189+ indicator_capable = True
190+except:
191+ indicator_capable = False
192+
193 class PithosNotificationIcon:
194+ class Borg:
195+ """Application indicator can be instantiated only
196+ once. The plugin api, when toggling the activation
197+ state of a plugin, instantiates different instances
198+ of the plugin class. Therefore, we need to keep
199+ a reference to the indicator object. This class does that."""
200+ __shared_state = {}
201+ def __init__(self):
202+ self.__dict__ = self.__shared_state
203+ if not hasattr(self, "indicator"):
204+ self.indicator = appindicator.Indicator("pithos", \
205+ "pithos-mono", \
206+ appindicator.CATEGORY_APPLICATION_STATUS, \
207+ pithosconfig.getmediapath())
208+ self.indicator.set_status(appindicator.STATUS_ACTIVE)
209+
210+ def get_indicator(self):
211+ return self.indicator
212+
213 def __init__(self, window):
214+
215 self.window = window
216
217 self.delete_callback_handle = self.window.connect("delete-event", self.window.hide_on_delete)
218 self.state_callback_handle = self.window.connect("play-state-changed", self.play_state_changed)
219 self.song_callback_handle = self.window.connect("song-changed", self.song_changed)
220
221- self.statusicon = gtk.status_icon_new_from_file(pithosconfig.get_data_file('media', 'icon.png'))
222- self.statusicon.connect('activate', self.statusicon_clicked )
223+ if indicator_capable:
224+ self.ind = self.Borg().get_indicator()
225+
226+ else:
227+ self.statusicon = gtk.status_icon_new_from_file(pithosconfig.get_data_file('media', 'icon.png'))
228+ self.statusicon.connect('activate', self.statusicon_clicked )
229+
230 self.build_context_menu()
231
232 def build_context_menu(self):
233- """ build context menu for the right click menu on the status icon """
234+ """ build context menu for the right click menu on the status icon
235+ of for the appindicator """
236
237 def icon(image):
238 """ create an icon from a stock image """
239@@ -54,11 +87,21 @@
240 item.connect('activate', button[1])
241 if len(button) > 2:
242 item.set_image(button[2])
243+ item.show()
244 menu.append(item)
245 self.buttons[button[0]] = item
246
247- # connect our new menu to the statusicon
248- self.statusicon.connect('popup-menu', self.context_menu, menu)
249+ # connect our new menu to the statusicon or the appindicator
250+ if indicator_capable:
251+ # We have to add another entry for show / hide Pithos window
252+ item = gtk.ImageMenuItem("Show/Hide Pithos");
253+ item.connect('activate',self.statusicon_clicked); # since self.statusicon_clicked shows and hides
254+ item.show()
255+ menu.append(item)
256+ self.buttons["Show/Hide Pithos"] = item
257+ self.ind.set_menu(menu)
258+ else:
259+ self.statusicon.connect('popup-menu', self.context_menu, menu)
260
261
262 def play_state_changed(self, window, playing):
263@@ -74,7 +117,8 @@
264 button.set_image(gtk.image_new_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_MENU))
265
266 def song_changed(self, window, song):
267- self.statusicon.set_tooltip("%s by %s"%(song.title, song.artist))
268+ if not indicator_capable:
269+ self.statusicon.set_tooltip("%s by %s"%(song.title, song.artist))
270
271 def statusicon_clicked(self, status):
272 """ hide/unhide the window
273@@ -94,8 +138,15 @@
274 data.popup(None, None, None, 3, time)
275
276 def remove(self):
277- self.statusicon.set_visible(False)
278+ if indicator_capable:
279+ self.ind.set_status(appindicator.STATUS_PASSIVE)
280+ else:
281+ self.statusicon.set_visible(False)
282+
283 self.window.disconnect(self.delete_callback_handle)
284 self.window.disconnect(self.state_callback_handle)
285 self.window.disconnect(self.song_callback_handle)
286+
287+ # Pithos window needs to be reconnected to on_destro()
288+ self.window.connect('delete-event',self.window.on_destroy)
289
290
291=== modified file 'pithos/pithosconfig.py' (properties changed: -x to +x)
292--- pithos/pithosconfig.py 2010-07-22 19:56:55 +0000
293+++ pithos/pithosconfig.py 2010-07-22 22:24:47 +0000
294@@ -53,4 +53,7 @@
295 return abs_data_path
296 else:
297 raise project_path_not_found
298+
299+def getmediapath():
300+ return getdatapath() + "/media"
301
302
303=== modified file 'setup.py' (properties changed: -x to +x)