COL_BUILDER_STATE = 2 # str: State of builder
COL_BUILDER_BUILD_STATUS = 3 # str: State of current or last build
+ COL_BUILDER_BUILD_ETA_TEXT = 4 # str: Time remaining for build
+ COL_BUILDER_BUILD_ETA_PERCENT = 5 # int: Percent complete for build
+ COL_BUILDER_BUILD_ETA_TOTAL = 6 # int: Total estimated time for build
+
# Subscription modes. Each mode includes events of previous mode.
MODE_BUILDERS = 'builders' # builderAdded, builderRemoved
self.win = self.xml.get_widget('toplevel')
self.win.connect('destroy', gtk.main_quit)
- self.model = gtk.ListStore(gobject.TYPE_PYOBJECT, str, str, str)
+ self.model = gtk.ListStore(
+ gobject.TYPE_PYOBJECT, str, str, str, str, int, int)
- self.model.set_sort_column_id(self.COL_BUILDER_NAME, gtk.SORT_ASCENDING)
+ self.model.set_sort_column_id(
+ self.COL_BUILDER_STATE, gtk.SORT_ASCENDING)
view = gtk.TreeView(self.model)
SortableTreeViewColumn(
'Build Status', self.COL_BUILDER_BUILD_STATUS))
+ view.append_column(
+ gtk.TreeViewColumn('Build ETA',
+ gtk.CellRendererProgress(),
+ text = self.COL_BUILDER_BUILD_ETA_TEXT,
+ value = self.COL_BUILDER_BUILD_ETA_PERCENT))
+
view.show()
scrolledwindow = self.xml.get_widget('builders_scrolledwindow')
self.model.set_value(iter, self.COL_BUILDER, builder)
self.model.set_value(iter, self.COL_BUILDER_NAME, buildername)
-
+ self.model.set_value(iter, self.COL_BUILDER_BUILD_ETA_TEXT, 'n/a')
def remote_builderRemoved(self, buildername):
"""Called by the PB server when a builder has been removed from the
buildbot."""
lambda num:
model.set_value(iter,
self.COL_BUILDER_BUILD_STATUS,
- 'started build %d' % num))
+ 'Started build %d' % num))
self.model.foreach(updateStatus, None)
# Reflect state change in model
def updateState(model, path, iter, user_data):
+
if model.get_value(iter, self.COL_BUILDER_NAME) == buildername:
+
+ # Update state
+
model.set_value(iter, self.COL_BUILDER_STATE, statename)
+ # Update status
+
+ if statename == 'building':
+ model.set_value(
+ iter, self.COL_BUILDER_BUILD_STATUS, 'Unknown')
+
self.model.foreach(updateState, None)
def remote_buildFinished(self, buildername, build, result):
# Update build status
def updateStatus(model, path, iter, user_data):
+
if model.get_value(iter, self.COL_BUILDER_NAME) == buildername:
+
+ # Update build status
+
build.callRemote('getNumber').addCallback(
lambda num:
model.set_value(iter,
self.COL_BUILDER_BUILD_STATUS,
- 'finished build %d' % num))
+ 'Finished build %d' % num))
+
+ # Reset progress indicators
+
+ model.set_value(iter, self.COL_BUILDER_BUILD_ETA_TOTAL, 0)
+ model.set_value(iter, self.COL_BUILDER_BUILD_ETA_TEXT, 'n/a')
self.model.foreach(updateStatus, None)
def updateStatus(model, path, iter, user_data):
if model.get_value(iter, self.COL_BUILDER_NAME) == buildername:
- self.model.set_value(iter, self.COL_BUILDER_BUILD_STATUS,
- 'Started step "%s"' % stepname)
+ model.set_value(iter, self.COL_BUILDER_BUILD_STATUS,
+ 'Started step "%s"' % stepname)
self.model.foreach(updateStatus, None)
log.msg('"%s" to finish build in %s seconds' % (buildername, eta))
+ # Update build progress
+
+ def updateProgress(model, path, iter, user_data):
+
+ if model.get_value(iter, self.COL_BUILDER_NAME) == buildername:
+
+ min = int(eta/60)
+ sec = int(eta - min*60)
+
+ model.set_value(
+ iter, self.COL_BUILDER_BUILD_ETA_TEXT,
+ '%d:%02d remaining' % (min, sec))
+
+ total = model.get_value(iter, self.COL_BUILDER_BUILD_ETA_TOTAL)
+
+ if total == 0:
+ model.set_value(iter, self.COL_BUILDER_BUILD_ETA_TOTAL, eta)
+ total = eta
+
+ model.set_value(
+ iter, self.COL_BUILDER_BUILD_ETA_PERCENT,
+ 100 * (total - eta) / total)
+
+ self.model.foreach(updateProgress, None)
+
def remote_stepETAUpdate(self, buildername, build, stepname, step,
eta, expectations):
"""Called by the PB server to update the ETA for a step in a build.