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.
31 from bb.ui.crumbs.template import TemplateMgr
32 from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
33 from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
34 from bb.ui.crumbs.packageselectionpage import PackageSelectionPage
35 from bb.ui.crumbs.builddetailspage import BuildDetailsPage
36 from bb.ui.crumbs.imagedetailspage import ImageDetailsPage
37 from bb.ui.crumbs.hobwidget import hwc, HobButton, HobAltButton, hcc
38 from bb.ui.crumbs.hig import CrumbsMessageDialog, ImageSelectionDialog, \
39 AdvancedSettingDialog, LayerSelectionDialog, \
41 from bb.ui.crumbs.persistenttooltip import PersistentTooltip
42 import bb.ui.crumbs.utils
47 '''Represents the data structure of configuration.'''
50 def parse_proxy_string(cls, proxy):
51 pattern = "^\s*((http|https|ftp|git|cvs)://)?((\S+):(\S+)@)?(\S+):(\d+)/?"
52 match = re.search(pattern, proxy)
54 return match.group(2), match.group(4), match.group(5), match.group(6), match.group(7)
56 return None, None, None, "", ""
59 def make_host_string(cls, prot, user, passwd, host, default_prot=""):
60 if host == None or host == "":
65 if user != None and user != "":
66 if prot == None or prot == "":
68 return prot + "://" + user + ":" + passwd + "@" + host
70 if prot == None or prot == "":
73 return prot + "://" + host
76 def make_port_string(cls, port):
81 def make_proxy_string(cls, prot, user, passwd, host, port, default_prot=""):
82 if host == None or host == "" or port == None or port == "":
85 return Configuration.make_host_string(prot, user, passwd, host, default_prot) + ":" + Configuration.make_port_string(port)
91 self.dldir = self.sstatedir = self.sstatemirror = ""
92 self.pmake = self.bbthread = 0
93 self.curr_package_format = ""
94 self.image_rootfs_size = self.image_extra_size = 0
95 self.image_overhead_factor = 1
96 self.incompat_license = ""
97 self.curr_sdk_machine = ""
98 self.conf_version = self.lconf_version = ""
99 self.extra_setting = {}
100 self.toolchain_build = False
101 self.image_fstypes = ""
104 # image/recipes/packages
105 self.clear_selection()
107 self.user_selected_packages = []
109 self.default_task = "build"
112 self.enable_proxy = None
113 self.same_proxy = False
115 "http" : [None, None, None, "", ""], # protocol : [prot, user, passwd, host, port]
116 "https" : [None, None, None, "", ""],
117 "ftp" : [None, None, None, "", ""],
118 "git" : [None, None, None, "", ""],
119 "cvs" : [None, None, None, "", ""],
122 def clear_selection(self):
123 self.selected_image = None
124 self.selected_recipes = []
125 self.selected_packages = []
127 def split_proxy(self, protocol, proxy):
129 prot, user, passwd, host, port = Configuration.parse_proxy_string(proxy)
135 self.proxies[protocol] = entry
137 def combine_proxy(self, protocol):
138 entry = self.proxies[protocol]
139 return Configuration.make_proxy_string(entry[0], entry[1], entry[2], entry[3], entry[4], protocol)
141 def combine_host_only(self, protocol):
142 entry = self.proxies[protocol]
143 return Configuration.make_host_string(entry[0], entry[1], entry[2], entry[3], protocol)
145 def combine_port_only(self, protocol):
146 entry = self.proxies[protocol]
147 return Configuration.make_port_string(entry[4])
149 def update(self, params):
151 self.curr_distro = params["distro"]
152 self.dldir = params["dldir"]
153 self.sstatedir = params["sstatedir"]
154 self.sstatemirror = params["sstatemirror"]
155 self.pmake = int(params["pmake"].split()[1])
156 self.bbthread = params["bbthread"]
157 self.curr_package_format = " ".join(params["pclass"].split("package_")).strip()
158 self.image_rootfs_size = params["image_rootfs_size"]
159 self.image_extra_size = params["image_extra_size"]
160 self.image_overhead_factor = params['image_overhead_factor']
161 self.incompat_license = params["incompat_license"]
162 self.curr_sdk_machine = params["sdk_machine"]
163 self.conf_version = params["conf_version"]
164 self.lconf_version = params["lconf_version"]
165 self.image_fstypes = params["image_fstypes"]
166 # self.extra_setting/self.toolchain_build
168 self.layers = params["layer"].split()
169 self.default_task = params["default_task"]
172 self.enable_proxy = params["http_proxy"] != "" or params["https_proxy"] != "" or params["ftp_proxy"] != "" \
173 or params["git_proxy_host"] != "" or params["git_proxy_port"] != "" \
174 or params["cvs_proxy_host"] != "" or params["cvs_proxy_port"] != ""
175 self.split_proxy("http", params["http_proxy"])
176 self.split_proxy("https", params["https_proxy"])
177 self.split_proxy("ftp", params["ftp_proxy"])
178 self.split_proxy("git", params["git_proxy_host"] + ":" + params["git_proxy_port"])
179 self.split_proxy("cvs", params["cvs_proxy_host"] + ":" + params["cvs_proxy_port"])
181 def load(self, template):
182 self.curr_mach = template.getVar("MACHINE")
183 self.curr_package_format = " ".join(template.getVar("PACKAGE_CLASSES").split("package_")).strip()
184 self.curr_distro = template.getVar("DISTRO")
185 self.dldir = template.getVar("DL_DIR")
186 self.sstatedir = template.getVar("SSTATE_DIR")
187 self.sstatemirror = template.getVar("SSTATE_MIRROR")
189 self.pmake = int(template.getVar("PARALLEL_MAKE").split()[1])
193 self.bbthread = int(template.getVar("BB_NUMBER_THREADS"))
197 self.image_rootfs_size = int(template.getVar("IMAGE_ROOTFS_SIZE"))
201 self.image_extra_size = int(template.getVar("IMAGE_EXTRA_SPACE"))
204 # image_overhead_factor is read-only.
205 self.incompat_license = template.getVar("INCOMPATIBLE_LICENSE")
206 self.curr_sdk_machine = template.getVar("SDKMACHINE")
207 self.conf_version = template.getVar("CONF_VERSION")
208 self.lconf_version = template.getVar("LCONF_VERSION")
209 self.extra_setting = eval(template.getVar("EXTRA_SETTING"))
210 self.toolchain_build = eval(template.getVar("TOOLCHAIN_BUILD"))
211 self.image_fstypes = template.getVar("IMAGE_FSTYPES")
213 self.layers = template.getVar("BBLAYERS").split()
214 # image/recipes/packages
215 self.selected_image = template.getVar("__SELECTED_IMAGE__")
216 self.selected_recipes = template.getVar("DEPENDS").split()
217 self.selected_packages = template.getVar("IMAGE_INSTALL").split()
219 self.enable_proxy = eval(template.getVar("enable_proxy"))
220 self.same_proxy = eval(template.getVar("use_same_proxy"))
221 self.split_proxy("http", template.getVar("http_proxy"))
222 self.split_proxy("https", template.getVar("https_proxy"))
223 self.split_proxy("ftp", template.getVar("ftp_proxy"))
224 self.split_proxy("git", template.getVar("GIT_PROXY_HOST") + ":" + template.getVar("GIT_PROXY_PORT"))
225 self.split_proxy("cvs", template.getVar("CVS_PROXY_HOST") + ":" + template.getVar("CVS_PROXY_PORT"))
227 def save(self, template, defaults=False):
228 template.setVar("VERSION", "%s" % hobVer)
230 template.setVar("BBLAYERS", " ".join(self.layers))
233 template.setVar("MACHINE", self.curr_mach)
234 template.setVar("DISTRO", self.curr_distro)
235 template.setVar("DL_DIR", self.dldir)
236 template.setVar("SSTATE_DIR", self.sstatedir)
237 template.setVar("SSTATE_MIRROR", self.sstatemirror)
238 template.setVar("PARALLEL_MAKE", "-j %s" % self.pmake)
239 template.setVar("BB_NUMBER_THREADS", self.bbthread)
240 template.setVar("PACKAGE_CLASSES", " ".join(["package_" + i for i in self.curr_package_format.split()]))
241 template.setVar("IMAGE_ROOTFS_SIZE", self.image_rootfs_size)
242 template.setVar("IMAGE_EXTRA_SPACE", self.image_extra_size)
243 template.setVar("INCOMPATIBLE_LICENSE", self.incompat_license)
244 template.setVar("SDKMACHINE", self.curr_sdk_machine)
245 template.setVar("CONF_VERSION", self.conf_version)
246 template.setVar("LCONF_VERSION", self.lconf_version)
247 template.setVar("EXTRA_SETTING", self.extra_setting)
248 template.setVar("TOOLCHAIN_BUILD", self.toolchain_build)
249 template.setVar("IMAGE_FSTYPES", self.image_fstypes)
251 # image/recipes/packages
252 template.setVar("__SELECTED_IMAGE__", self.selected_image)
253 template.setVar("DEPENDS", self.selected_recipes)
254 template.setVar("IMAGE_INSTALL", self.user_selected_packages)
256 template.setVar("enable_proxy", self.enable_proxy)
257 template.setVar("use_same_proxy", self.same_proxy)
258 template.setVar("http_proxy", self.combine_proxy("http"))
259 template.setVar("https_proxy", self.combine_proxy("https"))
260 template.setVar("ftp_proxy", self.combine_proxy("ftp"))
261 template.setVar("GIT_PROXY_HOST", self.combine_host_only("git"))
262 template.setVar("GIT_PROXY_PORT", self.combine_port_only("git"))
263 template.setVar("CVS_PROXY_HOST", self.combine_host_only("cvs"))
264 template.setVar("CVS_PROXY_PORT", self.combine_port_only("cvs"))
267 '''Represents other variables like available machines, etc.'''
271 self.max_threads = 65535
274 self.image_types = []
275 self.runnable_image_types = []
276 self.runnable_machine_patterns = []
277 self.deployable_image_types = []
280 self.all_machines = []
281 self.all_package_formats = []
282 self.all_distros = []
283 self.all_sdk_machines = []
285 self.image_names = []
286 self.image_white_pattern = ""
287 self.image_black_pattern = ""
289 # for build log to show
291 self.target_arch = ""
293 self.distro_version = ""
294 self.tune_pkgarch = ""
296 def update(self, params):
297 self.max_threads = params["max_threads"]
298 self.core_base = params["core_base"]
299 self.image_addr = params["image_addr"]
300 self.image_types = params["image_types"].split()
301 self.runnable_image_types = params["runnable_image_types"].split()
302 self.runnable_machine_patterns = params["runnable_machine_patterns"].split()
303 self.deployable_image_types = params["deployable_image_types"].split()
304 self.tmpdir = params["tmpdir"]
305 self.image_white_pattern = params["image_white_pattern"]
306 self.image_black_pattern = params["image_black_pattern"]
307 self.kernel_image_type = params["kernel_image_type"]
308 # for build log to show
309 self.bb_version = params["bb_version"]
310 self.target_arch = params["target_arch"]
311 self.target_os = params["target_os"]
312 self.distro_version = params["distro_version"]
313 self.tune_pkgarch = params["tune_pkgarch"]
315 def hob_conf_filter(fn, data):
316 if fn.endswith("/local.conf"):
317 distro = data.getVar("DISTRO_HOB")
319 if distro != "defaultsetup":
320 data.setVar("DISTRO", distro)
322 data.delVar("DISTRO")
324 keys = ["MACHINE_HOB", "SDKMACHINE_HOB", "PACKAGE_CLASSES_HOB", \
325 "BB_NUMBER_THREADS_HOB", "PARALLEL_MAKE_HOB", "DL_DIR_HOB", \
326 "SSTATE_DIR_HOB", "SSTATE_MIRROR_HOB", "INCOMPATIBLE_LICENSE_HOB"]
328 var_hob = data.getVar(key)
330 data.setVar(key.split("_HOB")[0], var_hob)
333 if fn.endswith("/bblayers.conf"):
334 layers = data.getVar("BBLAYERS_HOB")
336 data.setVar("BBLAYERS", layers)
339 class Builder(gtk.Window):
342 RCPPKGINFO_POPULATING,
343 RCPPKGINFO_POPULATED,
349 FAST_IMAGE_GENERATING,
354 END_NOOP) = range(14)
356 (IMAGE_CONFIGURATION,
364 MACHINE_SELECTION : IMAGE_CONFIGURATION,
365 RCPPKGINFO_POPULATING : IMAGE_CONFIGURATION,
366 RCPPKGINFO_POPULATED : IMAGE_CONFIGURATION,
367 BASEIMG_SELECTED : IMAGE_CONFIGURATION,
368 RECIPE_SELECTION : RECIPE_DETAILS,
369 PACKAGE_GENERATING : BUILD_DETAILS,
370 PACKAGE_GENERATED : PACKAGE_DETAILS,
371 PACKAGE_SELECTION : PACKAGE_DETAILS,
372 FAST_IMAGE_GENERATING : BUILD_DETAILS,
373 IMAGE_GENERATING : BUILD_DETAILS,
374 IMAGE_GENERATED : IMAGE_DETAILS,
375 MY_IMAGE_OPENED : IMAGE_DETAILS,
380 def interpret_markup(cls, msg):
381 msg = msg.replace('&', '&')
382 msg = msg.replace('<', '<')
383 msg = msg.replace('>', '>')
384 msg = msg.replace('"', '"')
385 msg = msg.replace("'", "´")
388 def __init__(self, hobHandler, recipe_model, package_model):
389 super(Builder, self).__init__()
391 self.hob_image = "hob-image"
392 self.hob_toolchain = "hob-toolchain"
395 self.handler = hobHandler
400 self.logger = logging.getLogger("BitBake")
401 self.consolelog = None
402 self.current_logfile = None
404 # configuration and parameters
405 self.configuration = Configuration()
406 self.parameters = Parameters()
409 self.current_step = None
410 self.previous_step = None
412 self.stopping = False
414 # recipe model and package model
415 self.recipe_model = recipe_model
416 self.package_model = package_model
418 # Indicate whether user has customized the image
419 self.customized = False
421 # Indicate whether the UI is working
422 self.sensitive = True
424 # create visual elements
425 self.create_visual_elements()
427 # connect the signals to functions
428 self.connect("delete-event", self.destroy_window_cb)
429 self.recipe_model.connect ("recipe-selection-changed", self.recipelist_changed_cb)
430 self.package_model.connect("package-selection-changed", self.packagelist_changed_cb)
431 self.handler.connect("config-updated", self.handler_config_updated_cb)
432 self.handler.connect("package-formats-updated", self.handler_package_formats_updated_cb)
433 self.handler.connect("parsing-started", self.handler_parsing_started_cb)
434 self.handler.connect("parsing", self.handler_parsing_cb)
435 self.handler.connect("parsing-completed", self.handler_parsing_completed_cb)
436 self.handler.build.connect("build-started", self.handler_build_started_cb)
437 self.handler.build.connect("build-succeeded", self.handler_build_succeeded_cb)
438 self.handler.build.connect("build-failed", self.handler_build_failed_cb)
439 self.handler.build.connect("build-aborted", self.handler_build_aborted_cb)
440 self.handler.build.connect("task-started", self.handler_task_started_cb)
441 self.handler.build.connect("log-error", self.handler_build_failure_cb)
442 self.handler.build.connect("log", self.handler_build_log_cb)
443 self.handler.build.connect("no-provider", self.handler_no_provider_cb)
444 self.handler.connect("generating-data", self.handler_generating_data_cb)
445 self.handler.connect("data-generated", self.handler_data_generated_cb)
446 self.handler.connect("command-succeeded", self.handler_command_succeeded_cb)
447 self.handler.connect("command-failed", self.handler_command_failed_cb)
448 self.handler.connect("sanity-failed", self.handler_sanity_failed_cb)
449 self.handler.connect("recipe-populated", self.handler_recipe_populated_cb)
450 self.handler.connect("package-populated", self.handler_package_populated_cb)
452 self.handler.set_config_filter(hob_conf_filter)
454 self.initiate_new_build_async()
456 def create_visual_elements(self):
457 self.set_title("Hob")
458 self.set_icon_name("applications-development")
459 self.set_resizable(True)
460 window_width = self.get_screen().get_width()
461 window_height = self.get_screen().get_height()
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 fast_generate_image_async(self, log = False):
523 self.switch_page(self.FAST_IMAGE_GENERATING)
525 self.current_logfile = self.handler.get_logfile()
526 self.do_log(self.current_logfile)
528 _, all_recipes = self.recipe_model.get_selected_recipes()
529 self.set_user_config()
530 self.handler.reset_build()
531 self.handler.generate_packages(all_recipes, self.configuration.default_task)
533 def generate_image_async(self, cont = False):
534 self.switch_page(self.IMAGE_GENERATING)
535 self.handler.reset_build()
537 self.current_logfile = self.handler.get_logfile()
538 self.do_log(self.current_logfile)
540 self.set_user_config()
541 toolchain_packages = []
542 if self.configuration.toolchain_build:
543 toolchain_packages = self.package_model.get_selected_packages_toolchain()
544 if self.configuration.selected_image == self.recipe_model.__custom_image__:
545 packages = self.package_model.get_selected_packages()
546 image = self.hob_image
549 image = self.configuration.selected_image
550 self.handler.generate_image(image,
554 self.configuration.default_task)
556 def get_parameters_sync(self):
557 return self.handler.get_parameters()
559 def request_package_info_async(self):
560 self.handler.request_package_info()
562 def cancel_build_sync(self, force=False):
563 self.handler.cancel_build(force)
565 def cancel_parse_sync(self):
566 self.handler.cancel_parse()
568 def load_template(self, path):
569 if not os.path.isfile(path):
572 self.template = TemplateMgr()
573 # check compatibility
574 tempVer = self.template.getVersion(path)
575 if not tempVer or int(tempVer) < hobVer:
576 self.template.destroy()
581 self.template.load(path)
582 self.configuration.load(self.template)
583 except Exception as e:
584 self.show_error_dialog("Hob Exception - %s" % (str(e)))
587 self.template.destroy()
590 for layer in self.configuration.layers:
591 if not os.path.exists(layer+'/conf/layer.conf'):
594 self.save_defaults() # remember layers and settings
595 self.update_config_async()
598 def save_template(self, path, defaults=False):
599 if path.rfind("/") == -1:
603 filename = path[path.rfind("/") + 1:len(path)]
604 path = path[0:path.rfind("/")]
606 self.template = TemplateMgr()
608 self.template.open(filename, path)
609 self.configuration.save(self.template, defaults)
612 except Exception as e:
613 self.show_error_dialog("Hob Exception - %s" % (str(e)))
616 self.template.destroy()
619 def save_defaults(self):
620 if not os.path.exists(".hob/"):
622 self.save_template(".hob/default", True)
624 def switch_page(self, next_step):
625 # Main Workflow (Business Logic)
626 self.nb.set_current_page(self.__step2page__[next_step])
628 if next_step == self.MACHINE_SELECTION: # init step
629 self.image_configuration_page.show_machine()
631 elif next_step == self.RCPPKGINFO_POPULATING:
632 # MACHINE CHANGED action or SETTINGS CHANGED
633 # show the progress bar
634 self.image_configuration_page.show_info_populating()
636 elif next_step == self.RCPPKGINFO_POPULATED:
637 self.image_configuration_page.show_info_populated()
639 elif next_step == self.BASEIMG_SELECTED:
640 self.image_configuration_page.show_baseimg_selected()
642 elif next_step == self.RECIPE_SELECTION:
643 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
644 self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.ALL)
646 self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.INCLUDED)
648 elif next_step == self.PACKAGE_SELECTION:
649 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
650 self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
652 self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
653 self.package_details_page.show_page(self.current_logfile)
656 elif next_step == self.PACKAGE_GENERATING or next_step == self.FAST_IMAGE_GENERATING:
657 # both PACKAGE_GENERATING and FAST_IMAGE_GENERATING share the same page
658 self.build_details_page.show_page(next_step)
660 elif next_step == self.PACKAGE_GENERATED:
661 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
662 self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
664 self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
665 self.package_details_page.show_page(self.current_logfile)
667 elif next_step == self.IMAGE_GENERATING:
668 # after packages are generated, selected_packages need to
669 # be updated in package_model per selected_image in recipe_model
670 self.build_details_page.show_page(next_step)
672 elif next_step == self.IMAGE_GENERATED:
673 self.image_details_page.show_page(next_step)
675 elif next_step == self.MY_IMAGE_OPENED:
676 self.image_details_page.show_page(next_step)
678 self.previous_step = self.current_step
679 self.current_step = next_step
681 def set_user_config(self):
682 self.handler.init_cooker()
684 self.handler.set_bblayers(self.configuration.layers)
685 # set local configuration
686 self.handler.set_machine(self.configuration.curr_mach)
687 self.handler.set_package_format(self.configuration.curr_package_format)
688 self.handler.set_distro(self.configuration.curr_distro)
689 self.handler.set_dl_dir(self.configuration.dldir)
690 self.handler.set_sstate_dir(self.configuration.sstatedir)
691 self.handler.set_sstate_mirror(self.configuration.sstatemirror)
692 self.handler.set_pmake(self.configuration.pmake)
693 self.handler.set_bbthreads(self.configuration.bbthread)
694 self.handler.set_rootfs_size(self.configuration.image_rootfs_size)
695 self.handler.set_extra_size(self.configuration.image_extra_size)
696 self.handler.set_incompatible_license(self.configuration.incompat_license)
697 self.handler.set_sdk_machine(self.configuration.curr_sdk_machine)
698 self.handler.set_image_fstypes(self.configuration.image_fstypes)
699 self.handler.set_extra_config(self.configuration.extra_setting)
700 self.handler.set_extra_inherit("packageinfo")
701 self.handler.set_extra_inherit("image_types")
703 if self.configuration.enable_proxy == True:
704 self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
705 self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
706 self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
707 self.handler.set_git_proxy(self.configuration.combine_host_only("git"), self.configuration.combine_port_only("git"))
708 self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
709 elif self.configuration.enable_proxy == False:
710 self.handler.set_http_proxy("")
711 self.handler.set_https_proxy("")
712 self.handler.set_ftp_proxy("")
713 self.handler.set_git_proxy("", "")
714 self.handler.set_cvs_proxy("", "")
716 def update_recipe_model(self, selected_image, selected_recipes):
717 self.recipe_model.set_selected_image(selected_image)
718 self.recipe_model.set_selected_recipes(selected_recipes)
720 def update_package_model(self, selected_packages):
721 left = self.package_model.set_selected_packages(selected_packages)
722 self.configuration.selected_packages += left
724 def update_configuration_parameters(self, params):
726 self.configuration.update(params)
727 self.parameters.update(params)
730 self.configuration.curr_mach = ""
731 self.configuration.clear_selection()
732 self.image_configuration_page.switch_machine_combo()
733 self.switch_page(self.MACHINE_SELECTION)
736 def handler_config_updated_cb(self, handler, which, values):
737 if which == "distro":
738 self.parameters.all_distros = values
739 elif which == "machine":
740 self.parameters.all_machines = values
741 self.image_configuration_page.update_machine_combo()
742 elif which == "machine-sdk":
743 self.parameters.all_sdk_machines = values
745 def handler_package_formats_updated_cb(self, handler, formats):
746 self.parameters.all_package_formats = formats
748 def handler_command_succeeded_cb(self, handler, initcmd):
749 if initcmd == self.handler.GENERATE_CONFIGURATION:
750 self.update_configuration_parameters(self.get_parameters_sync())
752 elif initcmd == self.handler.SANITY_CHECK:
753 self.image_configuration_page.switch_machine_combo()
754 elif initcmd in [self.handler.GENERATE_RECIPES,
755 self.handler.GENERATE_PACKAGES,
756 self.handler.GENERATE_IMAGE]:
757 self.update_configuration_parameters(self.get_parameters_sync())
758 self.request_package_info_async()
759 elif initcmd == self.handler.POPULATE_PACKAGEINFO:
760 if self.current_step == self.RCPPKGINFO_POPULATING:
761 self.switch_page(self.RCPPKGINFO_POPULATED)
762 self.rcppkglist_populated()
765 self.rcppkglist_populated()
766 if self.current_step == self.FAST_IMAGE_GENERATING:
767 self.generate_image_async(True)
769 def show_error_dialog(self, msg):
770 lbl = "<b>Error</b>\n"
771 lbl = lbl + "%s\n\n" % Builder.interpret_markup(msg)
772 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
773 button = dialog.add_button("Close", gtk.RESPONSE_OK)
774 HobButton.style_button(button)
775 response = dialog.run()
778 def handler_command_failed_cb(self, handler, msg):
780 self.show_error_dialog(msg)
783 def handler_sanity_failed_cb(self, handler, msg):
784 msg = msg.replace("your local.conf", "Settings")
785 self.show_error_dialog(msg)
788 def window_sensitive(self, sensitive):
789 self.image_configuration_page.machine_combo.set_sensitive(sensitive)
790 self.image_configuration_page.machine_combo.child.set_sensitive(sensitive)
791 self.image_configuration_page.image_combo.set_sensitive(sensitive)
792 self.image_configuration_page.image_combo.child.set_sensitive(sensitive)
793 self.image_configuration_page.layer_button.set_sensitive(sensitive)
794 self.image_configuration_page.layer_info_icon.set_sensitive(sensitive)
795 self.image_configuration_page.toolbar.set_sensitive(sensitive)
796 self.image_configuration_page.config_build_button.set_sensitive(sensitive)
798 self.recipe_details_page.set_sensitive(sensitive)
799 self.package_details_page.set_sensitive(sensitive)
800 self.build_details_page.set_sensitive(sensitive)
801 self.image_details_page.set_sensitive(sensitive)
804 self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
806 self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
807 self.sensitive = sensitive
810 def handler_generating_data_cb(self, handler):
811 self.window_sensitive(False)
813 def handler_data_generated_cb(self, handler):
814 self.window_sensitive(True)
816 def rcppkglist_populated(self):
817 selected_image = self.configuration.selected_image
818 selected_recipes = self.configuration.selected_recipes[:]
819 selected_packages = self.configuration.selected_packages[:]
821 self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
822 self.image_configuration_page.update_image_desc()
823 self.update_recipe_model(selected_image, selected_recipes)
824 self.update_package_model(selected_packages)
826 def recipelist_changed_cb(self, recipe_model):
827 self.recipe_details_page.refresh_selection()
829 def packagelist_changed_cb(self, package_model):
830 self.package_details_page.refresh_selection()
832 def handler_recipe_populated_cb(self, handler):
833 self.image_configuration_page.update_progress_bar("Populated recipes", 0.99)
835 def handler_package_populated_cb(self, handler):
836 self.image_configuration_page.update_progress_bar("Populated packages", 1.0)
838 def handler_parsing_started_cb(self, handler, message):
839 if self.current_step != self.RCPPKGINFO_POPULATING:
843 if message["eventname"] == "TreeDataPreparationStarted":
844 fraction = 0.6 + fraction
845 self.image_configuration_page.stop_button.set_sensitive(False)
847 self.image_configuration_page.stop_button.set_sensitive(True)
849 self.image_configuration_page.update_progress_bar(message["title"], fraction)
851 def handler_parsing_cb(self, handler, message):
852 if self.current_step != self.RCPPKGINFO_POPULATING:
855 fraction = message["current"] * 1.0/message["total"]
856 if message["eventname"] == "TreeDataPreparationProgress":
857 fraction = 0.6 + 0.38 * fraction
859 fraction = 0.6 * fraction
860 self.image_configuration_page.update_progress_bar(message["title"], fraction)
862 def handler_parsing_completed_cb(self, handler, message):
863 if self.current_step != self.RCPPKGINFO_POPULATING:
866 if message["eventname"] == "TreeDataPreparationCompleted":
870 self.image_configuration_page.update_progress_bar(message["title"], fraction)
872 def handler_build_started_cb(self, running_build):
873 if self.current_step == self.FAST_IMAGE_GENERATING:
875 elif self.current_step == self.IMAGE_GENERATING:
876 if self.previous_step == self.FAST_IMAGE_GENERATING:
880 elif self.current_step == self.PACKAGE_GENERATING:
882 self.build_details_page.update_progress_bar("Build Started: ", fraction)
883 self.build_details_page.show_configurations(self.configuration, self.parameters)
885 def build_succeeded(self):
886 if self.current_step == self.FAST_IMAGE_GENERATING:
888 elif self.current_step == self.IMAGE_GENERATING:
890 self.parameters.image_names = []
891 selected_image = self.recipe_model.get_selected_image()
892 if selected_image == self.recipe_model.__custom_image__:
893 linkname = 'hob-image-' + self.configuration.curr_mach
895 linkname = selected_image + '-' + self.configuration.curr_mach
896 image_extension = self.get_image_extension()
897 for image_type in self.parameters.image_types:
898 if image_type in image_extension:
899 real_types = image_extension[image_type]
901 real_types = [image_type]
902 for real_image_type in real_types:
903 linkpath = self.parameters.image_addr + '/' + linkname + '.' + real_image_type
904 if os.path.exists(linkpath):
905 self.parameters.image_names.append(os.readlink(linkpath))
906 elif self.current_step == self.PACKAGE_GENERATING:
908 self.build_details_page.update_progress_bar("Build Completed: ", fraction)
909 self.handler.build_succeeded_async()
910 self.stopping = False
912 if self.current_step == self.PACKAGE_GENERATING:
913 self.switch_page(self.PACKAGE_GENERATED)
914 elif self.current_step == self.IMAGE_GENERATING:
915 self.switch_page(self.IMAGE_GENERATED)
917 def build_failed(self):
920 message = "Build stopped: "
921 fraction = self.build_details_page.progress_bar.get_fraction()
923 fail_to_next_edit = ""
924 if self.current_step == self.FAST_IMAGE_GENERATING:
925 fail_to_next_edit = "image configuration"
927 elif self.current_step == self.IMAGE_GENERATING:
928 if self.previous_step == self.FAST_IMAGE_GENERATING:
929 fail_to_next_edit = "image configuration"
931 fail_to_next_edit = "packages"
933 elif self.current_step == self.PACKAGE_GENERATING:
934 fail_to_next_edit = "recipes"
936 self.build_details_page.show_fail_page(fail_to_next_edit.split(' ')[0], fail_to_next_edit)
938 message = "Build failed: "
939 self.build_details_page.update_progress_bar(message, fraction, status)
940 self.build_details_page.show_back_button()
941 self.build_details_page.hide_stop_button()
942 self.handler.build_failed_async()
943 self.stopping = False
945 def handler_build_succeeded_cb(self, running_build):
946 if not self.stopping:
947 self.build_succeeded()
952 def handler_build_failed_cb(self, running_build):
955 def handler_build_aborted_cb(self, running_build):
958 def handler_no_provider_cb(self, running_build, msg):
959 dialog = CrumbsMessageDialog(self, Builder.interpret_markup(msg), gtk.STOCK_DIALOG_INFO)
960 button = dialog.add_button("Close", gtk.RESPONSE_OK)
961 HobButton.style_button(button)
966 def handler_task_started_cb(self, running_build, message):
967 fraction = message["current"] * 1.0/message["total"]
968 title = "Build packages"
969 if self.current_step == self.FAST_IMAGE_GENERATING:
970 if message["eventname"] == "sceneQueueTaskStarted":
971 fraction = 0.27 * fraction
972 elif message["eventname"] == "runQueueTaskStarted":
973 fraction = 0.27 + 0.63 * fraction
974 elif self.current_step == self.IMAGE_GENERATING:
975 title = "Build image"
976 if self.previous_step == self.FAST_IMAGE_GENERATING:
977 if message["eventname"] == "sceneQueueTaskStarted":
978 fraction = 0.27 + 0.63 + 0.03 * fraction
979 elif message["eventname"] == "runQueueTaskStarted":
980 fraction = 0.27 + 0.63 + 0.03 + 0.07 * fraction
982 if message["eventname"] == "sceneQueueTaskStarted":
983 fraction = 0.2 * fraction
984 elif message["eventname"] == "runQueueTaskStarted":
985 fraction = 0.2 + 0.8 * fraction
986 elif self.current_step == self.PACKAGE_GENERATING:
987 if message["eventname"] == "sceneQueueTaskStarted":
988 fraction = 0.2 * fraction
989 elif message["eventname"] == "runQueueTaskStarted":
990 fraction = 0.2 + 0.8 * fraction
991 self.build_details_page.update_progress_bar(title + ": ", fraction)
992 self.build_details_page.update_build_status(message["current"], message["total"], message["task"])
994 def handler_build_failure_cb(self, running_build):
995 self.build_details_page.show_issues()
997 def handler_build_log_cb(self, running_build, func, obj):
998 if hasattr(self.logger, func):
999 getattr(self.logger, func)(obj)
1001 def destroy_window_cb(self, widget, event):
1002 if not self.sensitive:
1004 lbl = "<b>Do you really want to exit the Hob image creator?</b>"
1005 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1006 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1007 HobAltButton.style_button(button)
1008 button = dialog.add_button("Exit Hob", gtk.RESPONSE_YES)
1009 HobButton.style_button(button)
1010 dialog.set_default_response(gtk.RESPONSE_YES)
1011 response = dialog.run()
1013 if response == gtk.RESPONSE_YES:
1019 def build_packages(self):
1020 _, all_recipes = self.recipe_model.get_selected_recipes()
1022 lbl = "<b>No selections made</b>\nYou have not made any selections"
1023 lbl = lbl + " so there isn't anything to bake at this time."
1024 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1025 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1026 HobButton.style_button(button)
1030 self.generate_packages_async(True)
1032 def build_image(self):
1033 selected_packages = self.package_model.get_selected_packages()
1034 if not selected_packages:
1035 lbl = "<b>No selections made</b>\nYou have not made any selections"
1036 lbl = lbl + " so there isn't anything to bake at this time."
1037 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1038 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1039 HobButton.style_button(button)
1043 self.generate_image_async(True)
1045 def just_bake(self):
1046 selected_image = self.recipe_model.get_selected_image()
1047 selected_packages = self.package_model.get_selected_packages() or []
1049 # If no base image and no selected packages don't build anything
1050 if not (selected_packages or selected_image != self.recipe_model.__custom_image__):
1051 lbl = "<b>No selections made</b>\nYou have not made any selections"
1052 lbl = lbl + " so there isn't anything to bake at this time."
1053 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1054 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1055 HobButton.style_button(button)
1060 self.fast_generate_image_async(True)
1062 def show_binb_dialog(self, binb):
1063 markup = "<b>Brought in by:</b>\n%s" % binb
1064 ptip = PersistentTooltip(markup, self)
1068 def show_layer_selection_dialog(self):
1069 dialog = LayerSelectionDialog(title = "Layers",
1070 layers = copy.deepcopy(self.configuration.layers),
1071 all_layers = self.parameters.all_layers,
1073 flags = gtk.DIALOG_MODAL
1074 | gtk.DIALOG_DESTROY_WITH_PARENT
1075 | gtk.DIALOG_NO_SEPARATOR)
1076 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1077 HobAltButton.style_button(button)
1078 button = dialog.add_button("OK", gtk.RESPONSE_YES)
1079 HobButton.style_button(button)
1080 response = dialog.run()
1081 if response == gtk.RESPONSE_YES:
1082 self.configuration.layers = dialog.layers
1083 self.save_defaults() # remember layers
1085 if dialog.layers_changed:
1086 self.update_config_async()
1089 def show_load_template_dialog(self):
1090 dialog = gtk.FileChooserDialog("Load Template Files", self,
1091 gtk.FILE_CHOOSER_ACTION_OPEN)
1092 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1093 HobAltButton.style_button(button)
1094 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1095 HobButton.style_button(button)
1096 filter = gtk.FileFilter()
1097 filter.set_name("Hob Files")
1098 filter.add_pattern("*.hob")
1099 dialog.add_filter(filter)
1101 response = dialog.run()
1103 if response == gtk.RESPONSE_YES:
1104 path = dialog.get_filename()
1106 return response == gtk.RESPONSE_YES, path
1108 def show_save_template_dialog(self):
1109 dialog = gtk.FileChooserDialog("Save Template Files", self,
1110 gtk.FILE_CHOOSER_ACTION_SAVE)
1111 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1112 HobAltButton.style_button(button)
1113 button = dialog.add_button("Save", gtk.RESPONSE_YES)
1114 HobButton.style_button(button)
1115 dialog.set_current_name("hob")
1116 response = dialog.run()
1117 if response == gtk.RESPONSE_YES:
1118 path = dialog.get_filename()
1119 self.save_template(path)
1122 def get_image_extension(self):
1123 image_extension = {}
1124 for type in self.parameters.image_types:
1125 ext = self.handler.runCommand(["getVariable", "IMAGE_EXTENSION_%s" % type])
1127 image_extension[type] = ext.split(' ')
1129 return image_extension
1131 def show_load_my_images_dialog(self):
1132 image_extension = self.get_image_extension()
1133 dialog = ImageSelectionDialog(self.parameters.image_addr, self.parameters.image_types,
1134 "Open My Images", self,
1135 gtk.FILE_CHOOSER_ACTION_SAVE, None,
1137 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1138 HobAltButton.style_button(button)
1139 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1140 HobButton.style_button(button)
1141 response = dialog.run()
1142 if response == gtk.RESPONSE_YES:
1143 if not dialog.image_names:
1144 lbl = "<b>No selections made</b>\nYou have not made any selections"
1145 crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1146 button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
1147 HobButton.style_button(button)
1149 crumbs_dialog.destroy()
1153 self.parameters.image_addr = dialog.image_folder
1154 self.parameters.image_names = dialog.image_names[:]
1155 self.switch_page(self.MY_IMAGE_OPENED)
1159 def show_adv_settings_dialog(self):
1160 dialog = AdvancedSettingDialog(title = "Settings",
1161 configuration = copy.deepcopy(self.configuration),
1162 all_image_types = self.parameters.image_types,
1163 all_package_formats = self.parameters.all_package_formats,
1164 all_distros = self.parameters.all_distros,
1165 all_sdk_machines = self.parameters.all_sdk_machines,
1166 max_threads = self.parameters.max_threads,
1168 flags = gtk.DIALOG_MODAL
1169 | gtk.DIALOG_DESTROY_WITH_PARENT
1170 | gtk.DIALOG_NO_SEPARATOR)
1171 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1172 HobAltButton.style_button(button)
1173 button = dialog.add_button("Save", gtk.RESPONSE_YES)
1174 HobButton.style_button(button)
1175 response = dialog.run()
1176 settings_changed = False
1177 if response == gtk.RESPONSE_YES:
1178 self.configuration = dialog.configuration
1179 self.save_defaults() # remember settings
1180 settings_changed = dialog.settings_changed
1182 return response == gtk.RESPONSE_YES, settings_changed
1184 def reparse_post_adv_settings(self):
1185 if not self.configuration.curr_mach:
1186 self.update_config_async()
1188 self.configuration.clear_selection()
1189 # DO reparse recipes
1190 self.populate_recipe_package_info_async()
1192 def deploy_image(self, image_name):
1194 lbl = "<b>Please select an image to deploy.</b>"
1195 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1196 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1197 HobButton.style_button(button)
1202 image_path = os.path.join(self.parameters.image_addr, image_name)
1203 dialog = DeployImageDialog(title = "Usb Image Maker",
1204 image_path = image_path,
1206 flags = gtk.DIALOG_MODAL
1207 | gtk.DIALOG_DESTROY_WITH_PARENT
1208 | gtk.DIALOG_NO_SEPARATOR)
1209 button = dialog.add_button("Close", gtk.RESPONSE_NO)
1210 HobAltButton.style_button(button)
1211 button = dialog.add_button("Make usb image", gtk.RESPONSE_YES)
1212 HobButton.style_button(button)
1213 response = dialog.run()
1216 def show_load_kernel_dialog(self):
1217 dialog = gtk.FileChooserDialog("Load Kernel Files", self,
1218 gtk.FILE_CHOOSER_ACTION_SAVE)
1219 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1220 HobAltButton.style_button(button)
1221 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1222 HobButton.style_button(button)
1223 filter = gtk.FileFilter()
1224 filter.set_name("Kernel Files")
1225 filter.add_pattern("*.bin")
1226 dialog.add_filter(filter)
1228 dialog.set_current_folder(self.parameters.image_addr)
1230 response = dialog.run()
1232 if response == gtk.RESPONSE_YES:
1233 kernel_path = dialog.get_filename()
1239 def runqemu_image(self, image_name, kernel_name):
1240 if not image_name or not kernel_name:
1241 lbl = "<b>Please select an %s to launch in QEMU.</b>" % ("kernel" if image_name else "image")
1242 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1243 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1244 HobButton.style_button(button)
1249 kernel_path = os.path.join(self.parameters.image_addr, kernel_name)
1250 image_path = os.path.join(self.parameters.image_addr, image_name)
1252 source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
1253 tmp_path = self.parameters.tmpdir
1254 cmdline = bb.ui.crumbs.utils.which_terminal()
1255 if os.path.exists(image_path) and os.path.exists(kernel_path) \
1256 and os.path.exists(source_env_path) and os.path.exists(tmp_path) \
1258 cmdline += "\' bash -c \"export OE_TMPDIR=" + tmp_path + "; "
1259 cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
1260 cmdline += "runqemu " + kernel_path + " " + image_path + "\"\'"
1261 subprocess.Popen(shlex.split(cmdline))
1263 lbl = "<b>Path error</b>\nOne of your paths is wrong,"
1264 lbl = lbl + " please make sure the following paths exist:\n"
1265 lbl = lbl + "image path:" + image_path + "\n"
1266 lbl = lbl + "kernel path:" + kernel_path + "\n"
1267 lbl = lbl + "source environment path:" + source_env_path + "\n"
1268 lbl = lbl + "tmp path: " + tmp_path + "."
1269 lbl = lbl + "You may be missing either xterm or vte for terminal services."
1270 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
1271 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1272 HobButton.style_button(button)
1276 def show_packages(self, ask=True):
1277 _, selected_recipes = self.recipe_model.get_selected_recipes()
1278 if selected_recipes and ask:
1279 lbl = "<b>Package list may be incomplete!</b>\nDo you want to build selected recipes"
1280 lbl = lbl + " to get a full list or just view the existing packages?"
1281 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1282 button = dialog.add_button("View packages", gtk.RESPONSE_NO)
1283 HobAltButton.style_button(button)
1284 button = dialog.add_button("Build packages", gtk.RESPONSE_YES)
1285 HobButton.style_button(button)
1286 dialog.set_default_response(gtk.RESPONSE_YES)
1287 response = dialog.run()
1289 if response == gtk.RESPONSE_YES:
1290 self.generate_packages_async(True)
1292 self.switch_page(self.PACKAGE_SELECTION)
1294 self.switch_page(self.PACKAGE_SELECTION)
1296 def show_recipes(self):
1297 self.switch_page(self.RECIPE_SELECTION)
1299 def show_image_details(self):
1300 self.switch_page(self.IMAGE_GENERATED)
1302 def show_configuration(self):
1303 self.switch_page(self.BASEIMG_SELECTED)
1305 def stop_build(self):
1307 lbl = "<b>Force Stop build?</b>\nYou've already selected Stop once,"
1308 lbl = lbl + " would you like to 'Force Stop' the build?\n\n"
1309 lbl = lbl + "This will stop the build as quickly as possible but may"
1310 lbl = lbl + " well leave your build directory in an unusable state"
1311 lbl = lbl + " that requires manual steps to fix.\n"
1312 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
1313 button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
1314 HobAltButton.style_button(button)
1315 button = dialog.add_button("Force Stop", gtk.RESPONSE_YES)
1316 HobButton.style_button(button)
1318 lbl = "<b>Stop build?</b>\n\nAre you sure you want to stop this"
1319 lbl = lbl + " build?\n\n'Force Stop' will stop the build as quickly as"
1320 lbl = lbl + " possible but may well leave your build directory in an"
1321 lbl = lbl + " unusable state that requires manual steps to fix.\n\n"
1322 lbl = lbl + "'Stop' will stop the build as soon as all in"
1323 lbl = lbl + " progress build tasks are finished. However if a"
1324 lbl = lbl + " lengthy compilation phase is in progress this may take"
1325 lbl = lbl + " some time."
1326 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
1327 button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
1328 HobAltButton.style_button(button)
1329 button = dialog.add_button("Stop", gtk.RESPONSE_OK)
1330 HobAltButton.style_button(button)
1331 button = dialog.add_button("Force Stop", gtk.RESPONSE_YES)
1332 HobButton.style_button(button)
1333 response = dialog.run()
1335 if response != gtk.RESPONSE_CANCEL:
1336 self.stopping = True
1337 if response == gtk.RESPONSE_OK:
1338 self.cancel_build_sync()
1339 elif response == gtk.RESPONSE_YES:
1340 self.cancel_build_sync(True)
1342 def do_log(self, consolelogfile = None):
1344 bb.utils.mkdirhier(os.path.dirname(consolelogfile))
1346 self.logger.removeHandler(self.consolelog)
1347 self.consolelog = None
1348 self.consolelog = logging.FileHandler(consolelogfile)
1349 bb.msg.addDefaultlogFilter(self.consolelog)
1350 format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
1351 self.consolelog.setFormatter(format)
1353 self.logger.addHandler(self.consolelog)