summaryrefslogtreecommitdiffstats
path: root/bitbake-dev/lib/bb/ui/depexp.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake-dev/lib/bb/ui/depexp.py')
-rw-r--r--bitbake-dev/lib/bb/ui/depexp.py271
1 files changed, 271 insertions, 0 deletions
diff --git a/bitbake-dev/lib/bb/ui/depexp.py b/bitbake-dev/lib/bb/ui/depexp.py
new file mode 100644
index 0000000000..9d92fa0a08
--- /dev/null
+++ b/bitbake-dev/lib/bb/ui/depexp.py
@@ -0,0 +1,271 @@
1#
2# BitBake Graphical GTK based Dependency Explorer
3#
4# Copyright (C) 2007 Ross Burton
5# Copyright (C) 2007 - 2008 Richard Purdie
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 2 as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20import gobject
21import gtk
22import threading
23
24# Package Model
25(COL_PKG_NAME) = (0)
26
27# Dependency Model
28(TYPE_DEP, TYPE_RDEP) = (0, 1)
29(COL_DEP_TYPE, COL_DEP_PARENT, COL_DEP_PACKAGE) = (0, 1, 2)
30
31class PackageDepView(gtk.TreeView):
32 def __init__(self, model, dep_type, label):
33 gtk.TreeView.__init__(self)
34 self.current = None
35 self.dep_type = dep_type
36 self.filter_model = model.filter_new()
37 self.filter_model.set_visible_func(self._filter)
38 self.set_model(self.filter_model)
39 #self.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE)
40 self.append_column(gtk.TreeViewColumn(label, gtk.CellRendererText(), text=COL_DEP_PACKAGE))
41
42 def _filter(self, model, iter):
43 (this_type, package) = model.get(iter, COL_DEP_TYPE, COL_DEP_PARENT)
44 if this_type != self.dep_type: return False
45 return package == self.current
46
47 def set_current_package(self, package):
48 self.current = package
49 self.filter_model.refilter()
50
51class PackageReverseDepView(gtk.TreeView):
52 def __init__(self, model, label):
53 gtk.TreeView.__init__(self)
54 self.current = None
55 self.filter_model = model.filter_new()
56 self.filter_model.set_visible_func(self._filter)
57 self.set_model(self.filter_model)
58 self.append_column(gtk.TreeViewColumn(label, gtk.CellRendererText(), text=COL_DEP_PARENT))
59
60 def _filter(self, model, iter):
61 package = model.get_value(iter, COL_DEP_PACKAGE)
62 return package == self.current
63
64 def set_current_package(self, package):
65 self.current = package
66 self.filter_model.refilter()
67
68class DepExplorer(gtk.Window):
69 def __init__(self):
70 gtk.Window.__init__(self)
71 self.set_title("Dependency Explorer")
72 self.set_default_size(500, 500)
73 self.connect("delete-event", gtk.main_quit)
74
75 # Create the data models
76 self.pkg_model = gtk.ListStore(gobject.TYPE_STRING)
77 self.depends_model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_STRING)
78
79 pane = gtk.HPaned()
80 pane.set_position(250)
81 self.add(pane)
82
83 # The master list of packages
84 scrolled = gtk.ScrolledWindow()
85 scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
86 scrolled.set_shadow_type(gtk.SHADOW_IN)
87 self.pkg_treeview = gtk.TreeView(self.pkg_model)
88 self.pkg_treeview.get_selection().connect("changed", self.on_cursor_changed)
89 self.pkg_treeview.append_column(gtk.TreeViewColumn("Package", gtk.CellRendererText(), text=COL_PKG_NAME))
90 pane.add1(scrolled)
91 scrolled.add(self.pkg_treeview)
92
93 box = gtk.VBox(homogeneous=True, spacing=4)
94
95 # Runtime Depends
96 scrolled = gtk.ScrolledWindow()
97 scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
98 scrolled.set_shadow_type(gtk.SHADOW_IN)
99 self.rdep_treeview = PackageDepView(self.depends_model, TYPE_RDEP, "Runtime Depends")
100 self.rdep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE)
101 scrolled.add(self.rdep_treeview)
102 box.add(scrolled)
103
104 # Build Depends
105 scrolled = gtk.ScrolledWindow()
106 scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
107 scrolled.set_shadow_type(gtk.SHADOW_IN)
108 self.dep_treeview = PackageDepView(self.depends_model, TYPE_DEP, "Build Depends")
109 self.dep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE)
110 scrolled.add(self.dep_treeview)
111 box.add(scrolled)
112 pane.add2(box)
113
114 # Reverse Depends
115 scrolled = gtk.ScrolledWindow()
116 scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
117 scrolled.set_shadow_type(gtk.SHADOW_IN)
118 self.revdep_treeview = PackageReverseDepView(self.depends_model, "Reverse Depends")
119 self.revdep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PARENT)
120 scrolled.add(self.revdep_treeview)
121 box.add(scrolled)
122 pane.add2(box)
123
124 self.show_all()
125
126 def on_package_activated(self, treeview, path, column, data_col):
127 model = treeview.get_model()
128 package = model.get_value(model.get_iter(path), data_col)
129
130 pkg_path = []
131 def finder(model, path, iter, needle):
132 package = model.get_value(iter, COL_PKG_NAME)
133 if package == needle:
134 pkg_path.append(path)
135 return True
136 else:
137 return False
138 self.pkg_model.foreach(finder, package)
139 if pkg_path:
140 self.pkg_treeview.get_selection().select_path(pkg_path[0])
141 self.pkg_treeview.scroll_to_cell(pkg_path[0])
142
143 def on_cursor_changed(self, selection):
144 (model, it) = selection.get_selected()
145 if iter is None:
146 current_package = None
147 else:
148 current_package = model.get_value(it, COL_PKG_NAME)
149 self.rdep_treeview.set_current_package(current_package)
150 self.dep_treeview.set_current_package(current_package)
151 self.revdep_treeview.set_current_package(current_package)
152
153
154def parse(depgraph, pkg_model, depends_model):
155
156 for package in depgraph["pn"]:
157 pkg_model.set(pkg_model.append(), COL_PKG_NAME, package)
158
159 for package in depgraph["depends"]:
160 for depend in depgraph["depends"][package]:
161 depends_model.set (depends_model.append(),
162 COL_DEP_TYPE, TYPE_DEP,
163 COL_DEP_PARENT, package,
164 COL_DEP_PACKAGE, depend)
165
166 for package in depgraph["rdepends-pn"]:
167 for rdepend in depgraph["rdepends-pn"][package]:
168 depends_model.set (depends_model.append(),
169 COL_DEP_TYPE, TYPE_RDEP,
170 COL_DEP_PARENT, package,
171 COL_DEP_PACKAGE, rdepend)
172
173class ProgressBar(gtk.Window):
174 def __init__(self):
175
176 gtk.Window.__init__(self)
177 self.set_title("Parsing .bb files, please wait...")
178 self.set_default_size(500, 0)
179 self.connect("delete-event", gtk.main_quit)
180
181 self.progress = gtk.ProgressBar()
182 self.add(self.progress)
183 self.show_all()
184
185class gtkthread(threading.Thread):
186 quit = threading.Event()
187 def __init__(self, shutdown):
188 threading.Thread.__init__(self)
189 self.setDaemon(True)
190 self.shutdown = shutdown
191
192 def run(self):
193 gobject.threads_init()
194 gtk.gdk.threads_init()
195 gtk.main()
196 gtkthread.quit.set()
197
198def init(server, eventHandler):
199
200 try:
201 cmdline = server.runCommand(["getCmdLineAction"])
202 if not cmdline or cmdline[0] != "generateDotGraph":
203 print "This UI is only compatible with the -g option"
204 return
205 ret = server.runCommand(["generateDepTreeEvent", cmdline[1], cmdline[2]])
206 if ret != True:
207 print "Couldn't run command! %s" % ret
208 return
209 except xmlrpclib.Fault, x:
210 print "XMLRPC Fault getting commandline:\n %s" % x
211 return
212
213 shutdown = 0
214
215 gtkgui = gtkthread(shutdown)
216 gtkgui.start()
217
218 gtk.gdk.threads_enter()
219 pbar = ProgressBar()
220 dep = DepExplorer()
221 gtk.gdk.threads_leave()
222
223 while True:
224 try:
225 event = eventHandler.waitEvent(0.25)
226 if gtkthread.quit.isSet():
227 break
228
229 if event is None:
230 continue
231 if event[0].startswith('bb.event.ParseProgress'):
232 x = event[1]['sofar']
233 y = event[1]['total']
234 if x == y:
235 print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors."
236 % ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'], event[1]['errors']))
237 pbar.hide()
238 gtk.gdk.threads_enter()
239 pbar.progress.set_fraction(float(x)/float(y))
240 pbar.progress.set_text("%d/%d (%2d %%)" % (x, y, x*100/y))
241 gtk.gdk.threads_leave()
242 continue
243
244 if event[0] == "bb.event.DepTreeGenerated":
245 gtk.gdk.threads_enter()
246 parse(event[1]['_depgraph'], dep.pkg_model, dep.depends_model)
247 gtk.gdk.threads_leave()
248
249 if event[0] == 'bb.command.CookerCommandCompleted':
250 continue
251 if event[0] == 'bb.command.CookerCommandFailed':
252 print "Command execution failed: %s" % event[1]['error']
253 break
254 if event[0] == 'bb.cooker.CookerExit':
255 break
256
257 continue
258
259 except KeyboardInterrupt:
260 if shutdown == 2:
261 print "\nThird Keyboard Interrupt, exit.\n"
262 break
263 if shutdown == 1:
264 print "\nSecond Keyboard Interrupt, stopping...\n"
265 server.runCommand(["stateStop"])
266 if shutdown == 0:
267 print "\nKeyboard Interrupt, closing down...\n"
268 server.runCommand(["stateShutdown"])
269 shutdown = shutdown + 1
270 pass
271