#!/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 gtk import glib from bb.ui.crumbs.progressbar import HobProgressBar from bb.ui.crumbs.hobcolor import HobColors from bb.ui.crumbs.hobwidget import hic, HobXpmLabelButtonBox from bb.ui.crumbs.hoblistmodel import RecipeListModel from bb.ui.crumbs.hobpages import HobPage from bb.ui.crumbs.hig import CrumbsDialog, BinbDialog, \ AdvancedSettingDialog, LayerSelectionDialog # # ImageConfigurationPage # class ImageConfigurationPage (HobPage): __dummy_machine__ = "--select a machine--" def __init__(self, builder): super(ImageConfigurationPage, self).__init__(builder, "Image configuration") self.image_combo_id = None self.create_visual_elements() def create_visual_elements(self): # create visual elements self.toolbar = gtk.Toolbar() self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL) self.toolbar.set_style(gtk.TOOLBAR_BOTH) _, template_button = self.append_toolbar_button(self.toolbar, "Template", hic.ICON_TEMPLATES_DISPLAY_FILE, hic.ICON_TEMPLATES_HOVER_FILE, "Load a hob building template saved before", self.template_button_clicked_cb) _, 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) _, settings_button = self.append_toolbar_button(self.toolbar, "Settings", hic.ICON_SETTINGS_DISPLAY_FILE, hic.ICON_SETTINGS_HOVER_FILE, "Other advanced settings for build", self.settings_button_clicked_cb) self.config_top_button = self.add_onto_top_bar(self.toolbar) self.gtable = gtk.Table(40, 40, True) self.create_config_machine() self.create_config_baseimg() self.config_build_button = self.create_config_build_button() def _remove_all_widget(self): children = self.gtable.get_children() or [] for child in children: self.gtable.remove(child) children = self.box_group_area.get_children() or [] for child in children: self.box_group_area.remove(child) children = self.get_children() or [] for child in children: self.remove(child) def _pack_components(self): self._remove_all_widget() self.pack_start(self.config_top_button, expand=False, fill=False) self.pack_start(self.group_align, expand=True, fill=True) self.box_group_area.pack_start(self.gtable, expand=True, fill=True) self.box_group_area.pack_end(self.config_build_button, expand=False, fill=False) def show_machine(self): self._pack_components() self.set_config_machine_layout() self.show_all() self.progress_bar.reset() self.progress_bar.hide() self.config_build_button.hide_all() def update_progress_bar(self, title, fraction, status=True): self.progress_bar.update(fraction) self.progress_bar.set_title(title) self.progress_bar.set_rcstyle(status) def show_info_populating(self): self._pack_components() self.set_config_machine_layout() self.show_all() self.config_build_button.hide_all() def show_info_populated(self): self._pack_components() self.set_config_machine_layout() self.set_config_baseimg_layout() self.show_all() self.progress_bar.reset() self.progress_bar.hide() def create_config_machine(self): self.machine_title = gtk.Label() self.machine_title.set_alignment(0.0, 0.5) mark = "Select a machine" % self.span_tag('24px', 'bold') self.machine_title.set_markup(mark) self.machine_title_desc = gtk.Label() self.machine_title_desc.set_alignment(0, 0.5) mark = ("This is the profile of the target machine for which you" " are building the image.\n") % (self.span_tag(px='14px')) self.machine_title_desc.set_markup(mark) self.machine_combo = gtk.combo_box_new_text() self.machine_combo.connect("changed", self.machine_combo_changed_cb) icon_file = hic.ICON_LAYERS_DISPLAY_FILE hover_file = hic.ICON_LAYERS_HOVER_FILE self.layer_button = HobXpmLabelButtonBox(icon_file, hover_file, "Layers", "Add support for machines, software, etc") self.layer_button.connect("button-release-event", self.layer_button_clicked_cb) icon_file = hic.ICON_INFO_DISPLAY_FILE self.layer_info_icon = gtk.Image() pix_buffer = gtk.gdk.pixbuf_new_from_file(icon_file) self.layer_info_icon.set_from_pixbuf(pix_buffer) markup = "Layers are a powerful mechanism to extend the Yocto Project " markup += "with your own functionality.\n" markup += "For more on layers, check:\n" markup += "http://www.yoctoproject.org/docs/current/poky-ref-manual/" markup += "poky-ref-manual.html#usingpoky-changes-layers." self.layer_info_icon.set_tooltip_markup(markup) self.progress_bar = HobProgressBar() self.machine_separator = gtk.HSeparator() def set_config_machine_layout(self): self.gtable.attach(self.machine_title, 0, 40, 0, 4) self.gtable.attach(self.machine_title_desc, 0, 40, 4, 6) self.gtable.attach(self.machine_combo, 0, 12, 6, 9) self.gtable.attach(self.layer_button, 12, 36, 6, 10) self.gtable.attach(self.layer_info_icon, 36, 40, 6, 9) self.gtable.attach(self.progress_bar, 0, 40, 13, 17) self.gtable.attach(self.machine_separator, 0, 40, 12, 13) def create_config_baseimg(self): self.image_title = gtk.Label() self.image_title.set_alignment(0, 1.0) mark = "Select a base image" % self.span_tag('24px', 'bold') self.image_title.set_markup(mark) self.image_title_desc = gtk.Label() self.image_title_desc.set_alignment(0, 0.5) mark = ("Base images are a starting point for the type of image you want. " "You can build them as \n" "they are or customize them to your specific needs.\n") % self.span_tag('14px') self.image_title_desc.set_markup(mark) self.image_combo = gtk.combo_box_new_text() self.image_combo_id = self.image_combo.connect("changed", self.image_combo_changed_cb) self.image_desc = gtk.Label() self.image_desc.set_alignment(0, 0) self.image_desc.set_line_wrap(True) # button to view recipes icon_file = hic.ICON_RCIPE_DISPLAY_FILE hover_file = hic.ICON_RCIPE_HOVER_FILE self.view_recipes_button = HobXpmLabelButtonBox(icon_file, hover_file, "View Recipes", "Add/remove recipes and collections") self.view_recipes_button.connect("button-release-event", self.view_recipes_button_clicked_cb) # button to view packages icon_file = hic.ICON_PACKAGES_DISPLAY_FILE hover_file = hic.ICON_PACKAGES_HOVER_FILE self.view_packages_button = HobXpmLabelButtonBox(icon_file, hover_file, "View Packages", "Add/remove packages") self.view_packages_button.connect("button-release-event", self.view_packages_button_clicked_cb) self.image_separator = gtk.HSeparator() def set_config_baseimg_layout(self): self.gtable.attach(self.image_title, 0, 40, 13, 17) self.gtable.attach(self.image_title_desc, 0, 40, 17, 22) self.gtable.attach(self.image_combo, 0, 12, 22, 25) self.gtable.attach(self.image_desc, 14, 38, 22, 27) self.gtable.attach(self.view_recipes_button, 0, 20, 28, 32) self.gtable.attach(self.view_packages_button, 20, 40, 28, 32) self.gtable.attach(self.image_separator, 0, 40, 35, 36) def create_config_build_button(self): # Create the "Build packages" and "Just bake" buttons at the bottom button_box = gtk.HBox(False, 5) # create button "Just bake" just_bake_button = gtk.Button() label = gtk.Label() mark = "Just bake" % self.span_tag('24px', 'bold') label.set_markup(mark) just_bake_button.set_image(label) just_bake_button.set_size_request(205, 49) just_bake_button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.ORANGE)) just_bake_button.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.ORANGE)) just_bake_button.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.ORANGE)) just_bake_button.set_tooltip_text("Build image to get your target image") just_bake_button.set_flags(gtk.CAN_DEFAULT) just_bake_button.grab_default() just_bake_button.connect("clicked", self.just_bake_button_clicked_cb) button_box.pack_end(just_bake_button, expand=False, fill=False) label = gtk.Label(" or ") button_box.pack_end(label, expand=False, fill=False) # create button "Build Packages" build_packages_button = gtk.LinkButton("Build packages first based on recipe selection " "for late customization on packages for the target image", "Build Packages") build_packages_button.connect("clicked", self.build_packages_button_clicked_cb) button_box.pack_end(build_packages_button, expand=False, fill=False) return button_box def machine_combo_changed_cb(self, machine_combo): combo_item = machine_combo.get_active_text() if not combo_item or combo_item == self.__dummy_machine__: self.builder.switch_page(self.builder.MACHINE_SELECTION) else: self.builder.configuration.curr_mach = combo_item # Do reparse recipes self.builder.switch_page(self.builder.RCPPKGINFO_POPULATING) def update_machine_combo(self): all_machines = [self.__dummy_machine__] + self.builder.parameters.all_machines model = self.machine_combo.get_model() model.clear() for machine in all_machines: self.machine_combo.append_text(machine) self.machine_combo.set_active(0) def switch_machine_combo(self): model = self.machine_combo.get_model() active = 0 while active < len(model): if model[active][0] == self.builder.configuration.curr_mach: self.machine_combo.set_active(active) return active += 1 self.machine_combo.set_active(0) def image_combo_changed_idle_cb(self, selected_image, selected_recipes, selected_packages): self.builder.update_recipe_model(selected_image, selected_recipes) self.builder.update_package_model(selected_packages) self.builder.window_sensitive(True) def image_combo_changed_cb(self, combo): self.builder.window_sensitive(False) selected_image = self.image_combo.get_active_text() if not selected_image: return selected_recipes = [] image_path = self.builder.recipe_model.pn_path[selected_image] image_iter = self.builder.recipe_model.get_iter(image_path) selected_packages = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_INSTALL).split() mark = ("%s\n") % (self.span_tag('14px'), self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_DESC)) self.image_desc.set_markup(mark) self.builder.recipe_model.reset() self.builder.package_model.reset() glib.idle_add(self.image_combo_changed_idle_cb, selected_image, selected_recipes, selected_packages) def _image_combo_connect_signal(self): if not self.image_combo_id: self.image_combo_id = self.image_combo.connect("changed", self.image_combo_changed_cb) def _image_combo_disconnect_signal(self): if self.image_combo_id: self.image_combo.disconnect(self.image_combo_id) self.image_combo_id = None def update_image_combo(self, recipe_model, selected_image): # Update the image combo according to the images in the recipe_model # populate image combo filter = {RecipeListModel.COL_TYPE : ['image']} image_model = recipe_model.tree_model(filter) active = 0 cnt = 0 it = image_model.get_iter_first() self._image_combo_disconnect_signal() model = self.image_combo.get_model() model.clear() # append and set active while it: path = image_model.get_path(it) image_name = image_model[path][recipe_model.COL_NAME] self.image_combo.append_text(image_name) if image_name == selected_image: active = cnt it = image_model.iter_next(it) cnt = cnt + 1 self._image_combo_connect_signal() self.image_combo.set_active(-1) self.image_combo.set_active(active) def layer_button_clicked_cb(self, event, data): # Create a layer selection dialog self.builder.show_layer_selection_dialog() def view_recipes_button_clicked_cb(self, event, data): self.builder.show_recipes() def view_packages_button_clicked_cb(self, event, data): self.builder.show_packages() def just_bake_button_clicked_cb(self, button): self.builder.just_bake() def build_packages_button_clicked_cb(self, button): self.builder.build_packages() def template_button_clicked_cb(self, button): self.builder.show_load_template_dialog() def my_images_button_clicked_cb(self, button): self.builder.show_load_my_images_dialog() def settings_button_clicked_cb(self, button): # Create an advanced settings dialog self.builder.show_adv_settings_dialog()