2011-02-02 13:02:43 +00:00
|
|
|
#
|
|
|
|
# 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
|
|
|
|
|
2011-06-03 00:21:44 +00:00
|
|
|
extraCaches = ['bb.cache_extra:HobRecipeInfo']
|
|
|
|
|
2011-02-02 13:02:43 +00:00
|
|
|
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()
|
2011-03-09 05:39:38 +00:00
|
|
|
if response == gtk.RESPONSE_YES:
|
2011-02-02 13:02:43 +00:00
|
|
|
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"])
|
|
|
|
|