From 656f9a07588cc00704825a78de9649ca4a1552b8 Mon Sep 17 00:00:00 2001 From: Dongxiao Xu Date: Mon, 28 Nov 2011 14:32:40 +0800 Subject: Hob: A new implemetation (v2) This commit implements a new design for hob Some of the new features: - Friendly new designed GUI. Quick response to user actions. - Two step builds support package generation and image generation. - Support running GUI seprarately from bitbake server. - Recipe/package selection and deselection. - Accurate customization for image contents and size. - Progress bars showing the parsing and build status. - Load/save user configurations from/into templates. (Bitbake rev: 4dacd29f9c957d20f4583330b51e5420f9c3338d) Signed-off-by: Dongxiao Xu Signed-off-by: Shane Wang Signed-off-by: Liming An Signed-off-by: Fengxia Hua Designed-by: Belen Barros Pena Signed-off-by: Richard Purdie --- bitbake/lib/bb/ui/crumbs/imagedetailspage.py | 294 +++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100755 bitbake/lib/bb/ui/crumbs/imagedetailspage.py (limited to 'bitbake/lib/bb/ui/crumbs/imagedetailspage.py') diff --git a/bitbake/lib/bb/ui/crumbs/imagedetailspage.py b/bitbake/lib/bb/ui/crumbs/imagedetailspage.py new file mode 100755 index 0000000000..e8419e0ee9 --- /dev/null +++ b/bitbake/lib/bb/ui/crumbs/imagedetailspage.py @@ -0,0 +1,294 @@ +#!/usr/bin/env python +# +# BitBake Graphical GTK User Interface +# +# Copyright (C) 2012 Intel Corporation +# +# Authored by Dongxiao Xu +# Authored by Shane Wang +# +# 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.hobcolor import HobColors +from bb.ui.crumbs.hobwidget import hic, HobWidget +from bb.ui.crumbs.hobpages import HobPage + +# +# ImageDetailsPage +# +class ImageDetailsPage (HobPage): + + class DetailBox (gtk.EventBox): + def __init__(self, varlist, vallist, icon = None, button = None, color = HobColors.LIGHT_GRAY): + gtk.EventBox.__init__(self) + + # set color + style = self.get_style().copy() + style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False) + self.set_style(style) + + self.hbox = gtk.HBox() + self.hbox.set_border_width(15) + self.add(self.hbox) + + # pack the icon and the text on the left + row = len(varlist) + self.table = gtk.Table(row, 20, True) + self.table.set_size_request(100, -1) + self.hbox.pack_start(self.table, expand=True, fill=True, padding=15) + + colid = 0 + if icon != None: + self.table.attach(icon, colid, colid + 2, 0, 1) + colid = colid + 2 + for line in range(0, row): + self.table.attach(self.text2label(varlist[line], vallist[line]), colid, 20, line, line + 1) + + # pack the button on the right + if button != None: + self.hbox.pack_end(button, expand=False, fill=False) + + def text2label(self, variable, value): + # append the name:value to the left box + # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard" + markup = "%s" % variable + markup += "%s" % value + label = gtk.Label() + label.set_alignment(0.0, 0.5) + label.set_markup(markup) + return label + + def __init__(self, builder): + super(ImageDetailsPage, self).__init__(builder, "Image details") + + self.image_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) + self.create_visual_elements() + + def create_visual_elements(self): + # create visual elements + # create the toolbar + self.toolbar = gtk.Toolbar() + self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL) + self.toolbar.set_style(gtk.TOOLBAR_BOTH) + + _, my_images_button = self.append_toolbar_button(self.toolbar, + "My images", + hic.ICON_IMAGES_DISPLAY_FILE, + hic.ICON_IMAGES_HOVER_FILE, + "Open images built out previously for running or deployment", + self.my_images_button_clicked_cb) + + self.details_top_buttons = self.add_onto_top_bar(self.toolbar) + + def _remove_all_widget(self): + children = self.get_children() or [] + for child in children: + self.remove(child) + children = self.box_group_area.get_children() or [] + for child in children: + self.box_group_area.remove(child) + + def _size_to_string(self, size): + if len(str(int(size))) > 6: + size_str = '%.1f' % (size*1.0/(1024*1024)) + ' MB' + elif len(str(int(size))) > 3: + size_str = '%.1f' % (size*1.0/1024) + ' KB' + else: + size_str = str(size) + ' B' + return size_str + + def show_page(self, step): + build_succeeded = (step == self.builder.IMAGE_GENERATED) + image_addr = self.builder.parameters.image_addr + image_names = self.builder.parameters.image_names + if build_succeeded: + image_addr = self.builder.parameters.image_addr + image_names = self.builder.parameters.image_names + machine = self.builder.configuration.curr_mach + base_image = self.builder.recipe_model.get_selected_image() + layers = self.builder.configuration.layers + pkg_num = "%s" % len(self.builder.package_model.get_selected_packages()) + else: + pkg_num = "N/A" + + self._remove_all_widget() + self.pack_start(self.details_top_buttons, expand=False, fill=False) + self.pack_start(self.group_align, expand=True, fill=True) + + if build_succeeded: + # building is the previous step + icon = gtk.Image() + pixmap_path = hic.ICON_INDI_CONFIRM_FILE + color = HobColors.RUNNING + pix_buffer = gtk.gdk.pixbuf_new_from_file(pixmap_path) + icon.set_from_pixbuf(pix_buffer) + varlist = [""] + vallist = ["Your image is ready"] + build_result = self.DetailBox(varlist=varlist, vallist=vallist, icon=icon, button=None, color=color) + self.box_group_area.pack_start(build_result, expand=False, fill=False) + + # Name + self.image_store.clear() + for image_name in image_names: + image_size = self._size_to_string(os.stat(os.path.join(image_addr, image_name)).st_size) + self.image_store.set(self.image_store.append(), 0, image_name, 1, image_size, 2, False) + images_widget, treeview = HobWidget.gen_images_widget(600, 200, 100) + treeview.set_model(self.image_store) + self.box_group_area.pack_start(images_widget, expand=False, fill=False) + + # Machine, Base image and Layers + layer_num_limit = 15 + varlist = ["Machine: ", "Base image: ", "Layers: "] + vallist = [] + if build_succeeded: + vallist.append(machine) + vallist.append(base_image) + i = 0 + for layer in layers: + varlist.append(" - ") + if i > layer_num_limit: + break + i += 1 + vallist.append("") + i = 0 + for layer in layers: + if i > layer_num_limit: + break + elif i == layer_num_limit: + vallist.append("and more...") + else: + vallist.append(layer) + i += 1 + + edit_config_button = gtk.LinkButton("Changes settings for build", "Edit configuration") + edit_config_button.connect("clicked", self.edit_config_button_clicked_cb) + setting_detail = self.DetailBox(varlist=varlist, vallist=vallist, icon=None, button=edit_config_button) + self.box_group_area.pack_start(setting_detail, expand=False, fill=False) + + # Packages included, and Total image size + varlist = ["Packages included: ", "Total image size: "] + vallist = [] + vallist.append(pkg_num) + vallist.append(image_size) + if build_succeeded: + edit_packages_button = gtk.LinkButton("Change package selection for customization", "Edit packages") + edit_packages_button.connect("clicked", self.edit_packages_button_clicked_cb) + else: # get to this page from "My images" + edit_packages_button = None + package_detail = self.DetailBox(varlist=varlist, vallist=vallist, icon=None, button=edit_packages_button) + self.box_group_area.pack_start(package_detail, expand=False, fill=False) + if build_succeeded: + buttonlist = ["Build new image", "Save as template", "Run image", "Deploy image"] + else: # get to this page from "My images" + buttonlist = ["Build new image", "Run image", "Deploy image"] + details_bottom_buttons = self.create_bottom_buttons(buttonlist) + self.box_group_area.pack_end(details_bottom_buttons, expand=False, fill=False) + + self.show_all() + + def create_bottom_buttons(self, buttonlist): + # Create the buttons at the bottom + bottom_buttons = gtk.HBox(False, 5) + created = False + + # create button "Deploy image" + name = "Deploy image" + if name in buttonlist: + deploy_button = gtk.Button() + label = gtk.Label() + mark = "Deploy image" % self.span_tag('24px', 'bold') + label.set_markup(mark) + deploy_button.set_image(label) + deploy_button.set_size_request(205, 49) + deploy_button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.ORANGE)) + deploy_button.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.ORANGE)) + deploy_button.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.ORANGE)) + deploy_button.set_tooltip_text("Deploy image to get your target board") + deploy_button.set_flags(gtk.CAN_DEFAULT) + deploy_button.grab_default() + deploy_button.connect("clicked", self.deploy_button_clicked_cb) + bottom_buttons.pack_end(deploy_button, expand=False, fill=False) + created = True + + name = "Run image" + if name in buttonlist: + if created == True: + # separator + label = gtk.Label(" or ") + bottom_buttons.pack_end(label, expand=False, fill=False) + + # create button "Run image" + run_button = gtk.LinkButton("Launch and boot the image in the QEMU emulator", "Run image") + run_button.connect("clicked", self.run_button_clicked_cb) + bottom_buttons.pack_end(run_button, expand=False, fill=False) + created = True + + name = "Save as template" + if name in buttonlist: + if created == True: + # separator + label = gtk.Label(" or ") + bottom_buttons.pack_end(label, expand=False, fill=False) + + # create button "Save as template" + save_button = gtk.LinkButton("Save the hob build template for future use", "Save as template") + save_button.connect("clicked", self.save_button_clicked_cb) + bottom_buttons.pack_end(save_button, expand=False, fill=False) + create = True + + name = "Build new image" + if name in buttonlist: + # create button "Build new image" + build_new_button = gtk.LinkButton("Initiate another new build from the beginning", "Build new image") + build_new_button.connect("clicked", self.build_new_button_clicked_cb) + bottom_buttons.pack_start(build_new_button, expand=False, fill=False) + + return bottom_buttons + + def _get_selected_image(self): + image_name = "" + iter = self.image_store.get_iter_first() + while iter: + path = self.image_store.get_path(iter) + if self.image_store[path][2]: + image_name = self.image_store[path][0] + break + iter = self.image_store.iter_next(iter) + + return image_name + + def save_button_clicked_cb(self, button): + self.builder.show_save_template_dialog() + + def deploy_button_clicked_cb(self, button): + image_name = self._get_selected_image() + self.builder.deploy_image(image_name) + + def run_button_clicked_cb(self, button): + image_name = self._get_selected_image() + self.builder.runqemu_image(image_name) + + def build_new_button_clicked_cb(self, button): + self.builder.initiate_new_build() + + def edit_config_button_clicked_cb(self, button): + self.builder.show_configuration() + + def edit_packages_button_clicked_cb(self, button): + self.builder.show_packages(ask=False) + + def my_images_button_clicked_cb(self, button): + self.builder.show_load_my_images_dialog() -- cgit v1.2.3-54-g00ecf