hob enhancements and UI bug fixes
cover hob enhancements and UI bug fixes
This series includes several bug fixes and improvements for UI's including:
* Hide the goggle progress bar after cache load
* Adapt to recent msg.py change and reduce messages in RunningBuildTreeView
* Change hob to track and list all packages which bring in the listed package rather than just the first, it's expected that this will increase the usability of the UI by making changes more obvious
Amongst increased usefulness of hob this series ensures goggle is reliably usable once more.
Regards,
Joshua
The following changes since commit d5abdacaf9ac604ef8d8c1bafb9b30617827cb4f:
Fixup remaining bb.msg.domain users (2011-08-15 17:31:18 +0100)
are available in the git repository at:
git://github.com/incandescant/bitbake hob
https://github.com/incandescant/bitbake/tree/hob
Joshua Lock (11):
bb/ui/crumbs/runningbuild: reduce number of messages after recent msg
change
bb/ui/crumbs/runningbuild: hide the progress bar on cache load
complete
bb/ui/crumbs/tasklistmodel: more robust checking for substrings bb/ui/crumbs/tasklistmodel: remove useless items from dependency list bb/ui/crumbs/tasklistmodel: store all binb, not just the first
hob: don't try and build if user selects Bake with no selections made bb/ui/crumbs/tasklistmodel: track the PN for each entry in the model bb/ui/hob: fix package only build bb/ui/crumbs/hobeventhandler: fix return values of
*_image_output_type
bb/ui/crumbs/hobprefs: fix setting IMAGE_FSYTPES bb/ui/hob: warn and prevent image build if no IMAGE_FSTYPE is set
lib/bb/ui/crumbs/hobeventhandler.py | 8 +- lib/bb/ui/crumbs/hobprefs.py | 2 +- lib/bb/ui/crumbs/runningbuild.py | 5 +- lib/bb/ui/crumbs/tasklistmodel.py | 106 ++++++++++++++++++++--------------- lib/bb/ui/hob.py | 34 ++++++++++- 5 files changed, 100 insertions(+), 55 deletions(-)
Signature · 1 line
1.7.6
PATCH 1/11 bb/ui/crumbs/runningbuild: reduce number of messages after recent msg change
The recent change to the message module to remove custom logging domains resulted in an increased number of messages being displayed in the running build view, ignore all messages lower than log level INFO.
--- lib/bb/ui/crumbs/runningbuild.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
lib/bb/ui/crumbs/runningbuild.py +2 -1
@@ -91,7 +91,8 @@ class RunningBuild (gobject.GObject): parent = self.tasks_to_iter[(package, task)] if(isinstance(event, logging.LogRecord)): - if (event.msg.startswith ("Running task")): + if (event.levelno < logging.INFO or + event.msg.startswith("Running task")): return # don't add these to the list if event.levelno >= logging.ERROR:
Signature · 1 line
1.7.6
PATCH 2/11 bb/ui/crumbs/runningbuild: hide the progress bar on cache load complete
In reply to Joshua LockWhen we receive the CacheLoadComplete command we need to ensure the progress bar is hidden as we can't expect the ParseComplete event, where this would usually be done.
This patch makes the Goggle UI usable again.
--- lib/bb/ui/crumbs/runningbuild.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
lib/bb/ui/crumbs/runningbuild.py +1 -1
@@ -254,7 +254,7 @@ class RunningBuild (gobject.GObject): pbar.update(event.current, self.progress_total) elif isinstance(event, bb.event.CacheLoadCompleted) and pbar: pbar.update(self.progress_total, self.progress_total) - + pbar.hide() elif isinstance(event, bb.event.ParseStarted) and pbar: if event.total == 0: return
Signature · 1 line
1.7.6
PATCH 3/11 bb/ui/crumbs/tasklistmodel: more robust checking for substrings
In reply to Joshua LockRelying on the count() method of Str to determine whether the string contains a substring is error prone purely because the return value doesn't strictly convert to a Boolean value.
To that end take the more pythonic approach of using the in operator (foo in bar) to check for the substring.
Further, add a helper method for the common case of testing whether a pn is -native, -cross or virtual/
--- lib/bb/ui/crumbs/tasklistmodel.py | 26 +++++++++++++++++--------- 1 files changed, 17 insertions(+), 9 deletions(-)
lib/bb/ui/crumbs/tasklistmodel.py +17 -9
@@ -124,6 +124,14 @@ class TaskListModel(gtk.ListStore): gobject.TYPE_BOOLEAN, gobject.TYPE_STRING) + """ + Helper method to determine whether name is a target pn + """ + def non_target_name(self, name): + if ('-native' in name) or ('-cross' in name) or name.startswith('virtual/'): + return True + return False + def contents_changed_cb(self, tree_model, path, it=None): pkg_cnt = self.contents.iter_n_children(None) self.emit("contents-changed", pkg_cnt)
@@ -132,7 +140,7 @@ class TaskListModel(gtk.ListStore): if not model.get_value(it, self.COL_INC) or model.get_value(it, self.COL_TYPE) == 'image': return False name = model.get_value(it, self.COL_NAME) - if name.count('-native') or name.count('-cross'): + if self.non_target_name(name): return False else: return True
@@ -196,7 +204,7 @@ class TaskListModel(gtk.ListStore): return False else: name = model.get_value(it, self.COL_NAME) - if name.count('-native') or name.count('-cross'): + if self.non_target_name(name): return False return True
@@ -226,9 +234,9 @@ class TaskListModel(gtk.ListStore): lic = event_model["pn"][item]["license"] group = event_model["pn"][item]["section"] filename = event_model["pn"][item]["filename"] - if name.count('task-') > 0: + if ('task-' in name): atype = 'task' - elif name.count('-image-') > 0: + elif ('-image-' in name): atype = 'image' depends = event_model["depends"].get(item, [])
@@ -352,14 +360,14 @@ class TaskListModel(gtk.ListStore): # If the iterated item is included and depends on the removed # item it should also be removed. # FIXME: need to ensure partial name matching doesn't happen - if inc and deps.count(marked_name) and itname not in removed: + if inc and marked_name in deps and itname not in removed: # found a dependency, remove it removed.append(itname) self.mark(path) # If the iterated item was brought in by the removed (passed) item # try and find an alternative dependee and update the binb column - if inc and binb.count(marked_name): + if inc and marked_name in binb: bib = self.find_alt_dependency(itname) self[path][self.COL_BINB] = bib
@@ -411,7 +419,7 @@ class TaskListModel(gtk.ListStore): deps = self.contents[path][self.COL_DEPS] itname = self.contents[path][self.COL_NAME] inc = self.contents[path][self.COL_INC] - if itname != name and inc and deps.count(name) > 0: + if itname != name and inc and name in deps: # if this item depends on the item, return this items name return itname it = self.contents.iter_next(it)
@@ -471,7 +479,7 @@ class TaskListModel(gtk.ListStore): def find_path_for_item(self, item_name): # We don't include virtual/* or *-native items in the model so save a # heavy iteration loop by exiting early for these items - if item_name.startswith("virtual/") or item_name.count('-native') or item_name.count('-cross'): + if self.non_target_name(item_name): return None it = self.get_iter_first()
@@ -561,7 +569,7 @@ class TaskListModel(gtk.ListStore): if not itype == 'package': continue - if deps.count(pn) != 0: + if pn not in deps: revdeps.append(name) if pn in revdeps:
Signature · 1 line
1.7.6
PATCH 4/11 bb/ui/crumbs/tasklistmodel: remove useless items from dependency list
In reply to Joshua LockEnsure the dependency list is uniquified, doesn't include self references and further doesn't include -dev references.
--- lib/bb/ui/crumbs/tasklistmodel.py | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-)
lib/bb/ui/crumbs/tasklistmodel.py +10 -2
@@ -239,10 +239,11 @@ class TaskListModel(gtk.ListStore): elif ('-image-' in name): atype = 'image' + # Create a combined list of build and runtime dependencies and + # then remove any duplicate entries and any entries for -dev + # packages depends = event_model["depends"].get(item, []) rdepends = event_model["rdepends-pn"].get(item, []) - if ("%s-dev" % item) in rdepends: - rdepends.remove("%s-dev" % item) packages = {} for pkg in event_model["packages"]: if event_model["packages"][pkg]["pn"] == name:
@@ -250,6 +251,13 @@ class TaskListModel(gtk.ListStore): deps.extend(depends) deps.extend(event_model["rdepends-pkg"].get(pkg, [])) deps.extend(rdepends) + deps = self.squish(deps) + # rdepends-pn includes pn-dev + if ("%s-dev" % item) in deps: + deps.remove("%s-dev" % item) + # rdepends-on includes pn + if pkg in deps: + deps.remove(pkg) packages[pkg] = deps for p in packages:
Signature · 1 line
1.7.6
PATCH 5/11 bb/ui/crumbs/tasklistmodel: store all binb, not just the first
In reply to Joshua LockThis makes it easier for the user to determine what the effects of a removal may be, further it means we no longer need the find_alt_dependency method which could be a fairly time-consuming method depending on the size of the contents table.
Partially addresses [YOCTO #1365]
--- lib/bb/ui/crumbs/tasklistmodel.py | 50 ++++++++++++------------------------ 1 files changed, 17 insertions(+), 33 deletions(-)
lib/bb/ui/crumbs/tasklistmodel.py +17 -33
@@ -350,7 +350,7 @@ class TaskListModel(gtk.ListStore): inc = self[path][self.COL_INC] deps = self[path][self.COL_DEPS] - binb = self[path][self.COL_BINB] + binb = self[path][self.COL_BINB].split(', ') itype = self[path][self.COL_TYPE] itname = self[path][self.COL_NAME]
@@ -362,7 +362,7 @@ class TaskListModel(gtk.ListStore): # we should keep it and its dependencies, the easiest way to do so # is to save its name and re-mark it for inclusion once dependency # processing is complete - if binb == "User Selected": + if "User Selected" in binb: usersel[itname] = self[path][self.COL_IMG] # If the iterated item is included and depends on the removed
@@ -376,8 +376,8 @@ class TaskListModel(gtk.ListStore): # If the iterated item was brought in by the removed (passed) item # try and find an alternative dependee and update the binb column if inc and marked_name in binb: - bib = self.find_alt_dependency(itname) - self[path][self.COL_BINB] = bib + binb.remove(marked_name) + self[path][self.COL_BINB] = ', '.join(binb).lstrip(', ') # Re-add any removed user selected items for u in usersel:
@@ -415,25 +415,6 @@ class TaskListModel(gtk.ListStore): it = self.contents.iter_next(it) """ - Find the name of an item in the image contents which depends on the item - name. - Returns either an item name (str) or None - """ - def find_alt_dependency(self, name): - it = self.contents.get_iter_first() - while it: - # iterate all items in the contents model - path = self.contents.get_path(it) - deps = self.contents[path][self.COL_DEPS] - itname = self.contents[path][self.COL_NAME] - inc = self.contents[path][self.COL_INC] - if itname != name and inc and name in deps: - # if this item depends on the item, return this items name - return itname - it = self.contents.iter_next(it) - return "" - - """ Check the self.contents gtk.TreeModel for an item where COL_NAME matches item_name Returns True if a match is found, False otherwise
@@ -456,7 +437,10 @@ class TaskListModel(gtk.ListStore): cur_inc = self[item_path][self.COL_INC] if not cur_inc: self[item_path][self.COL_INC] = True - self[item_path][self.COL_BINB] = binb + + bin = self[item_path][self.COL_BINB].split(', ') + bin.append(binb) + self[item_path][self.COL_BINB] = ', '.join(bin).lstrip(', ') # We want to do some magic with things which are brought in by the # base image so tag them as so
@@ -469,16 +453,16 @@ class TaskListModel(gtk.ListStore): # add all of the deps and set their binb to this item for dep in deps.split(" "): # If the contents model doesn't already contain dep, add it - # We only care to show things which will end up in the - # resultant image, so filter cross and native recipes dep_included = self.contents_includes_name(dep) path = self.find_path_for_item(dep) - if not dep_included and path: - self.include_item(path, name, image_contents) - # Set brought in by for any no longer orphan packages - elif dep_included and path: - if not self[path][self.COL_BINB]: - self[path][self.COL_BINB] = name + if not path: + continue + if dep_included: + bin = self[path][self.COL_BINB].split(', ') + bin.append(name) + self[path][self.COL_BINB] = ', '.join(bin).lstrip(', ') + else: + self.include_item(path, binb=name, image_contents=image_contents) """ Find the model path for the item_name
@@ -535,7 +519,7 @@ class TaskListModel(gtk.ListStore): it = self.contents.get_iter_first() while it: - sel = self.contents.get_value(it, self.COL_BINB) == "User Selected" + sel = "User Selected" in self.contents.get_value(it, self.COL_BINB) name = self.contents.get_value(it, self.COL_NAME) allpkgs.append(name) if sel:
Signature · 1 line
1.7.6
PATCH 6/11 hob: don't try and build if user selects Bake with no selections made
In reply to Joshua LockIf the user hasn't made any selections inform them that they need to do so before clicking Bake.
Fixes [YOCTO #1384]
--- lib/bb/ui/hob.py | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
lib/bb/ui/hob.py +13 -1
@@ -405,7 +405,19 @@ class MainWindow (gtk.Window): build_image = True rep = self.model.get_build_rep() - if not rep.base_image: + + # If no base image and no user selected packages don't build anything + if not self.selected_image and not len(rep.userpkgs): + lbl = "<b>No selections made</b>\nYou have not made any selections" + lbl = lbl + " so there isn't anything to bake at this time." + dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO) + dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) + dialog.run() + dialog.destroy() + return + # Else if no base image, ask whether to just build packages or whether + # to build a rootfs with the selected packages in + elif not self.selected_image: lbl = "<b>Build empty image or only packages?</b>\nA base image" lbl = lbl + " has not been selected.\n\'Empty image' will build" lbl = lbl + " an image with only the selected packages as its"
Signature · 1 line
1.7.6
PATCH 7/11 bb/ui/crumbs/tasklistmodel: track the PN for each entry in the model
In reply to Joshua LockNow that we've switched to packages in the model, rather than PN, it makes sense to add an extra field to store the PN of the package.
This patch includes a convenience method to retrieve a list of selected PN's.
--- lib/bb/ui/crumbs/tasklistmodel.py | 20 ++++++++++++++++++-- 1 files changed, 18 insertions(+), 2 deletions(-)
lib/bb/ui/crumbs/tasklistmodel.py +18 -2
@@ -89,7 +89,7 @@ class TaskListModel(gtk.ListStore): providing convenience functions to access gtk.TreeModel subclasses which provide filtered views of the data. """ - (COL_NAME, COL_DESC, COL_LIC, COL_GROUP, COL_DEPS, COL_BINB, COL_TYPE, COL_INC, COL_IMG, COL_PATH) = range(10) + (COL_NAME, COL_DESC, COL_LIC, COL_GROUP, COL_DEPS, COL_BINB, COL_TYPE, COL_INC, COL_IMG, COL_PATH, COL_PN) = range(11) __gsignals__ = { "tasklist-populated" : (gobject.SIGNAL_RUN_LAST,
@@ -122,6 +122,7 @@ class TaskListModel(gtk.ListStore): gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, + gobject.TYPE_STRING, gobject.TYPE_STRING) """
@@ -265,7 +266,8 @@ class TaskListModel(gtk.ListStore): self.COL_LIC, lic, self.COL_GROUP, group, self.COL_DEPS, " ".join(packages[p]), self.COL_BINB, "", self.COL_TYPE, atype, self.COL_INC, False, - self.COL_IMG, False, self.COL_PATH, filename) + self.COL_IMG, False, self.COL_PATH, filename, + self.COL_PN, item) self.emit("tasklist-populated")
@@ -527,6 +529,20 @@ class TaskListModel(gtk.ListStore): it = self.contents.iter_next(it) return userpkgs, allpkgs + """ + Return a squished (uniquified) list of the PN's of all selected items + """ + def get_selected_pn(self): + pns = [] + + it = self.contents.get_iter_first() + while it: + if self.contents.get_value(it, self.COL_BINB): + pns.append(self.contents.get_value(it, self.COL_PN)) + it = self.contents.iter_next(it) + + return self.squish(pns) + def image_contents_removed(self): it = self.get_iter_first() while it:
Signature · 1 line
1.7.6
PATCH 8/11 bb/ui/hob: fix package only build
In reply to Joshua LockUse the models new get_selected_pn method to return a list of PN's for the selected items and pass that for a package only build, rather than passing a list of package names (which buildTargets can't handle).
Fixes [YOCTO #1385]
--- lib/bb/ui/hob.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
lib/bb/ui/hob.py +2 -1
@@ -174,6 +174,7 @@ class MainWindow (gtk.Window): self.toggle_package(path, model, image=True) if len(userp): self.model.set_selected_packages(userp) + self.selected_image = model[path][self.model.COL_NAME] def reload_triggered_cb(self, handler, image, packages): if image:
@@ -451,7 +452,7 @@ class MainWindow (gtk.Window): self.handler.build_image(image_name, self.configurator) else: - self.handler.build_packages(rep.allpkgs.split(" ")) + self.handler.build_packages(self.model.get_selected_pn()) self.nb.set_current_page(1)
Signature · 1 line
1.7.6
PATCH 9/11 bb/ui/crumbs/hobeventhandler: fix return values of *_image_output_type
In reply to Joshua LockThese methods are expected to return lists.
--- lib/bb/ui/crumbs/hobeventhandler.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
lib/bb/ui/crumbs/hobeventhandler.py +4 -4
@@ -310,17 +310,17 @@ class HobHandler(gobject.GObject): def add_image_output_type(self, output_type): if output_type not in self.image_output_types: self.image_output_types.append(output_type) - fstypes = " ".join(self.image_output_types) + fstypes = " ".join(self.image_output_types).lstrip(" ") self.set_fstypes(fstypes) - return fstypes + return self.image_output_types def remove_image_output_type(self, output_type): if output_type in self.image_output_types: ind = self.image_output_types.index(output_type) self.image_output_types.pop(ind) - fstypes = " ".join(self.image_output_types) + fstypes = " ".join(self.image_output_types).lstrip(" ") self.set_fstypes(fstypes) - return fstypes + return self.image_output_types def get_image_deploy_dir(self): return self.server.runCommand(["getVariable", "DEPLOY_DIR_IMAGE"])
Signature · 1 line
1.7.6
PATCH 10/11 bb/ui/crumbs/hobprefs: fix setting IMAGE_FSYTPES
In reply to Joshua LockWe were setting the value as a list when a string is expected
--- lib/bb/ui/crumbs/hobprefs.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
lib/bb/ui/crumbs/hobprefs.py +1 -1
@@ -38,7 +38,7 @@ class HobPrefs(gtk.Dialog): else: self.selected_image_types = handler.remove_image_output_type(ot) - self.configurator.setLocalConfVar('IMAGE_FSTYPES', "%s" % self.selected_image_types) + self.configurator.setLocalConfVar('IMAGE_FSTYPES', "%s" % " ".join(self.selected_image_types).lstrip(" ")) def sdk_machine_combo_changed_cb(self, combo, handler): sdk_mach = combo.get_active_text()
Signature · 1 line
1.7.6
PATCH 11/11 bb/ui/hob: warn and prevent image build if no IMAGE_FSTYPE is set
In reply to Joshua LockIf IMAGE_FSTYPE is empty and the user has opted to build an image warn them and prevent the build.
Fixes [YOCTO #1267]
--- lib/bb/ui/hob.py | 17 ++++++++++++++++- 1 files changed, 16 insertions(+), 1 deletions(-)
lib/bb/ui/hob.py +16 -1
@@ -437,7 +437,22 @@ class MainWindow (gtk.Window): elif response == gtk.RESPONSE_OK: rep.base_image = "empty" - if build_image: + # Ensure at least one value is set in IMAGE_FSTYPES. + have_selected_fstype = False + if (len(self.prefs.selected_image_types) and + len(self.prefs.selected_image_types[0])): + have_selected_fstype = True + + if build_image and not have_selected_fstype: + lbl = "<b>No image output type selected</b>\nThere is no image output" + lbl = lbl + " selected for the build. Please set an output image type" + lbl = lbl + " in the preferences (Edit -> Preferences)." + dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO) + dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) + dialog.run() + dialog.destroy() + return + elif build_image: self.handler.make_temp_dir() recipepath = self.handler.get_temp_recipe_path(rep.base_image) image_name = recipepath.rstrip(".bb")
Signature · 1 line
1.7.6