Add progress indicator widget for build ETA.
authorTim Potter <tpot@hp.com>
Tue, 8 Apr 2008 05:56:55 +0000 (15:56 +1000)
committerTim Potter <tpot@hp.com>
Tue, 8 Apr 2008 05:56:55 +0000 (15:56 +1000)
gbuildbotclient

index 0310824bfc974d550f82d5b0dfd25fbcb6683b17..cd72a7b7909d51e808fb8c07a887a1a218884ce6 100755 (executable)
@@ -72,6 +72,10 @@ class App(pb.Referenceable):
     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
@@ -97,9 +101,11 @@ class App(pb.Referenceable):
         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)
 
@@ -120,6 +126,12 @@ class App(pb.Referenceable):
             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')
@@ -156,7 +168,7 @@ class App(pb.Referenceable):
 
         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."""
@@ -188,7 +200,7 @@ class App(pb.Referenceable):
                     lambda num:
                         model.set_value(iter, 
                                         self.COL_BUILDER_BUILD_STATUS,
-                                        'started build %d' % num))
+                                        'Started build %d' % num))
 
         self.model.foreach(updateStatus, None)
 
@@ -203,9 +215,19 @@ class App(pb.Referenceable):
         # 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):
@@ -218,12 +240,21 @@ class App(pb.Referenceable):
         # 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)
 
@@ -241,8 +272,8 @@ class App(pb.Referenceable):
 
         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)
 
@@ -273,6 +304,31 @@ class App(pb.Referenceable):
 
         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.