Merge lp:~ted/indicator-jenkins/gobject-introspection into lp:indicator-jenkins

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
Reviewer Review Type Date Requested Status
Thomi Richards Pending
Review via email: mp+95590@code.launchpad.net

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:

Subscribers

People subscribed via source and target branches

to all changes: