bitbake: Add new UI hob, a prototype Gtk+ GUI for creating images

Hob is a first stab at implementing an interactive GUI for BitBake.

Signed-off-by: Joshua Lock <josh@linux.intel.com>
This commit is contained in:
Joshua Lock 2011-02-02 13:02:43 +00:00 committed by Richard Purdie
parent c2814caa5d
commit 6dbceb0be9
2 changed files with 734 additions and 0 deletions

View File

@ -0,0 +1,138 @@
#
# BitBake Graphical GTK User Interface
#
# Copyright (C) 2011 Intel Corporation
#
# Authored by Joshua Lock <josh@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
from bb.ui.crumbs.progress import ProgressBar
progress_total = 0
class HobHandler(gobject.GObject):
"""
This object does BitBake event handling for the hob gui.
"""
__gsignals__ = {
"machines-updated" : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,)),
"distros-updated" : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,)),
"generating-data" : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
()),
"data-generated" : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
())
}
def __init__(self, taskmodel, server):
gobject.GObject.__init__(self)
self.model = taskmodel
self.server = server
self.current_command = None
self.building = False
self.command_map = {
"findConfigFilesDistro" : ("findConfigFiles", "MACHINE", "findConfigFilesMachine"),
"findConfigFilesMachine" : ("generateTargetsTree", "classes/image.bbclass", None),
"generateTargetsTree" : (None, None, None),
}
def run_next_command(self):
# FIXME: this is ugly and I *will* replace it
if self.current_command:
next_cmd = self.command_map[self.current_command]
command = next_cmd[0]
argument = next_cmd[1]
self.current_command = next_cmd[2]
if command == "generateTargetsTree":
self.emit("generating-data")
self.server.runCommand([command, argument])
def handle_event(self, event, running_build, pbar=None):
if not event:
return
# If we're running a build, use the RunningBuild event handler
if self.building:
running_build.handle_event(event)
elif isinstance(event, bb.event.TargetsTreeGenerated):
self.emit("data-generated")
if event._model:
self.model.populate(event._model)
elif isinstance(event, bb.event.ConfigFilesFound):
var = event._variable
if var == "distro":
distros = event._values
distros.sort()
self.emit("distros-updated", distros)
elif var == "machine":
machines = event._values
machines.sort()
self.emit("machines-updated", machines)
elif isinstance(event, bb.command.CommandCompleted):
self.run_next_command()
elif isinstance(event, bb.event.CacheLoadStarted) and pbar:
pbar.set_title("Loading cache")
bb.ui.crumbs.hobeventhandler.progress_total = event.total
pbar.update(0, bb.ui.crumbs.hobeventhandler.progress_total)
elif isinstance(event, bb.event.CacheLoadProgress) and pbar:
pbar.update(event.current, bb.ui.crumbs.hobeventhandler.progress_total)
elif isinstance(event, bb.event.CacheLoadCompleted) and pbar:
pbar.update(bb.ui.crumbs.hobeventhandler.progress_total, bb.ui.crumbs.hobeventhandler.progress_total)
elif isinstance(event, bb.event.ParseStarted) and pbar:
pbar.set_title("Processing recipes")
bb.ui.crumbs.hobeventhandler.progress_total = event.total
pbar.update(0, bb.ui.crumbs.hobeventhandler.progress_total)
elif isinstance(event, bb.event.ParseProgress) and pbar:
pbar.update(event.current, bb.ui.crumbs.hobeventhandler.progress_total)
elif isinstance(event, bb.event.ParseCompleted) and pbar:
pbar.hide()
return
def event_handle_idle_func (self, eventHandler, running_build, pbar):
# Consume as many messages as we can in the time available to us
event = eventHandler.getEvent()
while event:
self.handle_event(event, running_build, pbar)
event = eventHandler.getEvent()
return True
def set_machine(self, machine):
self.server.runCommand(["setVariable", "MACHINE", machine])
self.current_command = "findConfigFilesMachine"
self.emit("generating-data")
self.run_next_command()
def set_distro(self, distro):
self.server.runCommand(["setVariable", "DISTRO", distro])
def run_build(self, targets):
self.building = True
self.server.runCommand(["buildTargets", targets, "build"])
def cancel_build(self):
# Note: this may not be the right way to stop an in-progress build
self.server.runCommand(["stateStop"])

596
bitbake/lib/bb/ui/hob.py Normal file
View File

@ -0,0 +1,596 @@
#
# BitBake Graphical GTK User Interface
#
# Copyright (C) 2011 Intel Corporation
#
# Authored by Joshua Lock <josh@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
from bb.ui.crumbs.progress import ProgressBar
from bb.ui.crumbs.tasklistmodel import TaskListModel
from bb.ui.crumbs.hobeventhandler import HobHandler
from bb.ui.crumbs.runningbuild import RunningBuildTreeView, RunningBuild
import xmlrpclib
import logging
import Queue
class MainWindow (gtk.Window):
def __init__(self, taskmodel, handler, curr_mach=None, curr_distro=None):
gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
self.model = taskmodel
self.model.connect("tasklist-populated", self.update_model)
self.curr_mach = curr_mach
self.curr_distro = curr_distro
self.handler = handler
self.set_border_width(10)
self.connect("delete-event", gtk.main_quit)
self.set_title("BitBake Image Creator")
self.set_default_size(700, 600)
self.build = RunningBuild()
self.build.connect("build-succeeded", self.running_build_succeeded_cb)
self.build.connect("build-failed", self.running_build_failed_cb)
createview = self.create_build_gui()
buildview = self.view_build_gui()
self.nb = gtk.Notebook()
self.nb.append_page(createview)
self.nb.append_page(buildview)
self.nb.set_current_page(0)
self.nb.set_show_tabs(False)
self.add(self.nb)
self.generating = False
def scroll_tv_cb(self, model, path, it, view):
view.scroll_to_cell(path)
def running_build_failed_cb(self, running_build):
# FIXME: handle this
return
def running_build_succeeded_cb(self, running_build):
label = gtk.Label("Build completed, start another build?")
dialog = gtk.Dialog("Build complete",
self,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_NO, gtk.RESPONSE_NO,
gtk.STOCK_YES, gtk.RESPONSE_YES))
dialog.vbox.pack_start(label)
label.show()
response = dialog.run()
dialog.destroy()
if not response == gtk.RESPONSE_YES:
self.model.reset() # NOTE: really?
self.nb.set_current_page(0)
return
def machine_combo_changed_cb(self, combo, handler):
mach = combo.get_active_text()
if mach != self.curr_mach:
self.curr_mach = mach
handler.set_machine(mach)
def update_machines(self, handler, machines):
active = 0
for machine in machines:
self.machine_combo.append_text(machine)
if machine == self.curr_mach:
self.machine_combo.set_active(active)
active = active + 1
self.machine_combo.connect("changed", self.machine_combo_changed_cb, handler)
def update_distros(self, handler, distros):
# FIXME: when we add UI for changing distro this will be used
return
def data_generated(self, handler):
self.generating = False
def spin_idle_func(self, pbar):
if self.generating:
pbar.pulse()
return True
else:
pbar.hide()
return False
def busy(self, handler):
self.generating = True
pbar = ProgressBar(self)
pbar.connect("delete-event", gtk.main_quit) # NOTE: questionable...
pbar.pulse()
gobject.timeout_add (200,
self.spin_idle_func,
pbar)
def update_model(self, model):
pkgsaz_model = gtk.TreeModelSort(self.model.packages_model())
pkgsaz_model.set_sort_column_id(self.model.COL_NAME, gtk.SORT_ASCENDING)
self.pkgsaz_tree.set_model(pkgsaz_model)
# FIXME: need to implement a custom sort function, as otherwise the column
# is re-ordered when toggling the inclusion state (COL_INC)
pkgsgrp_model = gtk.TreeModelSort(self.model.packages_model())
pkgsgrp_model.set_sort_column_id(self.model.COL_GROUP, gtk.SORT_ASCENDING)
self.pkgsgrp_tree.set_model(pkgsgrp_model)
self.contents_tree.set_model(self.model.contents_model())
self.images_tree.set_model(self.model.images_model())
self.tasks_tree.set_model(self.model.tasks_model())
def reset_clicked_cb(self, button):
label = gtk.Label("Are you sure you want to reset the image contents?")
dialog = gtk.Dialog("Confirm reset", self,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
dialog.vbox.pack_start(label)
label.show()
response = dialog.run()
dialog.destroy()
if (response == gtk.RESPONSE_ACCEPT):
self.model.reset()
return
def bake_clicked_cb(self, button):
if not self.model.targets_contains_image():
label = gtk.Label("No image was selected. Just build the selected packages?")
dialog = gtk.Dialog("Warning, no image selected",
self,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_NO, gtk.RESPONSE_NO,
gtk.STOCK_YES, gtk.RESPONSE_YES))
dialog.vbox.pack_start(label)
label.show()
response = dialog.run()
dialog.destroy()
if not response == gtk.RESPONSE_YES:
return
# Note: We could "squash" the targets list to only include things not brought in by an image
task_list = self.model.get_targets()
if len(task_list):
tasks = " ".join(task_list)
# TODO: show a confirmation dialog
print("Including these extra tasks in IMAGE_INSTALL: %s" % tasks)
else:
return
self.nb.set_current_page(1)
self.handler.run_build(task_list)
return
def advanced_expander_cb(self, expander, param):
return
def images(self):
self.images_tree = gtk.TreeView()
self.images_tree.set_headers_visible(True)
self.images_tree.set_headers_clickable(False)
self.images_tree.set_enable_search(True)
self.images_tree.set_search_column(0)
self.images_tree.get_selection().set_mode(gtk.SELECTION_NONE)
col = gtk.TreeViewColumn('Package')
col1 = gtk.TreeViewColumn('Description')
col2 = gtk.TreeViewColumn('License')
col3 = gtk.TreeViewColumn('Include')
col3.set_resizable(False)
self.images_tree.append_column(col)
self.images_tree.append_column(col1)
self.images_tree.append_column(col2)
self.images_tree.append_column(col3)
cell = gtk.CellRendererText()
cell1 = gtk.CellRendererText()
cell2 = gtk.CellRendererText()
cell3 = gtk.CellRendererToggle()
cell3.set_property('activatable', True)
cell3.connect("toggled", self.toggle_include_cb, self.images_tree)
col.pack_start(cell, True)
col1.pack_start(cell1, True)
col2.pack_start(cell2, True)
col3.pack_start(cell3, True)
col.set_attributes(cell, text=self.model.COL_NAME)
col1.set_attributes(cell1, text=self.model.COL_DESC)
col2.set_attributes(cell2, text=self.model.COL_LIC)
col3.set_attributes(cell3, active=self.model.COL_INC)
self.images_tree.show()
scroll = gtk.ScrolledWindow()
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
scroll.set_shadow_type(gtk.SHADOW_IN)
scroll.add(self.images_tree)
return scroll
def toggle_package(self, path, model):
# Convert path to path in original model
opath = model.convert_path_to_child_path(path)
# current include status
inc = self.model[opath][self.model.COL_INC]
if inc:
self.model.mark(opath)
self.model.sweep_up()
#self.model.remove_package_full(cpath)
else:
self.model.include_item(opath)
return
def remove_package_cb(self, cell, path):
model = self.model.contents_model()
label = gtk.Label("Are you sure you want to remove this item?")
dialog = gtk.Dialog("Confirm removal", self,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
dialog.vbox.pack_start(label)
label.show()
response = dialog.run()
dialog.destroy()
if (response == gtk.RESPONSE_ACCEPT):
self.toggle_package(path, model)
def toggle_include_cb(self, cell, path, tv):
model = tv.get_model()
self.toggle_package(path, model)
def toggle_pkg_include_cb(self, cell, path, tv):
# there's an extra layer of models in the packages case.
sort_model = tv.get_model()
cpath = sort_model.convert_path_to_child_path(path)
self.toggle_package(cpath, sort_model.get_model())
def pkgsaz(self):
self.pkgsaz_tree = gtk.TreeView()
self.pkgsaz_tree.set_headers_visible(True)
self.pkgsaz_tree.set_headers_clickable(True)
self.pkgsaz_tree.set_enable_search(True)
self.pkgsaz_tree.set_search_column(0)
self.pkgsaz_tree.get_selection().set_mode(gtk.SELECTION_NONE)
col = gtk.TreeViewColumn('Package')
col1 = gtk.TreeViewColumn('Description')
col1.set_resizable(True)
col2 = gtk.TreeViewColumn('License')
col2.set_resizable(True)
col3 = gtk.TreeViewColumn('Group')
col4 = gtk.TreeViewColumn('Include')
col4.set_resizable(False)
self.pkgsaz_tree.append_column(col)
self.pkgsaz_tree.append_column(col1)
self.pkgsaz_tree.append_column(col2)
self.pkgsaz_tree.append_column(col3)
self.pkgsaz_tree.append_column(col4)
cell = gtk.CellRendererText()
cell1 = gtk.CellRendererText()
cell1.set_property('width-chars', 20)
cell2 = gtk.CellRendererText()
cell2.set_property('width-chars', 20)
cell3 = gtk.CellRendererText()
cell4 = gtk.CellRendererToggle()
cell4.set_property('activatable', True)
cell4.connect("toggled", self.toggle_pkg_include_cb, self.pkgsaz_tree)
col.pack_start(cell, True)
col1.pack_start(cell1, True)
col2.pack_start(cell2, True)
col3.pack_start(cell3, True)
col4.pack_start(cell4, True)
col.set_attributes(cell, text=self.model.COL_NAME)
col1.set_attributes(cell1, text=self.model.COL_DESC)
col2.set_attributes(cell2, text=self.model.COL_LIC)
col3.set_attributes(cell3, text=self.model.COL_GROUP)
col4.set_attributes(cell4, active=self.model.COL_INC)
self.pkgsaz_tree.show()
scroll = gtk.ScrolledWindow()
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
scroll.set_shadow_type(gtk.SHADOW_IN)
scroll.add(self.pkgsaz_tree)
return scroll
def pkgsgrp(self):
self.pkgsgrp_tree = gtk.TreeView()
self.pkgsgrp_tree.set_headers_visible(True)
self.pkgsgrp_tree.set_headers_clickable(False)
self.pkgsgrp_tree.set_enable_search(True)
self.pkgsgrp_tree.set_search_column(0)
self.pkgsgrp_tree.get_selection().set_mode(gtk.SELECTION_NONE)
col = gtk.TreeViewColumn('Package')
col1 = gtk.TreeViewColumn('Description')
col1.set_resizable(True)
col2 = gtk.TreeViewColumn('License')
col2.set_resizable(True)
col3 = gtk.TreeViewColumn('Group')
col4 = gtk.TreeViewColumn('Include')
col4.set_resizable(False)
self.pkgsgrp_tree.append_column(col)
self.pkgsgrp_tree.append_column(col1)
self.pkgsgrp_tree.append_column(col2)
self.pkgsgrp_tree.append_column(col3)
self.pkgsgrp_tree.append_column(col4)
cell = gtk.CellRendererText()
cell1 = gtk.CellRendererText()
cell1.set_property('width-chars', 20)
cell2 = gtk.CellRendererText()
cell2.set_property('width-chars', 20)
cell3 = gtk.CellRendererText()
cell4 = gtk.CellRendererToggle()
cell4.set_property("activatable", True)
cell4.connect("toggled", self.toggle_pkg_include_cb, self.pkgsgrp_tree)
col.pack_start(cell, True)
col1.pack_start(cell1, True)
col2.pack_start(cell2, True)
col3.pack_start(cell3, True)
col4.pack_start(cell4, True)
col.set_attributes(cell, text=self.model.COL_NAME)
col1.set_attributes(cell1, text=self.model.COL_DESC)
col2.set_attributes(cell2, text=self.model.COL_LIC)
col3.set_attributes(cell3, text=self.model.COL_GROUP)
col4.set_attributes(cell4, active=self.model.COL_INC)
self.pkgsgrp_tree.show()
scroll = gtk.ScrolledWindow()
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
scroll.set_shadow_type(gtk.SHADOW_IN)
scroll.add(self.pkgsgrp_tree)
return scroll
def tasks(self):
self.tasks_tree = gtk.TreeView()
self.tasks_tree.set_headers_visible(True)
self.tasks_tree.set_headers_clickable(False)
self.tasks_tree.set_enable_search(True)
self.tasks_tree.set_search_column(0)
self.tasks_tree.get_selection().set_mode(gtk.SELECTION_NONE)
col = gtk.TreeViewColumn('Package')
col1 = gtk.TreeViewColumn('Description')
col2 = gtk.TreeViewColumn('Include')
col2.set_resizable(False)
self.tasks_tree.append_column(col)
self.tasks_tree.append_column(col1)
self.tasks_tree.append_column(col2)
cell = gtk.CellRendererText()
cell1 = gtk.CellRendererText()
cell2 = gtk.CellRendererToggle()
cell2.set_property('activatable', True)
cell2.connect("toggled", self.toggle_include_cb, self.tasks_tree)
col.pack_start(cell, True)
col1.pack_start(cell1, True)
col2.pack_start(cell2, True)
col.set_attributes(cell, text=self.model.COL_NAME)
col1.set_attributes(cell1, text=self.model.COL_DESC)
col2.set_attributes(cell2, active=self.model.COL_INC)
self.tasks_tree.show()
scroll = gtk.ScrolledWindow()
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
scroll.set_shadow_type(gtk.SHADOW_IN)
scroll.add(self.tasks_tree)
return scroll
def cancel_build(self, button):
label = gtk.Label("Do you really want to stop this build?")
dialog = gtk.Dialog("Cancel build",
self,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_NO, gtk.RESPONSE_NO,
gtk.STOCK_YES, gtk.RESPONSE_YES))
dialog.vbox.pack_start(label)
label.show()
response = dialog.run()
dialog.destroy()
if not response == gtk.RESPONSE_YES:
self.handler.cancel_build()
return
def view_build_gui(self):
vbox = gtk.VBox(False, 6)
vbox.show()
build_tv = RunningBuildTreeView()
build_tv.show()
build_tv.set_model(self.build.model)
self.build.model.connect("row-inserted", self.scroll_tv_cb, build_tv)
scrolled_view = gtk.ScrolledWindow ()
scrolled_view.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled_view.add(build_tv)
scrolled_view.show()
vbox.pack_start(scrolled_view, expand=True, fill=True)
hbox = gtk.HBox(False, 6)
hbox.show()
vbox.pack_start(hbox, expand=False, fill=False)
cancel = gtk.Button(stock=gtk.STOCK_CANCEL)
cancel.connect("clicked", self.cancel_build)
cancel.show()
hbox.pack_end(cancel, expand=False, fill=False)
return vbox
def create_build_gui(self):
vbox = gtk.VBox(False, 6)
vbox.show()
hbox = gtk.HBox(False, 6)
hbox.show()
vbox.pack_start(hbox, expand=False, fill=False)
label = gtk.Label("Machine:")
label.show()
hbox.pack_start(label, expand=False, fill=False, padding=6)
self.machine_combo = gtk.combo_box_new_text()
self.machine_combo.set_active(0)
self.machine_combo.show()
self.machine_combo.set_tooltip_text("Selects the architecture of the target board for which you would like to build an image.")
hbox.pack_start(self.machine_combo, expand=False, fill=False, padding=6)
ins = gtk.Notebook()
vbox.pack_start(ins, expand=True, fill=True)
ins.set_show_tabs(True)
label = gtk.Label("Images")
label.show()
ins.append_page(self.images(), tab_label=label)
label = gtk.Label("Tasks")
label.show()
ins.append_page(self.tasks(), tab_label=label)
label = gtk.Label("Packages (by Group)")
label.show()
ins.append_page(self.pkgsgrp(), tab_label=label)
label = gtk.Label("Packages (by Name)")
label.show()
ins.append_page(self.pkgsaz(), tab_label=label)
ins.set_current_page(0)
ins.show_all()
hbox = gtk.HBox()
hbox.show()
vbox.pack_start(hbox, expand=False, fill=False)
label = gtk.Label("Image contents:")
label.show()
hbox.pack_start(label, expand=False, fill=False, padding=6)
con = self.contents()
con.show()
vbox.pack_start(con, expand=True, fill=True)
#advanced = gtk.Expander(label="Advanced")
#advanced.connect("notify::expanded", self.advanced_expander_cb)
#advanced.show()
#vbox.pack_start(advanced, expand=False, fill=False)
hbox = gtk.HBox()
hbox.show()
vbox.pack_start(hbox, expand=False, fill=False)
bake = gtk.Button("Bake")
bake.connect("clicked", self.bake_clicked_cb)
bake.show()
hbox.pack_end(bake, expand=False, fill=False, padding=6)
reset = gtk.Button("Reset")
reset.connect("clicked", self.reset_clicked_cb)
reset.show()
hbox.pack_end(reset, expand=False, fill=False, padding=6)
return vbox
def contents(self):
self.contents_tree = gtk.TreeView()
self.contents_tree.set_headers_visible(True)
self.contents_tree.get_selection().set_mode(gtk.SELECTION_NONE)
# allow searching in the package column
self.contents_tree.set_search_column(0)
col = gtk.TreeViewColumn('Package')
col.set_sort_column_id(0)
col1 = gtk.TreeViewColumn('Brought in by')
col1.set_resizable(True)
col2 = gtk.TreeViewColumn('Remove')
col2.set_expand(False)
self.contents_tree.append_column(col)
self.contents_tree.append_column(col1)
self.contents_tree.append_column(col2)
cell = gtk.CellRendererText()
cell1 = gtk.CellRendererText()
cell1.set_property('width-chars', 20)
cell2 = gtk.CellRendererToggle()
cell2.connect("toggled", self.remove_package_cb)
col.pack_start(cell, True)
col1.pack_start(cell1, True)
col2.pack_start(cell2, True)
col.set_attributes(cell, text=self.model.COL_NAME)
col1.set_attributes(cell1, text=self.model.COL_BINB)
col2.set_attributes(cell2, active=self.model.COL_INC)
self.contents_tree.show()
scroll = gtk.ScrolledWindow()
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
scroll.set_shadow_type(gtk.SHADOW_IN)
scroll.add(self.contents_tree)
return scroll
def main (server, eventHandler):
gobject.threads_init()
gtk.gdk.threads_init()
taskmodel = TaskListModel()
handler = HobHandler(taskmodel, server)
mach = server.runCommand(["getVariable", "MACHINE"])
distro = server.runCommand(["getVariable", "DISTRO"])
window = MainWindow(taskmodel, handler, mach, distro)
window.show_all ()
handler.connect("machines-updated", window.update_machines)
handler.connect("distros-updated", window.update_distros)
handler.connect("generating-data", window.busy)
handler.connect("data-generated", window.data_generated)
pbar = ProgressBar(window)
pbar.connect("delete-event", gtk.main_quit)
try:
# kick the while thing off
handler.current_command = "findConfigFilesDistro"
server.runCommand(["findConfigFiles", "DISTRO"])
except xmlrpclib.Fault:
print("XMLRPC Fault getting commandline:\n %s" % x)
return 1
# This timeout function regularly probes the event queue to find out if we
# have any messages waiting for us.
gobject.timeout_add (100,
handler.event_handle_idle_func,
eventHandler,
window.build,
pbar)
try:
gtk.main()
except EnvironmentError as ioerror:
# ignore interrupted io
if ioerror.args[0] == 4:
pass
finally:
server.runCommand(["stateStop"])