summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/crumbs/builder.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/builder.py')
-rwxr-xr-xbitbake/lib/bb/ui/crumbs/builder.py873
1 files changed, 873 insertions, 0 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/builder.py b/bitbake/lib/bb/ui/crumbs/builder.py
new file mode 100755
index 0000000000..007167337f
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/builder.py
@@ -0,0 +1,873 @@
1#!/usr/bin/env python
2#
3# BitBake Graphical GTK User Interface
4#
5# Copyright (C) 2011-2012 Intel Corporation
6#
7# Authored by Joshua Lock <josh@linux.intel.com>
8# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
9# Authored by Shane Wang <shane.wang@intel.com>
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License version 2 as
13# published by the Free Software Foundation.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License along
21# with this program; if not, write to the Free Software Foundation, Inc.,
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23
24import gtk
25import copy
26import os
27import subprocess
28import shlex
29from bb.ui.crumbs.template import TemplateMgr
30from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
31from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
32from bb.ui.crumbs.packageselectionpage import PackageSelectionPage
33from bb.ui.crumbs.builddetailspage import BuildDetailsPage
34from bb.ui.crumbs.imagedetailspage import ImageDetailsPage
35from bb.ui.crumbs.hobwidget import hwc
36from bb.ui.crumbs.hig import CrumbsDialog, BinbDialog, \
37 AdvancedSettingDialog, LayerSelectionDialog, \
38 DeployImageDialog, ImageSelectionDialog
39
40class Configuration:
41 '''Represents the data structure of configuration.'''
42
43 def __init__(self, params):
44 # Settings
45 self.curr_mach = ""
46 self.curr_distro = params["distro"]
47 self.dldir = params["dldir"]
48 self.sstatedir = params["sstatedir"]
49 self.sstatemirror = params["sstatemirror"]
50 self.pmake = params["pmake"]
51 self.bbthread = params["bbthread"]
52 self.curr_package_format = " ".join(params["pclass"].split("package_")).strip()
53 self.image_rootfs_size = params["image_rootfs_size"]
54 self.image_extra_size = params["image_extra_size"]
55 self.image_overhead_factor = params['image_overhead_factor']
56 self.incompat_license = params["incompat_license"]
57 self.curr_sdk_machine = params["sdk_machine"]
58 self.extra_setting = {}
59 self.toolchain_build = False
60 self.image_fstypes = params["image_fstypes"].split()
61 # bblayers.conf
62 self.layers = params["layer"].split()
63 # image/recipes/packages
64 self.selected_image = None
65 self.selected_recipes = []
66 self.selected_packages = []
67
68 def load(self, template):
69 self.curr_mach = template.getVar("MACHINE")
70 self.curr_package_format = " ".join(template.getVar("PACKAGE_CLASSES").split("package_")).strip()
71 self.curr_distro = template.getVar("DISTRO")
72 self.dldir = template.getVar("DL_DIR")
73 self.sstatedir = template.getVar("SSTATE_DIR")
74 self.sstatemirror = template.getVar("SSTATE_MIRROR")
75 self.pmake = int(template.getVar("PARALLEL_MAKE").split()[1])
76 self.bbthread = int(template.getVar("BB_NUMBER_THREAD"))
77 self.image_rootfs_size = int(template.getVar("IMAGE_ROOTFS_SIZE"))
78 self.image_extra_size = int(template.getVar("IMAGE_EXTRA_SPACE"))
79 # image_overhead_factor is read-only.
80 self.incompat_license = template.getVar("INCOMPATIBLE_LICENSE")
81 self.curr_sdk_machine = template.getVar("SDKMACHINE")
82 self.extra_setting = eval(template.getVar("EXTRA_SETTING"))
83 self.toolchain_build = eval(template.getVar("TOOLCHAIN_BUILD"))
84 self.image_fstypes = template.getVar("IMAGE_FSTYPES").split()
85 # bblayers.conf
86 self.layers = template.getVar("BBLAYERS").split()
87 # image/recipes/packages
88 self.selected_image = template.getVar("__SELECTED_IMAGE__")
89 self.selected_recipes = template.getVar("DEPENDS").split()
90 self.selected_packages = template.getVar("IMAGE_INSTALL").split()
91
92 def save(self, template, filename):
93 # bblayers.conf
94 template.setVar("BBLAYERS", " ".join(self.layers))
95 # local.conf
96 template.setVar("MACHINE", self.curr_mach)
97 template.setVar("DISTRO", self.curr_distro)
98 template.setVar("DL_DIR", self.dldir)
99 template.setVar("SSTATE_DIR", self.sstatedir)
100 template.setVar("SSTATE_MIRROR", self.sstatemirror)
101 template.setVar("PARALLEL_MAKE", "-j %s" % self.pmake)
102 template.setVar("BB_NUMBER_THREAD", self.bbthread)
103 template.setVar("PACKAGE_CLASSES", " ".join(["package_" + i for i in self.curr_package_format.split()]))
104 template.setVar("IMAGE_ROOTFS_SIZE", self.image_rootfs_size)
105 template.setVar("IMAGE_EXTRA_SPACE", self.image_extra_size)
106 template.setVar("INCOMPATIBLE_LICENSE", self.incompat_license)
107 template.setVar("SDKMACHINE", self.curr_sdk_machine)
108 template.setVar("EXTRA_SETTING", self.extra_setting)
109 template.setVar("TOOLCHAIN_BUILD", self.toolchain_build)
110 template.setVar("IMAGE_FSTYPES", " ".join(self.image_fstypes).lstrip(" "))
111 # image/recipes/packages
112 self.selected_image = filename
113 template.setVar("__SELECTED_IMAGE__", self.selected_image)
114 template.setVar("DEPENDS", self.selected_recipes)
115 template.setVar("IMAGE_INSTALL", self.selected_packages)
116
117class Parameters:
118 '''Represents other variables like available machines, etc.'''
119
120 def __init__(self, params):
121 # Variables
122 self.all_machines = []
123 self.all_package_formats = []
124 self.all_distros = []
125 self.all_sdk_machines = []
126 self.max_threads = params["max_threads"]
127 self.all_layers = []
128 self.core_base = params["core_base"]
129 self.image_names = []
130 self.image_addr = params["image_addr"]
131 self.image_types = params["image_types"].split()
132
133class Builder(gtk.Window):
134
135 (MACHINE_SELECTION,
136 LAYER_CHANGED,
137 RCPPKGINFO_POPULATING,
138 RCPPKGINFO_POPULATED,
139 RECIPE_SELECTION,
140 PACKAGE_GENERATING,
141 PACKAGE_GENERATED,
142 PACKAGE_SELECTION,
143 FAST_IMAGE_GENERATING,
144 IMAGE_GENERATING,
145 IMAGE_GENERATED,
146 MY_IMAGE_OPENED,
147 BACK,
148 END_NOOP) = range(14)
149
150 (IMAGE_CONFIGURATION,
151 RECIPE_DETAILS,
152 BUILD_DETAILS,
153 PACKAGE_DETAILS,
154 IMAGE_DETAILS,
155 END_TAB) = range(6)
156
157 __step2page__ = {
158 MACHINE_SELECTION : IMAGE_CONFIGURATION,
159 LAYER_CHANGED : IMAGE_CONFIGURATION,
160 RCPPKGINFO_POPULATING : IMAGE_CONFIGURATION,
161 RCPPKGINFO_POPULATED : IMAGE_CONFIGURATION,
162 RECIPE_SELECTION : RECIPE_DETAILS,
163 PACKAGE_GENERATING : BUILD_DETAILS,
164 PACKAGE_GENERATED : PACKAGE_DETAILS,
165 PACKAGE_SELECTION : PACKAGE_DETAILS,
166 FAST_IMAGE_GENERATING : BUILD_DETAILS,
167 IMAGE_GENERATING : BUILD_DETAILS,
168 IMAGE_GENERATED : IMAGE_DETAILS,
169 MY_IMAGE_OPENED : IMAGE_DETAILS,
170 END_NOOP : None,
171 }
172
173 def __init__(self, hobHandler, recipe_model, package_model):
174 super(Builder, self).__init__()
175
176 # handler
177 self.handler = hobHandler
178
179 self.template = None
180
181 # settings
182 params = self.handler.get_parameters()
183 self.configuration = Configuration(params)
184 self.parameters = Parameters(params)
185
186 # build step
187 self.current_step = None
188 self.previous_step = None
189
190 self.stopping = False
191 self.build_succeeded = True
192
193 # recipe model and package model
194 self.recipe_model = recipe_model
195 self.package_model = package_model
196
197 # create visual elements
198 self.create_visual_elements()
199
200 # connect the signals to functions
201 #self.connect("configure-event", self.resize_window_cb)
202 self.connect("delete-event", self.destroy_window_cb)
203 self.recipe_model.connect ("recipe-selection-changed", self.recipelist_changed_cb)
204 self.package_model.connect("package-selection-changed", self.packagelist_changed_cb)
205 self.recipe_model.connect ("recipelist-populated", self.recipelist_populated_cb)
206 self.package_model.connect("packagelist-populated", self.packagelist_populated_cb)
207 self.handler.connect("config-updated", self.handler_config_updated_cb)
208 self.handler.connect("package-formats-updated", self.handler_package_formats_updated_cb)
209 self.handler.connect("layers-updated", self.handler_layers_updated_cb)
210 self.handler.connect("parsing-started", self.handler_parsing_started_cb)
211 self.handler.connect("parsing", self.handler_parsing_cb)
212 self.handler.connect("parsing-completed", self.handler_parsing_completed_cb)
213 self.handler.build.connect("build-started", self.handler_build_started_cb)
214 self.handler.build.connect("build-succeeded", self.handler_build_succeeded_cb)
215 self.handler.build.connect("build-failed", self.handler_build_failed_cb)
216 self.handler.build.connect("task-started", self.handler_task_started_cb)
217 self.handler.connect("generating-data", self.handler_generating_data_cb)
218 self.handler.connect("data-generated", self.handler_data_generated_cb)
219 self.handler.connect("command-succeeded", self.handler_command_succeeded_cb)
220 self.handler.connect("command-failed", self.handler_command_failed_cb)
221
222 self.switch_page(self.MACHINE_SELECTION)
223
224 def create_visual_elements(self):
225 self.set_title("HOB -- Image Creator")
226 self.set_icon_name("applications-development")
227 self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
228 self.set_resizable(True)
229 window_width = self.get_screen().get_width()
230 window_height = self.get_screen().get_height()
231 if window_width >= hwc.MAIN_WIN_WIDTH:
232 window_width = hwc.MAIN_WIN_WIDTH
233 window_height = hwc.MAIN_WIN_HEIGHT
234 else:
235 lbl = "<b>Screen dimension mismatched</b>\nfor better usability and visual effects,"
236 lbl = lbl + " the screen dimension should be 1024x768 or above."
237 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
238 dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
239 dialog.run()
240 dialog.destroy()
241 self.set_size_request(window_width, window_height)
242
243 self.vbox = gtk.VBox(False, 0)
244 self.vbox.set_border_width(0)
245 self.add(self.vbox)
246
247 # create pages
248 self.image_configuration_page = ImageConfigurationPage(self)
249 self.recipe_details_page = RecipeSelectionPage(self)
250 self.build_details_page = BuildDetailsPage(self)
251 self.package_details_page = PackageSelectionPage(self)
252 self.image_details_page = ImageDetailsPage(self)
253
254 self.nb = gtk.Notebook()
255 self.nb.set_show_tabs(False)
256 self.nb.insert_page(self.image_configuration_page, None, self.IMAGE_CONFIGURATION)
257 self.nb.insert_page(self.recipe_details_page, None, self.RECIPE_DETAILS)
258 self.nb.insert_page(self.build_details_page, None, self.BUILD_DETAILS)
259 self.nb.insert_page(self.package_details_page, None, self.PACKAGE_DETAILS)
260 self.nb.insert_page(self.image_details_page, None, self.IMAGE_DETAILS)
261 self.vbox.pack_start(self.nb, expand=True, fill=True)
262
263 self.show_all()
264 self.nb.set_current_page(0)
265
266 def get_split_model(self):
267 return self.handler.split_model
268
269 def load_template(self, path):
270 self.template = TemplateMgr()
271 self.template.load(path)
272 self.configuration.load(self.template)
273
274 if self.get_split_model():
275 if not set(self.configuration.layers) <= set(self.parameters.all_layers):
276 return False
277 else:
278 for layer in self.configuration.layers:
279 if not os.path.exists(layer+'/conf/layer.conf'):
280 return False
281
282 self.switch_page(self.LAYER_CHANGED)
283
284 self.template.destroy()
285 self.template = None
286
287 def save_template(self, path):
288 if path.rfind("/") == -1:
289 filename = "default"
290 path = "."
291 else:
292 filename = path[path.rfind("/") + 1:len(path)]
293 path = path[0:path.rfind("/")]
294
295 self.template = TemplateMgr()
296 self.template.open(filename, path)
297 self.configuration.save(self.template, filename)
298
299 self.template.save()
300 self.template.destroy()
301 self.template = None
302
303 def switch_page(self, next_step):
304 # Main Workflow (Business Logic)
305 self.nb.set_current_page(self.__step2page__[next_step])
306
307 if next_step == self.MACHINE_SELECTION: # init step
308 self.image_configuration_page.show_machine()
309
310 elif next_step == self.LAYER_CHANGED:
311 # after layers is changd by users
312 self.image_configuration_page.show_machine()
313 self.handler.refresh_layers(self.configuration.layers)
314
315 elif next_step == self.RCPPKGINFO_POPULATING:
316 # MACHINE CHANGED action or SETTINGS CHANGED
317 # show the progress bar
318 self.image_configuration_page.show_info_populating()
319 self.generate_recipes()
320
321 elif next_step == self.RCPPKGINFO_POPULATED:
322 self.image_configuration_page.show_info_populated()
323
324 elif next_step == self.RECIPE_SELECTION:
325 pass
326
327 elif next_step == self.PACKAGE_SELECTION:
328 pass
329
330 elif next_step == self.PACKAGE_GENERATING or next_step == self.FAST_IMAGE_GENERATING:
331 # both PACKAGE_GENEATING and FAST_IMAGE_GENERATING share the same page
332 self.build_details_page.show_page(next_step)
333 self.generate_packages()
334
335 elif next_step == self.PACKAGE_GENERATED:
336 pass
337
338 elif next_step == self.IMAGE_GENERATING:
339 # after packages are generated, selected_packages need to
340 # be updated in package_model per selected_image in recipe_model
341 self.build_details_page.show_page(next_step)
342 self.generate_image()
343
344 elif next_step == self.IMAGE_GENERATED:
345 self.image_details_page.show_page(next_step)
346
347 elif next_step == self.MY_IMAGE_OPENED:
348 self.image_details_page.show_page(next_step)
349
350 self.previous_step = self.current_step
351 self.current_step = next_step
352
353 def set_user_config(self):
354 self.handler.init_cooker()
355 # set bb layers
356 self.handler.set_bblayers(self.configuration.layers)
357 # set local configuration
358 self.handler.set_machine(self.configuration.curr_mach)
359 self.handler.set_package_format(self.configuration.curr_package_format)
360 self.handler.set_distro(self.configuration.curr_distro)
361 self.handler.set_dl_dir(self.configuration.dldir)
362 self.handler.set_sstate_dir(self.configuration.sstatedir)
363 self.handler.set_sstate_mirror(self.configuration.sstatemirror)
364 self.handler.set_pmake(self.configuration.pmake)
365 self.handler.set_bbthreads(self.configuration.bbthread)
366 self.handler.set_rootfs_size(self.configuration.image_rootfs_size)
367 self.handler.set_extra_size(self.configuration.image_extra_size)
368 self.handler.set_incompatible_license(self.configuration.incompat_license)
369 self.handler.set_sdk_machine(self.configuration.curr_sdk_machine)
370 self.handler.set_image_fstypes(self.configuration.image_fstypes)
371 self.handler.set_extra_config(self.configuration.extra_setting)
372 self.handler.set_extra_inherit("packageinfo")
373
374 def reset_recipe_model(self):
375 self.recipe_model.reset()
376
377 def reset_package_model(self):
378 self.package_model.reset()
379
380 def update_recipe_model(self, selected_image, selected_recipes):
381 self.recipe_model.set_selected_image(selected_image)
382 self.recipe_model.set_selected_recipes(selected_recipes)
383
384 def update_package_model(self, selected_packages):
385 left = self.package_model.set_selected_packages(selected_packages)
386 self.configuration.selected_packages += left
387
388 def generate_packages(self):
389 # Build packages
390 _, all_recipes = self.recipe_model.get_selected_recipes()
391 self.set_user_config()
392 self.handler.reset_build()
393 self.handler.generate_packages(all_recipes)
394
395 def generate_recipes(self):
396 # Parse recipes
397 self.set_user_config()
398 self.handler.generate_recipes()
399
400 def generate_image(self):
401 # Build image
402 self.set_user_config()
403 all_packages = self.package_model.get_selected_packages()
404 self.handler.reset_build()
405 self.handler.generate_image(all_packages, self.configuration.toolchain_build)
406
407
408 # Callback Functions
409 def handler_config_updated_cb(self, handler, which, values):
410 if which == "distro":
411 self.parameters.all_distros = values
412 elif which == "machine":
413 self.parameters.all_machines = values
414 self.image_configuration_page.update_machine_combo()
415 elif which == "machine-sdk":
416 self.parameters.all_sdk_machines = values
417
418 def handler_package_formats_updated_cb(self, handler, formats):
419 self.parameters.all_package_formats = formats
420
421 def handler_layers_updated_cb(self, handler, layers):
422 self.parameters.all_layers = layers
423
424 def handler_command_succeeded_cb(self, handler, initcmd):
425 if initcmd == self.handler.LAYERS_REFRESH:
426 self.image_configuration_page.switch_machine_combo()
427 elif initcmd in [self.handler.GENERATE_RECIPES,
428 self.handler.GENERATE_PACKAGES,
429 self.handler.GENERATE_IMAGE]:
430 self.handler.request_package_info_async()
431 elif initcmd == self.handler.POPULATE_PACKAGEINFO:
432 if self.current_step == self.FAST_IMAGE_GENERATING:
433 self.switch_page(self.IMAGE_GENERATING)
434 elif self.current_step == self.RCPPKGINFO_POPULATING:
435 self.switch_page(self.RCPPKGINFO_POPULATED)
436 elif self.current_step == self.PACKAGE_GENERATING:
437 self.switch_page(self.PACKAGE_GENERATED)
438 elif self.current_step == self.IMAGE_GENERATING:
439 self.switch_page(self.IMAGE_GENERATED)
440
441 def handler_command_failed_cb(self, handler, msg):
442 lbl = "<b>Error</b>\n"
443 lbl = lbl + "%s\n\n" % msg
444 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
445 dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
446 response = dialog.run()
447 dialog.destroy()
448 self.handler.clear_busy()
449 self.configuration.curr_mach = None
450 self.image_configuration_page.switch_machine_combo()
451 self.switch_page(self.MACHINE_SELECTION)
452
453 def window_sensitive(self, sensitive):
454 self.set_sensitive(sensitive)
455 if sensitive:
456 self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
457 else:
458 self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
459
460
461 def handler_generating_data_cb(self, handler):
462 self.window_sensitive(False)
463
464 def handler_data_generated_cb(self, handler):
465 self.window_sensitive(True)
466
467 def recipelist_populated_cb(self, recipe_model):
468 selected_image = self.configuration.selected_image
469 selected_recipes = self.configuration.selected_recipes[:]
470 selected_packages = self.configuration.selected_packages[:]
471
472 self.recipe_model.image_list_append(selected_image,
473 " ".join(selected_recipes),
474 " ".join(selected_packages))
475
476 self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
477
478 self.update_recipe_model(selected_image, selected_recipes)
479
480 def packagelist_populated_cb(self, package_model):
481 selected_packages = self.configuration.selected_packages[:]
482 self.update_package_model(selected_packages)
483
484 def recipelist_changed_cb(self, recipe_model):
485 self.recipe_details_page.refresh_selection()
486
487 def packagelist_changed_cb(self, package_model):
488 self.package_details_page.refresh_selection()
489
490 def handler_parsing_started_cb(self, handler, message):
491 if self.current_step != self.RCPPKGINFO_POPULATING:
492 return
493
494 fraction = 0
495 if message["eventname"] == "TreeDataPreparationStarted":
496 fraction = 0.6 + fraction
497 self.image_configuration_page.update_progress_bar(message["title"], fraction)
498
499 def handler_parsing_cb(self, handler, message):
500 if self.current_step != self.RCPPKGINFO_POPULATING:
501 return
502
503 fraction = message["current"] * 1.0/message["total"]
504 if message["eventname"] == "TreeDataPreparationProgress":
505 fraction = 0.6 + 0.4 * fraction
506 else:
507 fraction = 0.6 * fraction
508 self.image_configuration_page.update_progress_bar(message["title"], fraction)
509
510 def handler_parsing_completed_cb(self, handler, message):
511 if self.current_step != self.RCPPKGINFO_POPULATING:
512 return
513
514 if message["eventname"] == "TreeDataPreparationCompleted":
515 fraction = 1.0
516 else:
517 fraction = 0.6
518 self.image_configuration_page.update_progress_bar(message["title"], fraction)
519
520 def handler_build_started_cb(self, running_build):
521 if self.current_step == self.FAST_IMAGE_GENERATING:
522 fraction = 0
523 elif self.current_step == self.IMAGE_GENERATING:
524 if self.previous_step == self.FAST_IMAGE_GENERATING:
525 fraction = 0.9
526 else:
527 fraction = 0
528 elif self.current_step == self.PACKAGE_GENERATING:
529 fraction = 0
530 self.build_details_page.update_progress_bar("Build Started: ", fraction)
531
532 def handler_build_succeeded_cb(self, running_build):
533 self.build_succeeded = True
534 if self.current_step == self.FAST_IMAGE_GENERATING:
535 fraction = 0.9
536 elif self.current_step == self.IMAGE_GENERATING:
537 fraction = 1.0
538 self.parameters.image_names = []
539 linkname = 'hob-image-' + self.configuration.curr_mach
540 for image_type in self.parameters.image_types:
541 linkpath = self.parameters.image_addr + '/' + linkname + '.' + image_type
542 if os.path.exists(linkpath):
543 self.parameters.image_names.append(os.readlink(linkpath))
544 elif self.current_step == self.PACKAGE_GENERATING:
545 fraction = 1.0
546 self.build_details_page.update_progress_bar("Build Completed: ", fraction)
547
548 def handler_build_failed_cb(self, running_build):
549 self.build_succeeded = False
550 if self.current_step == self.FAST_IMAGE_GENERATING:
551 fraction = 0.9
552 elif self.current_step == self.IMAGE_GENERATING:
553 fraction = 1.0
554 elif self.current_step == self.PACKAGE_GENERATING:
555 fraction = 1.0
556 self.build_details_page.update_progress_bar("Build Failed: ", fraction, False)
557 self.build_details_page.show_back_button()
558 self.build_details_page.hide_stop_button()
559 self.handler.build_failed_async()
560 self.stopping = False
561
562 def handler_task_started_cb(self, running_build, message):
563 fraction = message["current"] * 1.0/message["total"]
564 title = "Build packages"
565 if self.current_step == self.FAST_IMAGE_GENERATING:
566 if message["eventname"] == "sceneQueueTaskStarted":
567 fraction = 0.27 * fraction
568 elif message["eventname"] == "runQueueTaskStarted":
569 fraction = 0.27 + 0.63 * fraction
570 elif self.current_step == self.IMAGE_GENERATING:
571 title = "Build image"
572 if self.previous_step == self.FAST_IMAGE_GENERATING:
573 if message["eventname"] == "sceneQueueTaskStarted":
574 fraction = 0.27 + 0.63 + 0.03 * fraction
575 elif message["eventname"] == "runQueueTaskStarted":
576 fraction = 0.27 + 0.63 + 0.03 + 0.07 * fraction
577 else:
578 if message["eventname"] == "sceneQueueTaskStarted":
579 fraction = 0.2 * fraction
580 elif message["eventname"] == "runQueueTaskStarted":
581 fraction = 0.2 + 0.8 * fraction
582 elif self.current_step == self.PACKAGE_GENERATING:
583 if message["eventname"] == "sceneQueueTaskStarted":
584 fraction = 0.2 * fraction
585 elif message["eventname"] == "runQueueTaskStarted":
586 fraction = 0.2 + 0.8 * fraction
587 self.build_details_page.update_progress_bar(title + ": ", fraction)
588
589 def destroy_window_cb(self, widget, event):
590 lbl = "<b>Do you really want to exit the Hob image creator?</b>"
591 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
592 dialog.add_button(gtk.STOCK_YES, gtk.RESPONSE_YES)
593 dialog.add_button(gtk.STOCK_NO, gtk.RESPONSE_NO)
594 dialog.set_default_response(gtk.RESPONSE_NO)
595 response = dialog.run()
596 dialog.destroy()
597 if response == gtk.RESPONSE_YES:
598 gtk.main_quit()
599 return False
600 else:
601 return True
602
603 def build_packages(self):
604 _, all_recipes = self.recipe_model.get_selected_recipes()
605 if not all_recipes:
606 lbl = "<b>No selections made</b>\nYou have not made any selections"
607 lbl = lbl + " so there isn't anything to bake at this time."
608 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
609 dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
610 dialog.run()
611 dialog.destroy()
612 return
613 self.switch_page(self.PACKAGE_GENERATING)
614
615 def build_image(self):
616 selected_packages = self.package_model.get_selected_packages()
617 if not selected_packages:
618 lbl = "<b>No selections made</b>\nYou have not made any selections"
619 lbl = lbl + " so there isn't anything to bake at this time."
620 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
621 dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
622 dialog.run()
623 dialog.destroy()
624 return
625 self.switch_page(self.IMAGE_GENERATING)
626
627 def just_bake(self):
628 selected_image = self.recipe_model.get_selected_image()
629 selected_packages = self.package_model.get_selected_packages() or []
630
631 # If no base image and no selected packages don't build anything
632 if not (selected_packages or selected_image != self.recipe_model.__dummy_image__):
633 lbl = "<b>No selections made</b>\nYou have not made any selections"
634 lbl = lbl + " so there isn't anything to bake at this time."
635 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
636 dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
637 dialog.run()
638 dialog.destroy()
639 return
640
641 self.switch_page(self.FAST_IMAGE_GENERATING)
642
643 def show_binb_dialog(self, binb):
644 binb_dialog = BinbDialog("Brought in by:", binb, self)
645 binb_dialog.run()
646 binb_dialog.destroy()
647
648 def show_layer_selection_dialog(self):
649 dialog = LayerSelectionDialog(title = "Layer Selection",
650 layers = copy.deepcopy(self.configuration.layers),
651 all_layers = self.parameters.all_layers,
652 split_model = self.get_split_model(),
653 parent = self,
654 flags = gtk.DIALOG_MODAL
655 | gtk.DIALOG_DESTROY_WITH_PARENT
656 | gtk.DIALOG_NO_SEPARATOR,
657 buttons = (gtk.STOCK_OK, gtk.RESPONSE_YES,
658 gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
659 response = dialog.run()
660 if response == gtk.RESPONSE_YES:
661 self.configuration.layers = dialog.layers
662 # DO refresh layers
663 if dialog.layers_changed:
664 self.switch_page(self.LAYER_CHANGED)
665 dialog.destroy()
666
667 def show_load_template_dialog(self):
668 dialog = gtk.FileChooserDialog("Load Template Files", self,
669 gtk.FILE_CHOOSER_ACTION_SAVE,
670 (gtk.STOCK_OPEN, gtk.RESPONSE_YES,
671 gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
672 filter = gtk.FileFilter()
673 filter.set_name("HOB Files")
674 filter.add_pattern("*.hob")
675 dialog.add_filter(filter)
676
677 response = dialog.run()
678 if response == gtk.RESPONSE_YES:
679 path = dialog.get_filename()
680 self.load_template(path)
681 dialog.destroy()
682
683 def show_save_template_dialog(self):
684 dialog = gtk.FileChooserDialog("Save Template Files", self,
685 gtk.FILE_CHOOSER_ACTION_SAVE,
686 (gtk.STOCK_SAVE, gtk.RESPONSE_YES,
687 gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
688 dialog.set_current_name("hob")
689 response = dialog.run()
690 if response == gtk.RESPONSE_YES:
691 path = dialog.get_filename()
692 self.save_template(path)
693 dialog.destroy()
694
695 def show_load_my_images_dialog(self):
696 dialog = ImageSelectionDialog(self.parameters.image_addr, self.parameters.image_types,
697 "Open My Images", self,
698 gtk.FILE_CHOOSER_ACTION_SAVE,
699 (gtk.STOCK_OPEN, gtk.RESPONSE_YES,
700 gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
701
702 response = dialog.run()
703 if response == gtk.RESPONSE_YES:
704 if not dialog.image_names:
705 lbl = "<b>No selections made</b>\nYou have not made any selections"
706 crumbs_dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
707 crumbs_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
708 crumbs_dialog.run()
709 crumbs_dialog.destroy()
710 dialog.destroy()
711 return
712
713 self.parameters.image_addr = dialog.image_folder
714 self.parameters.image_names = dialog.image_names[:]
715 self.switch_page(self.MY_IMAGE_OPENED)
716
717 dialog.destroy()
718
719 def show_adv_settings_dialog(self):
720 dialog = AdvancedSettingDialog(title = "Settings",
721 configuration = copy.deepcopy(self.configuration),
722 all_image_types = self.parameters.image_types,
723 all_package_formats = self.parameters.all_package_formats,
724 all_distros = self.parameters.all_distros,
725 all_sdk_machines = self.parameters.all_sdk_machines,
726 max_threads = self.parameters.max_threads,
727 split_model = self.get_split_model(),
728 parent = self,
729 flags = gtk.DIALOG_MODAL
730 | gtk.DIALOG_DESTROY_WITH_PARENT
731 | gtk.DIALOG_NO_SEPARATOR,
732 buttons = ("Save", gtk.RESPONSE_YES,
733 gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
734 response = dialog.run()
735 if response == gtk.RESPONSE_YES:
736 self.configuration = dialog.configuration
737 # DO reparse recipes
738 if dialog.settings_changed:
739 if self.configuration.curr_mach == "":
740 self.switch_page(self.MACHINE_SELECTION)
741 else:
742 self.switch_page(self.RCPPKGINFO_POPULATING)
743 dialog.destroy()
744
745 def deploy_image(self, image_name):
746 if not image_name:
747 lbl = "<b>Please select an image to deploy.</b>"
748 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
749 dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
750 dialog.run()
751 dialog.destroy()
752 return
753
754 image_path = os.path.join(self.parameters.image_addr, image_name)
755 dialog = DeployImageDialog(title = "Usb Image Maker",
756 image_path = image_path,
757 parent = self,
758 flags = gtk.DIALOG_MODAL
759 | gtk.DIALOG_DESTROY_WITH_PARENT
760 | gtk.DIALOG_NO_SEPARATOR,
761 buttons = ("Close", gtk.RESPONSE_NO,
762 "Make usb image", gtk.RESPONSE_YES))
763 response = dialog.run()
764 dialog.destroy()
765
766 def runqemu_image(self, image_name):
767 if not image_name:
768 lbl = "<b>Please select an image to launch in QEMU.</b>"
769 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
770 dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
771 dialog.run()
772 dialog.destroy()
773 return
774
775 dialog = gtk.FileChooserDialog("Load Kernel Files", self,
776 gtk.FILE_CHOOSER_ACTION_SAVE,
777 (gtk.STOCK_OPEN, gtk.RESPONSE_YES,
778 gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
779 filter = gtk.FileFilter()
780 filter.set_name("Kernel Files")
781 filter.add_pattern("*.bin")
782 dialog.add_filter(filter)
783
784 dialog.set_current_folder(self.parameters.image_addr)
785
786 response = dialog.run()
787 if response == gtk.RESPONSE_YES:
788 kernel_path = dialog.get_filename()
789 image_path = os.path.join(self.parameters.image_addr, image_name)
790 dialog.destroy()
791
792 if response == gtk.RESPONSE_YES:
793 source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
794 tmp_path = os.path.join(os.getcwd(), "tmp")
795 if os.path.exists(image_path) and os.path.exists(kernel_path) \
796 and os.path.exists(source_env_path) and os.path.exists(tmp_path):
797 cmdline = "/usr/bin/xterm -e "
798 cmdline += "\" export OE_TMPDIR=" + tmp_path + "; "
799 cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
800 cmdline += "runqemu " + kernel_path + " " + image_path + "; bash\""
801 subprocess.Popen(shlex.split(cmdline))
802 else:
803 lbl = "<b>Path error</b>\nOne of your paths is wrong,"
804 lbl = lbl + " please make sure the following paths exist:\n"
805 lbl = lbl + "image path:" + image_path + "\n"
806 lbl = lbl + "kernel path:" + kernel_path + "\n"
807 lbl = lbl + "source environment path:" + source_env_path + "\n"
808 lbl = lbl + "tmp path: " + tmp_path + "."
809 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
810 dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
811 dialog.run()
812 dialog.destroy()
813
814 def show_packages(self, ask=True):
815 _, selected_recipes = self.recipe_model.get_selected_recipes()
816 if selected_recipes and ask:
817 lbl = "<b>Package list may be incomplete!</b>\nDo you want to build selected recipes"
818 lbl = lbl + " to get a full list (Yes) or just view the existing packages (No)?"
819 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
820 dialog.add_button(gtk.STOCK_YES, gtk.RESPONSE_YES)
821 dialog.add_button(gtk.STOCK_NO, gtk.RESPONSE_NO)
822 dialog.set_default_response(gtk.RESPONSE_YES)
823 response = dialog.run()
824 dialog.destroy()
825 if response == gtk.RESPONSE_YES:
826 self.switch_page(self.PACKAGE_GENERATING)
827 else:
828 self.switch_page(self.PACKAGE_SELECTION)
829 else:
830 self.switch_page(self.PACKAGE_SELECTION)
831
832 def show_recipes(self):
833 self.switch_page(self.RECIPE_SELECTION)
834
835 def initiate_new_build(self):
836 self.configuration.curr_mach = ""
837 self.image_configuration_page.switch_machine_combo()
838 self.switch_page(self.MACHINE_SELECTION)
839
840 def show_configuration(self):
841 self.switch_page(self.RCPPKGINFO_POPULATED)
842
843 def stop_build(self):
844 if self.stopping:
845 lbl = "<b>Force Stop build?</b>\nYou've already selected Stop once,"
846 lbl = lbl + " would you like to 'Force Stop' the build?\n\n"
847 lbl = lbl + "This will stop the build as quickly as possible but may"
848 lbl = lbl + " well leave your build directory in an unusable state"
849 lbl = lbl + " that requires manual steps to fix.\n"
850 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
851 dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
852 dialog.add_button("Force Stop", gtk.RESPONSE_YES)
853 else:
854 lbl = "<b>Stop build?</b>\n\nAre you sure you want to stop this"
855 lbl = lbl + " build?\n\n'Force Stop' will stop the build as quickly as"
856 lbl = lbl + " possible but may well leave your build directory in an"
857 lbl = lbl + " unusable state that requires manual steps to fix.\n\n"
858 lbl = lbl + "'Stop' will stop the build as soon as all in"
859 lbl = lbl + " progress build tasks are finished. However if a"
860 lbl = lbl + " lengthy compilation phase is in progress this may take"
861 lbl = lbl + " some time."
862 dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
863 dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
864 dialog.add_button("Stop", gtk.RESPONSE_OK)
865 dialog.add_button("Force Stop", gtk.RESPONSE_YES)
866 response = dialog.run()
867 dialog.destroy()
868 if response != gtk.RESPONSE_CANCEL:
869 self.stopping = True
870 if response == gtk.RESPONSE_OK:
871 self.handler.cancel_build()
872 elif response == gtk.RESPONSE_YES:
873 self.handler.cancel_build(True)