mirror of
https://git.yoctoproject.org/poky
synced 2026-05-31 12:49:46 +00:00
bitbake-dev: Refactor goggle to pull out useful components.
Separate the GTK components and abstractions to a separate module where they can be used by other user interfaces. This module includes the model, the view and abstraction that populates the model.
This commit is contained in:
committed by
Richard Purdie
parent
49e8c06b77
commit
340b2b5612
@@ -0,0 +1,18 @@
|
|||||||
|
#
|
||||||
|
# BitBake UI Implementation
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2007 Richard Purdie
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
#
|
||||||
|
# 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 gobject
|
||||||
|
import gtk
|
||||||
|
|
||||||
|
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):
|
||||||
|
gtk.TreeStore.__init__ (self,
|
||||||
|
gobject.TYPE_STRING,
|
||||||
|
gobject.TYPE_STRING,
|
||||||
|
gobject.TYPE_STRING,
|
||||||
|
gobject.TYPE_STRING,
|
||||||
|
gobject.TYPE_STRING,
|
||||||
|
gobject.TYPE_BOOLEAN)
|
||||||
|
|
||||||
|
class RunningBuild (gobject.GObject):
|
||||||
|
__gsignals__ = {
|
||||||
|
'build-finished' : (gobject.SIGNAL_RUN_LAST,
|
||||||
|
gobject.TYPE_NONE,
|
||||||
|
())
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
if event[1].has_key ('pid'):
|
||||||
|
pid = event[1]['pid']
|
||||||
|
if self.pids_to_task.has_key(pid):
|
||||||
|
(package, task) = self.pids_to_task[pid]
|
||||||
|
parent = self.tasks_to_iter[(package, task)]
|
||||||
|
|
||||||
|
if event[0].startswith('bb.msg.Msg'):
|
||||||
|
# Set a pretty icon for the message based on it's type.
|
||||||
|
if (event[0].startswith ('bb.msg.MsgWarn')):
|
||||||
|
icon = "dialog-warning"
|
||||||
|
elif (event[0].startswith ('bb.msg.MsgErr')):
|
||||||
|
icon = "dialog-error"
|
||||||
|
else:
|
||||||
|
icon = None
|
||||||
|
|
||||||
|
# Ignore the "Running task i of n .." messages
|
||||||
|
if (event[1]['_message'].startswith ("Running task")):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Add the message to the tree either at the top level if parent is
|
||||||
|
# None otherwise as a descendent of a task.
|
||||||
|
self.model.append (parent,
|
||||||
|
(event[0].split()[-1], # e.g. MsgWarn, MsgError
|
||||||
|
package,
|
||||||
|
task,
|
||||||
|
event[1]['_message'],
|
||||||
|
icon,
|
||||||
|
False))
|
||||||
|
elif event[0].startswith('bb.build.TaskStarted'):
|
||||||
|
(package, task) = (event[1]['_package'], event[1]['_task'])
|
||||||
|
|
||||||
|
# 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:
|
||||||
|
parent = self.model.append (None, (None,
|
||||||
|
package,
|
||||||
|
None,
|
||||||
|
"Package: %s" % (package),
|
||||||
|
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
|
||||||
|
i = self.model.append (parent, (None,
|
||||||
|
package,
|
||||||
|
task,
|
||||||
|
"Task: %s" % (task),
|
||||||
|
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")
|
||||||
|
|
||||||
|
elif event[0].startswith('bb.build.Task'):
|
||||||
|
|
||||||
|
if event[0].startswith('bb.build.TaskFailed'):
|
||||||
|
# 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]
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ import gobject
|
|||||||
import gtk
|
import gtk
|
||||||
import threading
|
import threading
|
||||||
import bb.ui.uihelper
|
import bb.ui.uihelper
|
||||||
|
from bb.ui.crumbs.runningbuild import RunningBuildTreeView, RunningBuild
|
||||||
|
|
||||||
def event_handle_idle_func (eventHandler, build):
|
def event_handle_idle_func (eventHandler, build):
|
||||||
|
|
||||||
@@ -33,151 +34,6 @@ def event_handle_idle_func (eventHandler, build):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
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):
|
|
||||||
gtk.TreeStore.__init__ (self,
|
|
||||||
gobject.TYPE_STRING,
|
|
||||||
gobject.TYPE_STRING,
|
|
||||||
gobject.TYPE_STRING,
|
|
||||||
gobject.TYPE_STRING,
|
|
||||||
gobject.TYPE_STRING,
|
|
||||||
gobject.TYPE_BOOLEAN)
|
|
||||||
|
|
||||||
class RunningBuild (gobject.GObject):
|
|
||||||
__gsignals__ = {
|
|
||||||
'build-finished' : (gobject.SIGNAL_RUN_LAST,
|
|
||||||
gobject.TYPE_NONE,
|
|
||||||
())
|
|
||||||
}
|
|
||||||
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.
|
|
||||||
if event[1].has_key ('pid'):
|
|
||||||
pid = event[1]['pid']
|
|
||||||
if self.pids_to_task.has_key(pid):
|
|
||||||
(package, task) = self.pids_to_task[pid]
|
|
||||||
parent = self.tasks_to_iter[(package, task)]
|
|
||||||
|
|
||||||
if event[0].startswith('bb.msg.Msg'):
|
|
||||||
# Set a pretty icon for the message based on it's type.
|
|
||||||
if (event[0].startswith ('bb.msg.MsgWarn')):
|
|
||||||
icon = "dialog-warning"
|
|
||||||
elif (event[0].startswith ('bb.msg.MsgErr')):
|
|
||||||
icon = "dialog-error"
|
|
||||||
else:
|
|
||||||
icon = None
|
|
||||||
|
|
||||||
# Ignore the "Running task i of n .." messages
|
|
||||||
if (event[1]['_message'].startswith ("Running task")):
|
|
||||||
return
|
|
||||||
|
|
||||||
# Add the message to the tree either at the top level if parent is
|
|
||||||
# None otherwise as a descendent of a task.
|
|
||||||
self.model.append (parent,
|
|
||||||
(event[0].split()[-1], # e.g. MsgWarn, MsgError
|
|
||||||
package,
|
|
||||||
task,
|
|
||||||
event[1]['_message'],
|
|
||||||
icon,
|
|
||||||
False))
|
|
||||||
elif event[0].startswith('bb.build.TaskStarted'):
|
|
||||||
(package, task) = (event[1]['_package'], event[1]['_task'])
|
|
||||||
|
|
||||||
# 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:
|
|
||||||
parent = self.model.append (None, (None,
|
|
||||||
package,
|
|
||||||
None,
|
|
||||||
"Package: %s" % (package),
|
|
||||||
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
|
|
||||||
i = self.model.append (parent, (None,
|
|
||||||
package,
|
|
||||||
task,
|
|
||||||
"Task: %s" % (task),
|
|
||||||
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")
|
|
||||||
|
|
||||||
elif event[0].startswith('bb.build.Task'):
|
|
||||||
|
|
||||||
if event[0].startswith('bb.build.TaskFailed'):
|
|
||||||
# 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]
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
class MainWindow (gtk.Window):
|
class MainWindow (gtk.Window):
|
||||||
def __init__ (self):
|
def __init__ (self):
|
||||||
gtk.Window.__init__ (self, gtk.WINDOW_TOPLEVEL)
|
gtk.Window.__init__ (self, gtk.WINDOW_TOPLEVEL)
|
||||||
|
|||||||
Reference in New Issue
Block a user