summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/crumbs/builder.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/builder.py')
-rwxr-xr-xbitbake/lib/bb/ui/crumbs/builder.py1476
1 files changed, 1476 insertions, 0 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/builder.py b/bitbake/lib/bb/ui/crumbs/builder.py
new file mode 100755
index 0000000000..ab6750b741
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/builder.py
@@ -0,0 +1,1476 @@
1#!/usr/bin/env python
2#
3# BitBake Graphical GTK User Interface
4#
5# Copyright (C) 2011-2012 Intel Corporation
6#
7# Authored by Joshua Lock <josh@linux.intel.com>
8# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
9# Authored by Shane Wang <shane.wang@intel.com>
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License version 2 as
13# published by the Free Software Foundation.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License along
21# with this program; if not, write to the Free Software Foundation, Inc.,
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23
24import glib
25import gtk, gobject
26import copy
27import os
28import subprocess
29import shlex
30import re
31import logging
32import sys
33import signal
34import time
35from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
36from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
37from bb.ui.crumbs.packageselectionpage import PackageSelectionPage
38from bb.ui.crumbs.builddetailspage import BuildDetailsPage
39from bb.ui.crumbs.imagedetailspage import ImageDetailsPage
40from bb.ui.crumbs.sanitycheckpage import SanityCheckPage
41from bb.ui.crumbs.hobwidget import hwc, HobButton, HobAltButton
42from bb.ui.crumbs.persistenttooltip import PersistentTooltip
43import bb.ui.crumbs.utils
44from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
45from bb.ui.crumbs.hig.simplesettingsdialog import SimpleSettingsDialog
46from bb.ui.crumbs.hig.advancedsettingsdialog import AdvancedSettingsDialog
47from bb.ui.crumbs.hig.deployimagedialog import DeployImageDialog
48from bb.ui.crumbs.hig.layerselectiondialog import LayerSelectionDialog
49from bb.ui.crumbs.hig.imageselectiondialog import ImageSelectionDialog
50from bb.ui.crumbs.hig.parsingwarningsdialog import ParsingWarningsDialog
51from bb.ui.crumbs.hig.propertydialog import PropertyDialog
52
53hobVer = 20120808
54
55class Configuration:
56 '''Represents the data structure of configuration.'''
57
58 @classmethod
59 def parse_proxy_string(cls, proxy):
60 pattern = "^\s*((http|https|ftp|socks|cvs)://)?((\S+):(\S+)@)?([^\s:]+)(:(\d+))?/?"
61 match = re.search(pattern, proxy)
62 if match:
63 return match.group(2), match.group(4), match.group(5), match.group(6), match.group(8)
64 else:
65 return None, None, None, "", ""
66
67 @classmethod
68 def make_host_string(cls, prot, user, passwd, host, default_prot=""):
69 if host == None or host == "":
70 return ""
71
72 passwd = passwd or ""
73
74 if user != None and user != "":
75 if prot == None or prot == "":
76 prot = default_prot
77 return prot + "://" + user + ":" + passwd + "@" + host
78 else:
79 if prot == None or prot == "":
80 return host
81 else:
82 return prot + "://" + host
83
84 @classmethod
85 def make_port_string(cls, port):
86 port = port or ""
87 return port
88
89 @classmethod
90 def make_proxy_string(cls, prot, user, passwd, host, port, default_prot=""):
91 if host == None or host == "":# or port == None or port == "":
92 return ""
93
94 return Configuration.make_host_string(prot, user, passwd, host, default_prot) + (":" + Configuration.make_port_string(port) if port else "")
95
96 def __init__(self):
97 self.curr_mach = ""
98 self.selected_image = None
99 # settings
100 self.curr_distro = ""
101 self.dldir = self.sstatedir = self.sstatemirror = ""
102 self.pmake = self.bbthread = 0
103 self.curr_package_format = ""
104 self.image_rootfs_size = self.image_extra_size = 0
105 self.image_overhead_factor = 1
106 self.incompat_license = ""
107 self.curr_sdk_machine = ""
108 self.conf_version = self.lconf_version = ""
109 self.extra_setting = {}
110 self.toolchain_build = False
111 self.image_fstypes = ""
112 self.image_size = None
113 self.image_packages = []
114 # bblayers.conf
115 self.layers = []
116 # image/recipes/packages
117 self.clear_selection()
118
119 self.user_selected_packages = []
120
121 self.default_task = "build"
122
123 # proxy settings
124 self.enable_proxy = None
125 self.same_proxy = False
126 self.proxies = {
127 "http" : [None, None, None, "", ""], # protocol : [prot, user, passwd, host, port]
128 "https" : [None, None, None, "", ""],
129 "ftp" : [None, None, None, "", ""],
130 "socks" : [None, None, None, "", ""],
131 "cvs" : [None, None, None, "", ""],
132 }
133
134 def clear_selection(self):
135 self.selected_recipes = []
136 self.selected_packages = []
137 self.initial_selected_image = None
138 self.initial_selected_packages = []
139 self.initial_user_selected_packages = []
140
141 def split_proxy(self, protocol, proxy):
142 entry = []
143 prot, user, passwd, host, port = Configuration.parse_proxy_string(proxy)
144 entry.append(prot)
145 entry.append(user)
146 entry.append(passwd)
147 entry.append(host)
148 entry.append(port)
149 self.proxies[protocol] = entry
150
151 def combine_proxy(self, protocol):
152 entry = self.proxies[protocol]
153 return Configuration.make_proxy_string(entry[0], entry[1], entry[2], entry[3], entry[4], protocol)
154
155 def combine_host_only(self, protocol):
156 entry = self.proxies[protocol]
157 return Configuration.make_host_string(entry[0], entry[1], entry[2], entry[3], protocol)
158
159 def combine_port_only(self, protocol):
160 entry = self.proxies[protocol]
161 return Configuration.make_port_string(entry[4])
162
163 def update(self, params):
164 # settings
165 self.curr_distro = params["distro"]
166 self.dldir = params["dldir"]
167 self.sstatedir = params["sstatedir"]
168 self.sstatemirror = params["sstatemirror"]
169 self.pmake = int(params["pmake"].split()[1])
170 self.bbthread = params["bbthread"]
171 self.curr_package_format = " ".join(params["pclass"].split("package_")).strip()
172 self.image_rootfs_size = params["image_rootfs_size"]
173 self.image_extra_size = params["image_extra_size"]
174 self.image_overhead_factor = params['image_overhead_factor']
175 self.incompat_license = params["incompat_license"]
176 self.curr_sdk_machine = params["sdk_machine"]
177 self.conf_version = params["conf_version"]
178 self.lconf_version = params["lconf_version"]
179 self.image_fstypes = params["image_fstypes"]
180 # self.extra_setting/self.toolchain_build
181 # bblayers.conf
182 self.layers = params["layer"].split()
183 self.layers_non_removable = params["layers_non_removable"].split()
184 self.default_task = params["default_task"]
185
186 # proxy settings
187 self.enable_proxy = params["http_proxy"] != "" or params["https_proxy"] != "" \
188 or params["ftp_proxy"] != "" or params["socks_proxy"] != "" \
189 or params["cvs_proxy_host"] != "" or params["cvs_proxy_port"] != ""
190 self.split_proxy("http", params["http_proxy"])
191 self.split_proxy("https", params["https_proxy"])
192 self.split_proxy("ftp", params["ftp_proxy"])
193 self.split_proxy("socks", params["socks_proxy"])
194 self.split_proxy("cvs", params["cvs_proxy_host"] + ":" + params["cvs_proxy_port"])
195
196 def save(self, handler, defaults=False):
197 # bblayers.conf
198 handler.set_var_in_file("BBLAYERS", self.layers, "bblayers.conf")
199 # local.conf
200 if not defaults:
201 handler.early_assign_var_in_file("MACHINE", self.curr_mach, "local.conf")
202 handler.set_var_in_file("DISTRO", self.curr_distro, "local.conf")
203 handler.set_var_in_file("DL_DIR", self.dldir, "local.conf")
204 handler.set_var_in_file("SSTATE_DIR", self.sstatedir, "local.conf")
205 sstate_mirror_list = self.sstatemirror.split("\\n ")
206 sstate_mirror_list_modified = []
207 for mirror in sstate_mirror_list:
208 if mirror != "":
209 mirror = mirror + "\\n"
210 sstate_mirror_list_modified.append(mirror)
211 handler.set_var_in_file("SSTATE_MIRRORS", sstate_mirror_list_modified, "local.conf")
212 handler.set_var_in_file("PARALLEL_MAKE", "-j %s" % self.pmake, "local.conf")
213 handler.set_var_in_file("BB_NUMBER_THREADS", self.bbthread, "local.conf")
214 handler.set_var_in_file("PACKAGE_CLASSES", " ".join(["package_" + i for i in self.curr_package_format.split()]), "local.conf")
215 handler.set_var_in_file("IMAGE_ROOTFS_SIZE", self.image_rootfs_size, "local.conf")
216 handler.set_var_in_file("IMAGE_EXTRA_SPACE", self.image_extra_size, "local.conf")
217 handler.set_var_in_file("INCOMPATIBLE_LICENSE", self.incompat_license, "local.conf")
218 handler.set_var_in_file("SDKMACHINE", self.curr_sdk_machine, "local.conf")
219 handler.set_var_in_file("CONF_VERSION", self.conf_version, "local.conf")
220 handler.set_var_in_file("LCONF_VERSION", self.lconf_version, "bblayers.conf")
221 handler.set_extra_config(self.extra_setting)
222 handler.set_var_in_file("TOOLCHAIN_BUILD", self.toolchain_build, "local.conf")
223 handler.set_var_in_file("IMAGE_FSTYPES", self.image_fstypes, "local.conf")
224 if not defaults:
225 # image/recipes/packages
226 handler.set_var_in_file("__SELECTED_IMAGE__", self.selected_image, "local.conf")
227 handler.set_var_in_file("DEPENDS", self.selected_recipes, "local.conf")
228 handler.set_var_in_file("IMAGE_INSTALL", self.user_selected_packages, "local.conf")
229 # proxy
230 handler.set_var_in_file("enable_proxy", self.enable_proxy, "local.conf")
231 handler.set_var_in_file("use_same_proxy", self.same_proxy, "local.conf")
232 handler.set_var_in_file("http_proxy", self.combine_proxy("http"), "local.conf")
233 handler.set_var_in_file("https_proxy", self.combine_proxy("https"), "local.conf")
234 handler.set_var_in_file("ftp_proxy", self.combine_proxy("ftp"), "local.conf")
235 handler.set_var_in_file("all_proxy", self.combine_proxy("socks"), "local.conf")
236 handler.set_var_in_file("CVS_PROXY_HOST", self.combine_host_only("cvs"), "local.conf")
237 handler.set_var_in_file("CVS_PROXY_PORT", self.combine_port_only("cvs"), "local.conf")
238
239 def __str__(self):
240 s = "VERSION: '%s', BBLAYERS: '%s', MACHINE: '%s', DISTRO: '%s', DL_DIR: '%s'," % \
241 (hobVer, " ".join(self.layers), self.curr_mach, self.curr_distro, self.dldir )
242 s += "SSTATE_DIR: '%s', SSTATE_MIRROR: '%s', PARALLEL_MAKE: '-j %s', BB_NUMBER_THREADS: '%s', PACKAGE_CLASSES: '%s', " % \
243 (self.sstatedir, self.sstatemirror, self.pmake, self.bbthread, " ".join(["package_" + i for i in self.curr_package_format.split()]))
244 s += "IMAGE_ROOTFS_SIZE: '%s', IMAGE_EXTRA_SPACE: '%s', INCOMPATIBLE_LICENSE: '%s', SDKMACHINE: '%s', CONF_VERSION: '%s', " % \
245 (self.image_rootfs_size, self.image_extra_size, self.incompat_license, self.curr_sdk_machine, self.conf_version)
246 s += "LCONF_VERSION: '%s', EXTRA_SETTING: '%s', TOOLCHAIN_BUILD: '%s', IMAGE_FSTYPES: '%s', __SELECTED_IMAGE__: '%s', " % \
247 (self.lconf_version, self.extra_setting, self.toolchain_build, self.image_fstypes, self.selected_image)
248 s += "DEPENDS: '%s', IMAGE_INSTALL: '%s', enable_proxy: '%s', use_same_proxy: '%s', http_proxy: '%s', " % \
249 (self.selected_recipes, self.user_selected_packages, self.enable_proxy, self.same_proxy, self.combine_proxy("http"))
250 s += "https_proxy: '%s', ftp_proxy: '%s', all_proxy: '%s', CVS_PROXY_HOST: '%s', CVS_PROXY_PORT: '%s'" % \
251 (self.combine_proxy("https"), self.combine_proxy("ftp"), self.combine_proxy("socks"),
252 self.combine_host_only("cvs"), self.combine_port_only("cvs"))
253 return s
254
255class Parameters:
256 '''Represents other variables like available machines, etc.'''
257
258 def __init__(self):
259 # Variables
260 self.max_threads = 65535
261 self.core_base = ""
262 self.image_addr = ""
263 self.image_types = []
264 self.runnable_image_types = []
265 self.runnable_machine_patterns = []
266 self.deployable_image_types = []
267 self.tmpdir = ""
268
269 self.all_machines = []
270 self.all_package_formats = []
271 self.all_distros = []
272 self.all_sdk_machines = []
273 self.all_layers = []
274 self.image_names = []
275 self.image_white_pattern = ""
276 self.image_black_pattern = ""
277
278 # for build log to show
279 self.bb_version = ""
280 self.target_arch = ""
281 self.target_os = ""
282 self.distro_version = ""
283 self.tune_pkgarch = ""
284
285 def update(self, params):
286 self.max_threads = params["max_threads"]
287 self.core_base = params["core_base"]
288 self.image_addr = params["image_addr"]
289 self.image_types = params["image_types"].split()
290 self.runnable_image_types = params["runnable_image_types"].split()
291 self.runnable_machine_patterns = params["runnable_machine_patterns"].split()
292 self.deployable_image_types = params["deployable_image_types"].split()
293 self.tmpdir = params["tmpdir"]
294 self.image_white_pattern = params["image_white_pattern"]
295 self.image_black_pattern = params["image_black_pattern"]
296 self.kernel_image_type = params["kernel_image_type"]
297 # for build log to show
298 self.bb_version = params["bb_version"]
299 self.target_arch = params["target_arch"]
300 self.target_os = params["target_os"]
301 self.distro_version = params["distro_version"]
302 self.tune_pkgarch = params["tune_pkgarch"]
303
304def hob_conf_filter(fn, data):
305 if fn.endswith("/local.conf"):
306 distro = data.getVar("DISTRO_HOB")
307 if distro:
308 if distro != "defaultsetup":
309 data.setVar("DISTRO", distro)
310 else:
311 data.delVar("DISTRO")
312
313 keys = ["MACHINE_HOB", "SDKMACHINE_HOB", "PACKAGE_CLASSES_HOB", \
314 "BB_NUMBER_THREADS_HOB", "PARALLEL_MAKE_HOB", "DL_DIR_HOB", \
315 "SSTATE_DIR_HOB", "SSTATE_MIRRORS_HOB", "INCOMPATIBLE_LICENSE_HOB"]
316 for key in keys:
317 var_hob = data.getVar(key)
318 if var_hob:
319 data.setVar(key.split("_HOB")[0], var_hob)
320 return
321
322 if fn.endswith("/bblayers.conf"):
323 layers = data.getVar("BBLAYERS_HOB")
324 if layers:
325 data.setVar("BBLAYERS", layers)
326 return
327
328class Builder(gtk.Window):
329
330 (INITIAL_CHECKS,
331 MACHINE_SELECTION,
332 RCPPKGINFO_POPULATING,
333 RCPPKGINFO_POPULATED,
334 BASEIMG_SELECTED,
335 RECIPE_SELECTION,
336 PACKAGE_GENERATING,
337 PACKAGE_GENERATED,
338 PACKAGE_SELECTION,
339 FAST_IMAGE_GENERATING,
340 IMAGE_GENERATING,
341 IMAGE_GENERATED,
342 MY_IMAGE_OPENED,
343 BACK,
344 END_NOOP) = range(15)
345
346 (SANITY_CHECK,
347 IMAGE_CONFIGURATION,
348 RECIPE_DETAILS,
349 BUILD_DETAILS,
350 PACKAGE_DETAILS,
351 IMAGE_DETAILS,
352 END_TAB) = range(7)
353
354 __step2page__ = {
355 INITIAL_CHECKS : SANITY_CHECK,
356 MACHINE_SELECTION : IMAGE_CONFIGURATION,
357 RCPPKGINFO_POPULATING : IMAGE_CONFIGURATION,
358 RCPPKGINFO_POPULATED : IMAGE_CONFIGURATION,
359 BASEIMG_SELECTED : IMAGE_CONFIGURATION,
360 RECIPE_SELECTION : RECIPE_DETAILS,
361 PACKAGE_GENERATING : BUILD_DETAILS,
362 PACKAGE_GENERATED : PACKAGE_DETAILS,
363 PACKAGE_SELECTION : PACKAGE_DETAILS,
364 FAST_IMAGE_GENERATING : BUILD_DETAILS,
365 IMAGE_GENERATING : BUILD_DETAILS,
366 IMAGE_GENERATED : IMAGE_DETAILS,
367 MY_IMAGE_OPENED : IMAGE_DETAILS,
368 END_NOOP : None,
369 }
370
371 SANITY_CHECK_MIN_DISPLAY_TIME = 5
372
373 def __init__(self, hobHandler, recipe_model, package_model):
374 super(Builder, self).__init__()
375
376 self.hob_image = "hob-image"
377 self.hob_toolchain = "hob-toolchain"
378
379 # handler
380 self.handler = hobHandler
381
382 # logger
383 self.logger = logging.getLogger("BitBake")
384 self.consolelog = None
385 self.current_logfile = None
386
387 # configuration and parameters
388 self.configuration = Configuration()
389 self.parameters = Parameters()
390
391 # build step
392 self.current_step = None
393 self.previous_step = None
394
395 self.stopping = False
396
397 # recipe model and package model
398 self.recipe_model = recipe_model
399 self.package_model = package_model
400
401 # Indicate whether user has customized the image
402 self.customized = False
403
404 # Indicate whether the UI is working
405 self.sensitive = True
406
407 # Indicate whether the sanity check ran
408 self.sanity_checked = False
409
410 # save parsing warnings
411 self.parsing_warnings = []
412
413 # create visual elements
414 self.create_visual_elements()
415
416 # connect the signals to functions
417 self.connect("delete-event", self.destroy_window_cb)
418 self.recipe_model.connect ("recipe-selection-changed", self.recipelist_changed_cb)
419 self.package_model.connect("package-selection-changed", self.packagelist_changed_cb)
420 self.handler.connect("config-updated", self.handler_config_updated_cb)
421 self.handler.connect("package-formats-updated", self.handler_package_formats_updated_cb)
422 self.handler.connect("parsing-started", self.handler_parsing_started_cb)
423 self.handler.connect("parsing", self.handler_parsing_cb)
424 self.handler.connect("parsing-completed", self.handler_parsing_completed_cb)
425 self.handler.build.connect("build-started", self.handler_build_started_cb)
426 self.handler.build.connect("build-succeeded", self.handler_build_succeeded_cb)
427 self.handler.build.connect("build-failed", self.handler_build_failed_cb)
428 self.handler.build.connect("build-aborted", self.handler_build_aborted_cb)
429 self.handler.build.connect("task-started", self.handler_task_started_cb)
430 self.handler.build.connect("disk-full", self.handler_disk_full_cb)
431 self.handler.build.connect("log-error", self.handler_build_failure_cb)
432 self.handler.build.connect("log-warning", self.handler_build_failure_cb)
433 self.handler.build.connect("log", self.handler_build_log_cb)
434 self.handler.build.connect("no-provider", self.handler_no_provider_cb)
435 self.handler.connect("generating-data", self.handler_generating_data_cb)
436 self.handler.connect("data-generated", self.handler_data_generated_cb)
437 self.handler.connect("command-succeeded", self.handler_command_succeeded_cb)
438 self.handler.connect("command-failed", self.handler_command_failed_cb)
439 self.handler.connect("parsing-warning", self.handler_parsing_warning_cb)
440 self.handler.connect("sanity-failed", self.handler_sanity_failed_cb)
441 self.handler.connect("recipe-populated", self.handler_recipe_populated_cb)
442 self.handler.connect("package-populated", self.handler_package_populated_cb)
443
444 self.handler.append_to_bbfiles("${TOPDIR}/recipes/images/*.bb")
445 self.initiate_new_build_async()
446
447 signal.signal(signal.SIGINT, self.event_handle_SIGINT)
448
449 def create_visual_elements(self):
450 self.set_title("Hob")
451 self.set_icon_name("applications-development")
452 self.set_resizable(True)
453
454 try:
455 window_width = self.get_screen().get_width()
456 window_height = self.get_screen().get_height()
457 except AttributeError:
458 print "Please set DISPLAY variable before running Hob."
459 sys.exit(1)
460
461 if window_width >= hwc.MAIN_WIN_WIDTH:
462 window_width = hwc.MAIN_WIN_WIDTH
463 window_height = hwc.MAIN_WIN_HEIGHT
464 self.set_size_request(window_width, window_height)
465
466 self.vbox = gtk.VBox(False, 0)
467 self.vbox.set_border_width(0)
468 self.add(self.vbox)
469
470 # create pages
471 self.image_configuration_page = ImageConfigurationPage(self)
472 self.recipe_details_page = RecipeSelectionPage(self)
473 self.build_details_page = BuildDetailsPage(self)
474 self.package_details_page = PackageSelectionPage(self)
475 self.image_details_page = ImageDetailsPage(self)
476 self.sanity_check_page = SanityCheckPage(self)
477 self.display_sanity_check = False
478 self.sanity_check_post_func = False
479 self.had_network_error = False
480
481 self.nb = gtk.Notebook()
482 self.nb.set_show_tabs(False)
483 self.nb.insert_page(self.sanity_check_page, None, self.SANITY_CHECK)
484 self.nb.insert_page(self.image_configuration_page, None, self.IMAGE_CONFIGURATION)
485 self.nb.insert_page(self.recipe_details_page, None, self.RECIPE_DETAILS)
486 self.nb.insert_page(self.build_details_page, None, self.BUILD_DETAILS)
487 self.nb.insert_page(self.package_details_page, None, self.PACKAGE_DETAILS)
488 self.nb.insert_page(self.image_details_page, None, self.IMAGE_DETAILS)
489 self.vbox.pack_start(self.nb, expand=True, fill=True)
490
491 self.show_all()
492 self.nb.set_current_page(0)
493
494 def sanity_check_timeout(self):
495 # The minimum time for showing the 'sanity check' page has passe
496 # If someone set the 'sanity_check_post_step' meanwhile, execute it now
497 self.display_sanity_check = False
498 if self.sanity_check_post_func:
499 temp = self.sanity_check_post_func
500 self.sanity_check_post_func = None
501 temp()
502 return False
503
504 def show_sanity_check_page(self):
505 # This window must stay on screen for at least 5 seconds, according to the design document
506 self.nb.set_current_page(self.SANITY_CHECK)
507 self.sanity_check_post_step = None
508 self.display_sanity_check = True
509 self.sanity_check_page.start()
510 gobject.timeout_add(self.SANITY_CHECK_MIN_DISPLAY_TIME * 1000, self.sanity_check_timeout)
511
512 def execute_after_sanity_check(self, func):
513 if not self.display_sanity_check:
514 func()
515 else:
516 self.sanity_check_post_func = func
517
518 def generate_configuration(self):
519 if not self.sanity_checked:
520 self.show_sanity_check_page()
521 self.handler.generate_configuration()
522
523 def initiate_new_build_async(self):
524 self.configuration.selected_image = None
525 self.switch_page(self.MACHINE_SELECTION)
526 self.handler.init_cooker()
527 self.handler.set_extra_inherit("image_types")
528 self.generate_configuration()
529
530 def update_config_async(self):
531 self.switch_page(self.MACHINE_SELECTION)
532 self.set_user_config()
533 self.generate_configuration()
534
535 def sanity_check(self):
536 self.handler.trigger_sanity_check()
537
538 def populate_recipe_package_info_async(self):
539 self.switch_page(self.RCPPKGINFO_POPULATING)
540 # Parse recipes
541 self.set_user_config()
542 self.handler.generate_recipes()
543
544 def generate_packages_async(self, log = False):
545 self.switch_page(self.PACKAGE_GENERATING)
546 if log:
547 self.current_logfile = self.handler.get_logfile()
548 self.do_log(self.current_logfile)
549 # Build packages
550 _, all_recipes = self.recipe_model.get_selected_recipes()
551 self.set_user_config()
552 self.handler.reset_build()
553 self.handler.generate_packages(all_recipes, self.configuration.default_task)
554
555 def restore_initial_selected_packages(self):
556 self.package_model.set_selected_packages(self.configuration.initial_user_selected_packages, True)
557 self.package_model.set_selected_packages(self.configuration.initial_selected_packages)
558 for package in self.configuration.selected_packages:
559 if package not in self.configuration.initial_selected_packages:
560 self.package_model.exclude_item(self.package_model.find_path_for_item(package))
561
562 def fast_generate_image_async(self, log = False):
563 self.switch_page(self.FAST_IMAGE_GENERATING)
564 if log:
565 self.current_logfile = self.handler.get_logfile()
566 self.do_log(self.current_logfile)
567 # Build packages
568 _, all_recipes = self.recipe_model.get_selected_recipes()
569 self.set_user_config()
570 self.handler.reset_build()
571 self.handler.generate_packages(all_recipes, self.configuration.default_task)
572
573 def generate_image_async(self, cont = False):
574 self.switch_page(self.IMAGE_GENERATING)
575 self.handler.reset_build()
576 if not cont:
577 self.current_logfile = self.handler.get_logfile()
578 self.do_log(self.current_logfile)
579 # Build image
580 self.set_user_config()
581 toolchain_packages = []
582 base_image = None
583 if self.configuration.toolchain_build:
584 toolchain_packages = self.package_model.get_selected_packages_toolchain()
585 if self.configuration.selected_image == self.recipe_model.__custom_image__:
586 packages = self.package_model.get_selected_packages()
587 image = self.hob_image
588 base_image = self.configuration.initial_selected_image
589 else:
590 packages = []
591 image = self.configuration.selected_image
592 self.handler.generate_image(image,
593 base_image,
594 self.hob_toolchain,
595 packages,
596 toolchain_packages,
597 self.configuration.default_task)
598
599 def generate_new_image(self, image, description):
600 base_image = self.configuration.initial_selected_image
601 if base_image == self.recipe_model.__custom_image__:
602 base_image = None
603 packages = self.package_model.get_selected_packages()
604 self.handler.generate_new_image(image, base_image, packages, description)
605
606 def ensure_dir(self, directory):
607 self.handler.ensure_dir(directory)
608
609 def get_parameters_sync(self):
610 return self.handler.get_parameters()
611
612 def request_package_info_async(self):
613 self.handler.request_package_info()
614
615 def cancel_build_sync(self, force=False):
616 self.handler.cancel_build(force)
617
618 def cancel_parse_sync(self):
619 self.handler.cancel_parse()
620
621 def switch_page(self, next_step):
622 # Main Workflow (Business Logic)
623 self.nb.set_current_page(self.__step2page__[next_step])
624
625 if next_step == self.MACHINE_SELECTION: # init step
626 self.image_configuration_page.show_machine()
627
628 elif next_step == self.RCPPKGINFO_POPULATING:
629 # MACHINE CHANGED action or SETTINGS CHANGED
630 # show the progress bar
631 self.image_configuration_page.show_info_populating()
632
633 elif next_step == self.RCPPKGINFO_POPULATED:
634 self.image_configuration_page.show_info_populated()
635
636 elif next_step == self.BASEIMG_SELECTED:
637 self.image_configuration_page.show_baseimg_selected()
638
639 elif next_step == self.RECIPE_SELECTION:
640 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
641 self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.ALL)
642 else:
643 self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.INCLUDED)
644
645 elif next_step == self.PACKAGE_SELECTION:
646 self.configuration.initial_selected_packages = self.configuration.selected_packages
647 self.configuration.initial_user_selected_packages = self.configuration.user_selected_packages
648 self.package_details_page.set_title("Edit packages")
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)
651 else:
652 self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
653 self.package_details_page.show_page(self.current_logfile)
654
655
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)
659
660 elif next_step == self.PACKAGE_GENERATED:
661 self.package_details_page.set_title("Step 2 of 2: Edit packages")
662 if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
663 self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
664 else:
665 self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
666 self.package_details_page.show_page(self.current_logfile)
667
668 elif next_step == self.IMAGE_GENERATING:
669 # after packages are generated, selected_packages need to
670 # be updated in package_model per selected_image in recipe_model
671 self.build_details_page.show_page(next_step)
672
673 elif next_step == self.IMAGE_GENERATED:
674 self.image_details_page.show_page(next_step)
675
676 elif next_step == self.MY_IMAGE_OPENED:
677 self.image_details_page.show_page(next_step)
678
679 self.previous_step = self.current_step
680 self.current_step = next_step
681
682 def set_user_config_proxies(self):
683 if self.configuration.enable_proxy == True:
684 self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
685 self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
686 self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
687 self.handler.set_socks_proxy(self.configuration.combine_proxy("socks"))
688 self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
689 elif self.configuration.enable_proxy == False:
690 self.handler.set_http_proxy("")
691 self.handler.set_https_proxy("")
692 self.handler.set_ftp_proxy("")
693 self.handler.set_socks_proxy("")
694 self.handler.set_cvs_proxy("", "")
695
696 def set_user_config_extra(self):
697 self.handler.set_rootfs_size(self.configuration.image_rootfs_size)
698 self.handler.set_extra_size(self.configuration.image_extra_size)
699 self.handler.set_incompatible_license(self.configuration.incompat_license)
700 self.handler.set_sdk_machine(self.configuration.curr_sdk_machine)
701 self.handler.set_image_fstypes(self.configuration.image_fstypes)
702 self.handler.set_extra_config(self.configuration.extra_setting)
703 self.handler.set_extra_inherit("packageinfo image_types")
704 self.set_user_config_proxies()
705
706 def set_user_config(self):
707 self.handler.reset_cooker()
708 # set bb layers
709 self.handler.set_bblayers(self.configuration.layers)
710 # set local configuration
711 self.handler.set_machine(self.configuration.curr_mach)
712 self.handler.set_package_format(self.configuration.curr_package_format)
713 self.handler.set_distro(self.configuration.curr_distro)
714 self.handler.set_dl_dir(self.configuration.dldir)
715 self.handler.set_sstate_dir(self.configuration.sstatedir)
716 self.handler.set_sstate_mirrors(self.configuration.sstatemirror)
717 self.handler.set_pmake(self.configuration.pmake)
718 self.handler.set_bbthreads(self.configuration.bbthread)
719 self.set_user_config_extra()
720
721 def update_recipe_model(self, selected_image, selected_recipes):
722 self.recipe_model.set_selected_image(selected_image)
723 self.recipe_model.set_selected_recipes(selected_recipes)
724
725 def update_package_model(self, selected_packages, user_selected_packages=None):
726 if user_selected_packages:
727 left = self.package_model.set_selected_packages(user_selected_packages, True)
728 self.configuration.user_selected_packages += left
729 left = self.package_model.set_selected_packages(selected_packages)
730 self.configuration.selected_packages += left
731
732 def update_configuration_parameters(self, params):
733 if params:
734 self.configuration.update(params)
735 self.parameters.update(params)
736
737 def reset(self):
738 self.configuration.curr_mach = ""
739 self.configuration.clear_selection()
740 self.image_configuration_page.switch_machine_combo()
741 self.switch_page(self.MACHINE_SELECTION)
742
743 # Callback Functions
744 def handler_config_updated_cb(self, handler, which, values):
745 if which == "distro":
746 self.parameters.all_distros = values
747 elif which == "machine":
748 self.parameters.all_machines = values
749 self.image_configuration_page.update_machine_combo()
750 elif which == "machine-sdk":
751 self.parameters.all_sdk_machines = values
752
753 def handler_package_formats_updated_cb(self, handler, formats):
754 self.parameters.all_package_formats = formats
755
756 def switch_to_image_configuration_helper(self):
757 self.sanity_check_page.stop()
758 self.switch_page(self.IMAGE_CONFIGURATION)
759 self.image_configuration_page.switch_machine_combo()
760
761 def show_network_error_dialog_helper(self):
762 self.sanity_check_page.stop()
763 self.show_network_error_dialog()
764
765 def handler_command_succeeded_cb(self, handler, initcmd):
766 if initcmd == self.handler.GENERATE_CONFIGURATION:
767 if not self.configuration.curr_mach:
768 self.configuration.curr_mach = self.handler.runCommand(["getVariable", "HOB_MACHINE"]) or ""
769 self.update_configuration_parameters(self.get_parameters_sync())
770 if not self.sanity_checked:
771 self.sanity_check()
772 self.sanity_checked = True
773 elif initcmd == self.handler.SANITY_CHECK:
774 if self.had_network_error:
775 self.had_network_error = False
776 self.execute_after_sanity_check(self.show_network_error_dialog_helper)
777 else:
778 # Switch to the 'image configuration' page now, but we might need
779 # to wait for the minimum display time of the sanity check page
780 self.execute_after_sanity_check(self.switch_to_image_configuration_helper)
781 elif initcmd in [self.handler.GENERATE_RECIPES,
782 self.handler.GENERATE_PACKAGES,
783 self.handler.GENERATE_IMAGE]:
784 self.update_configuration_parameters(self.get_parameters_sync())
785 self.request_package_info_async()
786 elif initcmd == self.handler.POPULATE_PACKAGEINFO:
787 if self.current_step == self.RCPPKGINFO_POPULATING:
788 self.switch_page(self.RCPPKGINFO_POPULATED)
789 self.rcppkglist_populated()
790 return
791
792 self.rcppkglist_populated()
793 if self.current_step == self.FAST_IMAGE_GENERATING:
794 self.generate_image_async(True)
795
796 def show_error_dialog(self, msg):
797 lbl = "<b>Hob found an error</b>\n"
798 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR, msg)
799 button = dialog.add_button("Close", gtk.RESPONSE_OK)
800 HobButton.style_button(button)
801 response = dialog.run()
802 dialog.destroy()
803
804 def show_warning_dialog(self):
805 dialog = ParsingWarningsDialog(title = "View warnings",
806 warnings = self.parsing_warnings,
807 parent = None,
808 flags = gtk.DIALOG_DESTROY_WITH_PARENT
809 | gtk.DIALOG_NO_SEPARATOR)
810 response = dialog.run()
811 dialog.destroy()
812
813 def show_network_error_dialog(self):
814 lbl = "<b>Hob cannot connect to the network</b>\n"
815 msg = "Please check your network connection. If you are using a proxy server, please make sure it is configured correctly."
816 lbl = lbl + "%s\n\n" % glib.markup_escape_text(msg)
817 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
818 button = dialog.add_button("Close", gtk.RESPONSE_OK)
819 HobButton.style_button(button)
820 button = dialog.add_button("Proxy settings", gtk.RESPONSE_CANCEL)
821 HobButton.style_button(button)
822 res = dialog.run()
823 dialog.destroy()
824 if res == gtk.RESPONSE_CANCEL:
825 res, settings_changed = self.show_simple_settings_dialog(SimpleSettingsDialog.PROXIES_PAGE_ID)
826 if not res:
827 return
828 if settings_changed:
829 self.reparse_post_adv_settings()
830
831 def handler_command_failed_cb(self, handler, msg):
832 if msg:
833 self.show_error_dialog(msg)
834 self.reset()
835
836 def handler_parsing_warning_cb(self, handler, warn_msg):
837 self.parsing_warnings.append(warn_msg)
838
839 def handler_sanity_failed_cb(self, handler, msg, network_error):
840 self.reset()
841 if network_error:
842 # Mark this in an internal field. The "network error" dialog will be
843 # shown later, when a SanityCheckPassed event will be handled
844 # (as sent by sanity.bbclass)
845 self.had_network_error = True
846 else:
847 msg = msg.replace("your local.conf", "Settings")
848 self.show_error_dialog(msg)
849 self.reset()
850
851 def window_sensitive(self, sensitive):
852 self.image_configuration_page.machine_combo.set_sensitive(sensitive)
853 self.image_configuration_page.machine_combo.child.set_sensitive(sensitive)
854 self.image_configuration_page.image_combo.set_sensitive(sensitive)
855 self.image_configuration_page.image_combo.child.set_sensitive(sensitive)
856 self.image_configuration_page.layer_button.set_sensitive(sensitive)
857 self.image_configuration_page.layer_info_icon.set_sensitive(sensitive)
858 self.image_configuration_page.toolbar.set_sensitive(sensitive)
859 self.image_configuration_page.view_adv_configuration_button.set_sensitive(sensitive)
860 self.image_configuration_page.config_build_button.set_sensitive(sensitive)
861
862 self.recipe_details_page.set_sensitive(sensitive)
863 self.package_details_page.set_sensitive(sensitive)
864 self.build_details_page.set_sensitive(sensitive)
865 self.image_details_page.set_sensitive(sensitive)
866
867 if sensitive:
868 self.window.set_cursor(None)
869 else:
870 self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
871 self.sensitive = sensitive
872
873
874 def handler_generating_data_cb(self, handler):
875 self.window_sensitive(False)
876
877 def handler_data_generated_cb(self, handler):
878 self.window_sensitive(True)
879
880 def rcppkglist_populated(self):
881 selected_image = self.configuration.selected_image
882 selected_recipes = self.configuration.selected_recipes[:]
883 selected_packages = self.configuration.selected_packages[:]
884 user_selected_packages = self.configuration.user_selected_packages[:]
885
886 self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
887 self.image_configuration_page.update_image_desc()
888 self.update_recipe_model(selected_image, selected_recipes)
889 self.update_package_model(selected_packages, user_selected_packages)
890
891 def recipelist_changed_cb(self, recipe_model):
892 self.recipe_details_page.refresh_selection()
893
894 def packagelist_changed_cb(self, package_model):
895 self.package_details_page.refresh_selection()
896
897 def handler_recipe_populated_cb(self, handler):
898 self.image_configuration_page.update_progress_bar("Populating recipes", 0.99)
899
900 def handler_package_populated_cb(self, handler):
901 self.image_configuration_page.update_progress_bar("Populating packages", 1.0)
902
903 def handler_parsing_started_cb(self, handler, message):
904 if self.current_step != self.RCPPKGINFO_POPULATING:
905 return
906
907 fraction = 0
908 if message["eventname"] == "TreeDataPreparationStarted":
909 fraction = 0.6 + fraction
910 self.image_configuration_page.stop_button.set_sensitive(False)
911 self.image_configuration_page.update_progress_bar("Generating dependency tree", fraction)
912 else:
913 self.image_configuration_page.stop_button.set_sensitive(True)
914 self.image_configuration_page.update_progress_bar(message["title"], fraction)
915
916 def handler_parsing_cb(self, handler, message):
917 if self.current_step != self.RCPPKGINFO_POPULATING:
918 return
919
920 fraction = message["current"] * 1.0/message["total"]
921 if message["eventname"] == "TreeDataPreparationProgress":
922 fraction = 0.6 + 0.38 * fraction
923 self.image_configuration_page.update_progress_bar("Generating dependency tree", fraction)
924 else:
925 fraction = 0.6 * fraction
926 self.image_configuration_page.update_progress_bar(message["title"], fraction)
927
928 def handler_parsing_completed_cb(self, handler, message):
929 if self.current_step != self.RCPPKGINFO_POPULATING:
930 return
931
932 if message["eventname"] == "TreeDataPreparationCompleted":
933 fraction = 0.98
934 else:
935 fraction = 0.6
936 self.image_configuration_page.update_progress_bar("Generating dependency tree", fraction)
937
938 def handler_build_started_cb(self, running_build):
939 if self.current_step == self.FAST_IMAGE_GENERATING:
940 fraction = 0
941 elif self.current_step == self.IMAGE_GENERATING:
942 if self.previous_step == self.FAST_IMAGE_GENERATING:
943 fraction = 0.9
944 else:
945 fraction = 0
946 elif self.current_step == self.PACKAGE_GENERATING:
947 fraction = 0
948 self.build_details_page.update_progress_bar("Build Started: ", fraction)
949 self.build_details_page.show_configurations(self.configuration, self.parameters)
950
951 def build_succeeded(self):
952 if self.current_step == self.FAST_IMAGE_GENERATING:
953 fraction = 0.9
954 elif self.current_step == self.IMAGE_GENERATING:
955 fraction = 1.0
956 version = ""
957 self.parameters.image_names = []
958 selected_image = self.recipe_model.get_selected_image()
959 if selected_image == self.recipe_model.__custom_image__:
960 if self.configuration.initial_selected_image != selected_image:
961 version = self.recipe_model.get_custom_image_version()
962 linkname = 'hob-image' + version+ "-" + self.configuration.curr_mach
963 else:
964 linkname = selected_image + '-' + self.configuration.curr_mach
965 image_extension = self.get_image_extension()
966 for image_type in self.parameters.image_types:
967 if image_type in image_extension:
968 real_types = image_extension[image_type]
969 else:
970 real_types = [image_type]
971 for real_image_type in real_types:
972 linkpath = self.parameters.image_addr + '/' + linkname + '.' + real_image_type
973 if os.path.exists(linkpath):
974 self.parameters.image_names.append(os.readlink(linkpath))
975 elif self.current_step == self.PACKAGE_GENERATING:
976 fraction = 1.0
977 self.build_details_page.update_progress_bar("Build Completed: ", fraction)
978 self.handler.build_succeeded_async()
979 self.stopping = False
980
981 if self.current_step == self.PACKAGE_GENERATING:
982 self.switch_page(self.PACKAGE_GENERATED)
983 elif self.current_step == self.IMAGE_GENERATING:
984 self.switch_page(self.IMAGE_GENERATED)
985
986 def build_failed(self):
987 if self.stopping:
988 status = "stop"
989 message = "Build stopped: "
990 fraction = self.build_details_page.progress_bar.get_fraction()
991 stop_to_next_edit = ""
992 if self.current_step == self.FAST_IMAGE_GENERATING:
993 stop_to_next_edit = "image configuration"
994 elif self.current_step == self.IMAGE_GENERATING:
995 if self.previous_step == self.FAST_IMAGE_GENERATING:
996 stop_to_next_edit = "image configuration"
997 else:
998 stop_to_next_edit = "packages"
999 elif self.current_step == self.PACKAGE_GENERATING:
1000 stop_to_next_edit = "recipes"
1001 button = self.build_details_page.show_stop_page(stop_to_next_edit.split(' ')[0])
1002 self.set_default(button)
1003 else:
1004 fail_to_next_edit = ""
1005 if self.current_step == self.FAST_IMAGE_GENERATING:
1006 fail_to_next_edit = "image configuration"
1007 fraction = 0.9
1008 elif self.current_step == self.IMAGE_GENERATING:
1009 if self.previous_step == self.FAST_IMAGE_GENERATING:
1010 fail_to_next_edit = "image configuration"
1011 else:
1012 fail_to_next_edit = "packages"
1013 fraction = 1.0
1014 elif self.current_step == self.PACKAGE_GENERATING:
1015 fail_to_next_edit = "recipes"
1016 fraction = 1.0
1017 self.build_details_page.show_fail_page(fail_to_next_edit.split(' ')[0])
1018 status = "fail"
1019 message = "Build failed: "
1020 self.build_details_page.update_progress_bar(message, fraction, status)
1021 self.build_details_page.show_back_button()
1022 self.build_details_page.hide_stop_button()
1023 self.handler.build_failed_async()
1024 self.stopping = False
1025
1026 def handler_build_succeeded_cb(self, running_build):
1027 if not self.stopping:
1028 self.build_succeeded()
1029 else:
1030 self.build_failed()
1031
1032
1033 def handler_build_failed_cb(self, running_build):
1034 self.build_failed()
1035
1036 def handler_build_aborted_cb(self, running_build):
1037 self.build_failed()
1038
1039 def handler_no_provider_cb(self, running_build, msg):
1040 dialog = CrumbsMessageDialog(self, glib.markup_escape_text(msg), gtk.STOCK_DIALOG_INFO)
1041 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1042 HobButton.style_button(button)
1043 dialog.run()
1044 dialog.destroy()
1045 self.build_failed()
1046
1047 def handler_task_started_cb(self, running_build, message):
1048 fraction = message["current"] * 1.0/message["total"]
1049 title = "Build packages"
1050 if self.current_step == self.FAST_IMAGE_GENERATING:
1051 if message["eventname"] == "sceneQueueTaskStarted":
1052 fraction = 0.27 * fraction
1053 elif message["eventname"] == "runQueueTaskStarted":
1054 fraction = 0.27 + 0.63 * fraction
1055 elif self.current_step == self.IMAGE_GENERATING:
1056 title = "Build image"
1057 if self.previous_step == self.FAST_IMAGE_GENERATING:
1058 if message["eventname"] == "sceneQueueTaskStarted":
1059 fraction = 0.27 + 0.63 + 0.03 * fraction
1060 elif message["eventname"] == "runQueueTaskStarted":
1061 fraction = 0.27 + 0.63 + 0.03 + 0.07 * fraction
1062 else:
1063 if message["eventname"] == "sceneQueueTaskStarted":
1064 fraction = 0.2 * fraction
1065 elif message["eventname"] == "runQueueTaskStarted":
1066 fraction = 0.2 + 0.8 * fraction
1067 elif self.current_step == self.PACKAGE_GENERATING:
1068 if message["eventname"] == "sceneQueueTaskStarted":
1069 fraction = 0.2 * fraction
1070 elif message["eventname"] == "runQueueTaskStarted":
1071 fraction = 0.2 + 0.8 * fraction
1072 self.build_details_page.update_progress_bar(title + ": ", fraction)
1073 self.build_details_page.update_build_status(message["current"], message["total"], message["task"])
1074
1075 def handler_disk_full_cb(self, running_build):
1076 self.disk_full = True
1077
1078 def handler_build_failure_cb(self, running_build):
1079 self.build_details_page.show_issues()
1080
1081 def handler_build_log_cb(self, running_build, func, obj):
1082 if hasattr(self.logger, func):
1083 getattr(self.logger, func)(obj)
1084
1085 def destroy_window_cb(self, widget, event):
1086 if not self.sensitive:
1087 return True
1088 elif self.handler.building:
1089 self.stop_build()
1090 return True
1091 else:
1092 gtk.main_quit()
1093
1094 def event_handle_SIGINT(self, signal, frame):
1095 for w in gtk.window_list_toplevels():
1096 if w.get_modal():
1097 w.response(gtk.RESPONSE_DELETE_EVENT)
1098 sys.exit(0)
1099
1100 def build_packages(self):
1101 _, all_recipes = self.recipe_model.get_selected_recipes()
1102 if not all_recipes:
1103 lbl = "<b>No selections made</b>\nYou have not made any selections"
1104 lbl = lbl + " so there isn't anything to bake at this time."
1105 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1106 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1107 HobButton.style_button(button)
1108 dialog.run()
1109 dialog.destroy()
1110 return
1111 self.generate_packages_async(True)
1112
1113 def build_image(self):
1114 selected_packages = self.package_model.get_selected_packages()
1115 if not selected_packages:
1116 lbl = "<b>No selections made</b>\nYou have not made any selections"
1117 lbl = lbl + " so there isn't anything to bake at this time."
1118 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1119 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1120 HobButton.style_button(button)
1121 dialog.run()
1122 dialog.destroy()
1123 return
1124 self.generate_image_async(True)
1125
1126 def just_bake(self):
1127 selected_image = self.recipe_model.get_selected_image()
1128 selected_packages = self.package_model.get_selected_packages() or []
1129
1130 # If no base image and no selected packages don't build anything
1131 if not (selected_packages or selected_image != self.recipe_model.__custom_image__):
1132 lbl = "<b>No selections made</b>\nYou have not made any selections"
1133 lbl = lbl + " so there isn't anything to bake at this time."
1134 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1135 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1136 HobButton.style_button(button)
1137 dialog.run()
1138 dialog.destroy()
1139 return
1140
1141 self.fast_generate_image_async(True)
1142
1143 def show_recipe_property_dialog(self, properties):
1144 information = {}
1145 dialog = PropertyDialog(title = properties["name"] +' '+ "properties",
1146 parent = self,
1147 information = properties,
1148 flags = gtk.DIALOG_DESTROY_WITH_PARENT
1149 | gtk.DIALOG_NO_SEPARATOR)
1150
1151 dialog.set_modal(False)
1152
1153 button = dialog.add_button("Close", gtk.RESPONSE_NO)
1154 HobAltButton.style_button(button)
1155 button.connect("clicked", lambda w: dialog.destroy())
1156
1157 dialog.run()
1158
1159 def show_packages_property_dialog(self, properties):
1160 information = {}
1161 dialog = PropertyDialog(title = properties["name"] +' '+ "properties",
1162 parent = self,
1163 information = properties,
1164 flags = gtk.DIALOG_DESTROY_WITH_PARENT
1165 | gtk.DIALOG_NO_SEPARATOR)
1166
1167 dialog.set_modal(False)
1168
1169 button = dialog.add_button("Close", gtk.RESPONSE_NO)
1170 HobAltButton.style_button(button)
1171 button.connect("clicked", lambda w: dialog.destroy())
1172
1173 dialog.run()
1174
1175 def show_layer_selection_dialog(self):
1176 dialog = LayerSelectionDialog(title = "Layers",
1177 layers = copy.deepcopy(self.configuration.layers),
1178 layers_non_removable = copy.deepcopy(self.configuration.layers_non_removable),
1179 all_layers = self.parameters.all_layers,
1180 parent = self,
1181 flags = gtk.DIALOG_MODAL
1182 | gtk.DIALOG_DESTROY_WITH_PARENT
1183 | gtk.DIALOG_NO_SEPARATOR)
1184 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1185 HobAltButton.style_button(button)
1186 button = dialog.add_button("OK", gtk.RESPONSE_YES)
1187 HobButton.style_button(button)
1188 response = dialog.run()
1189 if response == gtk.RESPONSE_YES:
1190 self.configuration.layers = dialog.layers
1191 # DO refresh layers
1192 if dialog.layers_changed:
1193 self.update_config_async()
1194 dialog.destroy()
1195
1196 def get_image_extension(self):
1197 image_extension = {}
1198 for type in self.parameters.image_types:
1199 ext = self.handler.runCommand(["getVariable", "IMAGE_EXTENSION_%s" % type])
1200 if ext:
1201 image_extension[type] = ext.split(' ')
1202
1203 return image_extension
1204
1205 def show_load_my_images_dialog(self):
1206 image_extension = self.get_image_extension()
1207 dialog = ImageSelectionDialog(self.parameters.image_addr, self.parameters.image_types,
1208 "Open My Images", self,
1209 gtk.FILE_CHOOSER_ACTION_SAVE, None,
1210 image_extension)
1211 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1212 HobAltButton.style_button(button)
1213 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1214 HobButton.style_button(button)
1215 response = dialog.run()
1216 if response == gtk.RESPONSE_YES:
1217 if not dialog.image_names:
1218 lbl = "<b>No selections made</b>\nYou have not made any selections"
1219 crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1220 button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
1221 HobButton.style_button(button)
1222 crumbs_dialog.run()
1223 crumbs_dialog.destroy()
1224 dialog.destroy()
1225 return
1226
1227 self.parameters.image_addr = dialog.image_folder
1228 self.parameters.image_names = dialog.image_names[:]
1229 self.switch_page(self.MY_IMAGE_OPENED)
1230
1231 dialog.destroy()
1232
1233 def show_adv_settings_dialog(self, tab=None):
1234 dialog = AdvancedSettingsDialog(title = "Advanced configuration",
1235 configuration = copy.deepcopy(self.configuration),
1236 all_image_types = self.parameters.image_types,
1237 all_package_formats = self.parameters.all_package_formats,
1238 all_distros = self.parameters.all_distros,
1239 all_sdk_machines = self.parameters.all_sdk_machines,
1240 max_threads = self.parameters.max_threads,
1241 parent = self,
1242 flags = gtk.DIALOG_MODAL
1243 | gtk.DIALOG_DESTROY_WITH_PARENT
1244 | gtk.DIALOG_NO_SEPARATOR)
1245 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1246 HobAltButton.style_button(button)
1247 button = dialog.add_button("Save", gtk.RESPONSE_YES)
1248 HobButton.style_button(button)
1249 dialog.set_save_button(button)
1250 response = dialog.run()
1251 settings_changed = False
1252 if response == gtk.RESPONSE_YES:
1253 self.configuration = dialog.configuration
1254 self.configuration.save(self.handler, True) # remember settings
1255 settings_changed = dialog.settings_changed
1256 dialog.destroy()
1257 return response == gtk.RESPONSE_YES, settings_changed
1258
1259 def show_simple_settings_dialog(self, tab=None):
1260 dialog = SimpleSettingsDialog(title = "Settings",
1261 configuration = copy.deepcopy(self.configuration),
1262 all_image_types = self.parameters.image_types,
1263 all_package_formats = self.parameters.all_package_formats,
1264 all_distros = self.parameters.all_distros,
1265 all_sdk_machines = self.parameters.all_sdk_machines,
1266 max_threads = self.parameters.max_threads,
1267 parent = self,
1268 flags = gtk.DIALOG_MODAL
1269 | gtk.DIALOG_DESTROY_WITH_PARENT
1270 | gtk.DIALOG_NO_SEPARATOR,
1271 handler = self.handler)
1272 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1273 HobAltButton.style_button(button)
1274 button = dialog.add_button("Save", gtk.RESPONSE_YES)
1275 HobButton.style_button(button)
1276 if tab:
1277 dialog.switch_to_page(tab)
1278 response = dialog.run()
1279 settings_changed = False
1280 if response == gtk.RESPONSE_YES:
1281 self.configuration = dialog.configuration
1282 self.configuration.save(self.handler, True) # remember settings
1283 settings_changed = dialog.settings_changed
1284 if dialog.proxy_settings_changed:
1285 self.set_user_config_proxies()
1286 elif dialog.proxy_test_ran:
1287 # The user might have modified the proxies in the "Proxy"
1288 # tab, which in turn made the proxy settings modify in bb.
1289 # If "Cancel" was pressed, restore the previous proxy
1290 # settings inside bb.
1291 self.set_user_config_proxies()
1292 dialog.destroy()
1293 return response == gtk.RESPONSE_YES, settings_changed
1294
1295 def reparse_post_adv_settings(self):
1296 if not self.configuration.curr_mach:
1297 self.update_config_async()
1298 else:
1299 self.configuration.clear_selection()
1300 # DO reparse recipes
1301 self.populate_recipe_package_info_async()
1302
1303 def deploy_image(self, image_name):
1304 if not image_name:
1305 lbl = "<b>Please select an image to deploy.</b>"
1306 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1307 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1308 HobButton.style_button(button)
1309 dialog.run()
1310 dialog.destroy()
1311 return
1312
1313 image_path = os.path.join(self.parameters.image_addr, image_name)
1314 dialog = DeployImageDialog(title = "Usb Image Maker",
1315 image_path = image_path,
1316 parent = self,
1317 flags = gtk.DIALOG_MODAL
1318 | gtk.DIALOG_DESTROY_WITH_PARENT
1319 | gtk.DIALOG_NO_SEPARATOR)
1320 button = dialog.add_button("Close", gtk.RESPONSE_NO)
1321 HobAltButton.style_button(button)
1322 button = dialog.add_button("Make usb image", gtk.RESPONSE_YES)
1323 HobButton.style_button(button)
1324 response = dialog.run()
1325 dialog.destroy()
1326
1327 def show_load_kernel_dialog(self):
1328 dialog = gtk.FileChooserDialog("Load Kernel Files", self,
1329 gtk.FILE_CHOOSER_ACTION_SAVE)
1330 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1331 HobAltButton.style_button(button)
1332 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1333 HobButton.style_button(button)
1334 filter = gtk.FileFilter()
1335 filter.set_name("Kernel Files")
1336 filter.add_pattern("*.bin")
1337 dialog.add_filter(filter)
1338
1339 dialog.set_current_folder(self.parameters.image_addr)
1340
1341 response = dialog.run()
1342 kernel_path = ""
1343 if response == gtk.RESPONSE_YES:
1344 kernel_path = dialog.get_filename()
1345
1346 dialog.destroy()
1347
1348 return kernel_path
1349
1350 def runqemu_image(self, image_name, kernel_name):
1351 if not image_name or not kernel_name:
1352 lbl = "<b>Please select an %s to launch in QEMU.</b>" % ("kernel" if image_name else "image")
1353 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1354 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1355 HobButton.style_button(button)
1356 dialog.run()
1357 dialog.destroy()
1358 return
1359
1360 kernel_path = os.path.join(self.parameters.image_addr, kernel_name)
1361 image_path = os.path.join(self.parameters.image_addr, image_name)
1362
1363 source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
1364 tmp_path = self.parameters.tmpdir
1365 cmdline = bb.ui.crumbs.utils.which_terminal()
1366 if os.path.exists(image_path) and os.path.exists(kernel_path) \
1367 and os.path.exists(source_env_path) and os.path.exists(tmp_path) \
1368 and cmdline:
1369 cmdline += "\' bash -c \"export OE_TMPDIR=" + tmp_path + "; "
1370 cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
1371 cmdline += "runqemu " + kernel_path + " " + image_path + "\"\'"
1372 subprocess.Popen(shlex.split(cmdline))
1373 else:
1374 lbl = "<b>Path error</b>\nOne of your paths is wrong,"
1375 lbl = lbl + " please make sure the following paths exist:\n"
1376 lbl = lbl + "image path:" + image_path + "\n"
1377 lbl = lbl + "kernel path:" + kernel_path + "\n"
1378 lbl = lbl + "source environment path:" + source_env_path + "\n"
1379 lbl = lbl + "tmp path: " + tmp_path + "."
1380 lbl = lbl + "You may be missing either xterm or vte for terminal services."
1381 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
1382 button = dialog.add_button("Close", gtk.RESPONSE_OK)
1383 HobButton.style_button(button)
1384 dialog.run()
1385 dialog.destroy()
1386
1387 def show_packages(self, ask=True):
1388 _, selected_recipes = self.recipe_model.get_selected_recipes()
1389 if selected_recipes and ask:
1390 lbl = "<b>Package list may be incomplete!</b>\nDo you want to build selected recipes"
1391 lbl = lbl + " to get a full list or just view the existing packages?"
1392 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1393 button = dialog.add_button("View packages", gtk.RESPONSE_NO)
1394 HobAltButton.style_button(button)
1395 button = dialog.add_button("Build packages", gtk.RESPONSE_YES)
1396 HobButton.style_button(button)
1397 dialog.set_default_response(gtk.RESPONSE_YES)
1398 response = dialog.run()
1399 dialog.destroy()
1400 if response == gtk.RESPONSE_YES:
1401 self.generate_packages_async(True)
1402 else:
1403 self.switch_page(self.PACKAGE_SELECTION)
1404 else:
1405 self.switch_page(self.PACKAGE_SELECTION)
1406
1407 def show_recipes(self):
1408 self.switch_page(self.RECIPE_SELECTION)
1409
1410 def show_image_details(self):
1411 self.switch_page(self.IMAGE_GENERATED)
1412
1413 def show_configuration(self):
1414 self.switch_page(self.BASEIMG_SELECTED)
1415
1416 def stop_build(self):
1417 if self.stopping:
1418 lbl = "<b>Force Stop build?</b>\nYou've already selected Stop once,"
1419 lbl = lbl + " would you like to 'Force Stop' the build?\n\n"
1420 lbl = lbl + "This will stop the build as quickly as possible but may"
1421 lbl = lbl + " well leave your build directory in an unusable state"
1422 lbl = lbl + " that requires manual steps to fix.\n"
1423 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
1424 button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
1425 HobAltButton.style_button(button)
1426 button = dialog.add_button("Force Stop", gtk.RESPONSE_YES)
1427 HobButton.style_button(button)
1428 else:
1429 lbl = "<b>Stop build?</b>\n\nAre you sure you want to stop this"
1430 lbl = lbl + " build?\n\n'Stop' will stop the build as soon as all in"
1431 lbl = lbl + " progress build tasks are finished. However if a"
1432 lbl = lbl + " lengthy compilation phase is in progress this may take"
1433 lbl = lbl + " some time.\n\n"
1434 lbl = lbl + "'Force Stop' will stop the build as quickly as"
1435 lbl = lbl + " possible but may well leave your build directory in an"
1436 lbl = lbl + " unusable state that requires manual steps to fix."
1437 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
1438 button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
1439 HobAltButton.style_button(button)
1440 button = dialog.add_button("Force stop", gtk.RESPONSE_YES)
1441 HobAltButton.style_button(button)
1442 button = dialog.add_button("Stop", gtk.RESPONSE_OK)
1443 HobButton.style_button(button)
1444 response = dialog.run()
1445 dialog.destroy()
1446 if response != gtk.RESPONSE_CANCEL:
1447 self.stopping = True
1448 if response == gtk.RESPONSE_OK:
1449 self.build_details_page.progress_bar.set_stop_title("Stopping the build....")
1450 self.build_details_page.progress_bar.set_rcstyle("stop")
1451 self.cancel_build_sync()
1452 elif response == gtk.RESPONSE_YES:
1453 self.cancel_build_sync(True)
1454
1455 def do_log(self, consolelogfile = None):
1456 if consolelogfile:
1457 bb.utils.mkdirhier(os.path.dirname(consolelogfile))
1458 if self.consolelog:
1459 self.logger.removeHandler(self.consolelog)
1460 self.consolelog = None
1461 self.consolelog = logging.FileHandler(consolelogfile)
1462 bb.msg.addDefaultlogFilter(self.consolelog)
1463 format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
1464 self.consolelog.setFormatter(format)
1465
1466 self.logger.addHandler(self.consolelog)
1467
1468 def get_topdir(self):
1469 return self.handler.get_topdir()
1470
1471 def wait(self, delay):
1472 time_start = time.time()
1473 time_end = time_start + delay
1474 while time_end > time.time():
1475 while gtk.events_pending():
1476 gtk.main_iteration()