| #!/usr/bin/env python |
| # |
| # BitBake Graphical GTK User Interface |
| # |
| # Copyright (C) 2012 Intel Corporation |
| # |
| # Authored by Dongxiao Xu <dongxiao.xu@intel.com> |
| # Authored by Shane Wang <shane.wang@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.hobcolor import HobColors |
| from bb.ui.crumbs.hobwidget import hic, HobViewTable, HobAltButton, HobButton |
| from bb.ui.crumbs.hobpages import HobPage |
| import subprocess |
| from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog |
| from bb.ui.crumbs.hig.saveimagedialog import SaveImageDialog |
| |
| # |
| # ImageDetailsPage |
| # |
| class ImageDetailsPage (HobPage): |
| |
| class DetailBox (gtk.EventBox): |
| def __init__(self, widget = None, varlist = None, vallist = None, icon = None, button = None, button2=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.row = gtk.Table(1, 2, False) |
| self.row.set_border_width(10) |
| self.add(self.row) |
| |
| total_rows = 0 |
| if widget: |
| total_rows = 10 |
| if varlist and vallist: |
| # pack the icon and the text on the left |
| total_rows += len(varlist) |
| self.table = gtk.Table(total_rows, 20, True) |
| self.table.set_row_spacings(6) |
| self.table.set_size_request(100, -1) |
| self.row.attach(self.table, 0, 1, 0, 1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL) |
| |
| colid = 0 |
| rowid = 0 |
| self.line_widgets = {} |
| if icon: |
| self.table.attach(icon, colid, colid + 2, 0, 1) |
| colid = colid + 2 |
| if widget: |
| self.table.attach(widget, colid, 20, 0, 10) |
| rowid = 10 |
| if varlist and vallist: |
| for row in range(rowid, total_rows): |
| index = row - rowid |
| self.line_widgets[varlist[index]] = self.text2label(varlist[index], vallist[index]) |
| self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1) |
| # pack the button on the right |
| if button: |
| self.bbox = gtk.VBox() |
| self.bbox.pack_start(button, expand=True, fill=False) |
| if button2: |
| self.bbox.pack_start(button2, expand=True, fill=False) |
| self.bbox.set_size_request(150,-1) |
| self.row.attach(self.bbox, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.EXPAND) |
| |
| def update_line_widgets(self, variable, value): |
| if len(self.line_widgets) == 0: |
| return |
| if not isinstance(self.line_widgets[variable], gtk.Label): |
| return |
| self.line_widgets[variable].set_markup(self.format_line(variable, value)) |
| |
| def wrap_line(self, inputs): |
| # wrap the long text of inputs |
| wrap_width_chars = 75 |
| outputs = "" |
| tmps = inputs |
| less_chars = len(inputs) |
| while (less_chars - wrap_width_chars) > 0: |
| less_chars -= wrap_width_chars |
| outputs += tmps[:wrap_width_chars] + "\n " |
| tmps = inputs[less_chars:] |
| outputs += tmps |
| return outputs |
| |
| def format_line(self, variable, value): |
| wraped_value = self.wrap_line(value) |
| markup = "<span weight=\'bold\'>%s</span>" % variable |
| markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % wraped_value |
| return markup |
| |
| def text2label(self, variable, value): |
| # append the name:value to the left box |
| # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard" |
| label = gtk.Label() |
| label.set_alignment(0.0, 0.5) |
| label.set_markup(self.format_line(variable, value)) |
| return label |
| |
| class BuildDetailBox (gtk.EventBox): |
| def __init__(self, varlist = None, vallist = None, icon = 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(10) |
| self.add(self.hbox) |
| |
| total_rows = 0 |
| if varlist and vallist: |
| # pack the icon and the text on the left |
| total_rows += len(varlist) |
| self.table = gtk.Table(total_rows, 20, True) |
| self.table.set_row_spacings(6) |
| self.table.set_size_request(100, -1) |
| self.hbox.pack_start(self.table, expand=True, fill=True, padding=15) |
| |
| colid = 0 |
| rowid = 0 |
| self.line_widgets = {} |
| if icon: |
| self.table.attach(icon, colid, colid + 2, 0, 1) |
| colid = colid + 2 |
| if varlist and vallist: |
| for row in range(rowid, total_rows): |
| index = row - rowid |
| self.line_widgets[varlist[index]] = self.text2label(varlist[index], vallist[index]) |
| self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1) |
| |
| def update_line_widgets(self, variable, value): |
| if len(self.line_widgets) == 0: |
| return |
| if not isinstance(self.line_widgets[variable], gtk.Label): |
| return |
| self.line_widgets[variable].set_markup(self.format_line(variable, value)) |
| |
| def wrap_line(self, inputs): |
| # wrap the long text of inputs |
| wrap_width_chars = 75 |
| outputs = "" |
| tmps = inputs |
| less_chars = len(inputs) |
| while (less_chars - wrap_width_chars) > 0: |
| less_chars -= wrap_width_chars |
| outputs += tmps[:wrap_width_chars] + "\n " |
| tmps = inputs[less_chars:] |
| outputs += tmps |
| return outputs |
| |
| def format_line(self, variable, value): |
| wraped_value = self.wrap_line(value) |
| markup = "<span weight=\'bold\'>%s</span>" % variable |
| markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % wraped_value |
| return markup |
| |
| def text2label(self, variable, value): |
| # append the name:value to the left box |
| # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard" |
| label = gtk.Label() |
| label.set_alignment(0.0, 0.5) |
| label.set_markup(self.format_line(variable, value)) |
| return label |
| |
| def __init__(self, builder): |
| super(ImageDetailsPage, self).__init__(builder, "Image details") |
| |
| self.image_store = [] |
| self.button_ids = {} |
| self.details_bottom_buttons = gtk.HBox(False, 6) |
| self.image_saved = False |
| self.create_visual_elements() |
| self.name_field_template = "" |
| self.description_field_template = "" |
| |
| 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, |
| "Images", |
| hic.ICON_IMAGES_DISPLAY_FILE, |
| hic.ICON_IMAGES_HOVER_FILE, |
| "Open previously built images", |
| 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, |
| "View additional build settings", |
| self.settings_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) |
| children = self.details_bottom_buttons.get_children() or [] |
| for child in children: |
| self.details_bottom_buttons.remove(child) |
| |
| def show_page(self, step): |
| self.build_succeeded = (step == self.builder.IMAGE_GENERATED) |
| image_addr = self.builder.parameters.image_addr |
| image_names = self.builder.parameters.image_names |
| if self.build_succeeded: |
| 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()) |
| log_file = self.builder.current_logfile |
| else: |
| pkg_num = "N/A" |
| log_file = None |
| |
| # remove |
| for button_id, button in self.button_ids.items(): |
| button.disconnect(button_id) |
| self._remove_all_widget() |
| |
| # repack |
| self.pack_start(self.details_top_buttons, expand=False, fill=False) |
| self.pack_start(self.group_align, expand=True, fill=True) |
| |
| self.build_result = None |
| if self.image_saved or (self.build_succeeded and self.builder.current_step == self.builder.IMAGE_GENERATING): |
| # 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 = [""] |
| if self.image_saved: |
| vallist = ["Your image recipe has been saved"] |
| else: |
| vallist = ["Your image is ready"] |
| self.build_result = self.BuildDetailBox(varlist=varlist, vallist=vallist, icon=icon, color=color) |
| self.box_group_area.pack_start(self.build_result, expand=False, fill=False) |
| |
| self.buttonlist = ["Build new image", "Save image recipe", "Run image", "Deploy image"] |
| |
| # Name |
| self.image_store = [] |
| self.toggled_image = "" |
| default_image_size = 0 |
| self.num_toggled = 0 |
| i = 0 |
| for image_name in image_names: |
| image_size = HobPage._size_to_string(os.stat(os.path.join(image_addr, image_name)).st_size) |
| |
| image_attr = ("run" if (self.test_type_runnable(image_name) and self.test_mach_runnable(image_name)) else \ |
| ("deploy" if self.test_deployable(image_name) else "")) |
| is_toggled = (image_attr != "") |
| |
| if not self.toggled_image: |
| if i == (len(image_names) - 1): |
| is_toggled = True |
| if is_toggled: |
| default_image_size = image_size |
| self.toggled_image = image_name |
| |
| split_stuff = image_name.split('.') |
| if "rootfs" in split_stuff: |
| image_type = image_name[(len(split_stuff[0]) + len(".rootfs") + 1):] |
| else: |
| image_type = image_name[(len(split_stuff[0]) + 1):] |
| |
| self.image_store.append({'name': image_name, |
| 'type': image_type, |
| 'size': image_size, |
| 'is_toggled': is_toggled, |
| 'action_attr': image_attr,}) |
| |
| i = i + 1 |
| self.num_toggled += is_toggled |
| |
| is_runnable = self.create_bottom_buttons(self.buttonlist, self.toggled_image) |
| |
| # Generated image files info |
| varlist = ["Name: ", "Files created: ", "Directory: "] |
| vallist = [] |
| |
| vallist.append(image_name.split('.')[0]) |
| vallist.append(', '.join(fileitem['type'] for fileitem in self.image_store)) |
| vallist.append(image_addr) |
| |
| view_files_button = HobAltButton("View files") |
| view_files_button.connect("clicked", self.view_files_clicked_cb, image_addr) |
| view_files_button.set_tooltip_text("Open the directory containing the image files") |
| open_log_button = None |
| if log_file: |
| open_log_button = HobAltButton("Open log") |
| open_log_button.connect("clicked", self.open_log_clicked_cb, log_file) |
| open_log_button.set_tooltip_text("Open the build's log file") |
| self.image_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=view_files_button, button2=open_log_button) |
| self.box_group_area.pack_start(self.image_detail, expand=False, fill=True) |
| |
| # The default kernel box for the qemu images |
| self.sel_kernel = "" |
| self.kernel_detail = None |
| if 'qemu' in image_name: |
| self.sel_kernel = self.get_kernel_file_name() |
| |
| # varlist = ["Kernel: "] |
| # vallist = [] |
| # vallist.append(self.sel_kernel) |
| |
| # change_kernel_button = HobAltButton("Change") |
| # change_kernel_button.connect("clicked", self.change_kernel_cb) |
| # change_kernel_button.set_tooltip_text("Change qemu kernel file") |
| # self.kernel_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=change_kernel_button) |
| # self.box_group_area.pack_start(self.kernel_detail, expand=True, fill=True) |
| |
| # Machine, Image recipe and Layers |
| layer_num_limit = 15 |
| varlist = ["Machine: ", "Image recipe: ", "Layers: "] |
| vallist = [] |
| self.setting_detail = None |
| if self.build_succeeded: |
| vallist.append(machine) |
| if self.builder.recipe_model.is_custom_image(): |
| if self.builder.configuration.initial_selected_image == self.builder.recipe_model.__custom_image__: |
| base_image ="New image recipe" |
| else: |
| base_image = self.builder.configuration.initial_selected_image + " (edited)" |
| vallist.append(base_image) |
| i = 0 |
| for layer in layers: |
| if i > layer_num_limit: |
| break |
| varlist.append(" - ") |
| 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 = HobAltButton("Edit configuration") |
| edit_config_button.set_tooltip_text("Edit machine and image recipe") |
| edit_config_button.connect("clicked", self.edit_config_button_clicked_cb) |
| self.setting_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_config_button) |
| self.box_group_area.pack_start(self.setting_detail, expand=True, fill=True) |
| |
| # Packages included, and Total image size |
| varlist = ["Packages included: ", "Total image size: "] |
| vallist = [] |
| vallist.append(pkg_num) |
| vallist.append(default_image_size) |
| self.builder.configuration.image_size = default_image_size |
| self.builder.configuration.image_packages = self.builder.configuration.selected_packages |
| if self.build_succeeded: |
| edit_packages_button = HobAltButton("Edit packages") |
| edit_packages_button.set_tooltip_text("Edit the packages included in your image") |
| edit_packages_button.connect("clicked", self.edit_packages_button_clicked_cb) |
| else: # get to this page from "My images" |
| edit_packages_button = None |
| self.package_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_packages_button) |
| self.box_group_area.pack_start(self.package_detail, expand=True, fill=True) |
| |
| # pack the buttons at the bottom, at this time they are already created. |
| if self.build_succeeded: |
| self.box_group_area.pack_end(self.details_bottom_buttons, expand=False, fill=False) |
| else: # for "My images" page |
| self.details_separator = gtk.HSeparator() |
| self.box_group_area.pack_start(self.details_separator, expand=False, fill=False) |
| self.box_group_area.pack_start(self.details_bottom_buttons, expand=False, fill=False) |
| |
| self.show_all() |
| if self.kernel_detail and (not is_runnable): |
| self.kernel_detail.hide() |
| self.image_saved = False |
| |
| def view_files_clicked_cb(self, button, image_addr): |
| subprocess.call("xdg-open /%s" % image_addr, shell=True) |
| |
| def open_log_clicked_cb(self, button, log_file): |
| if log_file: |
| log_file = "file:///" + log_file |
| gtk.show_uri(screen=button.get_screen(), uri=log_file, timestamp=0) |
| |
| def refresh_package_detail_box(self, image_size): |
| self.package_detail.update_line_widgets("Total image size: ", image_size) |
| |
| def test_type_runnable(self, image_name): |
| type_runnable = False |
| for t in self.builder.parameters.runnable_image_types: |
| if image_name.endswith(t): |
| type_runnable = True |
| break |
| return type_runnable |
| |
| def test_mach_runnable(self, image_name): |
| mach_runnable = False |
| for t in self.builder.parameters.runnable_machine_patterns: |
| if t in image_name: |
| mach_runnable = True |
| break |
| return mach_runnable |
| |
| def test_deployable(self, image_name): |
| if self.builder.configuration.curr_mach.startswith("qemu"): |
| return False |
| deployable = False |
| for t in self.builder.parameters.deployable_image_types: |
| if image_name.endswith(t): |
| deployable = True |
| break |
| return deployable |
| |
| def get_kernel_file_name(self, kernel_addr=""): |
| kernel_name = "" |
| |
| if not kernel_addr: |
| kernel_addr = self.builder.parameters.image_addr |
| |
| files = [f for f in os.listdir(kernel_addr) if f[0] <> '.'] |
| for check_file in files: |
| if check_file.endswith(".bin"): |
| name_splits = check_file.split(".")[0] |
| if self.builder.parameters.kernel_image_type in name_splits.split("-"): |
| kernel_name = check_file |
| break |
| |
| return kernel_name |
| |
| def show_builded_images_dialog(self, widget, primary_action=""): |
| title = primary_action if primary_action else "Your builded images" |
| dialog = CrumbsDialog(title, self.builder, |
| gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) |
| dialog.set_border_width(12) |
| |
| label = gtk.Label() |
| label.set_use_markup(True) |
| label.set_alignment(0.0, 0.5) |
| label.set_padding(12,0) |
| if primary_action == "Run image": |
| label.set_markup("<span font_desc='12'>Select the image file you want to run:</span>") |
| elif primary_action == "Deploy image": |
| label.set_markup("<span font_desc='12'>Select the image file you want to deploy:</span>") |
| else: |
| label.set_markup("<span font_desc='12'>Select the image file you want to %s</span>" % primary_action) |
| dialog.vbox.pack_start(label, expand=False, fill=False) |
| |
| # filter created images as action attribution (deploy or run) |
| action_attr = "" |
| action_images = [] |
| for fileitem in self.image_store: |
| action_attr = fileitem['action_attr'] |
| if (action_attr == 'run' and primary_action == "Run image") \ |
| or (action_attr == 'deploy' and primary_action == "Deploy image"): |
| action_images.append(fileitem) |
| |
| # pack the corresponding 'runnable' or 'deploy' radio_buttons, if there has no more than one file. |
| # assume that there does not both have 'deploy' and 'runnable' files in the same building result |
| # in possible as design. |
| curr_row = 0 |
| rows = (len(action_images)) if len(action_images) < 10 else 10 |
| table = gtk.Table(rows, 10, True) |
| table.set_row_spacings(6) |
| table.set_col_spacing(0, 12) |
| table.set_col_spacing(5, 12) |
| |
| sel_parent_btn = None |
| for fileitem in action_images: |
| sel_btn = gtk.RadioButton(sel_parent_btn, fileitem['type']) |
| sel_parent_btn = sel_btn if not sel_parent_btn else sel_parent_btn |
| sel_btn.set_active(fileitem['is_toggled']) |
| sel_btn.connect('toggled', self.table_selected_cb, fileitem) |
| if curr_row < 10: |
| table.attach(sel_btn, 0, 4, curr_row, curr_row + 1, xpadding=24) |
| else: |
| table.attach(sel_btn, 5, 9, curr_row - 10, curr_row - 9, xpadding=24) |
| curr_row += 1 |
| |
| dialog.vbox.pack_start(table, expand=False, fill=False, padding=6) |
| |
| button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL) |
| HobAltButton.style_button(button) |
| |
| if primary_action: |
| button = dialog.add_button(primary_action, gtk.RESPONSE_YES) |
| HobButton.style_button(button) |
| |
| dialog.show_all() |
| |
| response = dialog.run() |
| dialog.destroy() |
| |
| if response != gtk.RESPONSE_YES: |
| return |
| |
| for fileitem in self.image_store: |
| if fileitem['is_toggled']: |
| if fileitem['action_attr'] == 'run': |
| self.builder.runqemu_image(fileitem['name'], self.sel_kernel) |
| elif fileitem['action_attr'] == 'deploy': |
| self.builder.deploy_image(fileitem['name']) |
| |
| def table_selected_cb(self, tbutton, image): |
| image['is_toggled'] = tbutton.get_active() |
| if image['is_toggled']: |
| self.toggled_image = image['name'] |
| |
| def change_kernel_cb(self, widget): |
| kernel_path = self.builder.show_load_kernel_dialog() |
| if kernel_path and self.kernel_detail: |
| import os.path |
| self.sel_kernel = os.path.basename(kernel_path) |
| markup = self.kernel_detail.format_line("Kernel: ", self.sel_kernel) |
| label = ((self.kernel_detail.get_children()[0]).get_children()[0]).get_children()[0] |
| label.set_markup(markup) |
| |
| def create_bottom_buttons(self, buttonlist, image_name): |
| # Create the buttons at the bottom |
| created = False |
| packed = False |
| self.button_ids = {} |
| is_runnable = False |
| |
| # create button "Deploy image" |
| name = "Deploy image" |
| if name in buttonlist and self.test_deployable(image_name): |
| deploy_button = HobButton('Deploy image') |
| #deploy_button.set_size_request(205, 49) |
| deploy_button.set_tooltip_text("Burn a live image to a USB drive or flash memory") |
| deploy_button.set_flags(gtk.CAN_DEFAULT) |
| button_id = deploy_button.connect("clicked", self.deploy_button_clicked_cb) |
| self.button_ids[button_id] = deploy_button |
| self.details_bottom_buttons.pack_end(deploy_button, expand=False, fill=False) |
| created = True |
| packed = True |
| |
| name = "Run image" |
| if name in buttonlist and self.test_type_runnable(image_name) and self.test_mach_runnable(image_name): |
| if created == True: |
| # separator |
| #label = gtk.Label(" or ") |
| #self.details_bottom_buttons.pack_end(label, expand=False, fill=False) |
| |
| # create button "Run image" |
| run_button = HobAltButton("Run image") |
| else: |
| # create button "Run image" as the primary button |
| run_button = HobButton("Run image") |
| #run_button.set_size_request(205, 49) |
| run_button.set_flags(gtk.CAN_DEFAULT) |
| packed = True |
| run_button.set_tooltip_text("Start up an image with qemu emulator") |
| button_id = run_button.connect("clicked", self.run_button_clicked_cb) |
| self.button_ids[button_id] = run_button |
| self.details_bottom_buttons.pack_end(run_button, expand=False, fill=False) |
| created = True |
| is_runnable = True |
| |
| name = "Save image recipe" |
| if name in buttonlist and self.builder.recipe_model.is_custom_image(): |
| save_button = HobAltButton("Save image recipe") |
| save_button.set_tooltip_text("Keep your changes saving them as an image recipe") |
| save_button.set_sensitive(not self.image_saved) |
| button_id = save_button.connect("clicked", self.save_button_clicked_cb) |
| self.button_ids[button_id] = save_button |
| self.details_bottom_buttons.pack_end(save_button, expand=False, fill=False) |
| |
| name = "Build new image" |
| if name in buttonlist: |
| # create button "Build new image" |
| if packed: |
| build_new_button = HobAltButton("Build new image") |
| else: |
| build_new_button = HobButton("Build new image") |
| build_new_button.set_flags(gtk.CAN_DEFAULT) |
| #build_new_button.set_size_request(205, 49) |
| self.details_bottom_buttons.pack_end(build_new_button, expand=False, fill=False) |
| build_new_button.set_tooltip_text("Create a new image from scratch") |
| button_id = build_new_button.connect("clicked", self.build_new_button_clicked_cb) |
| self.button_ids[button_id] = build_new_button |
| |
| return is_runnable |
| |
| def deploy_button_clicked_cb(self, button): |
| if self.toggled_image: |
| if self.num_toggled > 1: |
| self.set_sensitive(False) |
| self.show_builded_images_dialog(None, "Deploy image") |
| self.set_sensitive(True) |
| else: |
| self.builder.deploy_image(self.toggled_image) |
| |
| def run_button_clicked_cb(self, button): |
| if self.toggled_image: |
| if self.num_toggled > 1: |
| self.set_sensitive(False) |
| self.show_builded_images_dialog(None, "Run image") |
| self.set_sensitive(True) |
| else: |
| self.builder.runqemu_image(self.toggled_image, self.sel_kernel) |
| |
| def save_button_clicked_cb(self, button): |
| topdir = self.builder.get_topdir() |
| images_dir = topdir + "/recipes/images/custom/" |
| self.builder.ensure_dir(images_dir) |
| |
| self.name_field_template = self.builder.image_configuration_page.custom_image_selected |
| if self.name_field_template: |
| image_path = self.builder.recipe_model.pn_path[self.name_field_template] |
| image_iter = self.builder.recipe_model.get_iter(image_path) |
| self.description_field_template = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_DESC) |
| else: |
| self.name_field_template = "" |
| |
| dialog = SaveImageDialog(images_dir, self.name_field_template, self.description_field_template, |
| "Save image recipe", self.builder, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) |
| response = dialog.run() |
| dialog.destroy() |
| |
| def build_new_button_clicked_cb(self, button): |
| self.builder.initiate_new_build_async() |
| |
| def edit_config_button_clicked_cb(self, button): |
| self.builder.show_configuration() |
| |
| def edit_packages_button_clicked_cb(self, button): |
| self.builder.show_packages() |
| |
| 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 |
| response, settings_changed = self.builder.show_simple_settings_dialog() |
| if not response: |
| return |
| if settings_changed: |
| self.builder.reparse_post_adv_settings() |