diff options
author | Khem Raj <raj.khem@gmail.com> | 2011-02-23 10:48:51 -0800 |
---|---|---|
committer | Khem Raj <raj.khem@gmail.com> | 2011-02-23 10:48:51 -0800 |
commit | 951cbf3f65f347c7a7bbcae193218f9187a15fbf (patch) | |
tree | 96e9c74551e6931804992f8f49af05f732eb0fff /bitbake/lib/bb/ui | |
parent | adbaae2179a6c3746e53f7fbb2ca0939e85a7ea9 (diff) | |
download | openembedded-core-951cbf3f65f347c7a7bbcae193218f9187a15fbf.tar.gz openembedded-core-951cbf3f65f347c7a7bbcae193218f9187a15fbf.tar.bz2 openembedded-core-951cbf3f65f347c7a7bbcae193218f9187a15fbf.tar.xz openembedded-core-951cbf3f65f347c7a7bbcae193218f9187a15fbf.zip |
bitbake: Remove in-tree version
Bitbake should be used by checking it out from its own repo
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Diffstat (limited to 'bitbake/lib/bb/ui')
-rw-r--r-- | bitbake/lib/bb/ui/__init__.py | 17 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/crumbs/__init__.py | 17 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/crumbs/buildmanager.py | 455 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/crumbs/progress.py | 17 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/crumbs/puccho.glade | 606 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/crumbs/runningbuild.py | 311 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/depexp.py | 307 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/goggle.py | 110 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/knotty.py | 248 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/ncurses.py | 352 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/puccho.py | 425 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/uievent.py | 127 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/uihelper.py | 42 |
13 files changed, 0 insertions, 3034 deletions
diff --git a/bitbake/lib/bb/ui/__init__.py b/bitbake/lib/bb/ui/__init__.py deleted file mode 100644 index a4805ed02..000000000 --- a/bitbake/lib/bb/ui/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# -# BitBake UI Implementation -# -# Copyright (C) 2006-2007 Richard Purdie -# -# 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. diff --git a/bitbake/lib/bb/ui/crumbs/__init__.py b/bitbake/lib/bb/ui/crumbs/__init__.py deleted file mode 100644 index a4805ed02..000000000 --- a/bitbake/lib/bb/ui/crumbs/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# -# BitBake UI Implementation -# -# Copyright (C) 2006-2007 Richard Purdie -# -# 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. diff --git a/bitbake/lib/bb/ui/crumbs/buildmanager.py b/bitbake/lib/bb/ui/crumbs/buildmanager.py deleted file mode 100644 index e858d75e4..000000000 --- a/bitbake/lib/bb/ui/crumbs/buildmanager.py +++ /dev/null @@ -1,455 +0,0 @@ -# -# BitBake Graphical GTK User Interface -# -# Copyright (C) 2008 Intel Corporation -# -# Authored by Rob Bradford <rob@linux.intel.com> -# -# 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 -import threading -import os -import datetime -import time - -class BuildConfiguration: - """ Represents a potential *or* historic *or* concrete build. It - encompasses all the things that we need to tell bitbake to do to make it - build what we want it to build. - - It also stored the metadata URL and the set of possible machines (and the - distros / images / uris for these. Apart from the metdata URL these are - not serialised to file (since they may be transient). In some ways this - functionality might be shifted to the loader class.""" - - def __init__ (self): - self.metadata_url = None - - # Tuple of (distros, image, urls) - self.machine_options = {} - - self.machine = None - self.distro = None - self.image = None - self.urls = [] - self.extra_urls = [] - self.extra_pkgs = [] - - def get_machines_model (self): - model = gtk.ListStore (gobject.TYPE_STRING) - for machine in self.machine_options.keys(): - model.append ([machine]) - - return model - - def get_distro_and_images_models (self, machine): - distro_model = gtk.ListStore (gobject.TYPE_STRING) - - for distro in self.machine_options[machine][0]: - distro_model.append ([distro]) - - image_model = gtk.ListStore (gobject.TYPE_STRING) - - for image in self.machine_options[machine][1]: - image_model.append ([image]) - - return (distro_model, image_model) - - def get_repos (self): - self.urls = self.machine_options[self.machine][2] - return self.urls - - # It might be a lot lot better if we stored these in like, bitbake conf - # file format. - @staticmethod - def load_from_file (filename): - - conf = BuildConfiguration() - with open(filename, "r") as f: - for line in f: - data = line.split (";")[1] - if (line.startswith ("metadata-url;")): - conf.metadata_url = data.strip() - continue - if (line.startswith ("url;")): - conf.urls += [data.strip()] - continue - if (line.startswith ("extra-url;")): - conf.extra_urls += [data.strip()] - continue - if (line.startswith ("machine;")): - conf.machine = data.strip() - continue - if (line.startswith ("distribution;")): - conf.distro = data.strip() - continue - if (line.startswith ("image;")): - conf.image = data.strip() - continue - - return conf - - # Serialise to a file. This is part of the build process and we use this - # to be able to repeat a given build (using the same set of parameters) - # but also so that we can include the details of the image / machine / - # distro in the build manager tree view. - def write_to_file (self, filename): - f = open (filename, "w") - - lines = [] - - if (self.metadata_url): - lines += ["metadata-url;%s\n" % (self.metadata_url)] - - for url in self.urls: - lines += ["url;%s\n" % (url)] - - for url in self.extra_urls: - lines += ["extra-url;%s\n" % (url)] - - if (self.machine): - lines += ["machine;%s\n" % (self.machine)] - - if (self.distro): - lines += ["distribution;%s\n" % (self.distro)] - - if (self.image): - lines += ["image;%s\n" % (self.image)] - - f.writelines (lines) - f.close () - -class BuildResult(gobject.GObject): - """ Represents an historic build. Perhaps not successful. But it includes - things such as the files that are in the directory (the output from the - build) as well as a deserialised BuildConfiguration file that is stored in - ".conf" in the directory for the build. - - This is GObject so that it can be included in the TreeStore.""" - - (STATE_COMPLETE, STATE_FAILED, STATE_ONGOING) = \ - (0, 1, 2) - - def __init__ (self, parent, identifier): - gobject.GObject.__init__ (self) - self.date = None - - self.files = [] - self.status = None - self.identifier = identifier - self.path = os.path.join (parent, identifier) - - # Extract the date, since the directory name is of the - # format build-<year><month><day>-<ordinal> we can easily - # pull it out. - # TODO: Better to stat a file? - (_, date, revision) = identifier.split ("-") - print(date) - - year = int (date[0:4]) - month = int (date[4:6]) - day = int (date[6:8]) - - self.date = datetime.date (year, month, day) - - self.conf = None - - # By default builds are STATE_FAILED unless we find a "complete" file - # in which case they are STATE_COMPLETE - self.state = BuildResult.STATE_FAILED - for file in os.listdir (self.path): - if (file.startswith (".conf")): - conffile = os.path.join (self.path, file) - self.conf = BuildConfiguration.load_from_file (conffile) - elif (file.startswith ("complete")): - self.state = BuildResult.STATE_COMPLETE - else: - self.add_file (file) - - def add_file (self, file): - # Just add the file for now. Don't care about the type. - self.files += [(file, None)] - -class BuildManagerModel (gtk.TreeStore): - """ Model for the BuildManagerTreeView. This derives from gtk.TreeStore - but it abstracts nicely what the columns mean and the setup of the columns - in the model. """ - - (COL_IDENT, COL_DESC, COL_MACHINE, COL_DISTRO, COL_BUILD_RESULT, COL_DATE, COL_STATE) = \ - (0, 1, 2, 3, 4, 5, 6) - - def __init__ (self): - gtk.TreeStore.__init__ (self, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_OBJECT, - gobject.TYPE_INT64, - gobject.TYPE_INT) - -class BuildManager (gobject.GObject): - """ This class manages the historic builds that have been found in the - "results" directory but is also used for starting a new build.""" - - __gsignals__ = { - 'population-finished' : (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - ()), - 'populate-error' : (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - ()) - } - - def update_build_result (self, result, iter): - # Convert the date into something we can sort by. - date = long (time.mktime (result.date.timetuple())) - - # Add a top level entry for the build - - self.model.set (iter, - BuildManagerModel.COL_IDENT, result.identifier, - BuildManagerModel.COL_DESC, result.conf.image, - BuildManagerModel.COL_MACHINE, result.conf.machine, - BuildManagerModel.COL_DISTRO, result.conf.distro, - BuildManagerModel.COL_BUILD_RESULT, result, - BuildManagerModel.COL_DATE, date, - BuildManagerModel.COL_STATE, result.state) - - # And then we use the files in the directory as the children for the - # top level iter. - for file in result.files: - self.model.append (iter, (None, file[0], None, None, None, date, -1)) - - # This function is called as an idle by the BuildManagerPopulaterThread - def add_build_result (self, result): - gtk.gdk.threads_enter() - self.known_builds += [result] - - self.update_build_result (result, self.model.append (None)) - - gtk.gdk.threads_leave() - - def notify_build_finished (self): - # This is a bit of a hack. If we have a running build running then we - # will have a row in the model in STATE_ONGOING. Find it and make it - # as if it was a proper historic build (well, it is completed now....) - - # We need to use the iters here rather than the Python iterator - # interface to the model since we need to pass it into - # update_build_result - - iter = self.model.get_iter_first() - - while (iter): - (ident, state) = self.model.get(iter, - BuildManagerModel.COL_IDENT, - BuildManagerModel.COL_STATE) - - if state == BuildResult.STATE_ONGOING: - result = BuildResult (self.results_directory, ident) - self.update_build_result (result, iter) - iter = self.model.iter_next(iter) - - def notify_build_succeeded (self): - # Write the "complete" file so that when we create the BuildResult - # object we put into the model - - complete_file_path = os.path.join (self.cur_build_directory, "complete") - f = file (complete_file_path, "w") - f.close() - self.notify_build_finished() - - def notify_build_failed (self): - # Without a "complete" file then this will mark the build as failed: - self.notify_build_finished() - - # This function is called as an idle - def emit_population_finished_signal (self): - gtk.gdk.threads_enter() - self.emit ("population-finished") - gtk.gdk.threads_leave() - - class BuildManagerPopulaterThread (threading.Thread): - def __init__ (self, manager, directory): - threading.Thread.__init__ (self) - self.manager = manager - self.directory = directory - - def run (self): - # For each of the "build-<...>" directories .. - - if os.path.exists (self.directory): - for directory in os.listdir (self.directory): - - if not directory.startswith ("build-"): - continue - - build_result = BuildResult (self.directory, directory) - self.manager.add_build_result (build_result) - - gobject.idle_add (BuildManager.emit_population_finished_signal, - self.manager) - - def __init__ (self, server, results_directory): - gobject.GObject.__init__ (self) - - # The builds that we've found from walking the result directory - self.known_builds = [] - - # Save out the bitbake server, we need this for issuing commands to - # the cooker: - self.server = server - - # The TreeStore that we use - self.model = BuildManagerModel () - - # The results directory is where we create (and look for) the - # build-<xyz>-<n> directories. We need to populate ourselves from - # directory - self.results_directory = results_directory - self.populate_from_directory (self.results_directory) - - def populate_from_directory (self, directory): - thread = BuildManager.BuildManagerPopulaterThread (self, directory) - thread.start() - - # Come up with the name for the next build ident by combining "build-" - # with the date formatted as yyyymmdd and then an ordinal. We do this by - # an optimistic algorithm incrementing the ordinal if we find that it - # already exists. - def get_next_build_ident (self): - today = datetime.date.today () - datestr = str (today.year) + str (today.month) + str (today.day) - - revision = 0 - test_name = "build-%s-%d" % (datestr, revision) - test_path = os.path.join (self.results_directory, test_name) - - while (os.path.exists (test_path)): - revision += 1 - test_name = "build-%s-%d" % (datestr, revision) - test_path = os.path.join (self.results_directory, test_name) - - return test_name - - # Take a BuildConfiguration and then try and build it based on the - # parameters of that configuration. S - def do_build (self, conf): - server = self.server - - # Work out the build directory. Note we actually create the - # directories here since we need to write the ".conf" file. Otherwise - # we could have relied on bitbake's builder thread to actually make - # the directories as it proceeds with the build. - ident = self.get_next_build_ident () - build_directory = os.path.join (self.results_directory, - ident) - self.cur_build_directory = build_directory - os.makedirs (build_directory) - - conffile = os.path.join (build_directory, ".conf") - conf.write_to_file (conffile) - - # Add a row to the model representing this ongoing build. It's kinda a - # fake entry. If this build completes or fails then this gets updated - # with the real stuff like the historic builds - date = long (time.time()) - self.model.append (None, (ident, conf.image, conf.machine, conf.distro, - None, date, BuildResult.STATE_ONGOING)) - try: - server.runCommand(["setVariable", "BUILD_IMAGES_FROM_FEEDS", 1]) - server.runCommand(["setVariable", "MACHINE", conf.machine]) - server.runCommand(["setVariable", "DISTRO", conf.distro]) - server.runCommand(["setVariable", "PACKAGE_CLASSES", "package_ipk"]) - server.runCommand(["setVariable", "BBFILES", \ - """${OEROOT}/meta/packages/*/*.bb ${OEROOT}/meta-moblin/packages/*/*.bb"""]) - server.runCommand(["setVariable", "TMPDIR", "${OEROOT}/build/tmp"]) - server.runCommand(["setVariable", "IPK_FEED_URIS", \ - " ".join(conf.get_repos())]) - server.runCommand(["setVariable", "DEPLOY_DIR_IMAGE", - build_directory]) - server.runCommand(["buildTargets", [conf.image], "rootfs"]) - - except Exception as e: - print(e) - -class BuildManagerTreeView (gtk.TreeView): - """ The tree view for the build manager. This shows the historic builds - and so forth. """ - - # We use this function to control what goes in the cell since we store - # the date in the model as seconds since the epoch (for sorting) and so we - # need to make it human readable. - def date_format_custom_cell_data_func (self, col, cell, model, iter): - date = model.get (iter, BuildManagerModel.COL_DATE)[0] - datestr = time.strftime("%A %d %B %Y", time.localtime(date)) - cell.set_property ("text", datestr) - - # This format function controls what goes in the cell. We use this to map - # the integer state to a string and also to colourise the text - def state_format_custom_cell_data_fun (self, col, cell, model, iter): - state = model.get (iter, BuildManagerModel.COL_STATE)[0] - - if (state == BuildResult.STATE_ONGOING): - cell.set_property ("text", "Active") - cell.set_property ("foreground", "#000000") - elif (state == BuildResult.STATE_FAILED): - cell.set_property ("text", "Failed") - cell.set_property ("foreground", "#ff0000") - elif (state == BuildResult.STATE_COMPLETE): - cell.set_property ("text", "Complete") - cell.set_property ("foreground", "#00ff00") - else: - cell.set_property ("text", "") - - def __init__ (self): - gtk.TreeView.__init__(self) - - # Misc descriptiony thing - renderer = gtk.CellRendererText () - col = gtk.TreeViewColumn (None, renderer, - text=BuildManagerModel.COL_DESC) - self.append_column (col) - - # Machine - renderer = gtk.CellRendererText () - col = gtk.TreeViewColumn ("Machine", renderer, - text=BuildManagerModel.COL_MACHINE) - self.append_column (col) - - # distro - renderer = gtk.CellRendererText () - col = gtk.TreeViewColumn ("Distribution", renderer, - text=BuildManagerModel.COL_DISTRO) - self.append_column (col) - - # date (using a custom function for formatting the cell contents it - # takes epoch -> human readable string) - renderer = gtk.CellRendererText () - col = gtk.TreeViewColumn ("Date", renderer, - text=BuildManagerModel.COL_DATE) - self.append_column (col) - col.set_cell_data_func (renderer, - self.date_format_custom_cell_data_func) - - # For status. - renderer = gtk.CellRendererText () - col = gtk.TreeViewColumn ("Status", renderer, - text = BuildManagerModel.COL_STATE) - self.append_column (col) - col.set_cell_data_func (renderer, - self.state_format_custom_cell_data_fun) diff --git a/bitbake/lib/bb/ui/crumbs/progress.py b/bitbake/lib/bb/ui/crumbs/progress.py deleted file mode 100644 index 36eca3829..000000000 --- a/bitbake/lib/bb/ui/crumbs/progress.py +++ /dev/null @@ -1,17 +0,0 @@ -import gtk - -class ProgressBar(gtk.Dialog): - def __init__(self, parent): - - gtk.Dialog.__init__(self) - self.set_title("Parsing metadata, please wait...") - self.set_default_size(500, 0) - self.set_transient_for(parent) - self.set_destroy_with_parent(True) - self.progress = gtk.ProgressBar() - self.vbox.pack_start(self.progress) - self.show_all() - - def update(self, x, y): - self.progress.set_fraction(float(x)/float(y)) - self.progress.set_text("%2d %%" % (x*100/y)) diff --git a/bitbake/lib/bb/ui/crumbs/puccho.glade b/bitbake/lib/bb/ui/crumbs/puccho.glade deleted file mode 100644 index d7553a6e1..000000000 --- a/bitbake/lib/bb/ui/crumbs/puccho.glade +++ /dev/null @@ -1,606 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> -<!--Generated with glade3 3.4.5 on Mon Nov 10 12:24:12 2008 --> -<glade-interface> - <widget class="GtkDialog" id="build_dialog"> - <property name="title" translatable="yes">Start a build</property> - <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <property name="has_separator">False</property> - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox1"> - <property name="visible">True</property> - <property name="spacing">2</property> - <child> - <widget class="GtkTable" id="build_table"> - <property name="visible">True</property> - <property name="border_width">6</property> - <property name="n_rows">7</property> - <property name="n_columns">3</property> - <property name="column_spacing">5</property> - <property name="row_spacing">6</property> - <child> - <widget class="GtkAlignment" id="status_alignment"> - <property name="visible">True</property> - <property name="left_padding">12</property> - <child> - <widget class="GtkHBox" id="status_hbox"> - <property name="spacing">6</property> - <child> - <widget class="GtkImage" id="status_image"> - <property name="visible">True</property> - <property name="no_show_all">True</property> - <property name="xalign">0</property> - <property name="stock">gtk-dialog-error</property> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="status_label"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">If you see this text something is wrong...</property> - <property name="use_markup">True</property> - <property name="use_underline">True</property> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> - <packing> - <property name="right_attach">3</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label2"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes"><b>Build configuration</b></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="right_attach">3</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkComboBox" id="image_combo"> - <property name="visible">True</property> - <property name="sensitive">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="image_label"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="xalign">0</property> - <property name="xpad">12</property> - <property name="label" translatable="yes">Image:</property> - </widget> - <packing> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkComboBox" id="distribution_combo"> - <property name="visible">True</property> - <property name="sensitive">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="distribution_label"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="xalign">0</property> - <property name="xpad">12</property> - <property name="label" translatable="yes">Distribution:</property> - </widget> - <packing> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkComboBox" id="machine_combo"> - <property name="visible">True</property> - <property name="sensitive">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="machine_label"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="xalign">0</property> - <property name="xpad">12</property> - <property name="label" translatable="yes">Machine:</property> - </widget> - <packing> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkButton" id="refresh_button"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="label" translatable="yes">gtk-refresh</property> - <property name="use_stock">True</property> - <property name="response_id">0</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkEntry" id="location_entry"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="width_chars">32</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label3"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="xpad">12</property> - <property name="label" translatable="yes">Location:</property> - </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes"><b>Repository</b></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="right_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkAlignment" id="alignment1"> - <property name="visible">True</property> - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkAlignment" id="alignment2"> - <property name="visible">True</property> - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkAlignment" id="alignment3"> - <property name="visible">True</property> - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - <child internal-child="action_area"> - <widget class="GtkHButtonBox" id="dialog-action_area1"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> - </child> - </widget> - </child> - </widget> - <widget class="GtkDialog" id="dialog2"> - <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <property name="has_separator">False</property> - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox2"> - <property name="visible">True</property> - <property name="spacing">2</property> - <child> - <widget class="GtkTable" id="table2"> - <property name="visible">True</property> - <property name="border_width">6</property> - <property name="n_rows">7</property> - <property name="n_columns">3</property> - <property name="column_spacing">6</property> - <property name="row_spacing">6</property> - <child> - <widget class="GtkLabel" id="label7"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes"><b>Repositories</b></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="right_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkAlignment" id="alignment4"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="left_padding">12</property> - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <child> - <widget class="GtkTreeView" id="treeview1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_clickable">True</property> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="right_attach">3</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkEntry" id="entry1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label9"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes"><b>Additional packages</b></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="right_attach">3</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkAlignment" id="alignment6"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="xscale">0</property> - <child> - <widget class="GtkLabel" id="label8"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="xpad">12</property> - <property name="label" translatable="yes">Location: </property> - </widget> - </child> - </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkAlignment" id="alignment7"> - <property name="visible">True</property> - <property name="xalign">1</property> - <property name="xscale">0</property> - <child> - <widget class="GtkHButtonBox" id="hbuttonbox1"> - <property name="visible">True</property> - <property name="spacing">5</property> - <child> - <widget class="GtkButton" id="button7"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="label" translatable="yes">gtk-remove</property> - <property name="use_stock">True</property> - <property name="response_id">0</property> - </widget> - </child> - <child> - <widget class="GtkButton" id="button6"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="label" translatable="yes">gtk-edit</property> - <property name="use_stock">True</property> - <property name="response_id">0</property> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - <child> - <widget class="GtkButton" id="button5"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="label" translatable="yes">gtk-add</property> - <property name="use_stock">True</property> - <property name="response_id">0</property> - </widget> - <packing> - <property name="position">2</property> - </packing> - </child> - </widget> - </child> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkAlignment" id="alignment5"> - <property name="visible">True</property> - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label10"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="xpad">12</property> - <property name="label" translatable="yes">Search:</property> - </widget> - <packing> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkEntry" id="entry2"> - <property name="visible">True</property> - <property name="can_focus">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkAlignment" id="alignment8"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="left_padding">12</property> - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow2"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <child> - <widget class="GtkTreeView" id="treeview2"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_clickable">True</property> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="right_attach">3</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - <child internal-child="action_area"> - <widget class="GtkHButtonBox" id="dialog-action_area2"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - <child> - <widget class="GtkButton" id="button4"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="label" translatable="yes">gtk-close</property> - <property name="use_stock">True</property> - <property name="response_id">0</property> - </widget> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> - </child> - </widget> - </child> - </widget> - <widget class="GtkWindow" id="main_window"> - <child> - <widget class="GtkVBox" id="main_window_vbox"> - <property name="visible">True</property> - <child> - <widget class="GtkToolbar" id="main_toolbar"> - <property name="visible">True</property> - <child> - <widget class="GtkToolButton" id="main_toolbutton_build"> - <property name="visible">True</property> - <property name="label" translatable="yes">Build</property> - <property name="stock_id">gtk-execute</property> - </widget> - <packing> - <property name="expand">False</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - </packing> - </child> - <child> - <widget class="GtkVPaned" id="vpaned1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <child> - <widget class="GtkScrolledWindow" id="results_scrolledwindow"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="resize">False</property> - <property name="shrink">True</property> - </packing> - </child> - <child> - <widget class="GtkScrolledWindow" id="progress_scrolledwindow"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="resize">True</property> - <property name="shrink">True</property> - </packing> - </child> - </widget> - <packing> - <property name="position">1</property> - </packing> - </child> - </widget> - </child> - </widget> -</glade-interface> diff --git a/bitbake/lib/bb/ui/crumbs/runningbuild.py b/bitbake/lib/bb/ui/crumbs/runningbuild.py deleted file mode 100644 index 4703e6d84..000000000 --- a/bitbake/lib/bb/ui/crumbs/runningbuild.py +++ /dev/null @@ -1,311 +0,0 @@ - -# -# BitBake Graphical GTK User Interface -# -# Copyright (C) 2008 Intel Corporation -# -# Authored by Rob Bradford <rob@linux.intel.com> -# -# 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 -import logging -import time -import urllib -import urllib2 - -class Colors(object): - OK = "#ffffff" - RUNNING = "#aaffaa" - WARNING ="#f88017" - ERROR = "#ffaaaa" - -class RunningBuildModel (gtk.TreeStore): - (COL_LOG, COL_PACKAGE, COL_TASK, COL_MESSAGE, COL_ICON, COL_COLOR, COL_NUM_ACTIVE) = range(7) - - def __init__ (self): - gtk.TreeStore.__init__ (self, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_INT) - -class RunningBuild (gobject.GObject): - __gsignals__ = { - 'build-succeeded' : (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - ()), - 'build-failed' : (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - ()) - } - pids_to_task = {} - tasks_to_iter = {} - - def __init__ (self): - gobject.GObject.__init__ (self) - self.model = RunningBuildModel() - - def handle_event (self, event, pbar=None): - # Handle an event from the event queue, this may result in updating - # the model and thus the UI. Or it may be to tell us that the build - # has finished successfully (or not, as the case may be.) - - parent = None - pid = 0 - package = None - task = None - - # If we have a pid attached to this message/event try and get the - # (package, task) pair for it. If we get that then get the parent iter - # for the message. - if hasattr(event, 'pid'): - pid = event.pid - if hasattr(event, 'process'): - pid = event.process - - if pid and pid in self.pids_to_task: - (package, task) = self.pids_to_task[pid] - parent = self.tasks_to_iter[(package, task)] - - if(isinstance(event, logging.LogRecord)): - if (event.msg.startswith ("Running task")): - return # don't add these to the list - - if event.levelno >= logging.ERROR: - icon = "dialog-error" - color = Colors.ERROR - elif event.levelno >= logging.WARNING: - icon = "dialog-warning" - color = Colors.WARNING - else: - icon = None - color = Colors.OK - - # if we know which package we belong to, we'll append onto its list. - # otherwise, we'll jump to the top of the master list - if parent: - tree_add = self.model.append - else: - tree_add = self.model.prepend - tree_add(parent, - (None, - package, - task, - event.getMessage(), - icon, - color, - 0)) - - elif isinstance(event, bb.build.TaskStarted): - (package, task) = (event._package, event._task) - - # Save out this PID. - self.pids_to_task[pid] = (package, task) - - # Check if we already have this package in our model. If so then - # that can be the parent for the task. Otherwise we create a new - # top level for the package. - if ((package, None) in self.tasks_to_iter): - parent = self.tasks_to_iter[(package, None)] - else: - parent = self.model.prepend(None, (None, - package, - None, - "Package: %s" % (package), - None, - Colors.OK, - 0)) - self.tasks_to_iter[(package, None)] = parent - - # Because this parent package now has an active child mark it as - # such. - # @todo if parent is already in error, don't mark it green - self.model.set(parent, self.model.COL_ICON, "gtk-execute", - self.model.COL_COLOR, Colors.RUNNING) - - # Add an entry in the model for this task - i = self.model.append (parent, (None, - package, - task, - "Task: %s" % (task), - "gtk-execute", - Colors.RUNNING, - 0)) - - # update the parent's active task count - num_active = self.model.get(parent, self.model.COL_NUM_ACTIVE)[0] + 1 - self.model.set(parent, self.model.COL_NUM_ACTIVE, num_active) - - # Save out the iter so that we can find it when we have a message - # that we need to attach to a task. - self.tasks_to_iter[(package, task)] = i - - elif isinstance(event, bb.build.TaskBase): - current = self.tasks_to_iter[(package, task)] - parent = self.tasks_to_iter[(package, None)] - - # remove this task from the parent's active count - num_active = self.model.get(parent, self.model.COL_NUM_ACTIVE)[0] - 1 - self.model.set(parent, self.model.COL_NUM_ACTIVE, num_active) - - if isinstance(event, bb.build.TaskFailed): - # Mark the task and parent as failed - icon = "dialog-error" - color = Colors.ERROR - - logfile = event.logfile - if logfile and os.path.exists(logfile): - with open(logfile) as f: - logdata = f.read() - self.model.append(current, ('pastebin', None, None, logdata, 'gtk-error', Colors.OK, 0)) - - for i in (current, parent): - self.model.set(i, self.model.COL_ICON, icon, - self.model.COL_COLOR, color) - else: - icon = None - color = Colors.OK - - # Mark the task as inactive - self.model.set(current, self.model.COL_ICON, icon, - self.model.COL_COLOR, color) - - # Mark the parent package as inactive, but make sure to - # preserve error and active states - i = self.tasks_to_iter[(package, None)] - if self.model.get(parent, self.model.COL_ICON) != 'dialog-error': - self.model.set(parent, self.model.COL_ICON, icon) - if num_active == 0: - self.model.set(parent, self.model.COL_COLOR, Colors.OK) - - # Clear the iters and the pids since when the task goes away the - # pid will no longer be used for messages - del self.tasks_to_iter[(package, task)] - del self.pids_to_task[pid] - - elif isinstance(event, bb.event.BuildStarted): - - self.model.prepend(None, (None, - None, - None, - "Build Started (%s)" % time.strftime('%m/%d/%Y %H:%M:%S'), - None, - Colors.OK, - 0)) - elif isinstance(event, bb.event.BuildCompleted): - failures = int (event._failures) - self.model.prepend(None, (None, - None, - None, - "Build Completed (%s)" % time.strftime('%m/%d/%Y %H:%M:%S'), - None, - Colors.OK, - 0)) - - # Emit the appropriate signal depending on the number of failures - if (failures >= 1): - self.emit ("build-failed") - else: - self.emit ("build-succeeded") - - elif isinstance(event, bb.event.CacheLoadStarted) and pbar: - pbar.set_title("Loading cache") - self.progress_total = event.total - pbar.update(0, self.progress_total) - elif isinstance(event, bb.event.CacheLoadProgress) and pbar: - pbar.update(event.current, self.progress_total) - elif isinstance(event, bb.event.CacheLoadCompleted) and pbar: - pbar.update(self.progress_total, self.progress_total) - - elif isinstance(event, bb.event.ParseStarted) and pbar: - pbar.set_title("Processing recipes") - self.progress_total = event.total - pbar.update(0, self.progress_total) - elif isinstance(event, bb.event.ParseProgress) and pbar: - pbar.update(event.current, self.progress_total) - elif isinstance(event, bb.event.ParseCompleted) and pbar: - pbar.hide() - - return - - -def do_pastebin(text): - url = 'http://pastebin.com/api_public.php' - params = {'paste_code': text, 'paste_format': 'text'} - - req = urllib2.Request(url, urllib.urlencode(params)) - response = urllib2.urlopen(req) - paste_url = response.read() - - return paste_url - - -class RunningBuildTreeView (gtk.TreeView): - __gsignals__ = { - "button_press_event" : "override" - } - def __init__ (self): - gtk.TreeView.__init__ (self) - - # The icon that indicates whether we're building or failed. - renderer = gtk.CellRendererPixbuf () - col = gtk.TreeViewColumn ("Status", renderer) - col.add_attribute (renderer, "icon-name", 4) - self.append_column (col) - - # The message of the build. - self.message_renderer = gtk.CellRendererText () - self.message_column = gtk.TreeViewColumn ("Message", self.message_renderer, text=3) - self.message_column.add_attribute(self.message_renderer, 'background', 5) - self.message_renderer.set_property('editable', 5) - self.append_column (self.message_column) - - def do_button_press_event(self, event): - gtk.TreeView.do_button_press_event(self, event) - - if event.button == 3: - selection = super(RunningBuildTreeView, self).get_selection() - (model, iter) = selection.get_selected() - if iter is not None: - can_paste = model.get(iter, model.COL_LOG)[0] - if can_paste == 'pastebin': - # build a simple menu with a pastebin option - menu = gtk.Menu() - menuitem = gtk.MenuItem("Send log to pastebin") - menu.append(menuitem) - menuitem.connect("activate", self.pastebin_handler, (model, iter)) - menuitem.show() - menu.show() - menu.popup(None, None, None, event.button, event.time) - - def pastebin_handler(self, widget, data): - """ - Send the log data to pastebin, then add the new paste url to the - clipboard. - """ - (model, iter) = data - paste_url = do_pastebin(model.get(iter, model.COL_MESSAGE)[0]) - - # @todo Provide visual feedback to the user that it is done and that - # it worked. - print paste_url - - clipboard = gtk.clipboard_get() - clipboard.set_text(paste_url) - clipboard.store()
\ No newline at end of file diff --git a/bitbake/lib/bb/ui/depexp.py b/bitbake/lib/bb/ui/depexp.py deleted file mode 100644 index 3dbd5e0ec..000000000 --- a/bitbake/lib/bb/ui/depexp.py +++ /dev/null @@ -1,307 +0,0 @@ -# -# BitBake Graphical GTK based Dependency Explorer -# -# Copyright (C) 2007 Ross Burton -# Copyright (C) 2007 - 2008 Richard Purdie -# -# 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 gobject -import gtk -import Queue -import threading -import xmlrpclib -import bb -import bb.event -from bb.ui.crumbs.progress import ProgressBar - -# Package Model -(COL_PKG_NAME) = (0) - -# Dependency Model -(TYPE_DEP, TYPE_RDEP) = (0, 1) -(COL_DEP_TYPE, COL_DEP_PARENT, COL_DEP_PACKAGE) = (0, 1, 2) - - -class PackageDepView(gtk.TreeView): - def __init__(self, model, dep_type, label): - gtk.TreeView.__init__(self) - self.current = None - self.dep_type = dep_type - self.filter_model = model.filter_new() - self.filter_model.set_visible_func(self._filter) - self.set_model(self.filter_model) - #self.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE) - self.append_column(gtk.TreeViewColumn(label, gtk.CellRendererText(), text=COL_DEP_PACKAGE)) - - def _filter(self, model, iter): - (this_type, package) = model.get(iter, COL_DEP_TYPE, COL_DEP_PARENT) - if this_type != self.dep_type: return False - return package == self.current - - def set_current_package(self, package): - self.current = package - self.filter_model.refilter() - - -class PackageReverseDepView(gtk.TreeView): - def __init__(self, model, label): - gtk.TreeView.__init__(self) - self.current = None - self.filter_model = model.filter_new() - self.filter_model.set_visible_func(self._filter) - self.set_model(self.filter_model) - self.append_column(gtk.TreeViewColumn(label, gtk.CellRendererText(), text=COL_DEP_PARENT)) - - def _filter(self, model, iter): - package = model.get_value(iter, COL_DEP_PACKAGE) - return package == self.current - - def set_current_package(self, package): - self.current = package - self.filter_model.refilter() - - -class DepExplorer(gtk.Window): - def __init__(self): - gtk.Window.__init__(self) - self.set_title("Dependency Explorer") - self.set_default_size(500, 500) - self.connect("delete-event", gtk.main_quit) - - # Create the data models - self.pkg_model = gtk.ListStore(gobject.TYPE_STRING) - self.pkg_model.set_sort_column_id(COL_PKG_NAME, gtk.SORT_ASCENDING) - self.depends_model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_STRING) - self.depends_model.set_sort_column_id(COL_DEP_PACKAGE, gtk.SORT_ASCENDING) - - pane = gtk.HPaned() - pane.set_position(250) - self.add(pane) - - # The master list of packages - scrolled = gtk.ScrolledWindow() - scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled.set_shadow_type(gtk.SHADOW_IN) - - self.pkg_treeview = gtk.TreeView(self.pkg_model) - self.pkg_treeview.get_selection().connect("changed", self.on_cursor_changed) - column = gtk.TreeViewColumn("Package", gtk.CellRendererText(), text=COL_PKG_NAME) - self.pkg_treeview.append_column(column) - pane.add1(scrolled) - scrolled.add(self.pkg_treeview) - - box = gtk.VBox(homogeneous=True, spacing=4) - - # Runtime Depends - scrolled = gtk.ScrolledWindow() - scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled.set_shadow_type(gtk.SHADOW_IN) - self.rdep_treeview = PackageDepView(self.depends_model, TYPE_RDEP, "Runtime Depends") - self.rdep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE) - scrolled.add(self.rdep_treeview) - box.add(scrolled) - - # Build Depends - scrolled = gtk.ScrolledWindow() - scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled.set_shadow_type(gtk.SHADOW_IN) - self.dep_treeview = PackageDepView(self.depends_model, TYPE_DEP, "Build Depends") - self.dep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE) - scrolled.add(self.dep_treeview) - box.add(scrolled) - pane.add2(box) - - # Reverse Depends - scrolled = gtk.ScrolledWindow() - scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled.set_shadow_type(gtk.SHADOW_IN) - self.revdep_treeview = PackageReverseDepView(self.depends_model, "Reverse Depends") - self.revdep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PARENT) - scrolled.add(self.revdep_treeview) - box.add(scrolled) - pane.add2(box) - - self.show_all() - - def on_package_activated(self, treeview, path, column, data_col): - model = treeview.get_model() - package = model.get_value(model.get_iter(path), data_col) - - pkg_path = [] - def finder(model, path, iter, needle): - package = model.get_value(iter, COL_PKG_NAME) - if package == needle: - pkg_path.append(path) - return True - else: - return False - self.pkg_model.foreach(finder, package) - if pkg_path: - self.pkg_treeview.get_selection().select_path(pkg_path[0]) - self.pkg_treeview.scroll_to_cell(pkg_path[0]) - - def on_cursor_changed(self, selection): - (model, it) = selection.get_selected() - if iter is None: - current_package = None - else: - current_package = model.get_value(it, COL_PKG_NAME) - self.rdep_treeview.set_current_package(current_package) - self.dep_treeview.set_current_package(current_package) - self.revdep_treeview.set_current_package(current_package) - - -def parse(depgraph, pkg_model, depends_model): - for package in depgraph["pn"]: - pkg_model.set(pkg_model.append(), COL_PKG_NAME, package) - - for package in depgraph["depends"]: - for depend in depgraph["depends"][package]: - depends_model.set (depends_model.append(), - COL_DEP_TYPE, TYPE_DEP, - COL_DEP_PARENT, package, - COL_DEP_PACKAGE, depend) - - for package in depgraph["rdepends-pn"]: - for rdepend in depgraph["rdepends-pn"][package]: - depends_model.set (depends_model.append(), - COL_DEP_TYPE, TYPE_RDEP, - COL_DEP_PARENT, package, - COL_DEP_PACKAGE, rdepend) - - -class gtkthread(threading.Thread): - quit = threading.Event() - def __init__(self, shutdown): - threading.Thread.__init__(self) - self.setDaemon(True) - self.shutdown = shutdown - - def run(self): - gobject.threads_init() - gtk.gdk.threads_init() - gtk.main() - gtkthread.quit.set() - - -def main(server, eventHandler): - try: - cmdline = server.runCommand(["getCmdLineAction"]) - if not cmdline or cmdline[0] != "generateDotGraph": - print("This UI is only compatible with the -g option") - return - ret = server.runCommand(["generateDepTreeEvent", cmdline[1], cmdline[2]]) - if ret != True: - print("Couldn't run command! %s" % ret) - return - except xmlrpclib.Fault as x: - print("XMLRPC Fault getting commandline:\n %s" % x) - return - - shutdown = 0 - - gtkgui = gtkthread(shutdown) - gtkgui.start() - - gtk.gdk.threads_enter() - dep = DepExplorer() - pbar = ProgressBar(dep) - pbar.connect("delete-event", gtk.main_quit) - gtk.gdk.threads_leave() - - progress_total = 0 - while True: - try: - event = eventHandler.waitEvent(0.25) - if gtkthread.quit.isSet(): - server.runCommand(["stateStop"]) - break - - if event is None: - continue - - if isinstance(event, bb.event.CacheLoadStarted): - progress_total = event.total - gtk.gdk.threads_enter() - pbar.set_title("Loading Cache") - pbar.update(0, progress_total) - gtk.gdk.threads_leave() - - if isinstance(event, bb.event.CacheLoadProgress): - x = event.current - gtk.gdk.threads_enter() - pbar.update(x, progress_total) - gtk.gdk.threads_leave() - continue - - if isinstance(event, bb.event.CacheLoadCompleted): - gtk.gdk.threads_enter() - pbar.update(progress_total, progress_total) - gtk.gdk.threads_leave() - continue - - if isinstance(event, bb.event.ParseStarted): - progress_total = event.total - gtk.gdk.threads_enter() - pbar.set_title("Processing recipes") - pbar.update(0, progress_total) - gtk.gdk.threads_leave() - - if isinstance(event, bb.event.ParseProgress): - x = event.current - gtk.gdk.threads_enter() - pbar.update(x, progress_total) - gtk.gdk.threads_leave() - continue - - if isinstance(event, bb.event.ParseCompleted): - pbar.hide() - continue - - if isinstance(event, bb.event.DepTreeGenerated): - gtk.gdk.threads_enter() - parse(event._depgraph, dep.pkg_model, dep.depends_model) - gtk.gdk.threads_leave() - - if isinstance(event, bb.command.CommandCompleted): - continue - - if isinstance(event, bb.command.CommandFailed): - print("Command execution failed: %s" % event.error) - return event.exitcode - - if isinstance(event, bb.command.CommandExit): - return event.exitcode - - if isinstance(event, bb.cooker.CookerExit): - break - - continue - except EnvironmentError as ioerror: - # ignore interrupted io - if ioerror.args[0] == 4: - pass - except KeyboardInterrupt: - if shutdown == 2: - print("\nThird Keyboard Interrupt, exit.\n") - break - if shutdown == 1: - print("\nSecond Keyboard Interrupt, stopping...\n") - server.runCommand(["stateStop"]) - if shutdown == 0: - print("\nKeyboard Interrupt, closing down...\n") - server.runCommand(["stateShutdown"]) - shutdown = shutdown + 1 - pass diff --git a/bitbake/lib/bb/ui/goggle.py b/bitbake/lib/bb/ui/goggle.py deleted file mode 100644 index ec5a38dd4..000000000 --- a/bitbake/lib/bb/ui/goggle.py +++ /dev/null @@ -1,110 +0,0 @@ -# -# BitBake Graphical GTK User Interface -# -# Copyright (C) 2008 Intel Corporation -# -# Authored by Rob Bradford <rob@linux.intel.com> -# -# 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 gobject -import gtk -import xmlrpclib -from bb.ui.crumbs.runningbuild import RunningBuildTreeView, RunningBuild -from bb.ui.crumbs.progress import ProgressBar - -import Queue - - -def event_handle_idle_func (eventHandler, build, pbar): - - # Consume as many messages as we can in the time available to us - event = eventHandler.getEvent() - while event: - build.handle_event (event, pbar) - event = eventHandler.getEvent() - - return True - -def scroll_tv_cb (model, path, iter, view): - view.scroll_to_cell (path) - - -# @todo hook these into the GUI so the user has feedback... -def running_build_failed_cb (running_build): - pass - - -def running_build_succeeded_cb (running_build): - pass - - -class MainWindow (gtk.Window): - def __init__ (self): - gtk.Window.__init__ (self, gtk.WINDOW_TOPLEVEL) - - # Setup tree view and the scrolled window - scrolled_window = gtk.ScrolledWindow () - self.add (scrolled_window) - self.cur_build_tv = RunningBuildTreeView() - self.connect("delete-event", gtk.main_quit) - self.set_default_size(640, 480) - scrolled_window.add (self.cur_build_tv) - - -def main (server, eventHandler): - gobject.threads_init() - gtk.gdk.threads_init() - - window = MainWindow () - window.show_all () - pbar = ProgressBar(window) - pbar.connect("delete-event", gtk.main_quit) - - # Create the object for the current build - running_build = RunningBuild () - window.cur_build_tv.set_model (running_build.model) - running_build.model.connect("row-inserted", scroll_tv_cb, window.cur_build_tv) - running_build.connect ("build-succeeded", running_build_succeeded_cb) - running_build.connect ("build-failed", running_build_failed_cb) - - try: - cmdline = server.runCommand(["getCmdLineAction"]) - if not cmdline: - return 1 - ret = server.runCommand(cmdline) - if ret != True: - print("Couldn't get default commandline! %s" % ret) - return 1 - except xmlrpclib.Fault as x: - print("XMLRPC Fault getting commandline:\n %s" % x) - return 1 - - # Use a timeout function for probing the event queue to find out if we - # have a message waiting for us. - gobject.timeout_add (100, - event_handle_idle_func, - eventHandler, - running_build, - pbar) - - try: - gtk.main() - except EnvironmentError as ioerror: - # ignore interrupted io - if ioerror.args[0] == 4: - pass - finally: - server.runCommand(["stateStop"]) - diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py deleted file mode 100644 index 042dbe902..000000000 --- a/bitbake/lib/bb/ui/knotty.py +++ /dev/null @@ -1,248 +0,0 @@ -# -# BitBake (No)TTY UI Implementation -# -# Handling output to TTYs or files (no TTY) -# -# Copyright (C) 2006-2007 Richard Purdie -# -# 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. - -from __future__ import division - -import os -import sys -import xmlrpclib -import logging -import progressbar -import bb.msg -from bb.ui import uihelper - -logger = logging.getLogger("BitBake") -interactive = sys.stdout.isatty() - -class BBProgress(progressbar.ProgressBar): - def __init__(self, msg, maxval): - self.msg = msg - widgets = [progressbar.Percentage(), ' ', progressbar.Bar(), ' ', - progressbar.ETA()] - - progressbar.ProgressBar.__init__(self, maxval, [self.msg + ": "] + widgets) - -class NonInteractiveProgress(object): - fobj = sys.stdout - - def __init__(self, msg, maxval): - self.msg = msg - self.maxval = maxval - - def start(self): - self.fobj.write("%s..." % self.msg) - self.fobj.flush() - return self - - def update(self, value): - pass - - def finish(self): - self.fobj.write("done.\n") - self.fobj.flush() - -def new_progress(msg, maxval): - if interactive: - return BBProgress(msg, maxval) - else: - return NonInteractiveProgress(msg, maxval) - -def main(server, eventHandler): - - # Get values of variables which control our output - includelogs = server.runCommand(["getVariable", "BBINCLUDELOGS"]) - loglines = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"]) - - helper = uihelper.BBUIHelper() - - console = logging.StreamHandler(sys.stdout) - format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s") - console.setFormatter(format) - logger.addHandler(console) - - try: - cmdline = server.runCommand(["getCmdLineAction"]) - if not cmdline: - return 1 - ret = server.runCommand(cmdline) - if ret != True: - print("Couldn't get default commandline! %s" % ret) - return 1 - except xmlrpclib.Fault as x: - print("XMLRPC Fault getting commandline:\n %s" % x) - return 1 - - - parseprogress = None - cacheprogress = None - shutdown = 0 - return_value = 0 - while True: - try: - event = eventHandler.waitEvent(0.25) - if event is None: - continue - helper.eventHandler(event) - if isinstance(event, bb.runqueue.runQueueExitWait): - if not shutdown: - shutdown = 1 - if shutdown and helper.needUpdate: - activetasks, failedtasks = helper.getTasks() - if activetasks: - print("Waiting for %s active tasks to finish:" % len(activetasks)) - for tasknum, task in enumerate(activetasks): - print("%s: %s (pid %s)" % (tasknum, activetasks[task]["title"], task)) - - if isinstance(event, logging.LogRecord): - if event.levelno >= format.ERROR: - return_value = 1 - # For "normal" logging conditions, don't show note logs from tasks - # but do show them if the user has changed the default log level to - # include verbose/debug messages - if logger.getEffectiveLevel() > format.VERBOSE: - if event.taskpid != 0 and event.levelno <= format.NOTE: - continue - logger.handle(event) - continue - - if isinstance(event, bb.build.TaskFailed): - return_value = 1 - logfile = event.logfile - if logfile and os.path.exists(logfile): - print("ERROR: Logfile of failure stored in: %s" % logfile) - if 1 or includelogs: - print("Log data follows:") - f = open(logfile, "r") - lines = [] - while True: - l = f.readline() - if l == '': - break - l = l.rstrip() - if loglines: - lines.append(' | %s' % l) - if len(lines) > int(loglines): - lines.pop(0) - else: - print('| %s' % l) - f.close() - if lines: - for line in lines: - print(line) - if isinstance(event, bb.build.TaskBase): - logger.info(event._message) - continue - if isinstance(event, bb.event.ParseStarted): - parseprogress = new_progress("Parsing recipes", event.total).start() - continue - if isinstance(event, bb.event.ParseProgress): - parseprogress.update(event.current) - continue - if isinstance(event, bb.event.ParseCompleted): - parseprogress.finish() - print(("Parsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors." - % ( event.total, event.cached, event.parsed, event.virtuals, event.skipped, event.masked, event.errors))) - continue - - if isinstance(event, bb.event.CacheLoadStarted): - cacheprogress = new_progress("Loading cache", event.total).start() - continue - if isinstance(event, bb.event.CacheLoadProgress): - cacheprogress.update(event.current) - continue - if isinstance(event, bb.event.CacheLoadCompleted): - cacheprogress.finish() - print("Loaded %d entries from dependency cache." % event.num_entries) - continue - - if isinstance(event, bb.command.CommandCompleted): - break - if isinstance(event, bb.command.CommandFailed): - return_value = event.exitcode - logger.error("Command execution failed: %s", event.error) - break - if isinstance(event, bb.command.CommandExit): - return_value = event.exitcode - continue - if isinstance(event, bb.cooker.CookerExit): - break - if isinstance(event, bb.event.MultipleProviders): - logger.info("multiple providers are available for %s%s (%s)", event._is_runtime and "runtime " or "", - event._item, - ", ".join(event._candidates)) - logger.info("consider defining a PREFERRED_PROVIDER entry to match %s", event._item) - continue - if isinstance(event, bb.event.NoProvider): - if event._runtime: - r = "R" - else: - r = "" - - if event._dependees: - logger.error("Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)", r, event._item, ", ".join(event._dependees), r) - else: - logger.error("Nothing %sPROVIDES '%s'", r, event._item) - continue - - if isinstance(event, bb.runqueue.runQueueTaskStarted): - if event.noexec: - tasktype = 'noexec task' - else: - tasktype = 'task' - logger.info("Running %s %s of %s (ID: %s, %s)", - tasktype, - event.stats.completed + event.stats.active + - event.stats.failed + 1, - event.stats.total, event.taskid, event.taskstring) - continue - - if isinstance(event, bb.runqueue.runQueueTaskFailed): - logger.error("Task %s (%s) failed with exit code '%s'", - event.taskid, event.taskstring, event.exitcode) - continue - - # ignore - if isinstance(event, (bb.event.BuildBase, - bb.event.StampUpdate, - bb.event.ConfigParsed, - bb.event.RecipeParsed, - bb.runqueue.runQueueEvent, - bb.runqueue.runQueueExitWait)): - continue - - logger.error("Unknown event: %s", event) - - except EnvironmentError as ioerror: - # ignore interrupted io - if ioerror.args[0] == 4: - pass - except KeyboardInterrupt: - if shutdown == 2: - print("\nThird Keyboard Interrupt, exit.\n") - break - if shutdown == 1: - print("\nSecond Keyboard Interrupt, stopping...\n") - server.runCommand(["stateStop"]) - if shutdown == 0: - print("\nKeyboard Interrupt, closing down...\n") - server.runCommand(["stateShutdown"]) - shutdown = shutdown + 1 - pass - return return_value diff --git a/bitbake/lib/bb/ui/ncurses.py b/bitbake/lib/bb/ui/ncurses.py deleted file mode 100644 index 469f1b730..000000000 --- a/bitbake/lib/bb/ui/ncurses.py +++ /dev/null @@ -1,352 +0,0 @@ -# -# BitBake Curses UI Implementation -# -# Implements an ncurses frontend for the BitBake utility. -# -# Copyright (C) 2006 Michael 'Mickey' Lauer -# Copyright (C) 2006-2007 Richard Purdie -# -# 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. - -""" - We have the following windows: - - 1.) Main Window: Shows what we are ultimately building and how far we are. Includes status bar - 2.) Thread Activity Window: Shows one status line for every concurrent bitbake thread. - 3.) Command Line Window: Contains an interactive command line where you can interact w/ Bitbake. - - Basic window layout is like that: - - |---------------------------------------------------------| - | <Main Window> | <Thread Activity Window> | - | | 0: foo do_compile complete| - | Building Gtk+-2.6.10 | 1: bar do_patch complete | - | Status: 60% | ... | - | | ... | - | | ... | - |---------------------------------------------------------| - |<Command Line Window> | - |>>> which virtual/kernel | - |openzaurus-kernel | - |>>> _ | - |---------------------------------------------------------| - -""" - - -from __future__ import division -import logging -import os, sys, curses, itertools, time -import bb -import xmlrpclib -from bb import ui -from bb.ui import uihelper - -parsespin = itertools.cycle( r'|/-\\' ) - -X = 0 -Y = 1 -WIDTH = 2 -HEIGHT = 3 - -MAXSTATUSLENGTH = 32 - -class NCursesUI: - """ - NCurses UI Class - """ - class Window: - """Base Window Class""" - def __init__( self, x, y, width, height, fg=curses.COLOR_BLACK, bg=curses.COLOR_WHITE ): - self.win = curses.newwin( height, width, y, x ) - self.dimensions = ( x, y, width, height ) - """ - if curses.has_colors(): - color = 1 - curses.init_pair( color, fg, bg ) - self.win.bkgdset( ord(' '), curses.color_pair(color) ) - else: - self.win.bkgdset( ord(' '), curses.A_BOLD ) - """ - self.erase() - self.setScrolling() - self.win.noutrefresh() - - def erase( self ): - self.win.erase() - - def setScrolling( self, b = True ): - self.win.scrollok( b ) - self.win.idlok( b ) - - def setBoxed( self ): - self.boxed = True - self.win.box() - self.win.noutrefresh() - - def setText( self, x, y, text, *args ): - self.win.addstr( y, x, text, *args ) - self.win.noutrefresh() - - def appendText( self, text, *args ): - self.win.addstr( text, *args ) - self.win.noutrefresh() - - def drawHline( self, y ): - self.win.hline( y, 0, curses.ACS_HLINE, self.dimensions[WIDTH] ) - self.win.noutrefresh() - - class DecoratedWindow( Window ): - """Base class for windows with a box and a title bar""" - def __init__( self, title, x, y, width, height, fg=curses.COLOR_BLACK, bg=curses.COLOR_WHITE ): - NCursesUI.Window.__init__( self, x+1, y+3, width-2, height-4, fg, bg ) - self.decoration = NCursesUI.Window( x, y, width, height, fg, bg ) - self.decoration.setBoxed() - self.decoration.win.hline( 2, 1, curses.ACS_HLINE, width-2 ) - self.setTitle( title ) - - def setTitle( self, title ): - self.decoration.setText( 1, 1, title.center( self.dimensions[WIDTH]-2 ), curses.A_BOLD ) - - #-------------------------------------------------------------------------# -# class TitleWindow( Window ): - #-------------------------------------------------------------------------# -# """Title Window""" -# def __init__( self, x, y, width, height ): -# NCursesUI.Window.__init__( self, x, y, width, height ) -# version = bb.__version__ -# title = "BitBake %s" % version -# credit = "(C) 2003-2007 Team BitBake" -# #self.win.hline( 2, 1, curses.ACS_HLINE, width-2 ) -# self.win.border() -# self.setText( 1, 1, title.center( self.dimensions[WIDTH]-2 ), curses.A_BOLD ) -# self.setText( 1, 2, credit.center( self.dimensions[WIDTH]-2 ), curses.A_BOLD ) - - #-------------------------------------------------------------------------# - class ThreadActivityWindow( DecoratedWindow ): - #-------------------------------------------------------------------------# - """Thread Activity Window""" - def __init__( self, x, y, width, height ): - NCursesUI.DecoratedWindow.__init__( self, "Thread Activity", x, y, width, height ) - - def setStatus( self, thread, text ): - line = "%02d: %s" % ( thread, text ) - width = self.dimensions[WIDTH] - if ( len(line) > width ): - line = line[:width-3] + "..." - else: - line = line.ljust( width ) - self.setText( 0, thread, line ) - - #-------------------------------------------------------------------------# - class MainWindow( DecoratedWindow ): - #-------------------------------------------------------------------------# - """Main Window""" - def __init__( self, x, y, width, height ): - self.StatusPosition = width - MAXSTATUSLENGTH - NCursesUI.DecoratedWindow.__init__( self, None, x, y, width, height ) - curses.nl() - - def setTitle( self, title ): - title = "BitBake %s" % bb.__version__ - self.decoration.setText( 2, 1, title, curses.A_BOLD ) - self.decoration.setText( self.StatusPosition - 8, 1, "Status:", curses.A_BOLD ) - - def setStatus(self, status): - while len(status) < MAXSTATUSLENGTH: - status = status + " " - self.decoration.setText( self.StatusPosition, 1, status, curses.A_BOLD ) - - - #-------------------------------------------------------------------------# - class ShellOutputWindow( DecoratedWindow ): - #-------------------------------------------------------------------------# - """Interactive Command Line Output""" - def __init__( self, x, y, width, height ): - NCursesUI.DecoratedWindow.__init__( self, "Command Line Window", x, y, width, height ) - - #-------------------------------------------------------------------------# - class ShellInputWindow( Window ): - #-------------------------------------------------------------------------# - """Interactive Command Line Input""" - def __init__( self, x, y, width, height ): - NCursesUI.Window.__init__( self, x, y, width, height ) - -# put that to the top again from curses.textpad import Textbox -# self.textbox = Textbox( self.win ) -# t = threading.Thread() -# t.run = self.textbox.edit -# t.start() - - #-------------------------------------------------------------------------# - def main(self, stdscr, server, eventHandler): - #-------------------------------------------------------------------------# - height, width = stdscr.getmaxyx() - - # for now split it like that: - # MAIN_y + THREAD_y = 2/3 screen at the top - # MAIN_x = 2/3 left, THREAD_y = 1/3 right - # CLI_y = 1/3 of screen at the bottom - # CLI_x = full - - main_left = 0 - main_top = 0 - main_height = ( height // 3 * 2 ) - main_width = ( width // 3 ) * 2 - clo_left = main_left - clo_top = main_top + main_height - clo_height = height - main_height - main_top - 1 - clo_width = width - cli_left = main_left - cli_top = clo_top + clo_height - cli_height = 1 - cli_width = width - thread_left = main_left + main_width - thread_top = main_top - thread_height = main_height - thread_width = width - main_width - - #tw = self.TitleWindow( 0, 0, width, main_top ) - mw = self.MainWindow( main_left, main_top, main_width, main_height ) - taw = self.ThreadActivityWindow( thread_left, thread_top, thread_width, thread_height ) - clo = self.ShellOutputWindow( clo_left, clo_top, clo_width, clo_height ) - cli = self.ShellInputWindow( cli_left, cli_top, cli_width, cli_height ) - cli.setText( 0, 0, "BB>" ) - - mw.setStatus("Idle") - - helper = uihelper.BBUIHelper() - shutdown = 0 - - try: - cmdline = server.runCommand(["getCmdLineAction"]) - if not cmdline: - return - ret = server.runCommand(cmdline) - if ret != True: - print("Couldn't get default commandlind! %s" % ret) - return - except xmlrpclib.Fault as x: - print("XMLRPC Fault getting commandline:\n %s" % x) - return - - exitflag = False - while not exitflag: - try: - event = eventHandler.waitEvent(0.25) - if not event: - continue - - helper.eventHandler(event) - if isinstance(event, bb.build.TaskBase): - mw.appendText("NOTE: %s\n" % event._message) - if isinstance(event, logging.LogRecord): - mw.appendText(logging.getLevelName(event.levelno) + ': ' + event.getMessage() + '\n') - - if isinstance(event, bb.event.CacheLoadStarted): - self.parse_total = event.total - if isinstance(event, bb.event.CacheLoadProgress): - x = event.current - y = self.parse_total - mw.setStatus("Loading Cache: %s [%2d %%]" % ( next(parsespin), x*100/y ) ) - if isinstance(event, bb.event.CacheLoadCompleted): - mw.setStatus("Idle") - mw.appendText("Loaded %d entries from dependency cache.\n" - % ( event.num_entries)) - - if isinstance(event, bb.event.ParseStarted): - self.parse_total = event.total - if isinstance(event, bb.event.ParseProgress): - x = event.current - y = self.parse_total - mw.setStatus("Parsing Recipes: %s [%2d %%]" % ( next(parsespin), x*100/y ) ) - if isinstance(event, bb.event.ParseCompleted): - mw.setStatus("Idle") - mw.appendText("Parsing finished. %d cached, %d parsed, %d skipped, %d masked.\n" - % ( event.cached, event.parsed, event.skipped, event.masked )) - -# if isinstance(event, bb.build.TaskFailed): -# if event.logfile: -# if data.getVar("BBINCLUDELOGS", d): -# bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile) -# number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d) -# if number_of_lines: -# os.system('tail -n%s %s' % (number_of_lines, logfile)) -# else: -# f = open(logfile, "r") -# while True: -# l = f.readline() -# if l == '': -# break -# l = l.rstrip() -# print '| %s' % l -# f.close() -# else: -# bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile) - - if isinstance(event, bb.command.CommandCompleted): - # stop so the user can see the result of the build, but - # also allow them to now exit with a single ^C - shutdown = 2 - if isinstance(event, bb.command.CommandFailed): - mw.appendText("Command execution failed: %s" % event.error) - time.sleep(2) - exitflag = True - if isinstance(event, bb.command.CommandExit): - exitflag = True - if isinstance(event, bb.cooker.CookerExit): - exitflag = True - - if helper.needUpdate: - activetasks, failedtasks = helper.getTasks() - taw.erase() - taw.setText(0, 0, "") - if activetasks: - taw.appendText("Active Tasks:\n") - for task in activetasks.itervalues(): - taw.appendText(task["title"] + '\n') - if failedtasks: - taw.appendText("Failed Tasks:\n") - for task in failedtasks: - taw.appendText(task["title"] + '\n') - - curses.doupdate() - except EnvironmentError as ioerror: - # ignore interrupted io - if ioerror.args[0] == 4: - pass - - except KeyboardInterrupt: - if shutdown == 2: - mw.appendText("Third Keyboard Interrupt, exit.\n") - exitflag = True - if shutdown == 1: - mw.appendText("Second Keyboard Interrupt, stopping...\n") - server.runCommand(["stateStop"]) - if shutdown == 0: - mw.appendText("Keyboard Interrupt, closing down...\n") - server.runCommand(["stateShutdown"]) - shutdown = shutdown + 1 - pass - -def main(server, eventHandler): - if not os.isatty(sys.stdout.fileno()): - print("FATAL: Unable to run 'ncurses' UI without a TTY.") - return - ui = NCursesUI() - try: - curses.wrapper(ui.main, server, eventHandler) - except: - import traceback - traceback.print_exc() diff --git a/bitbake/lib/bb/ui/puccho.py b/bitbake/lib/bb/ui/puccho.py deleted file mode 100644 index 3ce4590c1..000000000 --- a/bitbake/lib/bb/ui/puccho.py +++ /dev/null @@ -1,425 +0,0 @@ -# -# BitBake Graphical GTK User Interface -# -# Copyright (C) 2008 Intel Corporation -# -# Authored by Rob Bradford <rob@linux.intel.com> -# -# 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 -import gtk.glade -import threading -import urllib2 -import os -import contextlib - -from bb.ui.crumbs.buildmanager import BuildManager, BuildConfiguration -from bb.ui.crumbs.buildmanager import BuildManagerTreeView - -from bb.ui.crumbs.runningbuild import RunningBuild, RunningBuildTreeView - -# The metadata loader is used by the BuildSetupDialog to download the -# available options to populate the dialog -class MetaDataLoader(gobject.GObject): - """ This class provides the mechanism for loading the metadata (the - fetching and parsing) from a given URL. The metadata encompasses details - on what machines are available. The distribution and images available for - the machine and the the uris to use for building the given machine.""" - __gsignals__ = { - 'success' : (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - ()), - 'error' : (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING,)) - } - - # We use these little helper functions to ensure that we take the gdk lock - # when emitting the signal. These functions are called as idles (so that - # they happen in the gtk / main thread's main loop. - def emit_error_signal (self, remark): - gtk.gdk.threads_enter() - self.emit ("error", remark) - gtk.gdk.threads_leave() - - def emit_success_signal (self): - gtk.gdk.threads_enter() - self.emit ("success") - gtk.gdk.threads_leave() - - def __init__ (self): - gobject.GObject.__init__ (self) - - class LoaderThread(threading.Thread): - """ This class provides an asynchronous loader for the metadata (by - using threads and signals). This is useful since the metadata may be - at a remote URL.""" - class LoaderImportException (Exception): - pass - - def __init__(self, loader, url): - threading.Thread.__init__ (self) - self.url = url - self.loader = loader - - def run (self): - result = {} - try: - with contextlib.closing (urllib2.urlopen (self.url)) as f: - # Parse the metadata format. The format is.... - # <machine>;<default distro>|<distro>...;<default image>|<image>...;<type##url>|... - for line in f: - components = line.split(";") - if (len (components) < 4): - raise MetaDataLoader.LoaderThread.LoaderImportException - machine = components[0] - distros = components[1].split("|") - images = components[2].split("|") - urls = components[3].split("|") - - result[machine] = (distros, images, urls) - - # Create an object representing this *potential* - # configuration. It can become concrete if the machine, distro - # and image are all chosen in the UI - configuration = BuildConfiguration() - configuration.metadata_url = self.url - configuration.machine_options = result - self.loader.configuration = configuration - - # Emit that we've actually got a configuration - gobject.idle_add (MetaDataLoader.emit_success_signal, - self.loader) - - except MetaDataLoader.LoaderThread.LoaderImportException as e: - gobject.idle_add (MetaDataLoader.emit_error_signal, self.loader, - "Repository metadata corrupt") - except Exception as e: - gobject.idle_add (MetaDataLoader.emit_error_signal, self.loader, - "Unable to download repository metadata") - print(e) - - def try_fetch_from_url (self, url): - # Try and download the metadata. Firing a signal if successful - thread = MetaDataLoader.LoaderThread(self, url) - thread.start() - -class BuildSetupDialog (gtk.Dialog): - RESPONSE_BUILD = 1 - - # A little helper method that just sets the states on the widgets based on - # whether we've got good metadata or not. - def set_configurable (self, configurable): - if (self.configurable == configurable): - return - - self.configurable = configurable - for widget in self.conf_widgets: - widget.set_sensitive (configurable) - - if not configurable: - self.machine_combo.set_active (-1) - self.distribution_combo.set_active (-1) - self.image_combo.set_active (-1) - - # GTK widget callbacks - def refresh_button_clicked (self, button): - # Refresh button clicked. - - url = self.location_entry.get_chars (0, -1) - self.loader.try_fetch_from_url(url) - - def repository_entry_editable_changed (self, entry): - if (len (entry.get_chars (0, -1)) > 0): - self.refresh_button.set_sensitive (True) - else: - self.refresh_button.set_sensitive (False) - self.clear_status_message() - - # If we were previously configurable we are no longer since the - # location entry has been changed - self.set_configurable (False) - - def machine_combo_changed (self, combobox): - active_iter = combobox.get_active_iter() - - if not active_iter: - return - - model = combobox.get_model() - - if model: - chosen_machine = model.get (active_iter, 0)[0] - - (distros_model, images_model) = \ - self.loader.configuration.get_distro_and_images_models (chosen_machine) - - self.distribution_combo.set_model (distros_model) - self.image_combo.set_model (images_model) - - # Callbacks from the loader - def loader_success_cb (self, loader): - self.status_image.set_from_icon_name ("info", - gtk.ICON_SIZE_BUTTON) - self.status_image.show() - self.status_label.set_label ("Repository metadata successfully downloaded") - - # Set the models on the combo boxes based on the models generated from - # the configuration that the loader has created - - # We just need to set the machine here, that then determines the - # distro and image options. Cunning huh? :-) - - self.configuration = self.loader.configuration - model = self.configuration.get_machines_model () - self.machine_combo.set_model (model) - - self.set_configurable (True) - - def loader_error_cb (self, loader, message): - self.status_image.set_from_icon_name ("error", - gtk.ICON_SIZE_BUTTON) - self.status_image.show() - self.status_label.set_text ("Error downloading repository metadata") - for widget in self.conf_widgets: - widget.set_sensitive (False) - - def clear_status_message (self): - self.status_image.hide() - self.status_label.set_label ( - """<i>Enter the repository location and press _Refresh</i>""") - - def __init__ (self): - gtk.Dialog.__init__ (self) - - # Cancel - self.add_button (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) - - # Build - button = gtk.Button ("_Build", None, True) - image = gtk.Image () - image.set_from_stock (gtk.STOCK_EXECUTE, gtk.ICON_SIZE_BUTTON) - button.set_image (image) - self.add_action_widget (button, BuildSetupDialog.RESPONSE_BUILD) - button.show_all () - - # Pull in *just* the table from the Glade XML data. - gxml = gtk.glade.XML (os.path.dirname(__file__) + "/crumbs/puccho.glade", - root = "build_table") - table = gxml.get_widget ("build_table") - self.vbox.pack_start (table, True, False, 0) - - # Grab all the widgets that we need to turn on/off when we refresh... - self.conf_widgets = [] - self.conf_widgets += [gxml.get_widget ("machine_label")] - self.conf_widgets += [gxml.get_widget ("distribution_label")] - self.conf_widgets += [gxml.get_widget ("image_label")] - self.conf_widgets += [gxml.get_widget ("machine_combo")] - self.conf_widgets += [gxml.get_widget ("distribution_combo")] - self.conf_widgets += [gxml.get_widget ("image_combo")] - - # Grab the status widgets - self.status_image = gxml.get_widget ("status_image") - self.status_label = gxml.get_widget ("status_label") - - # Grab the refresh button and connect to the clicked signal - self.refresh_button = gxml.get_widget ("refresh_button") - self.refresh_button.connect ("clicked", self.refresh_button_clicked) - - # Grab the location entry and connect to editable::changed - self.location_entry = gxml.get_widget ("location_entry") - self.location_entry.connect ("changed", - self.repository_entry_editable_changed) - - # Grab the machine combo and hook onto the changed signal. This then - # allows us to populate the distro and image combos - self.machine_combo = gxml.get_widget ("machine_combo") - self.machine_combo.connect ("changed", self.machine_combo_changed) - - # Setup the combo - cell = gtk.CellRendererText() - self.machine_combo.pack_start(cell, True) - self.machine_combo.add_attribute(cell, 'text', 0) - - # Grab the distro and image combos. We need these to populate with - # models once the machine is chosen - self.distribution_combo = gxml.get_widget ("distribution_combo") - cell = gtk.CellRendererText() - self.distribution_combo.pack_start(cell, True) - self.distribution_combo.add_attribute(cell, 'text', 0) - - self.image_combo = gxml.get_widget ("image_combo") - cell = gtk.CellRendererText() - self.image_combo.pack_start(cell, True) - self.image_combo.add_attribute(cell, 'text', 0) - - # Put the default descriptive text in the status box - self.clear_status_message() - - # Mark as non-configurable, this is just greys out the widgets the - # user can't yet use - self.configurable = False - self.set_configurable(False) - - # Show the table - table.show_all () - - # The loader and some signals connected to it to update the status - # area - self.loader = MetaDataLoader() - self.loader.connect ("success", self.loader_success_cb) - self.loader.connect ("error", self.loader_error_cb) - - def update_configuration (self): - """ A poorly named function but it updates the internal configuration - from the widgets. This can make that configuration concrete and can - thus be used for building """ - # Extract the chosen machine from the combo - model = self.machine_combo.get_model() - active_iter = self.machine_combo.get_active_iter() - if (active_iter): - self.configuration.machine = model.get(active_iter, 0)[0] - - # Extract the chosen distro from the combo - model = self.distribution_combo.get_model() - active_iter = self.distribution_combo.get_active_iter() - if (active_iter): - self.configuration.distro = model.get(active_iter, 0)[0] - - # Extract the chosen image from the combo - model = self.image_combo.get_model() - active_iter = self.image_combo.get_active_iter() - if (active_iter): - self.configuration.image = model.get(active_iter, 0)[0] - -# This function operates to pull events out from the event queue and then push -# them into the RunningBuild (which then drives the RunningBuild which then -# pushes through and updates the progress tree view.) -# -# TODO: Should be a method on the RunningBuild class -def event_handle_timeout (eventHandler, build): - # Consume as many messages as we can ... - event = eventHandler.getEvent() - while event: - build.handle_event (event) - event = eventHandler.getEvent() - return True - -class MainWindow (gtk.Window): - - # Callback that gets fired when the user hits a button in the - # BuildSetupDialog. - def build_dialog_box_response_cb (self, dialog, response_id): - conf = None - if (response_id == BuildSetupDialog.RESPONSE_BUILD): - dialog.update_configuration() - print(dialog.configuration.machine, dialog.configuration.distro, \ - dialog.configuration.image) - conf = dialog.configuration - - dialog.destroy() - - if conf: - self.manager.do_build (conf) - - def build_button_clicked_cb (self, button): - dialog = BuildSetupDialog () - - # For some unknown reason Dialog.run causes nice little deadlocks ... :-( - dialog.connect ("response", self.build_dialog_box_response_cb) - dialog.show() - - def __init__ (self): - gtk.Window.__init__ (self) - - # Pull in *just* the main vbox from the Glade XML data and then pack - # that inside the window - gxml = gtk.glade.XML (os.path.dirname(__file__) + "/crumbs/puccho.glade", - root = "main_window_vbox") - vbox = gxml.get_widget ("main_window_vbox") - self.add (vbox) - - # Create the tree views for the build manager view and the progress view - self.build_manager_view = BuildManagerTreeView() - self.running_build_view = RunningBuildTreeView() - - # Grab the scrolled windows that we put the tree views into - self.results_scrolledwindow = gxml.get_widget ("results_scrolledwindow") - self.progress_scrolledwindow = gxml.get_widget ("progress_scrolledwindow") - - # Put the tree views inside ... - self.results_scrolledwindow.add (self.build_manager_view) - self.progress_scrolledwindow.add (self.running_build_view) - - # Hook up the build button... - self.build_button = gxml.get_widget ("main_toolbutton_build") - self.build_button.connect ("clicked", self.build_button_clicked_cb) - -# I'm not very happy about the current ownership of the RunningBuild. I have -# my suspicions that this object should be held by the BuildManager since we -# care about the signals in the manager - -def running_build_succeeded_cb (running_build, manager): - # Notify the manager that a build has succeeded. This is necessary as part - # of the 'hack' that we use for making the row in the model / view - # representing the ongoing build change into a row representing the - # completed build. Since we know only one build can be running a time then - # we can handle this. - - # FIXME: Refactor all this so that the RunningBuild is owned by the - # BuildManager. It can then hook onto the signals directly and drive - # interesting things it cares about. - manager.notify_build_succeeded () - print("build succeeded") - -def running_build_failed_cb (running_build, manager): - # As above - print("build failed") - manager.notify_build_failed () - -def main (server, eventHandler): - # Initialise threading... - gobject.threads_init() - gtk.gdk.threads_init() - - main_window = MainWindow () - main_window.show_all () - - # Set up the build manager stuff in general - builds_dir = os.path.join (os.getcwd(), "results") - manager = BuildManager (server, builds_dir) - main_window.build_manager_view.set_model (manager.model) - - # Do the running build setup - running_build = RunningBuild () - main_window.running_build_view.set_model (running_build.model) - running_build.connect ("build-succeeded", running_build_succeeded_cb, - manager) - running_build.connect ("build-failed", running_build_failed_cb, manager) - - # We need to save the manager into the MainWindow so that the toolbar - # button can use it. - # FIXME: Refactor ? - main_window.manager = manager - - # Use a timeout function for probing the event queue to find out if we - # have a message waiting for us. - gobject.timeout_add (200, - event_handle_timeout, - eventHandler, - running_build) - - gtk.main() diff --git a/bitbake/lib/bb/ui/uievent.py b/bitbake/lib/bb/ui/uievent.py deleted file mode 100644 index 2fef4e465..000000000 --- a/bitbake/lib/bb/ui/uievent.py +++ /dev/null @@ -1,127 +0,0 @@ -# ex:ts=4:sw=4:sts=4:et -# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- -# -# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer -# Copyright (C) 2006 - 2007 Richard Purdie -# -# 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. - - -""" -Use this class to fork off a thread to recieve event callbacks from the bitbake -server and queue them for the UI to process. This process must be used to avoid -client/server deadlocks. -""" - -import socket, threading, pickle -from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler - -class BBUIEventQueue: - def __init__(self, BBServer): - - self.eventQueue = [] - self.eventQueueLock = threading.Lock() - self.eventQueueNotify = threading.Event() - - self.BBServer = BBServer - - self.t = threading.Thread() - self.t.setDaemon(True) - self.t.run = self.startCallbackHandler - self.t.start() - - def getEvent(self): - - self.eventQueueLock.acquire() - - if len(self.eventQueue) == 0: - self.eventQueueLock.release() - return None - - item = self.eventQueue.pop(0) - - if len(self.eventQueue) == 0: - self.eventQueueNotify.clear() - - self.eventQueueLock.release() - return item - - def waitEvent(self, delay): - self.eventQueueNotify.wait(delay) - return self.getEvent() - - def queue_event(self, event): - self.eventQueueLock.acquire() - self.eventQueue.append(event) - self.eventQueueNotify.set() - self.eventQueueLock.release() - - def send_event(self, event): - self.queue_event(pickle.loads(event)) - - def startCallbackHandler(self): - - server = UIXMLRPCServer() - self.host, self.port = server.socket.getsockname() - - server.register_function( self.system_quit, "event.quit" ) - server.register_function( self.send_event, "event.send" ) - server.socket.settimeout(1) - - self.EventHandle = self.BBServer.registerEventHandler(self.host, self.port) - - self.server = server - while not server.quit: - server.handle_request() - server.server_close() - - def system_quit( self ): - """ - Shut down the callback thread - """ - try: - self.BBServer.unregisterEventHandler(self.EventHandle) - except: - pass - self.server.quit = True - -class UIXMLRPCServer (SimpleXMLRPCServer): - - def __init__( self, interface = ("localhost", 0) ): - self.quit = False - SimpleXMLRPCServer.__init__( self, - interface, - requestHandler=SimpleXMLRPCRequestHandler, - logRequests=False, allow_none=True) - - def get_request(self): - while not self.quit: - try: - sock, addr = self.socket.accept() - sock.settimeout(1) - return (sock, addr) - except socket.timeout: - pass - return (None, None) - - def close_request(self, request): - if request is None: - return - SimpleXMLRPCServer.close_request(self, request) - - def process_request(self, request, client_address): - if request is None: - return - SimpleXMLRPCServer.process_request(self, request, client_address) - diff --git a/bitbake/lib/bb/ui/uihelper.py b/bitbake/lib/bb/ui/uihelper.py deleted file mode 100644 index 617d60db8..000000000 --- a/bitbake/lib/bb/ui/uihelper.py +++ /dev/null @@ -1,42 +0,0 @@ -# ex:ts=4:sw=4:sts=4:et -# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- -# -# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer -# Copyright (C) 2006 - 2007 Richard Purdie -# -# 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 bb.build - -class BBUIHelper: - def __init__(self): - self.needUpdate = False - self.running_tasks = {} - self.failed_tasks = [] - - def eventHandler(self, event): - if isinstance(event, bb.build.TaskStarted): - self.running_tasks[event.pid] = { 'title' : "%s %s" % (event._package, event._task) } - self.needUpdate = True - if isinstance(event, bb.build.TaskSucceeded): - del self.running_tasks[event.pid] - self.needUpdate = True - if isinstance(event, bb.build.TaskFailed): - del self.running_tasks[event.pid] - self.failed_tasks.append( { 'title' : "%s %s" % (event._package, event._task)}) - self.needUpdate = True - - def getTasks(self): - self.needUpdate = False - return (self.running_tasks, self.failed_tasks) |