2008-11-14 11:38:10 +00:00
|
|
|
#
|
|
|
|
# BitBake Graphical GTK User Interface
|
|
|
|
#
|
|
|
|
# Copyright (C) 2008 Intel Corporation
|
|
|
|
#
|
|
|
|
# Authored by Rob Bradford <rob@linux.intel.com>
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License version 2 as
|
|
|
|
# published by the Free Software Foundation.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License along
|
|
|
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
|
|
|
|
import gtk
|
2008-11-14 14:14:08 +00:00
|
|
|
import gobject
|
2008-11-14 11:38:10 +00:00
|
|
|
|
|
|
|
class RunningBuildModel (gtk.TreeStore):
|
|
|
|
(COL_TYPE, COL_PACKAGE, COL_TASK, COL_MESSAGE, COL_ICON, COL_ACTIVE) = (0, 1, 2, 3, 4, 5)
|
|
|
|
def __init__ (self):
|
2010-03-24 23:56:12 +00:00
|
|
|
gtk.TreeStore.__init__ (self,
|
2008-11-14 11:38:10 +00:00
|
|
|
gobject.TYPE_STRING,
|
|
|
|
gobject.TYPE_STRING,
|
|
|
|
gobject.TYPE_STRING,
|
|
|
|
gobject.TYPE_STRING,
|
|
|
|
gobject.TYPE_STRING,
|
|
|
|
gobject.TYPE_BOOLEAN)
|
|
|
|
|
|
|
|
class RunningBuild (gobject.GObject):
|
|
|
|
__gsignals__ = {
|
2010-03-24 23:56:12 +00:00
|
|
|
'build-succeeded' : (gobject.SIGNAL_RUN_LAST,
|
2008-11-14 14:14:08 +00:00
|
|
|
gobject.TYPE_NONE,
|
|
|
|
()),
|
|
|
|
'build-failed' : (gobject.SIGNAL_RUN_LAST,
|
|
|
|
gobject.TYPE_NONE,
|
|
|
|
())
|
2008-11-14 11:38:10 +00:00
|
|
|
}
|
|
|
|
pids_to_task = {}
|
|
|
|
tasks_to_iter = {}
|
|
|
|
|
|
|
|
def __init__ (self):
|
|
|
|
gobject.GObject.__init__ (self)
|
|
|
|
self.model = RunningBuildModel()
|
|
|
|
|
|
|
|
def handle_event (self, event):
|
|
|
|
# Handle an event from the event queue, this may result in updating
|
|
|
|
# the model and thus the UI. Or it may be to tell us that the build
|
|
|
|
# has finished successfully (or not, as the case may be.)
|
|
|
|
|
|
|
|
parent = None
|
|
|
|
pid = 0
|
|
|
|
package = None
|
|
|
|
task = None
|
|
|
|
|
|
|
|
# If we have a pid attached to this message/event try and get the
|
|
|
|
# (package, task) pair for it. If we get that then get the parent iter
|
|
|
|
# for the message.
|
2010-03-24 03:24:32 +00:00
|
|
|
if hasattr(event, 'pid'):
|
2010-01-19 14:48:19 +00:00
|
|
|
pid = event.pid
|
2008-11-14 11:38:10 +00:00
|
|
|
if self.pids_to_task.has_key(pid):
|
|
|
|
(package, task) = self.pids_to_task[pid]
|
|
|
|
parent = self.tasks_to_iter[(package, task)]
|
|
|
|
|
2010-01-19 14:48:19 +00:00
|
|
|
if isinstance(event, bb.msg.Msg):
|
2008-11-14 11:38:10 +00:00
|
|
|
# Set a pretty icon for the message based on it's type.
|
2010-01-19 14:48:19 +00:00
|
|
|
if isinstance(event, bb.msg.MsgWarn):
|
2008-11-14 11:38:10 +00:00
|
|
|
icon = "dialog-warning"
|
2010-01-19 14:48:19 +00:00
|
|
|
elif isinstance(event, bb.msg.MsgErr):
|
2008-11-14 11:38:10 +00:00
|
|
|
icon = "dialog-error"
|
|
|
|
else:
|
|
|
|
icon = None
|
|
|
|
|
|
|
|
# Ignore the "Running task i of n .." messages
|
2010-01-19 14:48:19 +00:00
|
|
|
if (event._message.startswith ("Running task")):
|
2008-11-14 11:38:10 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
# Add the message to the tree either at the top level if parent is
|
|
|
|
# None otherwise as a descendent of a task.
|
2010-03-24 23:56:12 +00:00
|
|
|
self.model.append (parent,
|
2010-01-19 14:48:19 +00:00
|
|
|
(event.__name__.split()[-1], # e.g. MsgWarn, MsgError
|
2010-03-24 23:56:12 +00:00
|
|
|
package,
|
2008-11-14 11:38:10 +00:00
|
|
|
task,
|
2010-01-19 14:48:19 +00:00
|
|
|
event._message,
|
2010-03-24 23:56:12 +00:00
|
|
|
icon,
|
2008-11-14 11:38:10 +00:00
|
|
|
False))
|
2010-01-19 14:48:19 +00:00
|
|
|
elif isinstance(event, bb.build.TaskStarted):
|
|
|
|
(package, task) = (event._package, event._task)
|
2008-11-14 11:38:10 +00:00
|
|
|
|
|
|
|
# Save out this PID.
|
|
|
|
self.pids_to_task[pid] = (package,task)
|
|
|
|
|
|
|
|
# Check if we already have this package in our model. If so then
|
|
|
|
# that can be the parent for the task. Otherwise we create a new
|
|
|
|
# top level for the package.
|
|
|
|
if (self.tasks_to_iter.has_key ((package, None))):
|
|
|
|
parent = self.tasks_to_iter[(package, None)]
|
|
|
|
else:
|
2010-03-24 23:56:12 +00:00
|
|
|
parent = self.model.append (None, (None,
|
|
|
|
package,
|
2008-11-14 11:38:10 +00:00
|
|
|
None,
|
2010-03-24 23:56:12 +00:00
|
|
|
"Package: %s" % (package),
|
2008-11-14 11:38:10 +00:00
|
|
|
None,
|
|
|
|
False))
|
|
|
|
self.tasks_to_iter[(package, None)] = parent
|
|
|
|
|
|
|
|
# Because this parent package now has an active child mark it as
|
|
|
|
# such.
|
|
|
|
self.model.set(parent, self.model.COL_ICON, "gtk-execute")
|
|
|
|
|
|
|
|
# Add an entry in the model for this task
|
2010-03-24 23:56:12 +00:00
|
|
|
i = self.model.append (parent, (None,
|
|
|
|
package,
|
2008-11-14 11:38:10 +00:00
|
|
|
task,
|
2010-03-24 23:56:12 +00:00
|
|
|
"Task: %s" % (task),
|
2008-11-14 11:38:10 +00:00
|
|
|
None,
|
|
|
|
False))
|
|
|
|
|
|
|
|
# Save out the iter so that we can find it when we have a message
|
|
|
|
# that we need to attach to a task.
|
|
|
|
self.tasks_to_iter[(package, task)] = i
|
|
|
|
|
|
|
|
# Mark this task as active.
|
|
|
|
self.model.set(i, self.model.COL_ICON, "gtk-execute")
|
|
|
|
|
2010-01-19 14:48:19 +00:00
|
|
|
elif isinstance(event, bb.build.Task):
|
2008-11-14 11:38:10 +00:00
|
|
|
|
2010-01-19 14:48:19 +00:00
|
|
|
if isinstance(event, bb.build.TaskFailed):
|
2008-11-14 11:38:10 +00:00
|
|
|
# Mark the task as failed
|
|
|
|
i = self.tasks_to_iter[(package, task)]
|
|
|
|
self.model.set(i, self.model.COL_ICON, "dialog-error")
|
|
|
|
|
|
|
|
# Mark the parent package as failed
|
|
|
|
i = self.tasks_to_iter[(package, None)]
|
|
|
|
self.model.set(i, self.model.COL_ICON, "dialog-error")
|
|
|
|
else:
|
|
|
|
# Mark the task as inactive
|
|
|
|
i = self.tasks_to_iter[(package, task)]
|
|
|
|
self.model.set(i, self.model.COL_ICON, None)
|
|
|
|
|
|
|
|
# Mark the parent package as inactive
|
|
|
|
i = self.tasks_to_iter[(package, None)]
|
|
|
|
self.model.set(i, self.model.COL_ICON, None)
|
|
|
|
|
|
|
|
|
|
|
|
# Clear the iters and the pids since when the task goes away the
|
|
|
|
# pid will no longer be used for messages
|
|
|
|
del self.tasks_to_iter[(package, task)]
|
|
|
|
del self.pids_to_task[pid]
|
|
|
|
|
2010-01-19 14:48:19 +00:00
|
|
|
elif isinstance(event, bb.event.BuildCompleted):
|
|
|
|
failures = int (event._failures)
|
2008-11-14 14:14:08 +00:00
|
|
|
|
|
|
|
# Emit the appropriate signal depending on the number of failures
|
|
|
|
if (failures > 1):
|
|
|
|
self.emit ("build-failed")
|
|
|
|
else:
|
|
|
|
self.emit ("build-succeeded")
|
|
|
|
|
2008-11-14 11:38:10 +00:00
|
|
|
class RunningBuildTreeView (gtk.TreeView):
|
|
|
|
def __init__ (self):
|
|
|
|
gtk.TreeView.__init__ (self)
|
|
|
|
|
|
|
|
# The icon that indicates whether we're building or failed.
|
|
|
|
renderer = gtk.CellRendererPixbuf ()
|
|
|
|
col = gtk.TreeViewColumn ("Status", renderer)
|
|
|
|
col.add_attribute (renderer, "icon-name", 4)
|
|
|
|
self.append_column (col)
|
|
|
|
|
|
|
|
# The message of the build.
|
|
|
|
renderer = gtk.CellRendererText ()
|
|
|
|
col = gtk.TreeViewColumn ("Message", renderer, text=3)
|
|
|
|
self.append_column (col)
|