Merge lp:~ted/indicator-jenkins/gobject-introspection into lp:indicator-jenkins
- gobject-introspection
- Merge into trunk
Proposed by
Ted Gould
on 2012-03-02
| 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 | 2012-03-02 | Pending | |
|
Review via email:
|
|||
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: |
