Merge lp:~ted/indicator-jenkins/gobject-introspection into lp:indicator-jenkins
- gobject-introspection
- Merge into trunk
Proposed by
Ted Gould
Status: | Merged |
---|---|
Merged at revision: | 43 |
Proposed branch: | lp:~ted/indicator-jenkins/gobject-introspection |
Merge into: | lp:indicator-jenkins |
Diff against target: |
409 lines (+68/-71) 7 files modified
graphics.py (+10/-10) indicator-jenkins (+15/-15) menu.py (+3/-3) model.py (+26/-27) notifications.py (+4/-6) server_monitor.py (+2/-2) settings_ui.py (+8/-8) |
To merge this branch: | bzr merge lp:~ted/indicator-jenkins/gobject-introspection |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thomi Richards | Pending | ||
Review via email: mp+95590@code.launchpad.net |
Commit message
Description of the change
Switch the indicator over to using GObject Introspection and the newer version of AppIndicator. This removes GTK2 deps as well.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'graphics.py' |
2 | --- graphics.py 2012-02-26 03:58:35 +0000 |
3 | +++ graphics.py 2012-03-02 15:31:21 +0000 |
4 | @@ -15,14 +15,14 @@ |
5 | |
6 | # Copyright 2012 Thomi Richards |
7 | |
8 | -import gtk |
9 | +from gi.repository import Gtk |
10 | import os |
11 | import os.path |
12 | import logging |
13 | |
14 | |
15 | _pixbuf_cache = {} |
16 | -_icon_loader = gtk.IconTheme() |
17 | +_icon_loader = Gtk.IconTheme() |
18 | |
19 | def _make_key(name, size): |
20 | return name + str(size) |
21 | @@ -41,7 +41,7 @@ |
22 | icon_path = os.path.join(os.path.dirname(__file__), 'images') |
23 | if os.path.exists(icon_path): |
24 | filename = os.path.join(icon_path, name + '.svg') |
25 | - pb = gtk.gdk.pixbuf_new_from_file_at_size(filename, size, size) |
26 | + pb = Gtk.Gdk.pixbuf_new_from_file_at_size(filename, size, size) |
27 | _pixbuf_cache[key] = pb |
28 | logging.debug("loading pixbuf %s with size %d from source directory", name, size) |
29 | return pb |
30 | @@ -49,7 +49,7 @@ |
31 | |
32 | |
33 | def get_image_by_name(name, size): |
34 | - img = gtk.Image() |
35 | + img = Gtk.Image() |
36 | img.set_from_pixbuf(load_pixbuf_by_name(name, size)) |
37 | return img |
38 | |
39 | @@ -81,13 +81,13 @@ |
40 | def combine_two_images(left_pb, right_pb): |
41 | """Combine two images side by side. |
42 | |
43 | - Both images must be the same height. Returns a gtk.gdk.Pixmap object |
44 | + Both images must be the same height. Returns a Gtk.Gdk.Pixmap object |
45 | |
46 | """ |
47 | - if type(left_pb) is not gtk.gdk.Pixbuf: |
48 | - raise TypeError("Left image must be a gtk.gdk.Pixbuf") |
49 | - if type(right_pb) is not gtk.gdk.Pixbuf: |
50 | - raise TypeError("Right image must be a gtk.gdk.Pixbuf") |
51 | + if type(left_pb) is not Gtk.Gdk.Pixbuf: |
52 | + raise TypeError("Left image must be a Gtk.Gdk.Pixbuf") |
53 | + if type(right_pb) is not Gtk.Gdk.Pixbuf: |
54 | + raise TypeError("Right image must be a Gtk.Gdk.Pixbuf") |
55 | |
56 | if left_pb.get_height() != right_pb.get_height(): |
57 | raise ValueError("Left and Right images must be the same height.") |
58 | @@ -96,7 +96,7 @@ |
59 | raise ValueError("Left and Right images must be the same width.") |
60 | |
61 | rwidth = left_pb.get_width() + right_pb.get_width() |
62 | - result = gtk.gdk.Pixbuf(right_pb.get_colorspace(), |
63 | + result = Gtk.Gdk.Pixbuf(right_pb.get_colorspace(), |
64 | right_pb.get_has_alpha(), |
65 | right_pb.get_bits_per_sample(), |
66 | rwidth, |
67 | |
68 | === modified file 'indicator-jenkins' |
69 | --- indicator-jenkins 2012-02-28 18:49:21 +0000 |
70 | +++ indicator-jenkins 2012-03-02 15:31:21 +0000 |
71 | @@ -16,9 +16,8 @@ |
72 | |
73 | # Copyright 2012 Thomi Richards |
74 | |
75 | -import gobject |
76 | -import gtk |
77 | -import appindicator |
78 | +from gi.repository import Gtk, GObject |
79 | +from gi.repository import AppIndicator3 |
80 | import logging |
81 | logging.basicConfig(level=logging.DEBUG, |
82 | format="%(asctime)s %(filename)s:%(lineno)d %(levelname)s %(message)s") |
83 | @@ -59,26 +58,27 @@ |
84 | else: |
85 | icon_name = "gnome-system" |
86 | |
87 | - self.ind = appindicator.Indicator ("indicator-jenkins", |
88 | + self.ind = AppIndicator3.Indicator.new ("indicator-jenkins", |
89 | icon_name, |
90 | - appindicator.CATEGORY_APPLICATION_STATUS) |
91 | - self.ind.set_status(appindicator.STATUS_ACTIVE) |
92 | + AppIndicator3.IndicatorCategory.APPLICATION_STATUS) |
93 | + self.ind.set_status(AppIndicator3.IndicatorStatus.ACTIVE) |
94 | + self.ind.set_title("Jenkins") |
95 | |
96 | def create_menu_entries(self): |
97 | """Create the menu that is shown under the app indicator.""" |
98 | - self.menu = gtk.Menu() |
99 | + self.menu = Gtk.Menu() |
100 | |
101 | self.create_jenkins_job_menu_entries() |
102 | - self.menu.append(gtk.SeparatorMenuItem()) |
103 | + self.menu.append(Gtk.SeparatorMenuItem()) |
104 | self.create_settings_and_quit_menu_entries() |
105 | #self.menu.popup(None, None, None, 2, 0) |
106 | |
107 | def create_settings_and_quit_menu_entries(self): |
108 | - mi_settings = gtk.MenuItem("Settings") |
109 | + mi_settings = Gtk.MenuItem("Settings") |
110 | mi_settings.connect("activate", self.on_settings) |
111 | self.menu.append(mi_settings) |
112 | |
113 | - mi_quit = gtk.MenuItem("Quit") |
114 | + mi_quit = Gtk.MenuItem("Quit") |
115 | mi_quit.connect("activate", self.on_quit) |
116 | self.menu.append(mi_quit) |
117 | |
118 | @@ -114,7 +114,7 @@ |
119 | menu_item.show() |
120 | else: |
121 | for pos, child in enumerate(self.menu.get_children()): |
122 | - if type(child) is gtk.SeparatorMenuItem: |
123 | + if type(child) is Gtk.SeparatorMenuItem: |
124 | # insert here, we've hit the end of the job list: |
125 | logging.debug("Inserting menu item '%s' at pos %d since next item is a separator.", menu_item.get_label(), pos) |
126 | self.menu.insert(menu_item, pos) |
127 | @@ -175,15 +175,15 @@ |
128 | get_server_monitor().stop() |
129 | for name, model in self.server_models.iteritems(): |
130 | get_settings().update_settings_from_model(model) |
131 | - gtk.main_quit() |
132 | + Gtk.main_quit() |
133 | |
134 | def on_settings(self, sender): |
135 | dialog = SettingsDialog(self.server_models['default']) |
136 | response = dialog.run() |
137 | dialog.destroy() |
138 | - if response == gtk.RESPONSE_REJECT: |
139 | + if response == Gtk.RESPONSE_REJECT: |
140 | logging.debug("User rejected changes.") |
141 | - elif response == gtk.RESPONSE_OK: |
142 | + elif response == Gtk.RESPONSE_OK: |
143 | logging.debug("User accepted changes.") |
144 | save_settings() |
145 | |
146 | @@ -193,7 +193,7 @@ |
147 | notifications.start() |
148 | get_server_monitor() # TODO - this is here so the WP spins up early. |
149 | ji = JenkinsIndicator() |
150 | - gtk.main() |
151 | + Gtk.main() |
152 | notifications.stop() |
153 | finally: |
154 | save_settings() |
155 | |
156 | === modified file 'menu.py' |
157 | --- menu.py 2012-02-26 04:11:05 +0000 |
158 | +++ menu.py 2012-03-02 15:31:21 +0000 |
159 | @@ -16,7 +16,7 @@ |
160 | # Copyright 2012 Thomi Richards |
161 | |
162 | |
163 | -import gtk |
164 | +from gi.repository import Gtk |
165 | import logging |
166 | import webbrowser |
167 | |
168 | @@ -24,7 +24,7 @@ |
169 | |
170 | logger = logging.getLogger(__name__) |
171 | |
172 | -class JenkinsJobMenuItem(gtk.ImageMenuItem): |
173 | +class JenkinsJobMenuItem(Gtk.ImageMenuItem): |
174 | """A menu item that has an image to represent the job state. |
175 | |
176 | We wrap a JenkinsJobModel and subscribe to it's property change notifications |
177 | @@ -81,7 +81,7 @@ |
178 | # img = combine_two_images(img, health_img) |
179 | |
180 | if img is not None: |
181 | - i = gtk.Image() |
182 | + i = Gtk.Image() |
183 | i.set_from_pixbuf(img) |
184 | self.set_image(i) |
185 | self.set_always_show_image(True) |
186 | |
187 | === modified file 'model.py' |
188 | --- model.py 2012-02-29 20:24:40 +0000 |
189 | +++ model.py 2012-03-02 15:31:21 +0000 |
190 | @@ -15,8 +15,7 @@ |
191 | |
192 | # Copyright 2012 Thomi Richards |
193 | |
194 | -import gobject |
195 | -import gtk |
196 | +from gi.repository import GObject, Gtk, GLib |
197 | import logging |
198 | |
199 | from server_monitor import get_server_monitor |
200 | @@ -24,24 +23,24 @@ |
201 | |
202 | logger = logging.getLogger(__name__) |
203 | |
204 | -class JenkinsServerModel(gobject.GObject): |
205 | +class JenkinsServerModel(GObject.GObject): |
206 | """A model for a jenkins server.""" |
207 | |
208 | - name = gobject.property(type=str) |
209 | - url = gobject.property(type=str) |
210 | - refresh_period = gobject.property(type=int, minimum=30, maximum=60*60) |
211 | + name = GObject.property(type=str) |
212 | + url = GObject.property(type=str) |
213 | + refresh_period = GObject.property(type=int, minimum=30, maximum=60*60, default=5*60) |
214 | |
215 | __gsignals__ = { |
216 | - 'job_added': (gobject.SIGNAL_RUN_LAST, |
217 | - gobject.TYPE_NONE, # signal return type |
218 | - (gobject.TYPE_PYOBJECT,)), # signal parameters |
219 | - 'job_removed': (gobject.SIGNAL_RUN_LAST, |
220 | - gobject.TYPE_NONE, |
221 | - (gobject.TYPE_PYOBJECT,)), |
222 | + 'job_added': (GObject.SIGNAL_RUN_LAST, |
223 | + GObject.TYPE_NONE, # signal return type |
224 | + (GObject.TYPE_PYOBJECT,)), # signal parameters |
225 | + 'job_removed': (GObject.SIGNAL_RUN_LAST, |
226 | + GObject.TYPE_NONE, |
227 | + (GObject.TYPE_PYOBJECT,)), |
228 | } |
229 | |
230 | def __init__(self, name, server_settings): |
231 | - gobject.GObject.__init__(self) |
232 | + GObject.GObject.__init__(self) |
233 | self.name = name |
234 | self.url = server_settings['url'] |
235 | self.refresh_period = server_settings['refresh_period'] * 1000 |
236 | @@ -145,25 +144,25 @@ |
237 | logger.debug("Enableding polling for server monitor.") |
238 | if not self.enabled: |
239 | self.enabled = True |
240 | - gtk.timeout_add(self.refresh_period, self._start_get_server_data) |
241 | + GLib.timeout_add(self.refresh_period, self._start_get_server_data) |
242 | self._start_get_server_data() |
243 | |
244 | |
245 | |
246 | -class JenkinsJobModel(gobject.GObject): |
247 | +class JenkinsJobModel(GObject.GObject): |
248 | """A model for a jenkins server job.""" |
249 | |
250 | - name = gobject.property(type=str) |
251 | - url = gobject.property(type=str) |
252 | - build = gobject.property(type=int) |
253 | - color = gobject.property(type=str) |
254 | - description = gobject.property(type=str) |
255 | - health_description = gobject.property(type=str) |
256 | - health_score = gobject.property(type=int, minimum=0, maximum=100) |
257 | - monitored = gobject.property(type=bool, default=False) |
258 | + name = GObject.property(type=str) |
259 | + url = GObject.property(type=str) |
260 | + build = GObject.property(type=int) |
261 | + color = GObject.property(type=str) |
262 | + description = GObject.property(type=str) |
263 | + health_description = GObject.property(type=str) |
264 | + health_score = GObject.property(type=int, minimum=0, maximum=100) |
265 | + monitored = GObject.property(type=bool, default=False) |
266 | |
267 | def __init__(self, name, url, color, monitored, server): |
268 | - gobject.GObject.__init__(self) |
269 | + GObject.GObject.__init__(self) |
270 | self.name = name |
271 | self.url = url |
272 | self.set_job_color(color) |
273 | @@ -227,7 +226,7 @@ |
274 | |
275 | def _enable_polling(self): |
276 | logger.debug("Starting server data polling for job '%s'", self.name) |
277 | - gtk.timeout_add(self._server_model.refresh_period, self.start_get_more_details) |
278 | + GLib.timeout_add(self._server_model.refresh_period, self.start_get_more_details) |
279 | self.start_get_more_details() |
280 | |
281 | def _on_monitored_changed(self, sender, prop): |
282 | @@ -237,5 +236,5 @@ |
283 | def __repr__(self): |
284 | return "<%s '%s'>" % (self.__class__.__name__, self.name) |
285 | |
286 | -gobject.type_register(JenkinsServerModel) |
287 | -gobject.type_register(JenkinsJobModel) |
288 | +GObject.type_register(JenkinsServerModel) |
289 | +GObject.type_register(JenkinsJobModel) |
290 | |
291 | === modified file 'notifications.py' |
292 | --- notifications.py 2012-02-26 05:09:30 +0000 |
293 | +++ notifications.py 2012-03-02 15:31:21 +0000 |
294 | @@ -15,7 +15,7 @@ |
295 | |
296 | # Copyright 2012 Thomi Richards |
297 | |
298 | -import pynotify |
299 | +from gi.repository import Notify |
300 | import logging |
301 | logger = logging.getLogger(__name__) |
302 | |
303 | @@ -26,8 +26,7 @@ |
304 | ) |
305 | |
306 | def start(): |
307 | - pynotify.init("indicator-jenkins") |
308 | - |
309 | + Notify.init("indicator-jenkins") |
310 | |
311 | def send_job_update_notification(job, prop): |
312 | """Send a desktop notification of a new build.""" |
313 | @@ -38,11 +37,10 @@ |
314 | health_image = get_pixbuf_for_health_score(job.health_score, 48) |
315 | state_image = load_pixbuf_by_name("status-" + job.color, 48) |
316 | combined_image = combine_two_images(health_image, state_image) |
317 | - n = pynotify.Notification(title, text) |
318 | + n = Notify.Notification(summary=title, body=text) |
319 | n.set_icon_from_pixbuf(combined_image) |
320 | if not n.show(): |
321 | logger.warning("Notification show failed.") |
322 | |
323 | - |
324 | def stop(): |
325 | - pynotify.uninit() |
326 | + Notify.uninit() |
327 | |
328 | === modified file 'server_monitor.py' |
329 | --- server_monitor.py 2012-02-24 08:25:05 +0000 |
330 | +++ server_monitor.py 2012-03-02 15:31:21 +0000 |
331 | @@ -15,7 +15,7 @@ |
332 | |
333 | # Copyright 2012 Thomi Richards |
334 | |
335 | -import gtk |
336 | +from gi.repository import Gtk, GLib |
337 | import jenkins |
338 | import logging |
339 | from multiprocessing import Process, get_logger, Event |
340 | @@ -55,7 +55,7 @@ |
341 | self._callback_queue = [] |
342 | # TODO - if we MUST poll for data, instead of running it all the time, |
343 | # only run it while there's an active request. |
344 | - gtk.timeout_add(1000, self._poll_for_data) |
345 | + GLib.timeout_add_seconds(1, self._poll_for_data) |
346 | |
347 | def start_get_server_data(self, server_url, callback): |
348 | """Start getting server data from 'server_url'.""" |
349 | |
350 | === modified file 'settings_ui.py' |
351 | --- settings_ui.py 2012-02-28 19:18:23 +0000 |
352 | +++ settings_ui.py 2012-03-02 15:31:21 +0000 |
353 | @@ -15,7 +15,7 @@ |
354 | |
355 | # Copyright 2012 Thomi Richards |
356 | |
357 | -import gtk |
358 | +from gi.repository import Gtk |
359 | import os |
360 | import os.path |
361 | import logging |
362 | @@ -26,7 +26,7 @@ |
363 | class SettingsDialog(object): |
364 | def __init__(self, jenkins_server_model): |
365 | self.server_model = jenkins_server_model |
366 | - self.builder = gtk.Builder() |
367 | + self.builder = Gtk.Builder() |
368 | ui_file_path = os.path.join( |
369 | os.path.dirname( |
370 | os.path.realpath(__file__) |
371 | @@ -42,24 +42,24 @@ |
372 | |
373 | self.url_entry.set_text(self.server_model.url) |
374 | |
375 | - cr = gtk.CellRendererPixbuf() |
376 | + cr = Gtk.CellRendererPixbuf() |
377 | cr.set_property("height", 24) |
378 | cr.set_property("width", 24) |
379 | - col1 = gtk.TreeViewColumn("State", cr, pixbuf=0) |
380 | + col1 = Gtk.TreeViewColumn("State", cr, pixbuf=0) |
381 | col1.set_resizable(False) |
382 | col1.set_fixed_width(24) |
383 | self.treeview.append_column(col1) |
384 | |
385 | - col2 = gtk.TreeViewColumn("Job Name", gtk.CellRendererText(), text=1) |
386 | + col2 = Gtk.TreeViewColumn("Job Name", Gtk.CellRendererText(), text=1) |
387 | col2.set_resizable(True) |
388 | self.treeview.append_column(col2) |
389 | |
390 | - cr = gtk.CellRendererToggle() |
391 | + cr = Gtk.CellRendererToggle() |
392 | cr.set_property("height", 24) |
393 | cr.set_property("width", 24) |
394 | cr.set_property('activatable', True) |
395 | cr.connect("toggled", self.job_toggled) |
396 | - col3 = gtk.TreeViewColumn("Track Job", cr, active=2) |
397 | + col3 = Gtk.TreeViewColumn("Track Job", cr, active=2) |
398 | col3.set_resizable(False) |
399 | self.treeview.append_column(col3) |
400 | |
401 | @@ -112,7 +112,7 @@ |
402 | return self.dlg.destroy() |
403 | |
404 | def _on_response(self, dlg, response_id): |
405 | - if response_id == gtk.RESPONSE_OK: |
406 | + if response_id == Gtk.RESPONSE_OK: |
407 | if self.server_model.url != self.url_entry.get_text(): |
408 | self.server_model.url = self.url_entry.get_text() |
409 | for item in self.job_model: |