3 # BitBake Graphical GTK User Interface
5 # Copyright (C) 2011-2012 Intel Corporation
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>
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.
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.
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.
33 from bb.ui.crumbs.template import TemplateMgr
34 from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
35 from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
36 from bb.ui.crumbs.packageselectionpage import PackageSelectionPage
37 from bb.ui.crumbs.builddetailspage import BuildDetailsPage
38 from bb.ui.crumbs.imagedetailspage import ImageDetailsPage
39 from bb.ui.crumbs.hobwidget import hwc, HobButton, HobAltButton
40 from bb.ui.crumbs.hig import CrumbsMessageDialog, ImageSelectionDialog, \
41 AdvancedSettingDialog, LayerSelectionDialog, \
43 from bb.ui.crumbs.persistenttooltip import PersistentTooltip
44 import bb.ui.crumbs.utils
49 '''Represents the data structure of configuration.'''
52 def parse_proxy_string(cls, proxy):
53 pattern = "^\s*((http|https|ftp|git|cvs)://)?((\S+):(\S+)@)?(\S+):(\d+)/?"
54 match = re.search(pattern, proxy)
56 return match.group(2), match.group(4), match.group(5), match.group(6), match.group(7)
58 return None, None, None, "", ""
61 def make_host_string(cls, prot, user, passwd, host, default_prot=""):
62 if host == None or host == "":
67 if user != None and user != "":
68 if prot == None or prot == "":
70 return prot + "://" + user + ":" + passwd + "@" + host
72 if prot == None or prot == "":
75 return prot + "://" + host
78 def make_port_string(cls, port):
83 def make_proxy_string(cls, prot, user, passwd, host, port, default_prot=""):
84 if host == None or host == "" or port == None or port == "":
87 return Configuration.make_host_string(prot, user, passwd, host, default_prot) + ":" + Configuration.make_port_string(port)
93 self.dldir = self.sstatedir = self.sstatemirror = ""
94 self.pmake = self.bbthread = 0
95 self.curr_package_format = ""
96 self.image_rootfs_size = self.image_extra_size = 0
97 self.image_overhead_factor = 1
98 self.incompat_license = ""
99 self.curr_sdk_machine = ""
100 self.conf_version = self.lconf_version = ""
101 self.extra_setting = {}
102 self.toolchain_build = False
103 self.image_fstypes = ""
106 # image/recipes/packages
107 self.clear_selection()
109 self.user_selected_packages = []
111 self.default_task = "build"
114 self.enable_proxy = None
115 self.same_proxy = False
117 "http" : [None, None, None, "", ""], # protocol : [prot, user, passwd, host, port]
118 "https" : [None, None, None, "", ""],
119 "ftp" : [None, None, None, "", ""],
120 "git" : [None, None, None, "", ""],
121 "cvs" : [None, None, None, "", ""],
124 def clear_selection(self):
125 self.selected_image = None
126 self.selected_recipes = []
127 self.selected_packages = []
128 self.initial_selected_packages = []
130 def split_proxy(self, protocol, proxy):
132 prot, user, passwd, host, port = Configuration.parse_proxy_string(proxy)
138 self.proxies[protocol] = entry
140 def combine_proxy(self, protocol):
141 entry = self.proxies[protocol]
142 return Configuration.make_proxy_string(entry[0], entry[1], entry[2], entry[3], entry[4], protocol)
144 def combine_host_only(self, protocol):
145 entry = self.proxies[protocol]
146 return Configuration.make_host_string(entry[0], entry[1], entry[2], entry[3], protocol)
148 def combine_port_only(self, protocol):
149 entry = self.proxies[protocol]
150 return Configuration.make_port_string(entry[4])
152 def update(self, params):
154 self.curr_distro = params["distro"]
155 self.dldir = params["dldir"]
156 self.sstatedir = params["sstatedir"]
157 self.sstatemirror = params["sstatemirror"]
158 self.pmake = int(params["pmake"].split()[1])
159 self.bbthread = params["bbthread"]
160 self.curr_package_format = " ".join(params["pclass"].split("package_")).strip()
161 self.image_rootfs_size = params["image_rootfs_size"]
162 self.image_extra_size = params["image_extra_size"]
163 self.image_overhead_factor = params['image_overhead_factor']
164 self.incompat_license = params["incompat_license"]
165 self.curr_sdk_machine = params["sdk_machine"]
166 self.conf_version = params["conf_version"]
167 self.lconf_version = params["lconf_version"]
168 self.image_fstypes = params["image_fstypes"]
169 # self.extra_setting/self.toolchain_build
171 self.layers = params["layer"].split()
172 self.default_task = params["default_task"]
175 self.enable_proxy = params["http_proxy"] != "" or params["https_proxy"] != "" or params["ftp_proxy"] != "" \
176 or params["git_proxy_host"] != "" or params["git_proxy_port"] != "" \
177 or params["cvs_proxy_host"] != "" or params["cvs_proxy_port"] != ""
178 self.split_proxy("http", params["http_proxy"])
179 self.split_proxy("https", params["https_proxy"])
180 self.split_proxy("ftp", params["ftp_proxy"])
181 self.split_proxy("git", params["git_proxy_host"] + ":" + params["git_proxy_port"])
182 self.split_proxy("cvs", params["cvs_proxy_host"] + ":" + params["cvs_proxy_port"])
184 def load(self, template):
185 self.curr_mach = template.getVar("MACHINE")
186 self.curr_package_format = " ".join(template.getVar("PACKAGE_CLASSES").split("package_")).strip()
187 self.curr_distro = template.getVar("DISTRO")
188 self.dldir = template.getVar("DL_DIR")
189 self.sstatedir = template.getVar("SSTATE_DIR")
190 self.sstatemirror = template.getVar("SSTATE_MIRROR")
192 self.pmake = int(template.getVar("PARALLEL_MAKE").split()[1])
196 self.bbthread = int(template.getVar("BB_NUMBER_THREADS"))
200 self.image_rootfs_size = int(template.getVar("IMAGE_ROOTFS_SIZE"))
204 self.image_extra_size = int(template.getVar("IMAGE_EXTRA_SPACE"))
207 # image_overhead_factor is read-only.
208 self.incompat_license = template.getVar("INCOMPATIBLE_LICENSE")
209 self.curr_sdk_machine = template.getVar("SDKMACHINE")
210 self.conf_version = template.getVar("CONF_VERSION")
211 self.lconf_version = template.getVar("LCONF_VERSION")
212 self.extra_setting = eval(template.getVar("EXTRA_SETTING"))
213 self.toolchain_build = eval(template.getVar("TOOLCHAIN_BUILD"))
214 self.image_fstypes = template.getVar("IMAGE_FSTYPES")
216 self.layers = template.getVar("BBLAYERS").split()
217 # image/recipes/packages
218 self.selected_image = template.getVar("__SELECTED_IMAGE__")
219 self.selected_recipes = template.getVar("DEPENDS").split()
220 self.selected_packages = template.getVar("IMAGE_INSTALL").split()
222 self.enable_proxy = eval(template.getVar("enable_proxy"))
223 self.same_proxy = eval(template.getVar("use_same_proxy"))
224 self.split_proxy("http", template.getVar("http_proxy"))
225 self.split_proxy("https", template.getVar("https_proxy"))
226 self.split_proxy("ftp", template.getVar("ftp_proxy"))
227 self.split_proxy("git", template.getVar("GIT_PROXY_HOST") + ":" + template.getVar("GIT_PROXY_PORT"))
228 self.split_proxy("cvs", template.getVar("CVS_PROXY_HOST") + ":" + template.getVar("CVS_PROXY_PORT"))
230 def save(self, template, defaults=False):
231 template.setVar("VERSION", "%s" % hobVer)
233 template.setVar("BBLAYERS", " ".join(self.layers))
236 template.setVar("MACHINE", self.curr_mach)
237 template.setVar("DISTRO", self.curr_distro)
238 template.setVar("DL_DIR", self.dldir)
239 template.setVar("SSTATE_DIR", self.sstatedir)
240 template.setVar("SSTATE_MIRROR", self.sstatemirror)
241 template.setVar("PARALLEL_MAKE", "-j %s" % self.pmake)
242 template.setVar("BB_NUMBER_THREADS", self.bbthread)
243 template.setVar("PACKAGE_CLASSES", " ".join(["package_" + i for i in self.curr_package_format.split()]))
244 template.setVar("IMAGE_ROOTFS_SIZE", self.image_rootfs_size)
245 template.setVar("IMAGE_EXTRA_SPACE", self.image_extra_size)
246 template.setVar("INCOMPATIBLE_LICENSE", self.incompat_license)
247 template.setVar("SDKMACHINE", self.curr_sdk_machine)
248 template.setVar("CONF_VERSION", self.conf_version)
249 template.setVar("LCONF_VERSION", self.lconf_version)
250 template.setVar("EXTRA_SETTING", self.extra_setting)
251 template.setVar("TOOLCHAIN_BUILD", self.toolchain_build)
252 template.setVar("IMAGE_FSTYPES", self.image_fstypes)
254 # image/recipes/packages
255 template.setVar("__SELECTED_IMAGE__", self.selected_image)
256 template.setVar("DEPENDS", self.selected_recipes)
257 template.setVar("IMAGE_INSTALL", self.user_selected_packages)
259 template.setVar("enable_proxy", self.enable_proxy)
260 template.setVar("use_same_proxy", self.same_proxy)
261 template.setVar("http_proxy", self.combine_proxy("http"))
262 template.setVar("https_proxy", self.combine_proxy("https"))
263 template.setVar("ftp_proxy", self.combine_proxy("ftp"))
264 template.setVar("GIT_PROXY_HOST", self.combine_host_only("git"))
265 template.setVar("GIT_PROXY_PORT", self.combine_port_only("git"))
266 template.setVar("CVS_PROXY_HOST", self.combine_host_only("cvs"))
267 template.setVar("CVS_PROXY_PORT", self.combine_port_only("cvs"))
270 '''Represents other variables like available machines, etc.'''
274 self.max_threads = 65535
277 self.image_types = []
278 self.runnable_image_types = []
279 self.runnable_machine_patterns = []
280 self.deployable_image_types = []
283 self.all_machines = []
284 self.all_package_formats = []
285 self.all_distros = []
286 self.all_sdk_machines = []
288 self.image_names = []
289 self.image_white_pattern = ""
290 self.image_black_pattern = ""
292 # for build log to show
294 self.target_arch = ""
296 self.distro_version = ""
297 self.tune_pkgarch = ""
299 def update(self, params):
300 self.max_threads = params["max_threads"]
301 self.core_base = params["core_base"]
302 self.image_addr = params["image_addr"]
303 self.image_types = params["image_types"].split()
304 self.runnable_image_types = params["runnable_image_types"].split()
305 self.runnable_machine_patterns = params["runnable_machine_patterns"].split()
306 self.deployable_image_types = params["deployable_image_types"].split()
307 self.tmpdir = params["tmpdir"]
308 self.image_white_pattern = params["image_white_pattern"]
309 self.image_black_pattern = params["image_black_pattern"]
310 self.kernel_image_type = params["kernel_image_type"]
311 # for build log to show
312 self.bb_version = params["bb_version"]
313 self.target_arch = params["target_arch"]
314 self.target_os = params["target_os"]
315 self.distro_version = params["distro_version"]
316 self.tune_pkgarch = params["tune_pkgarch"]
318 def hob_conf_filter(fn, data):
319 if fn.endswith("/local.conf"):
320 distro = data.getVar("DISTRO_HOB")
322 if distro != "defaultsetup":
323 data.setVar("DISTRO", distro)
325 data.delVar("DISTRO")
327 keys = ["MACHINE_HOB", "SDKMACHINE_HOB", "PACKAGE_CLASSES_HOB", \
328 "BB_NUMBER_THREADS_HOB", "PARALLEL_MAKE_HOB", "DL_DIR_HOB", \
329 "SSTATE_DIR_HOB", "SSTATE_MIRROR_HOB", "INCOMPATIBLE_LICENSE_HOB"]
331 var_hob = data.getVar(key)
333 data.setVar(key.split("_HOB")[0], var_hob)
336 if fn.endswith("/bblayers.conf"):
337 layers = data.getVar("BBLAYERS_HOB")
339 data.setVar("BBLAYERS", layers)
342 class Builder(gtk.Window):
345 RCPPKGINFO_POPULATING,
346 RCPPKGINFO_POPULATED,
352 FAST_IMAGE_GENERATING,
357 END_NOOP) = range(14)
359 (IMAGE_CONFIGURATION,
367 MACHINE_SELECTION : IMAGE_CONFIGURATION,
368 RCPPKGINFO_POPULATING : IMAGE_CONFIGURATION,
369 RCPPKGINFO_POPULATED : IMAGE_CONFIGURATION,
370 BASEIMG_SELECTED : IMAGE_CONFIGURATION,
371 RECIPE_SELECTION : RECIPE_DETAILS,
372 PACKAGE_GENERATING : BUILD_DETAILS,
373 PACKAGE_GENERATED : PACKAGE_DETAILS,
374 PACKAGE_SELECTION : PACKAGE_DETAILS,
375 FAST_IMAGE_GENERATING : BUILD_DETAILS,
376 IMAGE_GENERATING : BUILD_DETAILS,
377 IMAGE_GENERATED : IMAGE_DETAILS,
378 MY_IMAGE_OPENED : IMAGE_DETAILS,
382 def __init__(self, hobHandler, recipe_model, package_model):
383 super(Builder, self).__init__()
385 self.hob_image = "hob-image"
386 self.hob_toolchain = "hob-toolchain"
389 self.handler = hobHandler
394 self.logger = logging.getLogger("BitBake")
395 self.consolelog = None
396 self.current_logfile = None
398 # configuration and parameters
399 self.configuration = Configuration()
400 self.parameters = Parameters()
403 self.current_step = None
404 self.previous_step = None
406 self.stopping = False
408 # recipe model and package model
409 self.recipe_model = recipe_model
410 self.package_model = package_model
412 # Indicate whether user has customized the image
413 self.customized = False
415 # Indicate whether the UI is working
416 self.sensitive = True
418 # create visual elements
419 self.create_visual_elements()
421 # connect the signals to functions
422 self.connect("delete-event", self.destroy_window_cb)
423 self.recipe_model.connect ("recipe-selection-changed", self.recipelist_changed_cb)
424 self.package_model.connect("package-selection-changed", self.packagelist_changed_cb)
425 self.handler.connect("config-updated", self.handler_config_updated_cb)
426 self.handler.connect("package-formats-updated", self.handler_package_formats_updated_cb)
427 self.handler.connect("parsing-started", self.handler_parsing_started_cb)
428 self.handler.connect("parsing", self.handler_parsing_cb)
429 self.handler.connect("parsing-completed", self.handler_parsing_completed_cb)
430 self.handler.build.connect("build-started", self.handler_build_started_cb)
431 self.handler.build.connect("build-succeeded", self.handler_build_succeeded_cb)
432 self.handler.build.connect("build-failed", self.handler_build_failed_cb)
433 self.handler.build.connect("build-aborted", self.handler_build_aborted_cb)
434 self.handler.build.connect("task-started", self.handler_task_started_cb)
435 self.handler.build.connect("log-error", self.handler_build_failure_cb)
436 self.handler.build.connect("log", self.handler_build_log_cb)
437 self.handler.build.connect("no-provider", self.handler_no_provider_cb)
438 self.handler.connect("generating-data", self.handler_generating_data_cb)
439 self.handler.connect("data-generated", self.handler_data_generated_cb)
440 self.handler.connect("command-succeeded", self.handler_command_succeeded_cb)
441 self.handler.connect("command-failed", self.handler_command_failed_cb)
442 self.handler.connect("sanity-failed", self.handler_sanity_failed_cb)
443 self.handler.connect("recipe-populated", self.handler_recipe_populated_cb)
444 self.handler.connect("package-populated", self.handler_package_populated_cb)
446 self.handler.set_config_filter(hob_conf_filter)
448 self.initiate_new_build_async()
450 def create_visual_elements(self):
451 self.set_title("Hob")
452 self.set_icon_name("applications-development")
453 self.set_resizable(True)
456 window_width = self.get_screen().get_width()
457 window_height = self.get_screen().get_height()
458 except AttributeError:
459 print "Please set DISPLAY variable before running Hob."
462 if window_width >= hwc.MAIN_WIN_WIDTH:
463 window_width = hwc.MAIN_WIN_WIDTH
464 window_height = hwc.MAIN_WIN_HEIGHT
465 self.set_size_request(window_width, window_height)
467 self.vbox = gtk.VBox(False, 0)
468 self.vbox.set_border_width(0)
472 self.image_configuration_page = ImageConfigurationPage(self)
473 self.recipe_details_page = RecipeSelectionPage(self)
474 self.build_details_page = BuildDetailsPage(self)
475 self.package_details_page = PackageSelectionPage(self)
476 self.image_details_page = ImageDetailsPage(self)
478 self.nb = gtk.Notebook()
479 self.nb.set_show_tabs(False)
480 self.nb.insert_page(self.image_configuration_page, None, self.IMAGE_CONFIGURATION)
481 self.nb.insert_page(self.recipe_details_page, None, self.RECIPE_DETAILS)
482 self.nb.insert_page(self.build_details_page, None, self.BUILD_DETAILS)
483 self.nb.insert_page(self.package_details_page, None, self.PACKAGE_DETAILS)
484 self.nb.insert_page(self.image_details_page, None, self.IMAGE_DETAILS)
485 self.vbox.pack_start(self.nb, expand=True, fill=True)
488 self.nb.set_current_page(0)
490 def initiate_new_build_async(self):
491 self.switch_page(self.MACHINE_SELECTION)
492 if self.load_template(TemplateMgr.convert_to_template_pathfilename("default", ".hob/")) == False:
493 self.handler.init_cooker()
494 self.handler.set_extra_inherit("image_types")
495 self.handler.generate_configuration()
497 def update_config_async(self):
498 self.switch_page(self.MACHINE_SELECTION)
499 self.set_user_config()
500 self.handler.generate_configuration()
502 def sanity_check(self):
503 self.handler.trigger_sanity_check()
505 def populate_recipe_package_info_async(self):
506 self.switch_page(self.RCPPKGINFO_POPULATING)
508 self.set_user_config()
509 self.handler.generate_recipes()
511 def generate_packages_async(self, log = False):
512 self.switch_page(self.PACKAGE_GENERATING)
514 self.current_logfile = self.handler.get_logfile()
515 self.do_log(self.current_logfile)
517 _, all_recipes = self.recipe_model.get_selected_recipes()
518 self.set_user_config()
519 self.handler.reset_build()
520 self.handler.generate_packages(all_recipes, self.configuration.default_task)
522 def restore_initial_selected_packages(self):
523 self.package_model.set_selected_packages(self.configuration.initial_selected_packages)
524 for package in self.configuration.selected_packages:
525 if package not in self.configuration.initial_selected_packages:
526 self.package_model.exclude_item(self.package_model.find_path_for_item(package))
528 def fast_generate_image_async(self, log = False):
529 self.switch_page(self.FAST_IMAGE_GENERATING)
531 self.current_logfile = self.handler.get_logfile()
532 self.do_log(self.current_logfile)
534 _, all_recipes = self.recipe_model.get_selected_recipes()
535 self.set_user_config()
536 self.handler.reset_build()
537 self.handler.generate_packages(all_recipes, self.configuration.default_task)
539 def generate_image_async(self, cont = False):
540 self.switch_page(self.IMAGE_GENERATING)
541 self.handler.reset_build()
543 self.current_logfile = self.handler.get_logfile()
544 self.do_log(self.current_logfile)
546 self.set_user_config()
547 toolchain_packages = []
548 if self.configuration.toolchain_build:
549 toolchain_packages = self.package_model.get_selected_packages_toolchain()
550 if self.configuration.selected_image == self.recipe_model.__custom_image__:
551 packages = self.package_model.get_selected_packages()
552 image = self.hob_image
555 image = self.configuration.selected_image
556 self.handler.generate_image(image,
560 self.configuration.default_task)
562 def get_parameters_sync(self):
563 return self.handler.get_parameters()
565 def request_package_info_async(self):
566 self.handler.request_package_info()
568 def cancel_build_sync(self, force=False):
569 self.handler.cancel_build(force)
571 def cancel_parse_sync(self):
572 self.handler.cancel_parse()
574 def load_template(self, path):
575 if not os.path.isfile(path):
578 self.template = TemplateMgr()
579 # check compatibility
580 tempVer = self.template.getVersion(path)
581 if not tempVer or int(tempVer) < hobVer:
582 self.template.destroy()
587 self.template.load(path)
588 self.configuration.load(self.template)
589 except Exception as e:
590 self.show_error_dialog("Hob Exception - %s" % (str(e)))
593 self.template.destroy()
596 for layer in self.configuration.layers:
597 if not os.path.exists(layer+'/conf/layer.conf'):
600 self.save_defaults() # remember layers and settings
601 self.update_config_async()
604 def save_template(self, path, defaults=False):
605 if path.rfind("/") == -1:
609 filename = path[path.rfind("/") + 1:len(path)]
610 path = path[0:path.rfind("/")]
612 self.template = TemplateMgr()
614 self.template.open(filename, path)
615 self.configuration.save(self.template, defaults)
618 except Exception as e:
619 self.show_error_dialog("Hob Exception - %s" % (str(e)))
622 self.template.destroy()
625 def save_defaults(self):
626 if not os.path.exists(".hob/"):
628 self.save_template(".hob/default", True)
630 def switch_page(self, next_step):
631 # Main Workflow (Business Logic)
632 self.nb.set_current_page(self.__step2page__[next_step])
634 if next_step == self.MACHINE_SELECTION: # init step
635 self.image_configuration_page.show_machine()
637 elif next_step == self.RCPPKGINFO_POPULATING:
638 # MACHINE CHANGED action or SETTINGS CHANGED
639 # show the progress bar
640 self.image_configuration_page.show_info_populating()
642 elif next_step == self.RCPPKGINFO_POPULATED:
643 self.image_configuration_page.show_info_populated()
645 elif next_step == self.BASEIMG_SELECTED:
646 self.image_configuration_page.show_baseimg_selected()
648 elif next_step == self.RECIPE_SELECTION:
649 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
650 self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.ALL)
652 self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.INCLUDED)
654 elif next_step == self.PACKAGE_SELECTION:
655 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
656 self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
658 self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
659 self.package_details_page.show_page(self.current_logfile)
662 elif next_step == self.PACKAGE_GENERATING or next_step == self.FAST_IMAGE_GENERATING:
663 # both PACKAGE_GENERATING and FAST_IMAGE_GENERATING share the same page
664 self.build_details_page.show_page(next_step)
666 elif next_step == self.PACKAGE_GENERATED:
667 self.configuration.initial_selected_packages = self.configuration.selected_packages
668 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
669 self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
671 self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
672 self.package_details_page.show_page(self.current_logfile)
674 elif next_step == self.IMAGE_GENERATING:
675 # after packages are generated, selected_packages need to
676 # be updated in package_model per selected_image in recipe_model
677 self.build_details_page.show_page(next_step)
679 elif next_step == self.IMAGE_GENERATED:
680 self.image_details_page.show_page(next_step)
682 elif next_step == self.MY_IMAGE_OPENED:
683 self.image_details_page.show_page(next_step)
685 self.previous_step = self.current_step
686 self.current_step = next_step
688 def set_user_config(self):
689 self.handler.init_cooker()
691 self.handler.set_bblayers(self.configuration.layers)
692 # set local configuration
693 self.handler.set_machine(self.configuration.curr_mach)
694 self.handler.set_package_format(self.configuration.curr_package_format)
695 self.handler.set_distro(self.configuration.curr_distro)
696 self.handler.set_dl_dir(self.configuration.dldir)
697 self.handler.set_sstate_dir(self.configuration.sstatedir)
698 self.handler.set_sstate_mirror(self.configuration.sstatemirror)
699 self.handler.set_pmake(self.configuration.pmake)
700 self.handler.set_bbthreads(self.configuration.bbthread)
701 self.handler.set_rootfs_size(self.configuration.image_rootfs_size)
702 self.handler.set_extra_size(self.configuration.image_extra_size)
703 self.handler.set_incompatible_license(self.configuration.incompat_license)
704 self.handler.set_sdk_machine(self.configuration.curr_sdk_machine)
705 self.handler.set_image_fstypes(self.configuration.image_fstypes)
706 self.handler.set_extra_config(self.configuration.extra_setting)
707 self.handler.set_extra_inherit("packageinfo")
708 self.handler.set_extra_inherit("image_types")
710 if self.configuration.enable_proxy == True:
711 self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
712 self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
713 self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
714 self.handler.set_git_proxy(self.configuration.combine_host_only("git"), self.configuration.combine_port_only("git"))
715 self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
716 elif self.configuration.enable_proxy == False:
717 self.handler.set_http_proxy("")
718 self.handler.set_https_proxy("")
719 self.handler.set_ftp_proxy("")
720 self.handler.set_git_proxy("", "")
721 self.handler.set_cvs_proxy("", "")
723 def update_recipe_model(self, selected_image, selected_recipes):
724 self.recipe_model.set_selected_image(selected_image)
725 self.recipe_model.set_selected_recipes(selected_recipes)
727 def update_package_model(self, selected_packages):
728 left = self.package_model.set_selected_packages(selected_packages)
729 self.configuration.selected_packages += left
731 def update_configuration_parameters(self, params):
733 self.configuration.update(params)
734 self.parameters.update(params)
737 self.configuration.curr_mach = ""
738 self.configuration.clear_selection()
739 self.image_configuration_page.switch_machine_combo()
740 self.switch_page(self.MACHINE_SELECTION)
743 def handler_config_updated_cb(self, handler, which, values):
744 if which == "distro":
745 self.parameters.all_distros = values
746 elif which == "machine":
747 self.parameters.all_machines = values
748 self.image_configuration_page.update_machine_combo()
749 elif which == "machine-sdk":
750 self.parameters.all_sdk_machines = values
752 def handler_package_formats_updated_cb(self, handler, formats):
753 self.parameters.all_package_formats = formats
755 def handler_command_succeeded_cb(self, handler, initcmd):
756 if initcmd == self.handler.GENERATE_CONFIGURATION:
757 self.update_configuration_parameters(self.get_parameters_sync())
759 elif initcmd == self.handler.SANITY_CHECK:
760 self.image_configuration_page.switch_machine_combo()
761 elif initcmd in [self.handler.GENERATE_RECIPES,
762 self.handler.GENERATE_PACKAGES,
763 self.handler.GENERATE_IMAGE]:
764 self.update_configuration_parameters(self.get_parameters_sync())
765 self.request_package_info_async()
766 elif initcmd == self.handler.POPULATE_PACKAGEINFO:
767 if self.current_step == self.RCPPKGINFO_POPULATING:
768 self.switch_page(self.RCPPKGINFO_POPULATED)
769 self.rcppkglist_populated()
772 self.rcppkglist_populated()
773 if self.current_step == self.FAST_IMAGE_GENERATING:
774 self.generate_image_async(True)
776 def show_error_dialog(self, msg):
777 lbl = "<b>Error</b>\n"
778 lbl = lbl + "%s\n\n" % glib.markup_escape_text(msg)
779 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
780 button = dialog.add_button("Close", gtk.RESPONSE_OK)
781 HobButton.style_button(button)
782 response = dialog.run()
785 def handler_command_failed_cb(self, handler, msg):
787 self.show_error_dialog(msg)
790 def handler_sanity_failed_cb(self, handler, msg):
791 msg = msg.replace("your local.conf", "Settings")
792 self.show_error_dialog(msg)
795 def window_sensitive(self, sensitive):
796 self.image_configuration_page.machine_combo.set_sensitive(sensitive)
797 self.image_configuration_page.machine_combo.child.set_sensitive(sensitive)
798 self.image_configuration_page.image_combo.set_sensitive(sensitive)
799 self.image_configuration_page.image_combo.child.set_sensitive(sensitive)
800 self.image_configuration_page.layer_button.set_sensitive(sensitive)
801 self.image_configuration_page.layer_info_icon.set_sensitive(sensitive)
802 self.image_configuration_page.toolbar.set_sensitive(sensitive)
803 self.image_configuration_page.config_build_button.set_sensitive(sensitive)
805 self.recipe_details_page.set_sensitive(sensitive)
806 self.package_details_page.set_sensitive(sensitive)
807 self.build_details_page.set_sensitive(sensitive)
808 self.image_details_page.set_sensitive(sensitive)
811 self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
813 self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
814 self.sensitive = sensitive
817 def handler_generating_data_cb(self, handler):
818 self.window_sensitive(False)
820 def handler_data_generated_cb(self, handler):
821 self.window_sensitive(True)
823 def rcppkglist_populated(self):
824 selected_image = self.configuration.selected_image
825 selected_recipes = self.configuration.selected_recipes[:]
826 selected_packages = self.configuration.selected_packages[:]
828 self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
829 self.image_configuration_page.update_image_desc()
830 self.update_recipe_model(selected_image, selected_recipes)
831 self.update_package_model(selected_packages)
833 def recipelist_changed_cb(self, recipe_model):
834 self.recipe_details_page.refresh_selection()
836 def packagelist_changed_cb(self, package_model):
837 self.package_details_page.refresh_selection()
839 def handler_recipe_populated_cb(self, handler):
840 self.image_configuration_page.update_progress_bar("Populated recipes", 0.99)
842 def handler_package_populated_cb(self, handler):
843 self.image_configuration_page.update_progress_bar("Populated packages", 1.0)
845 def handler_parsing_started_cb(self, handler, message):
846 if self.current_step != self.RCPPKGINFO_POPULATING:
850 if message["eventname"] == "TreeDataPreparationStarted":
851 fraction = 0.6 + fraction
852 self.image_configuration_page.stop_button.set_sensitive(False)
854 self.image_configuration_page.stop_button.set_sensitive(True)
856 self.image_configuration_page.update_progress_bar(message["title"], fraction)
858 def handler_parsing_cb(self, handler, message):
859 if self.current_step != self.RCPPKGINFO_POPULATING:
862 fraction = message["current"] * 1.0/message["total"]
863 if message["eventname"] == "TreeDataPreparationProgress":
864 fraction = 0.6 + 0.38 * fraction
866 fraction = 0.6 * fraction
867 self.image_configuration_page.update_progress_bar(message["title"], fraction)
869 def handler_parsing_completed_cb(self, handler, message):
870 if self.current_step != self.RCPPKGINFO_POPULATING:
873 if message["eventname"] == "TreeDataPreparationCompleted":
877 self.image_configuration_page.update_progress_bar(message["title"], fraction)
879 def handler_build_started_cb(self, running_build):
880 if self.current_step == self.FAST_IMAGE_GENERATING:
882 elif self.current_step == self.IMAGE_GENERATING:
883 if self.previous_step == self.FAST_IMAGE_GENERATING:
887 elif self.current_step == self.PACKAGE_GENERATING:
889 self.build_details_page.update_progress_bar("Build Started: ", fraction)
890 self.build_details_page.show_configurations(self.configuration, self.parameters)
892 def build_succeeded(self):
893 if self.current_step == self.FAST_IMAGE_GENERATING:
895 elif self.current_step == self.IMAGE_GENERATING:
897 self.parameters.image_names = []
898 selected_image = self.recipe_model.get_selected_image()
899 if selected_image == self.recipe_model.__custom_image__:
900 linkname = 'hob-image-' + self.configuration.curr_mach
902 linkname = selected_image + '-' + self.configuration.curr_mach
903 image_extension = self.get_image_extension()
904 for image_type in self.parameters.image_types:
905 if image_type in image_extension:
906 real_types = image_extension[image_type]
908 real_types = [image_type]
909 for real_image_type in real_types:
910 linkpath = self.parameters.image_addr + '/' + linkname + '.' + real_image_type
911 if os.path.exists(linkpath):
912 self.parameters.image_names.append(os.readlink(linkpath))
913 elif self.current_step == self.PACKAGE_GENERATING:
915 self.build_details_page.update_progress_bar("Build Completed: ", fraction)
916 self.handler.build_succeeded_async()
917 self.stopping = False
919 if self.current_step == self.PACKAGE_GENERATING:
920 self.switch_page(self.PACKAGE_GENERATED)
921 elif self.current_step == self.IMAGE_GENERATING:
922 self.switch_page(self.IMAGE_GENERATED)
924 def build_failed(self):
927 message = "Build stopped: "
928 fraction = self.build_details_page.progress_bar.get_fraction()
930 fail_to_next_edit = ""
931 if self.current_step == self.FAST_IMAGE_GENERATING:
932 fail_to_next_edit = "image configuration"
934 elif self.current_step == self.IMAGE_GENERATING:
935 if self.previous_step == self.FAST_IMAGE_GENERATING:
936 fail_to_next_edit = "image configuration"
938 fail_to_next_edit = "packages"
940 elif self.current_step == self.PACKAGE_GENERATING:
941 fail_to_next_edit = "recipes"
943 self.build_details_page.show_fail_page(fail_to_next_edit.split(' ')[0], fail_to_next_edit)
945 message = "Build failed: "
946 self.build_details_page.update_progress_bar(message, fraction, status)
947 self.build_details_page.show_back_button()
948 self.build_details_page.hide_stop_button()
949 self.handler.build_failed_async()
950 self.stopping = False
952 def handler_build_succeeded_cb(self, running_build):
953 if not self.stopping:
954 self.build_succeeded()
959 def handler_build_failed_cb(self, running_build):
962 def handler_build_aborted_cb(self, running_build):
965 def handler_no_provider_cb(self, running_build, msg):
966 dialog = CrumbsMessageDialog(self, glib.markup_escape_text(msg), gtk.STOCK_DIALOG_INFO)
967 button = dialog.add_button("Close", gtk.RESPONSE_OK)
968 HobButton.style_button(button)
973 def handler_task_started_cb(self, running_build, message):
974 fraction = message["current"] * 1.0/message["total"]
975 title = "Build packages"
976 if self.current_step == self.FAST_IMAGE_GENERATING:
977 if message["eventname"] == "sceneQueueTaskStarted":
978 fraction = 0.27 * fraction
979 elif message["eventname"] == "runQueueTaskStarted":
980 fraction = 0.27 + 0.63 * fraction
981 elif self.current_step == self.IMAGE_GENERATING:
982 title = "Build image"
983 if self.previous_step == self.FAST_IMAGE_GENERATING:
984 if message["eventname"] == "sceneQueueTaskStarted":
985 fraction = 0.27 + 0.63 + 0.03 * fraction
986 elif message["eventname"] == "runQueueTaskStarted":
987 fraction = 0.27 + 0.63 + 0.03 + 0.07 * fraction
989 if message["eventname"] == "sceneQueueTaskStarted":
990 fraction = 0.2 * fraction
991 elif message["eventname"] == "runQueueTaskStarted":
992 fraction = 0.2 + 0.8 * fraction
993 elif self.current_step == self.PACKAGE_GENERATING:
994 if message["eventname"] == "sceneQueueTaskStarted":
995 fraction = 0.2 * fraction
996 elif message["eventname"] == "runQueueTaskStarted":
997 fraction = 0.2 + 0.8 * fraction
998 self.build_details_page.update_progress_bar(title + ": ", fraction)
999 self.build_details_page.update_build_status(message["current"], message["total"], message["task"])
1001 def handler_build_failure_cb(self, running_build):
1002 self.build_details_page.show_issues()
1004 def handler_build_log_cb(self, running_build, func, obj):
1005 if hasattr(self.logger, func):
1006 getattr(self.logger, func)(obj)
1008 def destroy_window_cb(self, widget, event):
1009 if not self.sensitive:
1011 lbl = "<b>Do you really want to exit the Hob image creator?</b>"
1012 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1013 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1014 HobAltButton.style_button(button)
1015 button = dialog.add_button("Exit Hob", gtk.RESPONSE_YES)
1016 HobButton.style_button(button)
1017 dialog.set_default_response(gtk.RESPONSE_YES)
1018 response = dialog.run()
1020 if response == gtk.RESPONSE_YES:
1026 def build_packages(self):
1027 _, all_recipes = self.recipe_model.get_selected_recipes()
1029 lbl = "<b>No selections made</b>\nYou have not made any selections"
1030 lbl = lbl + " so there isn't anything to bake at this time."
1031 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1032 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1033 HobButton.style_button(button)
1037 self.generate_packages_async(True)
1039 def build_image(self):
1040 selected_packages = self.package_model.get_selected_packages()
1041 if not selected_packages:
1042 lbl = "<b>No selections made</b>\nYou have not made any selections"
1043 lbl = lbl + " so there isn't anything to bake at this time."
1044 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1045 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1046 HobButton.style_button(button)
1050 self.generate_image_async(True)
1052 def just_bake(self):
1053 selected_image = self.recipe_model.get_selected_image()
1054 selected_packages = self.package_model.get_selected_packages() or []
1056 # If no base image and no selected packages don't build anything
1057 if not (selected_packages or selected_image != self.recipe_model.__custom_image__):
1058 lbl = "<b>No selections made</b>\nYou have not made any selections"
1059 lbl = lbl + " so there isn't anything to bake at this time."
1060 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1061 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1062 HobButton.style_button(button)
1067 self.fast_generate_image_async(True)
1069 def show_binb_dialog(self, binb):
1070 markup = "<b>Brought in by:</b>\n%s" % binb
1071 ptip = PersistentTooltip(markup, self)
1075 def show_layer_selection_dialog(self):
1076 dialog = LayerSelectionDialog(title = "Layers",
1077 layers = copy.deepcopy(self.configuration.layers),
1078 all_layers = self.parameters.all_layers,
1080 flags = gtk.DIALOG_MODAL
1081 | gtk.DIALOG_DESTROY_WITH_PARENT
1082 | gtk.DIALOG_NO_SEPARATOR)
1083 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1084 HobAltButton.style_button(button)
1085 button = dialog.add_button("OK", gtk.RESPONSE_YES)
1086 HobButton.style_button(button)
1087 response = dialog.run()
1088 if response == gtk.RESPONSE_YES:
1089 self.configuration.layers = dialog.layers
1090 self.save_defaults() # remember layers
1092 if dialog.layers_changed:
1093 self.update_config_async()
1096 def show_load_template_dialog(self):
1097 dialog = gtk.FileChooserDialog("Load Template Files", self,
1098 gtk.FILE_CHOOSER_ACTION_OPEN)
1099 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1100 HobAltButton.style_button(button)
1101 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1102 HobButton.style_button(button)
1103 filter = gtk.FileFilter()
1104 filter.set_name("Hob Files")
1105 filter.add_pattern("*.hob")
1106 dialog.add_filter(filter)
1108 response = dialog.run()
1110 if response == gtk.RESPONSE_YES:
1111 path = dialog.get_filename()
1113 return response == gtk.RESPONSE_YES, path
1115 def show_save_template_dialog(self):
1116 dialog = gtk.FileChooserDialog("Save Template Files", self,
1117 gtk.FILE_CHOOSER_ACTION_SAVE)
1118 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1119 HobAltButton.style_button(button)
1120 button = dialog.add_button("Save", gtk.RESPONSE_YES)
1121 HobButton.style_button(button)
1122 dialog.set_current_name("hob")
1123 response = dialog.run()
1124 if response == gtk.RESPONSE_YES:
1125 path = dialog.get_filename()
1126 self.save_template(path)
1129 def get_image_extension(self):
1130 image_extension = {}
1131 for type in self.parameters.image_types:
1132 ext = self.handler.runCommand(["getVariable", "IMAGE_EXTENSION_%s" % type])
1134 image_extension[type] = ext.split(' ')
1136 return image_extension
1138 def show_load_my_images_dialog(self):
1139 image_extension = self.get_image_extension()
1140 dialog = ImageSelectionDialog(self.parameters.image_addr, self.parameters.image_types,
1141 "Open My Images", self,
1142 gtk.FILE_CHOOSER_ACTION_SAVE, None,
1144 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1145 HobAltButton.style_button(button)
1146 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1147 HobButton.style_button(button)
1148 response = dialog.run()
1149 if response == gtk.RESPONSE_YES:
1150 if not dialog.image_names:
1151 lbl = "<b>No selections made</b>\nYou have not made any selections"
1152 crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1153 button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
1154 HobButton.style_button(button)
1156 crumbs_dialog.destroy()
1160 self.parameters.image_addr = dialog.image_folder
1161 self.parameters.image_names = dialog.image_names[:]
1162 self.switch_page(self.MY_IMAGE_OPENED)
1166 def show_adv_settings_dialog(self):
1167 dialog = AdvancedSettingDialog(title = "Settings",
1168 configuration = copy.deepcopy(self.configuration),
1169 all_image_types = self.parameters.image_types,
1170 all_package_formats = self.parameters.all_package_formats,
1171 all_distros = self.parameters.all_distros,
1172 all_sdk_machines = self.parameters.all_sdk_machines,
1173 max_threads = self.parameters.max_threads,
1175 flags = gtk.DIALOG_MODAL
1176 | gtk.DIALOG_DESTROY_WITH_PARENT
1177 | gtk.DIALOG_NO_SEPARATOR)
1178 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1179 HobAltButton.style_button(button)
1180 button = dialog.add_button("Save", gtk.RESPONSE_YES)
1181 HobButton.style_button(button)
1182 response = dialog.run()
1183 settings_changed = False
1184 if response == gtk.RESPONSE_YES:
1185 self.configuration = dialog.configuration
1186 self.save_defaults() # remember settings
1187 settings_changed = dialog.settings_changed
1189 return response == gtk.RESPONSE_YES, settings_changed
1191 def reparse_post_adv_settings(self):
1192 if not self.configuration.curr_mach:
1193 self.update_config_async()
1195 self.configuration.clear_selection()
1196 # DO reparse recipes
1197 self.populate_recipe_package_info_async()
1199 def deploy_image(self, image_name):
1201 lbl = "<b>Please select an image to deploy.</b>"
1202 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1203 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1204 HobButton.style_button(button)
1209 image_path = os.path.join(self.parameters.image_addr, image_name)
1210 dialog = DeployImageDialog(title = "Usb Image Maker",
1211 image_path = image_path,
1213 flags = gtk.DIALOG_MODAL
1214 | gtk.DIALOG_DESTROY_WITH_PARENT
1215 | gtk.DIALOG_NO_SEPARATOR)
1216 button = dialog.add_button("Close", gtk.RESPONSE_NO)
1217 HobAltButton.style_button(button)
1218 button = dialog.add_button("Make usb image", gtk.RESPONSE_YES)
1219 HobButton.style_button(button)
1220 response = dialog.run()
1223 def show_load_kernel_dialog(self):
1224 dialog = gtk.FileChooserDialog("Load Kernel Files", self,
1225 gtk.FILE_CHOOSER_ACTION_SAVE)
1226 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1227 HobAltButton.style_button(button)
1228 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1229 HobButton.style_button(button)
1230 filter = gtk.FileFilter()
1231 filter.set_name("Kernel Files")
1232 filter.add_pattern("*.bin")
1233 dialog.add_filter(filter)
1235 dialog.set_current_folder(self.parameters.image_addr)
1237 response = dialog.run()
1239 if response == gtk.RESPONSE_YES:
1240 kernel_path = dialog.get_filename()
1246 def runqemu_image(self, image_name, kernel_name):
1247 if not image_name or not kernel_name:
1248 lbl = "<b>Please select an %s to launch in QEMU.</b>" % ("kernel" if image_name else "image")
1249 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1250 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1251 HobButton.style_button(button)
1256 kernel_path = os.path.join(self.parameters.image_addr, kernel_name)
1257 image_path = os.path.join(self.parameters.image_addr, image_name)
1259 source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
1260 tmp_path = self.parameters.tmpdir
1261 cmdline = bb.ui.crumbs.utils.which_terminal()
1262 if os.path.exists(image_path) and os.path.exists(kernel_path) \
1263 and os.path.exists(source_env_path) and os.path.exists(tmp_path) \
1265 cmdline += "\' bash -c \"export OE_TMPDIR=" + tmp_path + "; "
1266 cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
1267 cmdline += "runqemu " + kernel_path + " " + image_path + "\"\'"
1268 subprocess.Popen(shlex.split(cmdline))
1270 lbl = "<b>Path error</b>\nOne of your paths is wrong,"
1271 lbl = lbl + " please make sure the following paths exist:\n"
1272 lbl = lbl + "image path:" + image_path + "\n"
1273 lbl = lbl + "kernel path:" + kernel_path + "\n"
1274 lbl = lbl + "source environment path:" + source_env_path + "\n"
1275 lbl = lbl + "tmp path: " + tmp_path + "."
1276 lbl = lbl + "You may be missing either xterm or vte for terminal services."
1277 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
1278 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1279 HobButton.style_button(button)
1283 def show_packages(self, ask=True):
1284 _, selected_recipes = self.recipe_model.get_selected_recipes()
1285 if selected_recipes and ask:
1286 lbl = "<b>Package list may be incomplete!</b>\nDo you want to build selected recipes"
1287 lbl = lbl + " to get a full list or just view the existing packages?"
1288 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1289 button = dialog.add_button("View packages", gtk.RESPONSE_NO)
1290 HobAltButton.style_button(button)
1291 button = dialog.add_button("Build packages", gtk.RESPONSE_YES)
1292 HobButton.style_button(button)
1293 dialog.set_default_response(gtk.RESPONSE_YES)
1294 response = dialog.run()
1296 if response == gtk.RESPONSE_YES:
1297 self.generate_packages_async(True)
1299 self.switch_page(self.PACKAGE_SELECTION)
1301 self.switch_page(self.PACKAGE_SELECTION)
1303 def show_recipes(self):
1304 self.switch_page(self.RECIPE_SELECTION)
1306 def show_image_details(self):
1307 self.switch_page(self.IMAGE_GENERATED)
1309 def show_configuration(self):
1310 self.switch_page(self.BASEIMG_SELECTED)
1312 def stop_build(self):
1314 lbl = "<b>Force Stop build?</b>\nYou've already selected Stop once,"
1315 lbl = lbl + " would you like to 'Force Stop' the build?\n\n"
1316 lbl = lbl + "This will stop the build as quickly as possible but may"
1317 lbl = lbl + " well leave your build directory in an unusable state"
1318 lbl = lbl + " that requires manual steps to fix.\n"
1319 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
1320 button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
1321 HobAltButton.style_button(button)
1322 button = dialog.add_button("Force Stop", gtk.RESPONSE_YES)
1323 HobButton.style_button(button)
1325 lbl = "<b>Stop build?</b>\n\nAre you sure you want to stop this"
1326 lbl = lbl + " build?\n\n'Force Stop' will stop the build as quickly as"
1327 lbl = lbl + " possible but may well leave your build directory in an"
1328 lbl = lbl + " unusable state that requires manual steps to fix.\n\n"
1329 lbl = lbl + "'Stop' will stop the build as soon as all in"
1330 lbl = lbl + " progress build tasks are finished. However if a"
1331 lbl = lbl + " lengthy compilation phase is in progress this may take"
1332 lbl = lbl + " some time."
1333 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
1334 button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
1335 HobAltButton.style_button(button)
1336 button = dialog.add_button("Stop", gtk.RESPONSE_OK)
1337 HobAltButton.style_button(button)
1338 button = dialog.add_button("Force Stop", gtk.RESPONSE_YES)
1339 HobButton.style_button(button)
1340 response = dialog.run()
1342 if response != gtk.RESPONSE_CANCEL:
1343 self.stopping = True
1344 if response == gtk.RESPONSE_OK:
1345 self.cancel_build_sync()
1346 elif response == gtk.RESPONSE_YES:
1347 self.cancel_build_sync(True)
1349 def do_log(self, consolelogfile = None):
1351 bb.utils.mkdirhier(os.path.dirname(consolelogfile))
1353 self.logger.removeHandler(self.consolelog)
1354 self.consolelog = None
1355 self.consolelog = logging.FileHandler(consolelogfile)
1356 bb.msg.addDefaultlogFilter(self.consolelog)
1357 format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
1358 self.consolelog.setFormatter(format)
1360 self.logger.addHandler(self.consolelog)