From patchwork Tue Jan 22 11:21:37 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [bitbake-devel] FW: [V2] hob: Hob should display warnings generated during parsing Date: Tue, 22 Jan 2013 11:21:37 -0000 From: Cristiana Voicu X-Patchwork-Id: 43161 Message-Id: To: Richard Purdie Cc: "bitbake-devel@lists.openembedded.org" Hello Richard, This patch was not merged ok. The file lib/bb/ui/crumbs/hig/parsingwarningsdialog.py(added in this patch), is not in the repo now. Thank you, Cristiana -----Original Message----- From: Voicu, Cristiana Sent: Monday, January 21, 2013 4:40 PM To: bitbake-devel@lists.openembedded.org Cc: Voicu, Cristiana Subject: [V2] hob: Hob should display warnings generated during parsing -now Hob catches the warnings generated during parsing, and after the parsing is completed, if there are any warnings, it shows a bar that contains a message with how many warnings has encountered, and a button "View warnings" -when "View warnings" button is clicked, Hob shows a dialog with the warnings; if there more than 1 warning, you can use "Previous" and "Next" button to see them [YOCTO #3215] Signed-off-by: Cristiana Voicu --- bitbake/lib/bb/ui/crumbs/builder.py | 17 +++ .../lib/bb/ui/crumbs/hig/parsingwarningsdialog.py | 161 ++++++++++++++++++++ bitbake/lib/bb/ui/crumbs/hobcolor.py | 1 + bitbake/lib/bb/ui/crumbs/hobeventhandler.py | 13 ++ bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py | 54 ++++++- bitbake/lib/bb/ui/crumbs/packageselectionpage.py | 1 + 6 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py -- 1.7.9.5 diff --git a/bitbake/lib/bb/ui/crumbs/builder.py b/bitbake/lib/bb/ui/crumbs/builder.py index b783dad..d57cf4c 100755 --- a/bitbake/lib/bb/ui/crumbs/builder.py +++ b/bitbake/lib/bb/ui/crumbs/builder.py @@ -46,6 +46,7 @@ from bb.ui.crumbs.hig.advancedsettingsdialog import AdvancedSettingsDialog from bb.ui.crumbs.hig.deployimagedialog import DeployImageDialog from bb.ui.crumbs.hig.layerselectiondialog import LayerSelectionDialog from bb.ui.crumbs.hig.imageselectiondialog import ImageSelectionDialog +from bb.ui.crumbs.hig.parsingwarningsdialog import +ParsingWarningsDialog hobVer = 20120808 @@ -446,6 +447,9 @@ class Builder(gtk.Window): # Indicate whether the sanity check ran self.sanity_checked = False + # save parsing warnings + self.parsing_warnings = [] + # create visual elements self.create_visual_elements() @@ -472,6 +476,7 @@ class Builder(gtk.Window): self.handler.connect("data-generated", self.handler_data_generated_cb) self.handler.connect("command-succeeded", self.handler_command_succeeded_cb) self.handler.connect("command-failed", self.handler_command_failed_cb) + self.handler.connect("parsing-warning", self.handler_parsing_warning_cb) self.handler.connect("sanity-failed", self.handler_sanity_failed_cb) self.handler.connect("recipe-populated", self.handler_recipe_populated_cb) self.handler.connect("package-populated", self.handler_package_populated_cb) @@ -880,6 +885,15 @@ class Builder(gtk.Window): response = dialog.run() dialog.destroy() + def show_warning_dialog(self): + dialog = ParsingWarningsDialog(title = "View warnings", + warnings = self.parsing_warnings, + parent = None, + flags = gtk.DIALOG_DESTROY_WITH_PARENT + | gtk.DIALOG_NO_SEPARATOR) + response = dialog.run() + dialog.destroy() + def show_network_error_dialog(self): lbl = "Hob cannot connect to the network\n" msg = "Please check your network connection. If you are using a proxy server, please make sure it is configured correctly." @@ -903,6 +917,9 @@ class Builder(gtk.Window): self.show_error_dialog(msg) self.reset() + def handler_parsing_warning_cb(self, handler, warn_msg): + self.parsing_warnings.append(warn_msg) + def handler_sanity_failed_cb(self, handler, msg, network_error): self.reset() if network_error: diff --git a/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py b/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py new file mode 100644 index 0000000..5cddd65 --- /dev/null +++ b/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py @@ -0,0 +1,161 @@ +# +# BitBake Graphical GTK User Interface +# +# Copyright (C) 2011-2012 Intel Corporation +# +# Authored by Cristiana Voicu # # This +program is free software; you can redistribute it and/or modify # it +under the terms of the GNU General Public License version 2 as # +published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, # but +WITHOUT ANY WARRANTY; without even the implied warranty of # +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU +General Public License for more details. +# +# You should have received a copy of the GNU General Public License +along # with this program; if not, write to the Free Software +Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import gtk +import gobject +from bb.ui.crumbs.hobwidget import HobAltButton from +bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog + +""" +The following are convenience classes for implementing GNOME HIG +compliant BitBake GUI's In summary: spacing = 12px, border-width = 6px +""" + +# +# ParsingWarningsDialog +# +class ParsingWarningsDialog (CrumbsDialog): + + def __init__(self, title, warnings, parent, flags, buttons=None): + super(ParsingWarningsDialog, self).__init__(title, parent, + flags, buttons) + + self.warnings = warnings + self.warning_on = 0 + self.warn_nb = len(warnings) + + # create visual elements on the dialog + self.create_visual_elements() + + def cancel_button_cb(self, button): + self.destroy() + + def previous_button_cb(self, button): + self.warning_on = self.warning_on - 1 + self.refresh_components() + + def next_button_cb(self, button): + self.warning_on = self.warning_on + 1 + self.refresh_components() + + def refresh_components(self): + lbl = self.warnings[self.warning_on] + #when the warning text has more than 400 chars, it uses a scroll bar + if 0<= len(lbl) < 400: + self.warning_label.set_size_request(320, 230) + self.warning_label.set_use_markup(True) + self.warning_label.set_line_wrap(True) + self.warning_label.set_markup(lbl) + self.warning_label.set_property("yalign", 0.00) + else: + self.textWindow.set_shadow_type(gtk.SHADOW_IN) + self.textWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.msgView = gtk.TextView() + self.msgView.set_editable(False) + self.msgView.set_wrap_mode(gtk.WRAP_WORD) + self.msgView.set_cursor_visible(False) + self.msgView.set_size_request(320, 230) + self.buf = gtk.TextBuffer() + self.buf.set_text(lbl) + self.msgView.set_buffer(self.buf) + self.textWindow.add(self.msgView) + self.msgView.show() + + if self.warning_on==0: + self.previous_button.set_sensitive(False) + else: + self.previous_button.set_sensitive(True) + + if self.warning_on==self.warn_nb-1: + self.next_button.set_sensitive(False) + else: + self.next_button.set_sensitive(True) + + if self.warn_nb>1: + self.heading = "Warning " + str(self.warning_on + 1) + " of " + str(self.warn_nb) + self.heading_label.set_markup('%s' % self.heading) + else: + self.heading = "Warning" + self.heading_label.set_markup('%s' % self.heading) + + self.show_all() + + if 0<= len(lbl) < 400: + self.textWindow.hide() + else: + self.warning_label.hide() + + def create_visual_elements(self): + self.set_size_request(350, 350) + self.heading_label = gtk.Label() + self.heading_label.set_alignment(0.1, 0) + self.warning_label = gtk.Label() + self.textWindow = gtk.ScrolledWindow() + + table = gtk.Table(1, 10, False) + + cancel_button = gtk.Button() + cancel_button.set_label("Close") + cancel_button.connect("clicked", self.cancel_button_cb) + cancel_button.set_size_request(110, 30) + + self.previous_button = gtk.Button() + image1 = gtk.image_new_from_stock(gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON) + image1.show() + box = gtk.HBox(False, 6) + box.show() + self.previous_button.add(box) + lbl = gtk.Label("Previous") + lbl.show() + box.pack_start(image1, expand=False, fill=False, padding=3) + box.pack_start(lbl, expand=True, fill=True, padding=3) + self.previous_button.connect("clicked", self.previous_button_cb) + self.previous_button.set_size_request(110, 30) + + self.next_button = gtk.Button() + image2 = gtk.image_new_from_stock(gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON) + image2.show() + box = gtk.HBox(False, 6) + box.show() + self.next_button.add(box) + lbl = gtk.Label("Next") + lbl.show() + box.pack_start(lbl, expand=True, fill=True, padding=3) + box.pack_start(image2, expand=False, fill=False, padding=3) + self.next_button.connect("clicked", self.next_button_cb) + self.next_button.set_size_request(110, 30) + + #when there more than one warning, we need "previous" and "next" button + if self.warn_nb>1: + self.vbox.pack_start(self.heading_label, expand=False, fill=False) + self.vbox.pack_start(self.warning_label, expand=False, fill=False) + self.vbox.pack_start(self.textWindow, expand=False, fill=False) + table.attach(cancel_button, 6, 7, 0, 1, xoptions=gtk.SHRINK) + table.attach(self.previous_button, 7, 8, 0, 1, xoptions=gtk.SHRINK) + table.attach(self.next_button, 8, 9, 0, 1, xoptions=gtk.SHRINK) + self.vbox.pack_end(table, expand=False, fill=False) + else: + self.vbox.pack_start(self.heading_label, expand=False, fill=False) + self.vbox.pack_start(self.warning_label, expand=False, fill=False) + self.vbox.pack_start(self.textWindow, expand=False, fill=False) + cancel_button = self.add_button("Cancel", gtk.RESPONSE_CANCEL) + HobAltButton.style_button(cancel_button) + + self.refresh_components() diff --git a/bitbake/lib/bb/ui/crumbs/hobcolor.py b/bitbake/lib/bb/ui/crumbs/hobcolor.py index e10f546..3316542 100644 --- a/bitbake/lib/bb/ui/crumbs/hobcolor.py +++ b/bitbake/lib/bb/ui/crumbs/hobcolor.py @@ -30,6 +30,7 @@ class HobColors: BLACK = "#000000" PALE_BLUE = "#53b8ff" DEEP_RED = "#aa3e3e" + KHAKI = "#fff68f" OK = WHITE RUNNING = PALE_GREEN diff --git a/bitbake/lib/bb/ui/crumbs/hobeventhandler.py b/bitbake/lib/bb/ui/crumbs/hobeventhandler.py index e690d4c..41022ef 100644 --- a/bitbake/lib/bb/ui/crumbs/hobeventhandler.py +++ b/bitbake/lib/bb/ui/crumbs/hobeventhandler.py @@ -41,6 +41,9 @@ class HobHandler(gobject.GObject): "command-failed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), + "parsing-warning" : (gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_STRING,)), "sanity-failed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_INT)), @@ -95,6 +98,7 @@ class HobHandler(gobject.GObject): self.server = server self.error_msg = "" self.initcmd = None + self.parsing = False def set_busy(self): if not self.generating: @@ -207,6 +211,11 @@ class HobHandler(gobject.GObject): formatter = bb.msg.BBLogFormatter() msg = formatter.format(event) self.error_msg += msg + '\n' + elif event.levelno >= logging.WARNING and self.parsing == True: + formatter = bb.msg.BBLogFormatter() + msg = formatter.format(event) + warn_msg = msg + '\n' + self.emit("parsing-warning", warn_msg) elif isinstance(event, bb.event.TargetsTreeGenerated): self.current_phase = "data generation" @@ -249,6 +258,8 @@ class HobHandler(gobject.GObject): message["total"] = None message["title"] = "Parsing recipes" self.emit("parsing-started", message) + if isinstance(event, bb.event.ParseStarted): + self.parsing = True elif isinstance(event, (bb.event.ParseProgress, bb.event.CacheLoadProgress, bb.event.TreeDataPreparationProgress)): @@ -267,6 +278,8 @@ class HobHandler(gobject.GObject): message["total"] = event.total message["title"] = "Parsing recipes" self.emit("parsing-completed", message) + if isinstance(event, bb.event.ParseCompleted): + self.parsing = False elif isinstance(event, bb.event.NetworkTestFailed): self.emit("network-failed") self.run_next_command() diff --git a/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py b/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py index b94f35c..ff77350 100644 --- a/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py +++ b/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py @@ -46,6 +46,7 @@ class ImageConfigurationPage (HobPage): # cleared. self.machine_combo_changed_by_manual = True self.stopping = False + self.warning_shift = 0 self.create_visual_elements() def create_visual_elements(self): @@ -141,6 +142,37 @@ class ImageConfigurationPage (HobPage): if self.builder.recipe_model.get_selected_image() == self.builder.recipe_model.__custom_image__: self.just_bake_button.hide() + def add_warnings_bar(self): + #create the warnings bar shown when recipes parsing generates warnings + color = HobColors.KHAKI + warnings_bar = gtk.EventBox() + warnings_bar.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) + warnings_bar.set_flags(gtk.CAN_DEFAULT) + warnings_bar.grab_default() + + build_stop_tab = gtk.Table(10, 20, True) + warnings_bar.add(build_stop_tab) + + icon = gtk.Image() + icon_pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_INDI_ALERT_FILE) + icon.set_from_pixbuf(icon_pix_buffer) + build_stop_tab.attach(icon, 0, 2, 0, 10) + + label = gtk.Label() + label.set_alignment(0.0, 0.5) + warnings_nb = len(self.builder.parsing_warnings) + if warnings_nb == 1: + label.set_markup("1 recipe parsing warning") + else: + label.set_markup("%s recipe parsing warnings" % warnings_nb) + build_stop_tab.attach(label, 2, 12, 0, 10) + + view_warnings_button = HobButton("View warnings") + view_warnings_button.connect('clicked', self.view_warnings_button_clicked_cb) + build_stop_tab.attach(view_warnings_button, 15, 19, 1, 9) + + return warnings_bar + def create_config_machine(self): self.machine_title = gtk.Label() self.machine_title.set_alignment(0.0, 0.5) @@ -187,6 +219,12 @@ class ImageConfigurationPage (HobPage): #self.gtable.attach(self.progress_box, 0, 40, 15, 18) self.gtable.attach(self.progress_bar, 0, 37, 15, 18) self.gtable.attach(self.stop_button, 37, 40, 15, 18, 0, 0) + if self.builder.parsing_warnings: + self.warnings_bar = self.add_warnings_bar() + self.gtable.attach(self.warnings_bar, 0, 40, 14, 18) + self.warning_shift = 4 + else: + self.warning_shift = 0 self.gtable.attach(self.machine_separator, 0, 40, 13, 14) def create_config_baseimg(self): @@ -222,12 +260,12 @@ class ImageConfigurationPage (HobPage): self.image_separator = gtk.HSeparator() def set_config_baseimg_layout(self): - self.gtable.attach(self.image_title, 0, 40, 15, 17) - self.gtable.attach(self.image_title_desc, 0, 40, 18, 22) - self.gtable.attach(self.image_combo, 0, 12, 23, 26) - self.gtable.attach(self.image_desc, 0, 12, 27, 33) - self.gtable.attach(self.view_adv_configuration_button, 14, 36, 23, 28) - self.gtable.attach(self.image_separator, 0, 40, 35, 36) + self.gtable.attach(self.image_title, 0, 40, 15+self.warning_shift, 17+self.warning_shift) + self.gtable.attach(self.image_title_desc, 0, 40, 18+self.warning_shift, 22+self.warning_shift) + self.gtable.attach(self.image_combo, 0, 12, 23+self.warning_shift, 26+self.warning_shift) + self.gtable.attach(self.image_desc, 0, 12, 27+self.warning_shift, 33+self.warning_shift) + self.gtable.attach(self.view_adv_configuration_button, 14, 36, 23+self.warning_shift, 28+self.warning_shift) + self.gtable.attach(self.image_separator, 0, 40, + 35+self.warning_shift, 36+self.warning_shift) def create_config_build_button(self): # Create the "Build packages" and "Build image" buttons at the bottom @@ -255,6 +293,9 @@ class ImageConfigurationPage (HobPage): self.progress_bar.set_rcstyle("stop") self.builder.cancel_parse_sync() + def view_warnings_button_clicked_cb(self, button): + self.builder.show_warning_dialog() + def machine_combo_changed_cb(self, machine_combo): self.stopping = False combo_item = machine_combo.get_active_text() @@ -435,6 +476,7 @@ class ImageConfigurationPage (HobPage): self.builder.reparse_post_adv_settings() def just_bake_button_clicked_cb(self, button): + self.builder.parsing_warnings = [] self.builder.just_bake() def edit_image_button_clicked_cb(self, button): diff --git a/bitbake/lib/bb/ui/crumbs/packageselectionpage.py b/bitbake/lib/bb/ui/crumbs/packageselectionpage.py index 2da9277..b3f2a05 100755 --- a/bitbake/lib/bb/ui/crumbs/packageselectionpage.py +++ b/bitbake/lib/bb/ui/crumbs/packageselectionpage.py @@ -197,6 +197,7 @@ class PackageSelectionPage (HobPage): self.show_all() def build_image_clicked_cb(self, button): + self.builder.parsing_warnings = [] self.builder.build_image() def back_button_clicked_cb(self, button):