summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/crumbs/hoblistmodel.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/hoblistmodel.py')
-rw-r--r--bitbake/lib/bb/ui/crumbs/hoblistmodel.py765
1 files changed, 765 insertions, 0 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/hoblistmodel.py b/bitbake/lib/bb/ui/crumbs/hoblistmodel.py
new file mode 100644
index 0000000000..227ae4b5de
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hoblistmodel.py
@@ -0,0 +1,765 @@
1#
2# BitBake Graphical GTK User Interface
3#
4# Copyright (C) 2011 Intel Corporation
5#
6# Authored by Joshua Lock <josh@linux.intel.com>
7# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
8# Authored by Shane Wang <shane.wang@intel.com>
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License version 2 as
12# published by the Free Software Foundation.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License along
20# with this program; if not, write to the Free Software Foundation, Inc.,
21# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23import gtk
24import gobject
25
26#
27# PackageListModel
28#
29class PackageListModel(gtk.TreeStore):
30 """
31 This class defines an gtk.TreeStore subclass which will convert the output
32 of the bb.event.TargetsTreeGenerated event into a gtk.TreeStore whilst also
33 providing convenience functions to access gtk.TreeModel subclasses which
34 provide filtered views of the data.
35 """
36 (COL_NAME, COL_VER, COL_REV, COL_RNM, COL_SEC, COL_SUM, COL_RDEP, COL_RPROV, COL_SIZE, COL_BINB, COL_INC) = range(11)
37
38 __gsignals__ = {
39 "packagelist-populated" : (gobject.SIGNAL_RUN_LAST,
40 gobject.TYPE_NONE,
41 ()),
42 "package-selection-changed" : (gobject.SIGNAL_RUN_LAST,
43 gobject.TYPE_NONE,
44 ()),
45 }
46
47 def __init__(self):
48
49 self.contents = None
50 self.images = None
51 self.pkgs_size = 0
52 self.pn_path = {}
53 self.pkg_path = {}
54
55 gtk.TreeStore.__init__ (self,
56 gobject.TYPE_STRING,
57 gobject.TYPE_STRING,
58 gobject.TYPE_STRING,
59 gobject.TYPE_STRING,
60 gobject.TYPE_STRING,
61 gobject.TYPE_STRING,
62 gobject.TYPE_STRING,
63 gobject.TYPE_STRING,
64 gobject.TYPE_STRING,
65 gobject.TYPE_STRING,
66 gobject.TYPE_BOOLEAN)
67
68
69 """
70 Find the model path for the item_name
71 Returns the path in the model or None
72 """
73 def find_path_for_item(self, item_name):
74 if item_name not in self.pkg_path.keys():
75 return None
76 else:
77 return self.pkg_path[item_name]
78
79 def find_item_for_path(self, item_path):
80 return self[item_path][self.COL_NAME]
81
82 """
83 Helper function to determine whether an item is an item specified by filter
84 """
85 def tree_model_filter(self, model, it, filter):
86 for key in filter.keys():
87 if model.get_value(it, key) not in filter[key]:
88 return False
89
90 return True
91
92 """
93 Create, if required, and return a filtered gtk.TreeModelSort
94 containing only the items specified by filter
95 """
96 def tree_model(self, filter):
97 model = self.filter_new()
98 model.set_visible_func(self.tree_model_filter, filter)
99
100 sort = gtk.TreeModelSort(model)
101 sort.set_sort_column_id(PackageListModel.COL_NAME, gtk.SORT_ASCENDING)
102 sort.set_default_sort_func(None)
103 return sort
104
105 def convert_vpath_to_path(self, view_model, view_path):
106 # view_model is the model sorted
107 # get the path of the model filtered
108 filtered_model_path = view_model.convert_path_to_child_path(view_path)
109 # get the model filtered
110 filtered_model = view_model.get_model()
111 # get the path of the original model
112 path = filtered_model.convert_path_to_child_path(filtered_model_path)
113 return path
114
115 def convert_path_to_vpath(self, view_model, path):
116 name = self.find_item_for_path(path)
117 it = view_model.get_iter_first()
118 while it:
119 child_it = view_model.iter_children(it)
120 while child_it:
121 view_name = view_model.get_value(child_it, self.COL_NAME)
122 if view_name == name:
123 view_path = view_model.get_path(child_it)
124 return view_path
125 child_it = view_model.iter_next(child_it)
126 it = view_model.iter_next(it)
127 return None
128
129 """
130 The populate() function takes as input the data from a
131 bb.event.PackageInfo event and populates the package list.
132 Once the population is done it emits gsignal packagelist-populated
133 to notify any listeners that the model is ready
134 """
135 def populate(self, pkginfolist):
136 self.clear()
137 self.pkgs_size = 0
138 self.pn_path = {}
139 self.pkg_path = {}
140
141 for pkginfo in pkginfolist:
142 pn = pkginfo['PN']
143 pv = pkginfo['PV']
144 pr = pkginfo['PR']
145 if pn in self.pn_path.keys():
146 pniter = self.get_iter(self.pn_path[pn])
147 else:
148 pniter = self.append(None)
149 self.set(pniter, self.COL_NAME, pn + '-' + pv + '-' + pr,
150 self.COL_INC, False)
151 self.pn_path[pn] = self.get_path(pniter)
152
153 pkg = pkginfo['PKG']
154 pkgv = pkginfo['PKGV']
155 pkgr = pkginfo['PKGR']
156 pkgsize = pkginfo['PKGSIZE_%s' % pkg] if 'PKGSIZE_%s' % pkg in pkginfo.keys() else "0"
157 pkg_rename = pkginfo['PKG_%s' % pkg] if 'PKG_%s' % pkg in pkginfo.keys() else ""
158 section = pkginfo['SECTION_%s' % pkg] if 'SECTION_%s' % pkg in pkginfo.keys() else ""
159 summary = pkginfo['SUMMARY_%s' % pkg] if 'SUMMARY_%s' % pkg in pkginfo.keys() else ""
160 rdep = pkginfo['RDEPENDS_%s' % pkg] if 'RDEPENDS_%s' % pkg in pkginfo.keys() else ""
161 rrec = pkginfo['RRECOMMENDS_%s' % pkg] if 'RRECOMMENDS_%s' % pkg in pkginfo.keys() else ""
162 rprov = pkginfo['RPROVIDES_%s' % pkg] if 'RPROVIDES_%s' % pkg in pkginfo.keys() else ""
163
164 if 'ALLOW_EMPTY_%s' % pkg in pkginfo.keys():
165 allow_empty = pkginfo['ALLOW_EMPTY_%s' % pkg]
166 elif 'ALLOW_EMPTY' in pkginfo.keys():
167 allow_empty = pkginfo['ALLOW_EMPTY']
168 else:
169 allow_empty = ""
170
171 if pkgsize == "0" and not allow_empty:
172 continue
173
174 if len(pkgsize) > 3:
175 size = '%.1f' % (int(pkgsize)*1.0/1024) + ' MB'
176 else:
177 size = pkgsize + ' KB'
178
179 it = self.append(pniter)
180 self.pkg_path[pkg] = self.get_path(it)
181 self.set(it, self.COL_NAME, pkg, self.COL_VER, pkgv,
182 self.COL_REV, pkgr, self.COL_RNM, pkg_rename,
183 self.COL_SEC, section, self.COL_SUM, summary,
184 self.COL_RDEP, rdep + ' ' + rrec,
185 self.COL_RPROV, rprov, self.COL_SIZE, size,
186 self.COL_BINB, "", self.COL_INC, False)
187
188 self.emit("packagelist-populated")
189
190 """
191 Check whether the item at item_path is included or not
192 """
193 def path_included(self, item_path):
194 return self[item_path][self.COL_INC]
195
196 """
197 Update the model, send out the notification.
198 """
199 def selection_change_notification(self):
200 self.emit("package-selection-changed")
201
202 """
203 Mark a certain package as selected.
204 All its dependencies are marked as selected.
205 The recipe provides the package is marked as selected.
206 If user explicitly selects a recipe, all its providing packages are selected
207 """
208 def include_item(self, item_path, binb=""):
209 if self.path_included(item_path):
210 return
211
212 item_name = self[item_path][self.COL_NAME]
213 item_rdep = self[item_path][self.COL_RDEP]
214
215 self[item_path][self.COL_INC] = True
216
217 self.selection_change_notification()
218
219 it = self.get_iter(item_path)
220
221 # If user explicitly selects a recipe, all its providing packages are selected.
222 if not self[item_path][self.COL_VER] and binb == "User Selected":
223 child_it = self.iter_children(it)
224 while child_it:
225 child_path = self.get_path(child_it)
226 child_included = self.path_included(child_path)
227 if not child_included:
228 self.include_item(child_path, binb="User Selected")
229 child_it = self.iter_next(child_it)
230 return
231
232 # The recipe provides the package is also marked as selected
233 parent_it = self.iter_parent(it)
234 if parent_it:
235 parent_path = self.get_path(parent_it)
236 self[parent_path][self.COL_INC] = True
237
238 item_bin = self[item_path][self.COL_BINB].split(', ')
239 if binb and not binb in item_bin:
240 item_bin.append(binb)
241 self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
242
243 if item_rdep:
244 # Ensure all of the items deps are included and, where appropriate,
245 # add this item to their COL_BINB
246 for dep in item_rdep.split(" "):
247 if dep.startswith('('):
248 continue
249 # If the contents model doesn't already contain dep, add it
250 dep_path = self.find_path_for_item(dep)
251 if not dep_path:
252 continue
253 dep_included = self.path_included(dep_path)
254
255 if dep_included and not dep in item_bin:
256 # don't set the COL_BINB to this item if the target is an
257 # item in our own COL_BINB
258 dep_bin = self[dep_path][self.COL_BINB].split(', ')
259 if not item_name in dep_bin:
260 dep_bin.append(item_name)
261 self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
262 elif not dep_included:
263 self.include_item(dep_path, binb=item_name)
264
265 """
266 Mark a certain package as de-selected.
267 All other packages that depends on this package are marked as de-selected.
268 If none of the packages provided by the recipe, the recipe should be marked as de-selected.
269 If user explicitly de-select a recipe, all its providing packages are de-selected.
270 """
271 def exclude_item(self, item_path):
272 if not self.path_included(item_path):
273 return
274
275 self[item_path][self.COL_INC] = False
276
277 self.selection_change_notification()
278
279 item_name = self[item_path][self.COL_NAME]
280 item_rdep = self[item_path][self.COL_RDEP]
281 it = self.get_iter(item_path)
282
283 # If user explicitly de-select a recipe, all its providing packages are de-selected.
284 if not self[item_path][self.COL_VER]:
285 child_it = self.iter_children(it)
286 while child_it:
287 child_path = self.get_path(child_it)
288 child_included = self[child_path][self.COL_INC]
289 if child_included:
290 self.exclude_item(child_path)
291 child_it = self.iter_next(child_it)
292 return
293
294 # If none of the packages provided by the recipe, the recipe should be marked as de-selected.
295 parent_it = self.iter_parent(it)
296 peer_iter = self.iter_children(parent_it)
297 enabled = 0
298 while peer_iter:
299 peer_path = self.get_path(peer_iter)
300 if self[peer_path][self.COL_INC]:
301 enabled = 1
302 break
303 peer_iter = self.iter_next(peer_iter)
304 if not enabled:
305 parent_path = self.get_path(parent_it)
306 self[parent_path][self.COL_INC] = False
307
308 # All packages that depends on this package are de-selected.
309 if item_rdep:
310 for dep in item_rdep.split(" "):
311 if dep.startswith('('):
312 continue
313 dep_path = self.find_path_for_item(dep)
314 if not dep_path:
315 continue
316 dep_bin = self[dep_path][self.COL_BINB].split(', ')
317 if item_name in dep_bin:
318 dep_bin.remove(item_name)
319 self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
320
321 item_bin = self[item_path][self.COL_BINB].split(', ')
322 if item_bin:
323 for binb in item_bin:
324 binb_path = self.find_path_for_item(binb)
325 if not binb_path:
326 continue
327 self.exclude_item(binb_path)
328
329 """
330 Package model may be incomplete, therefore when calling the
331 set_selected_packages(), some packages will not be set included.
332 Return the un-set packages list.
333 """
334 def set_selected_packages(self, packagelist):
335 left = []
336 for pn in packagelist:
337 if pn in self.pkg_path.keys():
338 path = self.pkg_path[pn]
339 self.include_item(item_path=path,
340 binb="User Selected")
341 else:
342 left.append(pn)
343
344 return left
345
346 def get_selected_packages(self):
347 packagelist = []
348
349 it = self.get_iter_first()
350 while it:
351 child_it = self.iter_children(it)
352 while child_it:
353 if self.get_value(child_it, self.COL_INC):
354 name = self.get_value(child_it, self.COL_NAME)
355 packagelist.append(name)
356 child_it = self.iter_next(child_it)
357 it = self.iter_next(it)
358
359 return packagelist
360
361 """
362 Return the selected package size, unit is KB.
363 """
364 def get_packages_size(self):
365 packages_size = 0
366 it = self.get_iter_first()
367 while it:
368 child_it = self.iter_children(it)
369 while child_it:
370 if self.get_value(child_it, self.COL_INC):
371 str_size = self.get_value(child_it, self.COL_SIZE)
372 if not str_size:
373 continue
374
375 unit = str_size.split()
376 if unit[1] == 'MB':
377 size = float(unit[0])*1024
378 else:
379 size = float(unit[0])
380 packages_size += size
381
382 child_it = self.iter_next(child_it)
383 it = self.iter_next(it)
384 return "%f" % packages_size
385
386 """
387 Empty self.contents by setting the include of each entry to None
388 """
389 def reset(self):
390 self.pkgs_size = 0
391 it = self.get_iter_first()
392 while it:
393 self.set(it, self.COL_INC, False)
394 child_it = self.iter_children(it)
395 while child_it:
396 self.set(child_it,
397 self.COL_INC, False,
398 self.COL_BINB, "")
399 child_it = self.iter_next(child_it)
400 it = self.iter_next(it)
401
402 self.selection_change_notification()
403
404#
405# RecipeListModel
406#
407class RecipeListModel(gtk.ListStore):
408 """
409 This class defines an gtk.ListStore subclass which will convert the output
410 of the bb.event.TargetsTreeGenerated event into a gtk.ListStore whilst also
411 providing convenience functions to access gtk.TreeModel subclasses which
412 provide filtered views of the data.
413 """
414 (COL_NAME, COL_DESC, COL_LIC, COL_GROUP, COL_DEPS, COL_BINB, COL_TYPE, COL_INC, COL_IMG, COL_INSTALL, COL_PN) = range(11)
415
416 __dummy_image__ = "--select a base image--"
417
418 __gsignals__ = {
419 "recipelist-populated" : (gobject.SIGNAL_RUN_LAST,
420 gobject.TYPE_NONE,
421 ()),
422 "recipe-selection-changed" : (gobject.SIGNAL_RUN_LAST,
423 gobject.TYPE_NONE,
424 ()),
425 }
426
427 """
428 """
429 def __init__(self):
430 gtk.ListStore.__init__ (self,
431 gobject.TYPE_STRING,
432 gobject.TYPE_STRING,
433 gobject.TYPE_STRING,
434 gobject.TYPE_STRING,
435 gobject.TYPE_STRING,
436 gobject.TYPE_STRING,
437 gobject.TYPE_STRING,
438 gobject.TYPE_BOOLEAN,
439 gobject.TYPE_BOOLEAN,
440 gobject.TYPE_STRING,
441 gobject.TYPE_STRING,
442 gobject.TYPE_STRING)
443
444 """
445 Find the model path for the item_name
446 Returns the path in the model or None
447 """
448 def find_path_for_item(self, item_name):
449 if self.non_target_name(item_name) or item_name not in self.pn_path.keys():
450 return None
451 else:
452 return self.pn_path[item_name]
453
454 def find_item_for_path(self, item_path):
455 return self[item_path][self.COL_NAME]
456
457 """
458 Helper method to determine whether name is a target pn
459 """
460 def non_target_name(self, name):
461 if name and ('-native' in name):
462 return True
463 return False
464
465 """
466 Helper function to determine whether an item is an item specified by filter
467 """
468 def tree_model_filter(self, model, it, filter):
469 name = model.get_value(it, self.COL_NAME)
470 if self.non_target_name(name):
471 return False
472
473 for key in filter.keys():
474 if model.get_value(it, key) not in filter[key]:
475 return False
476
477 return True
478
479 def sort_func(self, model, iter1, iter2):
480 val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
481 val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
482 return val1 > val2
483
484 """
485 Create, if required, and return a filtered gtk.TreeModelSort
486 containing only the items which are items specified by filter
487 """
488 def tree_model(self, filter):
489 model = self.filter_new()
490 model.set_visible_func(self.tree_model_filter, filter)
491
492 sort = gtk.TreeModelSort(model)
493 sort.set_default_sort_func(self.sort_func)
494 return sort
495
496 def convert_vpath_to_path(self, view_model, view_path):
497 filtered_model_path = view_model.convert_path_to_child_path(view_path)
498 filtered_model = view_model.get_model()
499
500 # get the path of the original model
501 path = filtered_model.convert_path_to_child_path(filtered_model_path)
502 return path
503
504 def convert_path_to_vpath(self, view_model, path):
505 it = view_model.get_iter_first()
506 while it:
507 name = self.find_item_for_path(path)
508 view_name = view_model.get_value(it, RecipeListModel.COL_NAME)
509 if view_name == name:
510 view_path = view_model.get_path(it)
511 return view_path
512 it = view_model.iter_next(it)
513 return None
514
515 def map_runtime(self, event_model, runtime, rdep_type, name):
516 if rdep_type not in ['pkg', 'pn'] or runtime not in ['rdepends', 'rrecs']:
517 return
518 package_depends = event_model["%s-%s" % (runtime, rdep_type)].get(name, [])
519 pn_depends = []
520 for package_depend in package_depends:
521 if 'task-' not in package_depend and package_depend in event_model["packages"].keys():
522 pn_depends.append(event_model["packages"][package_depend]["pn"])
523 else:
524 pn_depends.append(package_depend)
525 return list(set(pn_depends))
526
527 def subpkg_populate(self, event_model, pkg, desc, lic, group, atype, pn):
528 pn_depends = self.map_runtime(event_model, "rdepends", "pkg", pkg)
529 pn_depends += self.map_runtime(event_model, "rrecs", "pkg", pkg)
530 self.set(self.append(), self.COL_NAME, pkg, self.COL_DESC, desc,
531 self.COL_LIC, lic, self.COL_GROUP, group,
532 self.COL_DEPS, " ".join(pn_depends), self.COL_BINB, "",
533 self.COL_TYPE, atype, self.COL_INC, False,
534 self.COL_IMG, False, self.COL_INSTALL, "", self.COL_PN, pn)
535
536 """
537 The populate() function takes as input the data from a
538 bb.event.TargetsTreeGenerated event and populates the RecipeList.
539 Once the population is done it emits gsignal recipelist-populated
540 to notify any listeners that the model is ready
541 """
542 def populate(self, event_model):
543 # First clear the model, in case repopulating
544 self.clear()
545
546 # dummy image for prompt
547 self.set(self.append(), self.COL_NAME, self.__dummy_image__,
548 self.COL_DESC, "",
549 self.COL_LIC, "", self.COL_GROUP, "",
550 self.COL_DEPS, "", self.COL_BINB, "",
551 self.COL_TYPE, "image", self.COL_INC, False,
552 self.COL_IMG, False, self.COL_INSTALL, "", self.COL_PN, self.__dummy_image__)
553
554 for item in event_model["pn"]:
555 name = item
556 desc = event_model["pn"][item]["description"]
557 lic = event_model["pn"][item]["license"]
558 group = event_model["pn"][item]["section"]
559 install = []
560
561 if ('task-' in name):
562 if ('lib32-' in name or 'lib64-' in name):
563 atype = 'mltask'
564 else:
565 atype = 'task'
566 for pkg in event_model["pn"][name]["packages"]:
567 self.subpkg_populate(event_model, pkg, desc, lic, group, atype, name)
568 continue
569
570 elif ('-image-' in name):
571 atype = 'image'
572 depends = event_model["depends"].get(item, [])
573 rdepends = self.map_runtime(event_model, 'rdepends', 'pn', name)
574 depends = depends + rdepends
575 install = event_model["rdepends-pn"].get(item, [])
576
577 elif ('meta-' in name):
578 atype = 'toolchain'
579
580 elif (name == 'dummy-image' or name == 'dummy-toolchain'):
581 atype = 'dummy'
582
583 else:
584 if ('lib32-' in name or 'lib64-' in name):
585 atype = 'mlrecipe'
586 else:
587 atype = 'recipe'
588 depends = event_model["depends"].get(item, [])
589 depends += self.map_runtime(event_model, 'rdepends', 'pn', item)
590 for pkg in event_model["pn"][name]["packages"]:
591 depends += self.map_runtime(event_model, 'rdepends', 'pkg', item)
592 depends += self.map_runtime(event_model, 'rrecs', 'pkg', item)
593
594 self.set(self.append(), self.COL_NAME, item, self.COL_DESC, desc,
595 self.COL_LIC, lic, self.COL_GROUP, group,
596 self.COL_DEPS, " ".join(depends), self.COL_BINB, "",
597 self.COL_TYPE, atype, self.COL_INC, False,
598 self.COL_IMG, False, self.COL_INSTALL, " ".join(install), self.COL_PN, item)
599
600 self.pn_path = {}
601 it = self.get_iter_first()
602 while it:
603 pn = self.get_value(it, self.COL_NAME)
604 path = self.get_path(it)
605 self.pn_path[pn] = path
606 it = self.iter_next(it)
607
608 self.emit("recipelist-populated")
609
610 """
611 Update the model, send out the notification.
612 """
613 def selection_change_notification(self):
614 self.emit("recipe-selection-changed")
615
616 def path_included(self, item_path):
617 return self[item_path][self.COL_INC]
618
619 """
620 Append a certain image into the combobox
621 """
622 def image_list_append(self, name, deps, install):
623 # check whether a certain image is there
624 if not name or self.find_path_for_item(name):
625 return
626 it = self.append()
627 self.set(it, self.COL_NAME, name, self.COL_DESC, "",
628 self.COL_LIC, "", self.COL_GROUP, "",
629 self.COL_DEPS, deps, self.COL_BINB, "",
630 self.COL_TYPE, "image", self.COL_INC, False,
631 self.COL_IMG, False, self.COL_INSTALL, install,
632 self.COL_PN, name)
633 self.pn_path[name] = self.get_path(it)
634
635 """
636 Add this item, and any of its dependencies, to the image contents
637 """
638 def include_item(self, item_path, binb="", image_contents=False):
639 if self.path_included(item_path):
640 return
641
642 item_name = self[item_path][self.COL_NAME]
643 item_deps = self[item_path][self.COL_DEPS]
644
645 self[item_path][self.COL_INC] = True
646 self.selection_change_notification()
647
648 item_bin = self[item_path][self.COL_BINB].split(', ')
649 if binb and not binb in item_bin:
650 item_bin.append(binb)
651 self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
652
653 # We want to do some magic with things which are brought in by the
654 # base image so tag them as so
655 if image_contents:
656 self[item_path][self.COL_IMG] = True
657
658 if item_deps:
659 # Ensure all of the items deps are included and, where appropriate,
660 # add this item to their COL_BINB
661 for dep in item_deps.split(" "):
662 # If the contents model doesn't already contain dep, add it
663 dep_path = self.find_path_for_item(dep)
664 if not dep_path:
665 continue
666 dep_included = self.path_included(dep_path)
667
668 if dep_included and not dep in item_bin:
669 # don't set the COL_BINB to this item if the target is an
670 # item in our own COL_BINB
671 dep_bin = self[dep_path][self.COL_BINB].split(', ')
672 if not item_name in dep_bin:
673 dep_bin.append(item_name)
674 self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
675 elif not dep_included:
676 self.include_item(dep_path, binb=item_name, image_contents=image_contents)
677
678 def exclude_item(self, item_path):
679 if not self.path_included(item_path):
680 return
681
682 self[item_path][self.COL_INC] = False
683
684 self.selection_change_notification()
685
686 item_name = self[item_path][self.COL_NAME]
687 item_deps = self[item_path][self.COL_DEPS]
688 if item_deps:
689 for dep in item_deps.split(" "):
690 dep_path = self.find_path_for_item(dep)
691 if not dep_path:
692 continue
693 dep_bin = self[dep_path][self.COL_BINB].split(', ')
694 if item_name in dep_bin:
695 dep_bin.remove(item_name)
696 self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
697
698 item_bin = self[item_path][self.COL_BINB].split(', ')
699 if item_bin:
700 for binb in item_bin:
701 binb_path = self.find_path_for_item(binb)
702 if not binb_path:
703 continue
704 self.exclude_item(binb_path)
705
706 def reset(self):
707 it = self.get_iter_first()
708 while it:
709 self.set(it,
710 self.COL_INC, False,
711 self.COL_BINB, "",
712 self.COL_IMG, False)
713 it = self.iter_next(it)
714
715 self.selection_change_notification()
716
717 """
718 Returns two lists. One of user selected recipes and the other containing
719 all selected recipes
720 """
721 def get_selected_recipes(self):
722 allrecipes = []
723 userrecipes = []
724
725 it = self.get_iter_first()
726 while it:
727 if self.get_value(it, self.COL_INC):
728 name = self.get_value(it, self.COL_PN)
729 type = self.get_value(it, self.COL_TYPE)
730 if type != "image":
731 allrecipes.append(name)
732 sel = "User Selected" in self.get_value(it, self.COL_BINB)
733 if sel:
734 userrecipes.append(name)
735 it = self.iter_next(it)
736
737 return list(set(userrecipes)), list(set(allrecipes))
738
739 def set_selected_recipes(self, recipelist):
740 for pn in recipelist:
741 if pn in self.pn_path.keys():
742 path = self.pn_path[pn]
743 self.include_item(item_path=path,
744 binb="User Selected")
745
746 def get_selected_image(self):
747 it = self.get_iter_first()
748 while it:
749 if self.get_value(it, self.COL_INC):
750 name = self.get_value(it, self.COL_PN)
751 type = self.get_value(it, self.COL_TYPE)
752 if type == "image":
753 sel = "User Selected" in self.get_value(it, self.COL_BINB)
754 if sel:
755 return name
756 it = self.iter_next(it)
757 return None
758
759 def set_selected_image(self, img):
760 if img == None:
761 return
762 path = self.find_path_for_item(img)
763 self.include_item(item_path=path,
764 binb="User Selected",
765 image_contents=True)