diff options
author | Joshua Lock <josh@linux.intel.com> | 2011-07-01 15:58:50 -0700 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2011-07-05 14:40:30 +0100 |
commit | 4cc291c007103c19779f995e852b37dbad122293 (patch) | |
tree | 3447d62ef1ba2eca08137b8e13df58f8a337a453 /bitbake/lib/bb/ui/crumbs/hobeventhandler.py | |
parent | 7fc9c3488f7865111ec052d1cab213d216d2b414 (diff) | |
download | poky-4cc291c007103c19779f995e852b37dbad122293.tar.gz |
hob: re-designed interaction and implementation
Highlights include:
* Atempted GNOME HIG compliance
* Simplified UI and interaction model
* Sorting and type to find in tree views
* Preferences dialog to modify local settings
* Dialog to add and remove layers
* Search in packages list
* Save/Load image recipes
The build model has been changed, hob will attempt to build all dependent
packages of an image and then use the buildFile server method to build the
created image.
(Bitbake rev: 48e64acaae4a741b9f5630f426fb4e6142755c2c)
Signed-off-by: Joshua Lock <josh@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/hobeventhandler.py')
-rw-r--r-- | bitbake/lib/bb/ui/crumbs/hobeventhandler.py | 218 |
1 files changed, 172 insertions, 46 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/hobeventhandler.py b/bitbake/lib/bb/ui/crumbs/hobeventhandler.py index c474491d6a..fa79e0c7a2 100644 --- a/bitbake/lib/bb/ui/crumbs/hobeventhandler.py +++ b/bitbake/lib/bb/ui/crumbs/hobeventhandler.py | |||
@@ -19,7 +19,6 @@ | |||
19 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 19 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
20 | 20 | ||
21 | import gobject | 21 | import gobject |
22 | from bb.ui.crumbs.progress import ProgressBar | ||
23 | 22 | ||
24 | progress_total = 0 | 23 | progress_total = 0 |
25 | 24 | ||
@@ -29,46 +28,78 @@ class HobHandler(gobject.GObject): | |||
29 | This object does BitBake event handling for the hob gui. | 28 | This object does BitBake event handling for the hob gui. |
30 | """ | 29 | """ |
31 | __gsignals__ = { | 30 | __gsignals__ = { |
32 | "machines-updated" : (gobject.SIGNAL_RUN_LAST, | 31 | "machines-updated" : (gobject.SIGNAL_RUN_LAST, |
33 | gobject.TYPE_NONE, | 32 | gobject.TYPE_NONE, |
34 | (gobject.TYPE_PYOBJECT,)), | 33 | (gobject.TYPE_PYOBJECT,)), |
35 | "distros-updated" : (gobject.SIGNAL_RUN_LAST, | 34 | "sdk-machines-updated": (gobject.SIGNAL_RUN_LAST, |
36 | gobject.TYPE_NONE, | 35 | gobject.TYPE_NONE, |
37 | (gobject.TYPE_PYOBJECT,)), | 36 | (gobject.TYPE_PYOBJECT,)), |
38 | "generating-data" : (gobject.SIGNAL_RUN_LAST, | 37 | "distros-updated" : (gobject.SIGNAL_RUN_LAST, |
39 | gobject.TYPE_NONE, | 38 | gobject.TYPE_NONE, |
40 | ()), | 39 | (gobject.TYPE_PYOBJECT,)), |
41 | "data-generated" : (gobject.SIGNAL_RUN_LAST, | 40 | "package-formats-found" : (gobject.SIGNAL_RUN_LAST, |
42 | gobject.TYPE_NONE, | 41 | gobject.TYPE_NONE, |
43 | ()) | 42 | (gobject.TYPE_PYOBJECT,)), |
43 | "config-found" : (gobject.SIGNAL_RUN_LAST, | ||
44 | gobject.TYPE_NONE, | ||
45 | (gobject.TYPE_STRING,)), | ||
46 | "generating-data" : (gobject.SIGNAL_RUN_LAST, | ||
47 | gobject.TYPE_NONE, | ||
48 | ()), | ||
49 | "data-generated" : (gobject.SIGNAL_RUN_LAST, | ||
50 | gobject.TYPE_NONE, | ||
51 | ()), | ||
52 | "error" : (gobject.SIGNAL_RUN_LAST, | ||
53 | gobject.TYPE_NONE, | ||
54 | (gobject.TYPE_STRING,)), | ||
55 | "build-complete" : (gobject.SIGNAL_RUN_LAST, | ||
56 | gobject.TYPE_NONE, | ||
57 | ()), | ||
58 | "reload-triggered" : (gobject.SIGNAL_RUN_LAST, | ||
59 | gobject.TYPE_NONE, | ||
60 | (gobject.TYPE_STRING, | ||
61 | gobject.TYPE_STRING)), | ||
44 | } | 62 | } |
45 | 63 | ||
46 | def __init__(self, taskmodel, server): | 64 | def __init__(self, taskmodel, server): |
47 | gobject.GObject.__init__(self) | 65 | gobject.GObject.__init__(self) |
66 | self.current_command = None | ||
67 | self.building = None | ||
68 | self.gplv3_excluded = False | ||
69 | self.build_toolchain = False | ||
70 | self.build_toolchain_headers = False | ||
71 | self.generating = False | ||
72 | self.build_queue = [] | ||
48 | 73 | ||
49 | self.model = taskmodel | 74 | self.model = taskmodel |
50 | self.server = server | 75 | self.server = server |
51 | self.current_command = None | ||
52 | self.building = False | ||
53 | 76 | ||
54 | self.command_map = { | 77 | self.command_map = { |
55 | "findConfigFilesDistro" : ("findConfigFiles", "MACHINE", "findConfigFilesMachine"), | 78 | "findConfigFilePathLocal" : ("findConfigFilePath", ["hob.local.conf"], "findConfigFilePathHobLocal"), |
56 | "findConfigFilesMachine" : ("generateTargetsTree", "classes/image.bbclass", None), | 79 | "findConfigFilePathHobLocal" : ("findConfigFilePath", ["bblayers.conf"], "findConfigFilePathLayers"), |
57 | "generateTargetsTree" : (None, None, None), | 80 | "findConfigFilePathLayers" : ("findConfigFiles", ["DISTRO"], "findConfigFilesDistro"), |
81 | "findConfigFilesDistro" : ("findConfigFiles", ["MACHINE"], "findConfigFilesMachine"), | ||
82 | "findConfigFilesMachine" : ("findConfigFiles", ["MACHINE-SDK"], "findConfigFilesSdkMachine"), | ||
83 | "findConfigFilesSdkMachine" : ("findFilesMatchingInDir", ["rootfs_", "classes"], "findFilesMatchingPackage"), | ||
84 | "findFilesMatchingPackage" : ("generateTargetsTree", ["classes/image.bbclass"], None), | ||
85 | "generateTargetsTree" : (None, [], None), | ||
58 | } | 86 | } |
59 | 87 | ||
60 | def run_next_command(self): | 88 | def run_next_command(self): |
61 | # FIXME: this is ugly and I *will* replace it | 89 | # FIXME: this is ugly and I *will* replace it |
62 | if self.current_command: | 90 | if self.current_command: |
91 | if not self.generating: | ||
92 | self.emit("generating-data") | ||
93 | self.generating = True | ||
63 | next_cmd = self.command_map[self.current_command] | 94 | next_cmd = self.command_map[self.current_command] |
64 | command = next_cmd[0] | 95 | command = next_cmd[0] |
65 | argument = next_cmd[1] | 96 | argument = next_cmd[1] |
66 | self.current_command = next_cmd[2] | 97 | self.current_command = next_cmd[2] |
67 | if command == "generateTargetsTree": | 98 | args = [command] |
68 | self.emit("generating-data") | 99 | args.extend(argument) |
69 | self.server.runCommand([command, argument]) | 100 | self.server.runCommand(args) |
70 | 101 | ||
71 | def handle_event(self, event, running_build, pbar=None): | 102 | def handle_event(self, event, running_build, pbar): |
72 | if not event: | 103 | if not event: |
73 | return | 104 | return |
74 | 105 | ||
@@ -77,9 +108,9 @@ class HobHandler(gobject.GObject): | |||
77 | running_build.handle_event(event) | 108 | running_build.handle_event(event) |
78 | elif isinstance(event, bb.event.TargetsTreeGenerated): | 109 | elif isinstance(event, bb.event.TargetsTreeGenerated): |
79 | self.emit("data-generated") | 110 | self.emit("data-generated") |
111 | self.generating = False | ||
80 | if event._model: | 112 | if event._model: |
81 | self.model.populate(event._model) | 113 | self.model.populate(event._model) |
82 | |||
83 | elif isinstance(event, bb.event.ConfigFilesFound): | 114 | elif isinstance(event, bb.event.ConfigFilesFound): |
84 | var = event._variable | 115 | var = event._variable |
85 | if var == "distro": | 116 | if var == "distro": |
@@ -90,28 +121,44 @@ class HobHandler(gobject.GObject): | |||
90 | machines = event._values | 121 | machines = event._values |
91 | machines.sort() | 122 | machines.sort() |
92 | self.emit("machines-updated", machines) | 123 | self.emit("machines-updated", machines) |
93 | 124 | elif var == "machine-sdk": | |
125 | sdk_machines = event._values | ||
126 | sdk_machines.sort() | ||
127 | self.emit("sdk-machines-updated", sdk_machines) | ||
128 | elif isinstance(event, bb.event.ConfigFilePathFound): | ||
129 | path = event._path | ||
130 | self.emit("config-found", path) | ||
131 | elif isinstance(event, bb.event.FilesMatchingFound): | ||
132 | # FIXME: hard coding, should at least be a variable shared between | ||
133 | # here and the caller | ||
134 | if event._pattern == "rootfs_": | ||
135 | formats = [] | ||
136 | for match in event._matches: | ||
137 | classname, sep, cls = match.rpartition(".") | ||
138 | fs, sep, format = classname.rpartition("_") | ||
139 | formats.append(format) | ||
140 | formats.sort() | ||
141 | self.emit("package-formats-found", formats) | ||
94 | elif isinstance(event, bb.command.CommandCompleted): | 142 | elif isinstance(event, bb.command.CommandCompleted): |
95 | self.run_next_command() | 143 | self.run_next_command() |
96 | elif isinstance(event, bb.event.CacheLoadStarted) and pbar: | 144 | elif isinstance(event, bb.command.CommandFailed): |
97 | pbar.set_title("Loading cache") | 145 | self.emit("error", event.error) |
146 | elif isinstance(event, bb.event.CacheLoadStarted): | ||
98 | bb.ui.crumbs.hobeventhandler.progress_total = event.total | 147 | bb.ui.crumbs.hobeventhandler.progress_total = event.total |
99 | pbar.update(0, bb.ui.crumbs.hobeventhandler.progress_total) | 148 | pbar.set_text("Loading cache: %s/%s" % (0, bb.ui.crumbs.hobeventhandler.progress_total)) |
100 | elif isinstance(event, bb.event.CacheLoadProgress) and pbar: | 149 | elif isinstance(event, bb.event.CacheLoadProgress): |
101 | pbar.update(event.current, bb.ui.crumbs.hobeventhandler.progress_total) | 150 | pbar.set_text("Loading cache: %s/%s" % (event.current, bb.ui.crumbs.hobeventhandler.progress_total)) |
102 | elif isinstance(event, bb.event.CacheLoadCompleted) and pbar: | 151 | elif isinstance(event, bb.event.CacheLoadCompleted): |
103 | pbar.update(bb.ui.crumbs.hobeventhandler.progress_total, bb.ui.crumbs.hobeventhandler.progress_total) | 152 | pbar.set_text("Loading cache: %s/%s" % (bb.ui.crumbs.hobeventhandler.progress_total, bb.ui.crumbs.hobeventhandler.progress_total)) |
104 | elif isinstance(event, bb.event.ParseStarted) and pbar: | 153 | elif isinstance(event, bb.event.ParseStarted): |
105 | if event.total == 0: | 154 | if event.total == 0: |
106 | return | 155 | return |
107 | pbar.set_title("Processing recipes") | ||
108 | bb.ui.crumbs.hobeventhandler.progress_total = event.total | 156 | bb.ui.crumbs.hobeventhandler.progress_total = event.total |
109 | pbar.update(0, bb.ui.crumbs.hobeventhandler.progress_total) | 157 | pbar.set_text("Processing recipes: %s/%s" % (0, bb.ui.crumbs.hobeventhandler.progress_total)) |
110 | elif isinstance(event, bb.event.ParseProgress) and pbar: | 158 | elif isinstance(event, bb.event.ParseProgress): |
111 | pbar.update(event.current, bb.ui.crumbs.hobeventhandler.progress_total) | 159 | pbar.set_text("Processing recipes: %s/%s" % (event.current, bb.ui.crumbs.hobeventhandler.progress_total)) |
112 | elif isinstance(event, bb.event.ParseCompleted) and pbar: | 160 | elif isinstance(event, bb.event.ParseCompleted): |
113 | pbar.hide() | 161 | pbar.set_fraction(1.0) |
114 | |||
115 | return | 162 | return |
116 | 163 | ||
117 | def event_handle_idle_func (self, eventHandler, running_build, pbar): | 164 | def event_handle_idle_func (self, eventHandler, running_build, pbar): |
@@ -124,16 +171,95 @@ class HobHandler(gobject.GObject): | |||
124 | 171 | ||
125 | def set_machine(self, machine): | 172 | def set_machine(self, machine): |
126 | self.server.runCommand(["setVariable", "MACHINE", machine]) | 173 | self.server.runCommand(["setVariable", "MACHINE", machine]) |
127 | self.current_command = "findConfigFilesMachine" | 174 | |
128 | self.run_next_command() | 175 | def set_sdk_machine(self, sdk_machine): |
176 | self.server.runCommand(["setVariable", "SDKMACHINE", sdk_machine]) | ||
129 | 177 | ||
130 | def set_distro(self, distro): | 178 | def set_distro(self, distro): |
131 | self.server.runCommand(["setVariable", "DISTRO", distro]) | 179 | self.server.runCommand(["setVariable", "DISTRO", distro]) |
132 | 180 | ||
133 | def run_build(self, targets): | 181 | def set_package_format(self, format): |
134 | self.building = True | 182 | self.server.runCommand(["setVariable", "PACKAGE_CLASSES", "package_%s" % format]) |
183 | |||
184 | def reload_data(self, config=None): | ||
185 | img = self.model.selected_image | ||
186 | selected_packages, _ = self.model.get_selected_packages() | ||
187 | self.emit("reload-triggered", img, " ".join(selected_packages)) | ||
188 | self.server.runCommand(["reparseFiles"]) | ||
189 | self.current_command = "findConfigFilePathLayers" | ||
190 | self.run_next_command() | ||
191 | |||
192 | def set_bbthreads(self, threads): | ||
193 | self.server.runCommand(["setVariable", "BB_NUMBER_THREADS", threads]) | ||
194 | |||
195 | def set_pmake(self, threads): | ||
196 | pmake = "-j %s" % threads | ||
197 | self.server.runCommand(["setVariable", "BB_NUMBER_THREADS", pmake]) | ||
198 | |||
199 | def run_build(self, tgts): | ||
200 | self.building = "image" | ||
201 | targets = [] | ||
202 | targets.append(tgts) | ||
203 | if self.build_toolchain and self.build_toolchain_headers: | ||
204 | targets = ["meta-toolchain-sdk"] + targets | ||
205 | elif self.build_toolchain: | ||
206 | targets = ["meta-toolchain"] + targets | ||
135 | self.server.runCommand(["buildTargets", targets, "build"]) | 207 | self.server.runCommand(["buildTargets", targets, "build"]) |
136 | 208 | ||
137 | def cancel_build(self): | 209 | def build_packages(self, pkgs): |
138 | # Note: this may not be the right way to stop an in-progress build | 210 | self.building = "packages" |
139 | self.server.runCommand(["stateStop"]) | 211 | if 'meta-toolchain' in self.build_queue: |
212 | self.build_queue.remove('meta-toolchain') | ||
213 | pkgs.extend('meta-toolchain') | ||
214 | self.server.runCommand(["buildTargets", pkgs, "build"]) | ||
215 | |||
216 | def build_file(self, image): | ||
217 | self.building = "image" | ||
218 | self.server.runCommand(["buildFile", image, "build"]) | ||
219 | |||
220 | def cancel_build(self, force=False): | ||
221 | if force: | ||
222 | # Force the cooker to stop as quickly as possible | ||
223 | self.server.runCommand(["stateStop"]) | ||
224 | else: | ||
225 | # Wait for tasks to complete before shutting down, this helps | ||
226 | # leave the workdir in a usable state | ||
227 | self.server.runCommand(["stateShutdown"]) | ||
228 | |||
229 | def toggle_gplv3(self, excluded): | ||
230 | if self.gplv3_excluded != excluded: | ||
231 | self.gplv3_excluded = excluded | ||
232 | if excluded: | ||
233 | self.server.runCommand(["setVariable", "INCOMPATIBLE_LICENSE", "GPLv3"]) | ||
234 | else: | ||
235 | self.server.runCommand(["setVariable", "INCOMPATIBLE_LICENSE", ""]) | ||
236 | |||
237 | def toggle_toolchain(self, enabled): | ||
238 | if self.build_toolchain != enabled: | ||
239 | self.build_toolchain = enabled | ||
240 | |||
241 | def toggle_toolchain_headers(self, enabled): | ||
242 | if self.build_toolchain_headers != enabled: | ||
243 | self.build_toolchain_headers = enabled | ||
244 | |||
245 | def queue_image_recipe_path(self, path): | ||
246 | self.build_queue.append(path) | ||
247 | |||
248 | def build_complete_cb(self, running_build): | ||
249 | if len(self.build_queue) > 0: | ||
250 | next = self.build_queue.pop(0) | ||
251 | if next.endswith('.bb'): | ||
252 | self.build_file(next) | ||
253 | self.building = 'image' | ||
254 | self.build_file(next) | ||
255 | else: | ||
256 | self.build_packages(next.split(" ")) | ||
257 | else: | ||
258 | self.building = None | ||
259 | self.emit("build-complete") | ||
260 | |||
261 | def set_image_output_type(self, output_type): | ||
262 | self.server.runCommand(["setVariable", "IMAGE_FSTYPES", output_type]) | ||
263 | |||
264 | def get_image_deploy_dir(self): | ||
265 | return self.server.runCommand(["getVariable", "DEPLOY_DIR_IMAGE"]) | ||