Merge lp:~vinod-khare/pithos/appindicator into lp:~kevin-mehall/pithos/trunk
- appindicator
- Merge into trunk
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 |
Related bugs: |
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.
Commit message
Description of the change
Adds appindicator support for Ubuntu. Also adds a monochrome icon for the same.
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://
> fication_
> 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.
Unmerged revisions
Preview Diff
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' |
134 | Binary 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) |
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/notificati on_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?