diff options
author | Dongxiao Xu <dongxiao.xu@intel.com> | 2011-11-28 14:32:40 +0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2012-02-24 18:04:27 +0000 |
commit | 656f9a07588cc00704825a78de9649ca4a1552b8 (patch) | |
tree | 653c7941689599994d5876162c540fb7ee22736e /bitbake/lib/bb/ui/crumbs/imagedetailspage.py | |
parent | 14df6d53b6856ec78322b9c0ef01e26c0406fe28 (diff) | |
download | poky-656f9a07588cc00704825a78de9649ca4a1552b8.tar.gz |
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 <dongxiao.xu@intel.com>
Signed-off-by: Shane Wang <shane.wang@intel.com>
Signed-off-by: Liming An <limingx.l.an@intel.com>
Signed-off-by: Fengxia Hua <fengxia.hua@intel.com>
Designed-by: Belen Barros Pena <belen.barros.pena@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
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() | ||