diff options
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/imagedetailspage.py')
| -rwxr-xr-x | bitbake/lib/bb/ui/crumbs/imagedetailspage.py | 294 |
1 files changed, 294 insertions, 0 deletions
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 @@ | |||
| 1 | #!/usr/bin/env python | ||
| 2 | # | ||
| 3 | # BitBake Graphical GTK User Interface | ||
| 4 | # | ||
| 5 | # Copyright (C) 2012 Intel Corporation | ||
| 6 | # | ||
| 7 | # Authored by Dongxiao Xu <dongxiao.xu@intel.com> | ||
| 8 | # Authored by Shane Wang <shane.wang@intel.com> | ||
| 9 | # | ||
| 10 | # This program is free software; you can redistribute it and/or modify | ||
| 11 | # it under the terms of the GNU General Public License version 2 as | ||
| 12 | # published by the Free Software Foundation. | ||
| 13 | # | ||
| 14 | # This program is distributed in the hope that it will be useful, | ||
| 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | # GNU General Public License for more details. | ||
| 18 | # | ||
| 19 | # You should have received a copy of the GNU General Public License along | ||
| 20 | # with this program; if not, write to the Free Software Foundation, Inc., | ||
| 21 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 22 | |||
| 23 | import gobject | ||
| 24 | import gtk | ||
| 25 | from bb.ui.crumbs.hobcolor import HobColors | ||
| 26 | from bb.ui.crumbs.hobwidget import hic, HobWidget | ||
| 27 | from bb.ui.crumbs.hobpages import HobPage | ||
| 28 | |||
| 29 | # | ||
| 30 | # ImageDetailsPage | ||
| 31 | # | ||
| 32 | class ImageDetailsPage (HobPage): | ||
| 33 | |||
| 34 | class DetailBox (gtk.EventBox): | ||
| 35 | def __init__(self, varlist, vallist, icon = None, button = None, color = HobColors.LIGHT_GRAY): | ||
| 36 | gtk.EventBox.__init__(self) | ||
| 37 | |||
| 38 | # set color | ||
| 39 | style = self.get_style().copy() | ||
| 40 | style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False) | ||
| 41 | self.set_style(style) | ||
| 42 | |||
| 43 | self.hbox = gtk.HBox() | ||
| 44 | self.hbox.set_border_width(15) | ||
| 45 | self.add(self.hbox) | ||
| 46 | |||
| 47 | # pack the icon and the text on the left | ||
| 48 | row = len(varlist) | ||
| 49 | self.table = gtk.Table(row, 20, True) | ||
| 50 | self.table.set_size_request(100, -1) | ||
| 51 | self.hbox.pack_start(self.table, expand=True, fill=True, padding=15) | ||
| 52 | |||
| 53 | colid = 0 | ||
| 54 | if icon != None: | ||
| 55 | self.table.attach(icon, colid, colid + 2, 0, 1) | ||
| 56 | colid = colid + 2 | ||
| 57 | for line in range(0, row): | ||
| 58 | self.table.attach(self.text2label(varlist[line], vallist[line]), colid, 20, line, line + 1) | ||
| 59 | |||
| 60 | # pack the button on the right | ||
| 61 | if button != None: | ||
| 62 | self.hbox.pack_end(button, expand=False, fill=False) | ||
| 63 | |||
| 64 | def text2label(self, variable, value): | ||
| 65 | # append the name:value to the left box | ||
| 66 | # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard" | ||
| 67 | markup = "<span weight=\'bold\'>%s</span>" % variable | ||
| 68 | markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % value | ||
| 69 | label = gtk.Label() | ||
| 70 | label.set_alignment(0.0, 0.5) | ||
| 71 | label.set_markup(markup) | ||
| 72 | return label | ||
| 73 | |||
| 74 | def __init__(self, builder): | ||
| 75 | super(ImageDetailsPage, self).__init__(builder, "Image details") | ||
| 76 | |||
| 77 | self.image_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) | ||
| 78 | self.create_visual_elements() | ||
| 79 | |||
| 80 | def create_visual_elements(self): | ||
| 81 | # create visual elements | ||
| 82 | # create the toolbar | ||
| 83 | self.toolbar = gtk.Toolbar() | ||
| 84 | self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL) | ||
| 85 | self.toolbar.set_style(gtk.TOOLBAR_BOTH) | ||
| 86 | |||
| 87 | _, my_images_button = self.append_toolbar_button(self.toolbar, | ||
| 88 | "My images", | ||
| 89 | hic.ICON_IMAGES_DISPLAY_FILE, | ||
| 90 | hic.ICON_IMAGES_HOVER_FILE, | ||
| 91 | "Open images built out previously for running or deployment", | ||
| 92 | self.my_images_button_clicked_cb) | ||
| 93 | |||
| 94 | self.details_top_buttons = self.add_onto_top_bar(self.toolbar) | ||
| 95 | |||
| 96 | def _remove_all_widget(self): | ||
| 97 | children = self.get_children() or [] | ||
| 98 | for child in children: | ||
| 99 | self.remove(child) | ||
| 100 | children = self.box_group_area.get_children() or [] | ||
| 101 | for child in children: | ||
| 102 | self.box_group_area.remove(child) | ||
| 103 | |||
| 104 | def _size_to_string(self, size): | ||
| 105 | if len(str(int(size))) > 6: | ||
| 106 | size_str = '%.1f' % (size*1.0/(1024*1024)) + ' MB' | ||
| 107 | elif len(str(int(size))) > 3: | ||
| 108 | size_str = '%.1f' % (size*1.0/1024) + ' KB' | ||
| 109 | else: | ||
| 110 | size_str = str(size) + ' B' | ||
| 111 | return size_str | ||
| 112 | |||
| 113 | def show_page(self, step): | ||
| 114 | build_succeeded = (step == self.builder.IMAGE_GENERATED) | ||
| 115 | image_addr = self.builder.parameters.image_addr | ||
| 116 | image_names = self.builder.parameters.image_names | ||
| 117 | if build_succeeded: | ||
| 118 | image_addr = self.builder.parameters.image_addr | ||
| 119 | image_names = self.builder.parameters.image_names | ||
| 120 | machine = self.builder.configuration.curr_mach | ||
| 121 | base_image = self.builder.recipe_model.get_selected_image() | ||
| 122 | layers = self.builder.configuration.layers | ||
| 123 | pkg_num = "%s" % len(self.builder.package_model.get_selected_packages()) | ||
| 124 | else: | ||
| 125 | pkg_num = "N/A" | ||
| 126 | |||
| 127 | self._remove_all_widget() | ||
| 128 | self.pack_start(self.details_top_buttons, expand=False, fill=False) | ||
| 129 | self.pack_start(self.group_align, expand=True, fill=True) | ||
| 130 | |||
| 131 | if build_succeeded: | ||
| 132 | # building is the previous step | ||
| 133 | icon = gtk.Image() | ||
| 134 | pixmap_path = hic.ICON_INDI_CONFIRM_FILE | ||
| 135 | color = HobColors.RUNNING | ||
| 136 | pix_buffer = gtk.gdk.pixbuf_new_from_file(pixmap_path) | ||
| 137 | icon.set_from_pixbuf(pix_buffer) | ||
| 138 | varlist = [""] | ||
| 139 | vallist = ["Your image is ready"] | ||
| 140 | build_result = self.DetailBox(varlist=varlist, vallist=vallist, icon=icon, button=None, color=color) | ||
| 141 | self.box_group_area.pack_start(build_result, expand=False, fill=False) | ||
| 142 | |||
| 143 | # Name | ||
| 144 | self.image_store.clear() | ||
| 145 | for image_name in image_names: | ||
| 146 | image_size = self._size_to_string(os.stat(os.path.join(image_addr, image_name)).st_size) | ||
| 147 | self.image_store.set(self.image_store.append(), 0, image_name, 1, image_size, 2, False) | ||
| 148 | images_widget, treeview = HobWidget.gen_images_widget(600, 200, 100) | ||
| 149 | treeview.set_model(self.image_store) | ||
| 150 | self.box_group_area.pack_start(images_widget, expand=False, fill=False) | ||
| 151 | |||
| 152 | # Machine, Base image and Layers | ||
| 153 | layer_num_limit = 15 | ||
| 154 | varlist = ["Machine: ", "Base image: ", "Layers: "] | ||
| 155 | vallist = [] | ||
| 156 | if build_succeeded: | ||
| 157 | vallist.append(machine) | ||
| 158 | vallist.append(base_image) | ||
| 159 | i = 0 | ||
| 160 | for layer in layers: | ||
| 161 | varlist.append(" - ") | ||
| 162 | if i > layer_num_limit: | ||
| 163 | break | ||
| 164 | i += 1 | ||
| 165 | vallist.append("") | ||
| 166 | i = 0 | ||
| 167 | for layer in layers: | ||
| 168 | if i > layer_num_limit: | ||
| 169 | break | ||
| 170 | elif i == layer_num_limit: | ||
| 171 | vallist.append("and more...") | ||
| 172 | else: | ||
| 173 | vallist.append(layer) | ||
| 174 | i += 1 | ||
| 175 | |||
| 176 | edit_config_button = gtk.LinkButton("Changes settings for build", "Edit configuration") | ||
| 177 | edit_config_button.connect("clicked", self.edit_config_button_clicked_cb) | ||
| 178 | setting_detail = self.DetailBox(varlist=varlist, vallist=vallist, icon=None, button=edit_config_button) | ||
| 179 | self.box_group_area.pack_start(setting_detail, expand=False, fill=False) | ||
| 180 | |||
| 181 | # Packages included, and Total image size | ||
| 182 | varlist = ["Packages included: ", "Total image size: "] | ||
| 183 | vallist = [] | ||
| 184 | vallist.append(pkg_num) | ||
| 185 | vallist.append(image_size) | ||
| 186 | if build_succeeded: | ||
| 187 | edit_packages_button = gtk.LinkButton("Change package selection for customization", "Edit packages") | ||
| 188 | edit_packages_button.connect("clicked", self.edit_packages_button_clicked_cb) | ||
| 189 | else: # get to this page from "My images" | ||
| 190 | edit_packages_button = None | ||
| 191 | package_detail = self.DetailBox(varlist=varlist, vallist=vallist, icon=None, button=edit_packages_button) | ||
| 192 | self.box_group_area.pack_start(package_detail, expand=False, fill=False) | ||
| 193 | if build_succeeded: | ||
| 194 | buttonlist = ["Build new image", "Save as template", "Run image", "Deploy image"] | ||
| 195 | else: # get to this page from "My images" | ||
| 196 | buttonlist = ["Build new image", "Run image", "Deploy image"] | ||
| 197 | details_bottom_buttons = self.create_bottom_buttons(buttonlist) | ||
| 198 | self.box_group_area.pack_end(details_bottom_buttons, expand=False, fill=False) | ||
| 199 | |||
| 200 | self.show_all() | ||
| 201 | |||
| 202 | def create_bottom_buttons(self, buttonlist): | ||
| 203 | # Create the buttons at the bottom | ||
| 204 | bottom_buttons = gtk.HBox(False, 5) | ||
| 205 | created = False | ||
| 206 | |||
| 207 | # create button "Deploy image" | ||
| 208 | name = "Deploy image" | ||
| 209 | if name in buttonlist: | ||
| 210 | deploy_button = gtk.Button() | ||
| 211 | label = gtk.Label() | ||
| 212 | mark = "<span %s>Deploy image</span>" % self.span_tag('24px', 'bold') | ||
| 213 | label.set_markup(mark) | ||
| 214 | deploy_button.set_image(label) | ||
| 215 | deploy_button.set_size_request(205, 49) | ||
| 216 | deploy_button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.ORANGE)) | ||
| 217 | deploy_button.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.ORANGE)) | ||
| 218 | deploy_button.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.ORANGE)) | ||
| 219 | deploy_button.set_tooltip_text("Deploy image to get your target board") | ||
| 220 | deploy_button.set_flags(gtk.CAN_DEFAULT) | ||
| 221 | deploy_button.grab_default() | ||
| 222 | deploy_button.connect("clicked", self.deploy_button_clicked_cb) | ||
| 223 | bottom_buttons.pack_end(deploy_button, expand=False, fill=False) | ||
| 224 | created = True | ||
| 225 | |||
| 226 | name = "Run image" | ||
| 227 | if name in buttonlist: | ||
| 228 | if created == True: | ||
| 229 | # separator | ||
| 230 | label = gtk.Label(" or ") | ||
| 231 | bottom_buttons.pack_end(label, expand=False, fill=False) | ||
| 232 | |||
| 233 | # create button "Run image" | ||
| 234 | run_button = gtk.LinkButton("Launch and boot the image in the QEMU emulator", "Run image") | ||
| 235 | run_button.connect("clicked", self.run_button_clicked_cb) | ||
| 236 | bottom_buttons.pack_end(run_button, expand=False, fill=False) | ||
| 237 | created = True | ||
| 238 | |||
| 239 | name = "Save as template" | ||
| 240 | if name in buttonlist: | ||
| 241 | if created == True: | ||
| 242 | # separator | ||
| 243 | label = gtk.Label(" or ") | ||
| 244 | bottom_buttons.pack_end(label, expand=False, fill=False) | ||
| 245 | |||
| 246 | # create button "Save as template" | ||
| 247 | save_button = gtk.LinkButton("Save the hob build template for future use", "Save as template") | ||
| 248 | save_button.connect("clicked", self.save_button_clicked_cb) | ||
| 249 | bottom_buttons.pack_end(save_button, expand=False, fill=False) | ||
| 250 | create = True | ||
| 251 | |||
| 252 | name = "Build new image" | ||
| 253 | if name in buttonlist: | ||
| 254 | # create button "Build new image" | ||
| 255 | build_new_button = gtk.LinkButton("Initiate another new build from the beginning", "Build new image") | ||
| 256 | build_new_button.connect("clicked", self.build_new_button_clicked_cb) | ||
| 257 | bottom_buttons.pack_start(build_new_button, expand=False, fill=False) | ||
| 258 | |||
| 259 | return bottom_buttons | ||
| 260 | |||
| 261 | def _get_selected_image(self): | ||
| 262 | image_name = "" | ||
| 263 | iter = self.image_store.get_iter_first() | ||
| 264 | while iter: | ||
| 265 | path = self.image_store.get_path(iter) | ||
| 266 | if self.image_store[path][2]: | ||
| 267 | image_name = self.image_store[path][0] | ||
| 268 | break | ||
| 269 | iter = self.image_store.iter_next(iter) | ||
| 270 | |||
| 271 | return image_name | ||
| 272 | |||
| 273 | def save_button_clicked_cb(self, button): | ||
| 274 | self.builder.show_save_template_dialog() | ||
| 275 | |||
| 276 | def deploy_button_clicked_cb(self, button): | ||
| 277 | image_name = self._get_selected_image() | ||
| 278 | self.builder.deploy_image(image_name) | ||
| 279 | |||
| 280 | def run_button_clicked_cb(self, button): | ||
| 281 | image_name = self._get_selected_image() | ||
| 282 | self.builder.runqemu_image(image_name) | ||
| 283 | |||
| 284 | def build_new_button_clicked_cb(self, button): | ||
| 285 | self.builder.initiate_new_build() | ||
| 286 | |||
| 287 | def edit_config_button_clicked_cb(self, button): | ||
| 288 | self.builder.show_configuration() | ||
| 289 | |||
| 290 | def edit_packages_button_clicked_cb(self, button): | ||
| 291 | self.builder.show_packages(ask=False) | ||
| 292 | |||
| 293 | def my_images_button_clicked_cb(self, button): | ||
| 294 | self.builder.show_load_my_images_dialog() | ||
