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.py900
1 files changed, 900 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..b4d2a621b7
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hoblistmodel.py
@@ -0,0 +1,900 @@
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
25from bb.ui.crumbs.hobpages import HobPage
26
27#
28# PackageListModel
29#
30class PackageListModel(gtk.ListStore):
31 """
32 This class defines an gtk.ListStore subclass which will convert the output
33 of the bb.event.TargetsTreeGenerated event into a gtk.ListStore whilst also
34 providing convenience functions to access gtk.TreeModel subclasses which
35 provide filtered views of the data.
36 """
37
38 (COL_NAME, COL_VER, COL_REV, COL_RNM, COL_SEC, COL_SUM, COL_RDEP, COL_RPROV, COL_SIZE, COL_RCP, COL_BINB, COL_INC, COL_FADE_INC, COL_FONT, COL_FLIST) = range(15)
39
40 __gsignals__ = {
41 "package-selection-changed" : (gobject.SIGNAL_RUN_LAST,
42 gobject.TYPE_NONE,
43 ()),
44 }
45
46 __toolchain_required_packages__ = ["packagegroup-core-standalone-sdk-target", "packagegroup-core-standalone-sdk-target-dbg"]
47
48 def __init__(self):
49 self.rprov_pkg = {}
50 gtk.ListStore.__init__ (self,
51 gobject.TYPE_STRING,
52 gobject.TYPE_STRING,
53 gobject.TYPE_STRING,
54 gobject.TYPE_STRING,
55 gobject.TYPE_STRING,
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_BOOLEAN,
63 gobject.TYPE_BOOLEAN,
64 gobject.TYPE_STRING,
65 gobject.TYPE_STRING)
66 self.sort_column_id, self.sort_order = PackageListModel.COL_NAME, gtk.SORT_ASCENDING
67
68 """
69 Find the model path for the item_name
70 Returns the path in the model or None
71 """
72 def find_path_for_item(self, item_name):
73 pkg = item_name
74 if item_name not in self.pn_path.keys():
75 if item_name not in self.rprov_pkg.keys():
76 return None
77 pkg = self.rprov_pkg[item_name]
78 if pkg not in self.pn_path.keys():
79 return None
80
81 return self.pn_path[pkg]
82
83 def find_item_for_path(self, item_path):
84 return self[item_path][self.COL_NAME]
85
86 """
87 Helper function to determine whether an item is an item specified by filter
88 """
89 def tree_model_filter(self, model, it, filter):
90 name = model.get_value(it, self.COL_NAME)
91
92 for key in filter.keys():
93 if key == self.COL_NAME:
94 if filter[key] != 'Search packages by name':
95 if name and filter[key] not in name:
96 return False
97 else:
98 if model.get_value(it, key) not in filter[key]:
99 return False
100 self.filtered_nb += 1
101 return True
102
103 """
104 Create, if required, and return a filtered gtk.TreeModelSort
105 containing only the items specified by filter
106 """
107 def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=False, search_data=None, initial=False):
108 model = self.filter_new()
109 self.filtered_nb = 0
110 model.set_visible_func(self.tree_model_filter, filter)
111
112 sort = gtk.TreeModelSort(model)
113 sort.connect ('sort-column-changed', self.sort_column_changed_cb)
114 if initial:
115 sort.set_sort_column_id(PackageListModel.COL_NAME, gtk.SORT_ASCENDING)
116 sort.set_default_sort_func(None)
117 elif excluded_items_ahead:
118 sort.set_default_sort_func(self.exclude_item_sort_func, search_data)
119 elif included_items_ahead:
120 sort.set_default_sort_func(self.include_item_sort_func, search_data)
121 else:
122 if search_data and search_data!='Search recipes by name' and search_data!='Search package groups by name':
123 sort.set_default_sort_func(self.sort_func, search_data)
124 else:
125 sort.set_sort_column_id(self.sort_column_id, self.sort_order)
126 sort.set_default_sort_func(None)
127
128 sort.set_sort_func(PackageListModel.COL_INC, self.sort_column, PackageListModel.COL_INC)
129 sort.set_sort_func(PackageListModel.COL_SIZE, self.sort_column, PackageListModel.COL_SIZE)
130 sort.set_sort_func(PackageListModel.COL_BINB, self.sort_binb_column)
131 sort.set_sort_func(PackageListModel.COL_RCP, self.sort_column, PackageListModel.COL_RCP)
132 return sort
133
134 def sort_column_changed_cb (self, data):
135 self.sort_column_id, self.sort_order = data.get_sort_column_id ()
136
137 def sort_column(self, model, row1, row2, col):
138 value1 = model.get_value(row1, col)
139 value2 = model.get_value(row2, col)
140 if col==PackageListModel.COL_SIZE:
141 value1 = HobPage._string_to_size(value1)
142 value2 = HobPage._string_to_size(value2)
143
144 cmp_res = cmp(value1, value2)
145 if cmp_res!=0:
146 if col==PackageListModel.COL_INC:
147 return -cmp_res
148 else:
149 return cmp_res
150 else:
151 name1 = model.get_value(row1, PackageListModel.COL_NAME)
152 name2 = model.get_value(row2, PackageListModel.COL_NAME)
153 return cmp(name1,name2)
154
155 def sort_binb_column(self, model, row1, row2):
156 value1 = model.get_value(row1, PackageListModel.COL_BINB)
157 value2 = model.get_value(row2, PackageListModel.COL_BINB)
158 value1_list = value1.split(', ')
159 value2_list = value2.split(', ')
160
161 value1 = value1_list[0]
162 value2 = value2_list[0]
163
164 cmp_res = cmp(value1, value2)
165 if cmp_res==0:
166 cmp_size = cmp(len(value1_list), len(value2_list))
167 if cmp_size==0:
168 name1 = model.get_value(row1, PackageListModel.COL_NAME)
169 name2 = model.get_value(row2, PackageListModel.COL_NAME)
170 return cmp(name1,name2)
171 else:
172 return cmp_size
173 else:
174 return cmp_res
175
176 def exclude_item_sort_func(self, model, iter1, iter2, user_data=None):
177 if user_data:
178 val1 = model.get_value(iter1, PackageListModel.COL_NAME)
179 val2 = model.get_value(iter2, PackageListModel.COL_NAME)
180 return self.cmp_vals(val1, val2, user_data)
181 else:
182 val1 = model.get_value(iter1, PackageListModel.COL_FADE_INC)
183 val2 = model.get_value(iter2, PackageListModel.COL_INC)
184 return ((val1 == True) and (val2 == False))
185
186 def include_item_sort_func(self, model, iter1, iter2, user_data=None):
187 if user_data:
188 val1 = model.get_value(iter1, PackageListModel.COL_NAME)
189 val2 = model.get_value(iter2, PackageListModel.COL_NAME)
190 return self.cmp_vals(val1, val2, user_data)
191 else:
192 val1 = model.get_value(iter1, PackageListModel.COL_INC)
193 val2 = model.get_value(iter2, PackageListModel.COL_INC)
194 return ((val1 == False) and (val2 == True))
195
196 def sort_func(self, model, iter1, iter2, user_data):
197 val1 = model.get_value(iter1, PackageListModel.COL_NAME)
198 val2 = model.get_value(iter2, PackageListModel.COL_NAME)
199 return self.cmp_vals(val1, val2, user_data)
200
201 def cmp_vals(self, val1, val2, user_data):
202 if val1.startswith(user_data) and not val2.startswith(user_data):
203 return -1
204 elif not val1.startswith(user_data) and val2.startswith(user_data):
205 return 1
206 else:
207 return cmp(val1, val2)
208
209 def convert_vpath_to_path(self, view_model, view_path):
210 # view_model is the model sorted
211 # get the path of the model filtered
212 filtered_model_path = view_model.convert_path_to_child_path(view_path)
213 # get the model filtered
214 filtered_model = view_model.get_model()
215 # get the path of the original model
216 path = filtered_model.convert_path_to_child_path(filtered_model_path)
217 return path
218
219 def convert_path_to_vpath(self, view_model, path):
220 it = view_model.get_iter_first()
221 while it:
222 name = self.find_item_for_path(path)
223 view_name = view_model.get_value(it, PackageListModel.COL_NAME)
224 if view_name == name:
225 view_path = view_model.get_path(it)
226 return view_path
227 it = view_model.iter_next(it)
228 return None
229
230 """
231 The populate() function takes as input the data from a
232 bb.event.PackageInfo event and populates the package list.
233 """
234 def populate(self, pkginfolist):
235 # First clear the model, in case repopulating
236 self.clear()
237
238 def getpkgvalue(pkgdict, key, pkgname, defaultval = None):
239 value = pkgdict.get('%s_%s' % (key, pkgname), None)
240 if not value:
241 value = pkgdict.get(key, defaultval)
242 return value
243
244 for pkginfo in pkginfolist:
245 pn = pkginfo['PN']
246 pv = pkginfo['PV']
247 pr = pkginfo['PR']
248 pkg = pkginfo['PKG']
249 pkgv = getpkgvalue(pkginfo, 'PKGV', pkg)
250 pkgr = getpkgvalue(pkginfo, 'PKGR', pkg)
251 # PKGSIZE is artificial, will always be overridden with the package name if present
252 pkgsize = pkginfo.get('PKGSIZE_%s' % pkg, "0")
253 # PKG_%s is the renamed version
254 pkg_rename = pkginfo.get('PKG_%s' % pkg, "")
255 # The rest may be overridden or not
256 section = getpkgvalue(pkginfo, 'SECTION', pkg, "")
257 summary = getpkgvalue(pkginfo, 'SUMMARY', pkg, "")
258 rdep = getpkgvalue(pkginfo, 'RDEPENDS', pkg, "")
259 rrec = getpkgvalue(pkginfo, 'RRECOMMENDS', pkg, "")
260 rprov = getpkgvalue(pkginfo, 'RPROVIDES', pkg, "")
261 files_list = getpkgvalue(pkginfo, 'FILES_INFO', pkg, "")
262 for i in rprov.split():
263 self.rprov_pkg[i] = pkg
264
265 recipe = pn + '-' + pv + '-' + pr
266
267 allow_empty = getpkgvalue(pkginfo, 'ALLOW_EMPTY', pkg, "")
268
269 if pkgsize == "0" and not allow_empty:
270 continue
271
272 # pkgsize is in KB
273 size = HobPage._size_to_string(HobPage._string_to_size(pkgsize + ' KB'))
274 self.set(self.append(), self.COL_NAME, pkg, self.COL_VER, pkgv,
275 self.COL_REV, pkgr, self.COL_RNM, pkg_rename,
276 self.COL_SEC, section, self.COL_SUM, summary,
277 self.COL_RDEP, rdep + ' ' + rrec,
278 self.COL_RPROV, rprov, self.COL_SIZE, size,
279 self.COL_RCP, recipe, self.COL_BINB, "",
280 self.COL_INC, False, self.COL_FONT, '10', self.COL_FLIST, files_list)
281
282 self.pn_path = {}
283 it = self.get_iter_first()
284 while it:
285 pn = self.get_value(it, self.COL_NAME)
286 path = self.get_path(it)
287 self.pn_path[pn] = path
288 it = self.iter_next(it)
289
290 """
291 Update the model, send out the notification.
292 """
293 def selection_change_notification(self):
294 self.emit("package-selection-changed")
295
296 """
297 Check whether the item at item_path is included or not
298 """
299 def path_included(self, item_path):
300 return self[item_path][self.COL_INC]
301
302 """
303 Add this item, and any of its dependencies, to the image contents
304 """
305 def include_item(self, item_path, binb=""):
306 if self.path_included(item_path):
307 return
308
309 item_name = self[item_path][self.COL_NAME]
310 item_deps = self[item_path][self.COL_RDEP]
311
312 self[item_path][self.COL_INC] = True
313
314 item_bin = self[item_path][self.COL_BINB].split(', ')
315 if binb and not binb in item_bin:
316 item_bin.append(binb)
317 self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
318
319 if item_deps:
320 # Ensure all of the items deps are included and, where appropriate,
321 # add this item to their COL_BINB
322 for dep in item_deps.split(" "):
323 if dep.startswith('('):
324 continue
325 # If the contents model doesn't already contain dep, add it
326 dep_path = self.find_path_for_item(dep)
327 if not dep_path:
328 continue
329 dep_included = self.path_included(dep_path)
330
331 if dep_included and not dep in item_bin:
332 # don't set the COL_BINB to this item if the target is an
333 # item in our own COL_BINB
334 dep_bin = self[dep_path][self.COL_BINB].split(', ')
335 if not item_name in dep_bin:
336 dep_bin.append(item_name)
337 self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
338 elif not dep_included:
339 self.include_item(dep_path, binb=item_name)
340
341 def exclude_item(self, item_path):
342 if not self.path_included(item_path):
343 return
344
345 self[item_path][self.COL_INC] = False
346
347 item_name = self[item_path][self.COL_NAME]
348 item_deps = self[item_path][self.COL_RDEP]
349 if item_deps:
350 for dep in item_deps.split(" "):
351 if dep.startswith('('):
352 continue
353 dep_path = self.find_path_for_item(dep)
354 if not dep_path:
355 continue
356 dep_bin = self[dep_path][self.COL_BINB].split(', ')
357 if item_name in dep_bin:
358 dep_bin.remove(item_name)
359 self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
360
361 item_bin = self[item_path][self.COL_BINB].split(', ')
362 if item_bin:
363 for binb in item_bin:
364 binb_path = self.find_path_for_item(binb)
365 if not binb_path:
366 continue
367 self.exclude_item(binb_path)
368
369 """
370 Empty self.contents by setting the include of each entry to None
371 """
372 def reset(self):
373 it = self.get_iter_first()
374 while it:
375 self.set(it,
376 self.COL_INC, False,
377 self.COL_BINB, "")
378 it = self.iter_next(it)
379
380 self.selection_change_notification()
381
382 def get_selected_packages(self):
383 packagelist = []
384
385 it = self.get_iter_first()
386 while it:
387 if self.get_value(it, self.COL_INC):
388 name = self.get_value(it, self.COL_NAME)
389 packagelist.append(name)
390 it = self.iter_next(it)
391
392 return packagelist
393
394 def get_user_selected_packages(self):
395 packagelist = []
396
397 it = self.get_iter_first()
398 while it:
399 if self.get_value(it, self.COL_INC):
400 binb = self.get_value(it, self.COL_BINB)
401 if binb == "User Selected":
402 name = self.get_value(it, self.COL_NAME)
403 packagelist.append(name)
404 it = self.iter_next(it)
405
406 return packagelist
407
408 def get_selected_packages_toolchain(self):
409 packagelist = []
410
411 it = self.get_iter_first()
412 while it:
413 if self.get_value(it, self.COL_INC):
414 name = self.get_value(it, self.COL_NAME)
415 if name.endswith("-dev") or name.endswith("-dbg"):
416 packagelist.append(name)
417 it = self.iter_next(it)
418
419 return list(set(packagelist + self.__toolchain_required_packages__));
420
421 """
422 Package model may be incomplete, therefore when calling the
423 set_selected_packages(), some packages will not be set included.
424 Return the un-set packages list.
425 """
426 def set_selected_packages(self, packagelist, user_selected=False):
427 left = []
428 binb = 'User Selected' if user_selected else ''
429 for pn in packagelist:
430 if pn in self.pn_path.keys():
431 path = self.pn_path[pn]
432 self.include_item(item_path=path, binb=binb)
433 else:
434 left.append(pn)
435
436 self.selection_change_notification()
437 return left
438
439 """
440 Return the selected package size, unit is B.
441 """
442 def get_packages_size(self):
443 packages_size = 0
444 it = self.get_iter_first()
445 while it:
446 if self.get_value(it, self.COL_INC):
447 str_size = self.get_value(it, self.COL_SIZE)
448 if not str_size:
449 continue
450
451 packages_size += HobPage._string_to_size(str_size)
452
453 it = self.iter_next(it)
454 return packages_size
455
456 """
457 Resync the state of included items to a backup column before performing the fadeout visible effect
458 """
459 def resync_fadeout_column(self, model_first_iter=None):
460 it = model_first_iter
461 while it:
462 active = self.get_value(it, self.COL_INC)
463 self.set(it, self.COL_FADE_INC, active)
464 it = self.iter_next(it)
465
466#
467# RecipeListModel
468#
469class RecipeListModel(gtk.ListStore):
470 """
471 This class defines an gtk.ListStore subclass which will convert the output
472 of the bb.event.TargetsTreeGenerated event into a gtk.ListStore whilst also
473 providing convenience functions to access gtk.TreeModel subclasses which
474 provide filtered views of the data.
475 """
476 (COL_NAME, COL_DESC, COL_LIC, COL_GROUP, COL_DEPS, COL_BINB, COL_TYPE, COL_INC, COL_IMG, COL_INSTALL, COL_PN, COL_FADE_INC, COL_SUMMARY, COL_VERSION,
477 COL_REVISION, COL_HOMEPAGE, COL_BUGTRACKER, COL_FILE) = range(18)
478
479 __custom_image__ = "Start with an empty image recipe"
480
481 __gsignals__ = {
482 "recipe-selection-changed" : (gobject.SIGNAL_RUN_LAST,
483 gobject.TYPE_NONE,
484 ()),
485 }
486
487 """
488 """
489 def __init__(self):
490 gtk.ListStore.__init__ (self,
491 gobject.TYPE_STRING,
492 gobject.TYPE_STRING,
493 gobject.TYPE_STRING,
494 gobject.TYPE_STRING,
495 gobject.TYPE_STRING,
496 gobject.TYPE_STRING,
497 gobject.TYPE_STRING,
498 gobject.TYPE_BOOLEAN,
499 gobject.TYPE_BOOLEAN,
500 gobject.TYPE_STRING,
501 gobject.TYPE_STRING,
502 gobject.TYPE_BOOLEAN,
503 gobject.TYPE_STRING,
504 gobject.TYPE_STRING,
505 gobject.TYPE_STRING,
506 gobject.TYPE_STRING,
507 gobject.TYPE_STRING,
508 gobject.TYPE_STRING)
509 self.sort_column_id, self.sort_order = RecipeListModel.COL_NAME, gtk.SORT_ASCENDING
510
511 """
512 Find the model path for the item_name
513 Returns the path in the model or None
514 """
515 def find_path_for_item(self, item_name):
516 if self.non_target_name(item_name) or item_name not in self.pn_path.keys():
517 return None
518 else:
519 return self.pn_path[item_name]
520
521 def find_item_for_path(self, item_path):
522 return self[item_path][self.COL_NAME]
523
524 """
525 Helper method to determine whether name is a target pn
526 """
527 def non_target_name(self, name):
528 if name and ('-native' in name):
529 return True
530 return False
531
532 """
533 Helper function to determine whether an item is an item specified by filter
534 """
535 def tree_model_filter(self, model, it, filter):
536 name = model.get_value(it, self.COL_NAME)
537 if self.non_target_name(name):
538 return False
539
540 for key in filter.keys():
541 if key == self.COL_NAME:
542 if filter[key] != 'Search recipes by name' and filter[key] != 'Search package groups by name':
543 if filter[key] not in name:
544 return False
545 else:
546 if model.get_value(it, key) not in filter[key]:
547 return False
548 self.filtered_nb += 1
549
550 return True
551
552 def exclude_item_sort_func(self, model, iter1, iter2, user_data=None):
553 if user_data:
554 val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
555 val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
556 return self.cmp_vals(val1, val2, user_data)
557 else:
558 val1 = model.get_value(iter1, RecipeListModel.COL_FADE_INC)
559 val2 = model.get_value(iter2, RecipeListModel.COL_INC)
560 return ((val1 == True) and (val2 == False))
561
562 def include_item_sort_func(self, model, iter1, iter2, user_data=None):
563 if user_data:
564 val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
565 val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
566 return self.cmp_vals(val1, val2, user_data)
567 else:
568 val1 = model.get_value(iter1, RecipeListModel.COL_INC)
569 val2 = model.get_value(iter2, RecipeListModel.COL_INC)
570 return ((val1 == False) and (val2 == True))
571
572 def sort_func(self, model, iter1, iter2, user_data):
573 val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
574 val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
575 return self.cmp_vals(val1, val2, user_data)
576
577 def cmp_vals(self, val1, val2, user_data):
578 if val1.startswith(user_data) and not val2.startswith(user_data):
579 return -1
580 elif not val1.startswith(user_data) and val2.startswith(user_data):
581 return 1
582 else:
583 return cmp(val1, val2)
584
585 """
586 Create, if required, and return a filtered gtk.TreeModelSort
587 containing only the items specified by filter
588 """
589 def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=False, search_data=None, initial=False):
590 model = self.filter_new()
591 self.filtered_nb = 0
592 model.set_visible_func(self.tree_model_filter, filter)
593
594 sort = gtk.TreeModelSort(model)
595 sort.connect ('sort-column-changed', self.sort_column_changed_cb)
596 if initial:
597 sort.set_sort_column_id(RecipeListModel.COL_NAME, gtk.SORT_ASCENDING)
598 sort.set_default_sort_func(None)
599 elif excluded_items_ahead:
600 sort.set_default_sort_func(self.exclude_item_sort_func, search_data)
601 elif included_items_ahead:
602 sort.set_default_sort_func(self.include_item_sort_func, search_data)
603 else:
604 if search_data and search_data!='Search recipes by name' and search_data!='Search package groups by name':
605 sort.set_default_sort_func(self.sort_func, search_data)
606 else:
607 sort.set_sort_column_id(self.sort_column_id, self.sort_order)
608 sort.set_default_sort_func(None)
609
610 sort.set_sort_func(RecipeListModel.COL_INC, self.sort_column, RecipeListModel.COL_INC)
611 sort.set_sort_func(RecipeListModel.COL_GROUP, self.sort_column, RecipeListModel.COL_GROUP)
612 sort.set_sort_func(RecipeListModel.COL_BINB, self.sort_binb_column)
613 sort.set_sort_func(RecipeListModel.COL_LIC, self.sort_column, RecipeListModel.COL_LIC)
614 return sort
615
616 def sort_column_changed_cb (self, data):
617 self.sort_column_id, self.sort_order = data.get_sort_column_id ()
618
619 def sort_column(self, model, row1, row2, col):
620 value1 = model.get_value(row1, col)
621 value2 = model.get_value(row2, col)
622 cmp_res = cmp(value1, value2)
623 if cmp_res!=0:
624 if col==RecipeListModel.COL_INC:
625 return -cmp_res
626 else:
627 return cmp_res
628 else:
629 name1 = model.get_value(row1, RecipeListModel.COL_NAME)
630 name2 = model.get_value(row2, RecipeListModel.COL_NAME)
631 return cmp(name1,name2)
632
633 def sort_binb_column(self, model, row1, row2):
634 value1 = model.get_value(row1, RecipeListModel.COL_BINB)
635 value2 = model.get_value(row2, RecipeListModel.COL_BINB)
636 value1_list = value1.split(', ')
637 value2_list = value2.split(', ')
638
639 value1 = value1_list[0]
640 value2 = value2_list[0]
641
642 cmp_res = cmp(value1, value2)
643 if cmp_res==0:
644 cmp_size = cmp(len(value1_list), len(value2_list))
645 if cmp_size==0:
646 name1 = model.get_value(row1, RecipeListModel.COL_NAME)
647 name2 = model.get_value(row2, RecipeListModel.COL_NAME)
648 return cmp(name1,name2)
649 else:
650 return cmp_size
651 else:
652 return cmp_res
653
654 def convert_vpath_to_path(self, view_model, view_path):
655 filtered_model_path = view_model.convert_path_to_child_path(view_path)
656 filtered_model = view_model.get_model()
657
658 # get the path of the original model
659 path = filtered_model.convert_path_to_child_path(filtered_model_path)
660 return path
661
662 def convert_path_to_vpath(self, view_model, path):
663 it = view_model.get_iter_first()
664 while it:
665 name = self.find_item_for_path(path)
666 view_name = view_model.get_value(it, RecipeListModel.COL_NAME)
667 if view_name == name:
668 view_path = view_model.get_path(it)
669 return view_path
670 it = view_model.iter_next(it)
671 return None
672
673 """
674 The populate() function takes as input the data from a
675 bb.event.TargetsTreeGenerated event and populates the RecipeList.
676 """
677 def populate(self, event_model):
678 # First clear the model, in case repopulating
679 self.clear()
680
681 # dummy image for prompt
682 self.set_in_list(self.__custom_image__, "Use 'Edit image recipe' to customize recipes and packages " \
683 "to be included in your image ")
684
685 for item in event_model["pn"]:
686 name = item
687 desc = event_model["pn"][item]["description"]
688 lic = event_model["pn"][item]["license"]
689 group = event_model["pn"][item]["section"]
690 inherits = event_model["pn"][item]["inherits"]
691 summary = event_model["pn"][item]["summary"]
692 version = event_model["pn"][item]["version"]
693 revision = event_model["pn"][item]["prevision"]
694 homepage = event_model["pn"][item]["homepage"]
695 bugtracker = event_model["pn"][item]["bugtracker"]
696 filename = event_model["pn"][item]["filename"]
697 install = []
698
699 depends = event_model["depends"].get(item, []) + event_model["rdepends-pn"].get(item, [])
700
701 if ('packagegroup.bbclass' in " ".join(inherits)):
702 atype = 'packagegroup'
703 elif ('image.bbclass' in " ".join(inherits)):
704 if name != "hob-image":
705 atype = 'image'
706 install = event_model["rdepends-pkg"].get(item, []) + event_model["rrecs-pkg"].get(item, [])
707 elif ('meta-' in name):
708 atype = 'toolchain'
709 elif (name == 'dummy-image' or name == 'dummy-toolchain'):
710 atype = 'dummy'
711 else:
712 atype = 'recipe'
713
714 self.set(self.append(), self.COL_NAME, item, self.COL_DESC, desc,
715 self.COL_LIC, lic, self.COL_GROUP, group,
716 self.COL_DEPS, " ".join(depends), self.COL_BINB, "",
717 self.COL_TYPE, atype, self.COL_INC, False,
718 self.COL_IMG, False, self.COL_INSTALL, " ".join(install), self.COL_PN, item,
719 self.COL_SUMMARY, summary, self.COL_VERSION, version, self.COL_REVISION, revision,
720 self.COL_HOMEPAGE, homepage, self.COL_BUGTRACKER, bugtracker,
721 self.COL_FILE, filename)
722
723 self.pn_path = {}
724 it = self.get_iter_first()
725 while it:
726 pn = self.get_value(it, self.COL_NAME)
727 path = self.get_path(it)
728 self.pn_path[pn] = path
729 it = self.iter_next(it)
730
731 def set_in_list(self, item, desc):
732 self.set(self.append(), self.COL_NAME, item,
733 self.COL_DESC, desc,
734 self.COL_LIC, "", self.COL_GROUP, "",
735 self.COL_DEPS, "", self.COL_BINB, "",
736 self.COL_TYPE, "image", self.COL_INC, False,
737 self.COL_IMG, False, self.COL_INSTALL, "", self.COL_PN, item,
738 self.COL_SUMMARY, "", self.COL_VERSION, "", self.COL_REVISION, "",
739 self.COL_HOMEPAGE, "", self.COL_BUGTRACKER, "")
740 self.pn_path = {}
741 it = self.get_iter_first()
742 while it:
743 pn = self.get_value(it, self.COL_NAME)
744 path = self.get_path(it)
745 self.pn_path[pn] = path
746 it = self.iter_next(it)
747
748 """
749 Update the model, send out the notification.
750 """
751 def selection_change_notification(self):
752 self.emit("recipe-selection-changed")
753
754 def path_included(self, item_path):
755 return self[item_path][self.COL_INC]
756
757 """
758 Add this item, and any of its dependencies, to the image contents
759 """
760 def include_item(self, item_path, binb="", image_contents=False):
761 if self.path_included(item_path):
762 return
763
764 item_name = self[item_path][self.COL_NAME]
765 item_deps = self[item_path][self.COL_DEPS]
766
767 self[item_path][self.COL_INC] = True
768
769 item_bin = self[item_path][self.COL_BINB].split(', ')
770 if binb and not binb in item_bin:
771 item_bin.append(binb)
772 self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
773
774 # We want to do some magic with things which are brought in by the
775 # base image so tag them as so
776 if image_contents:
777 self[item_path][self.COL_IMG] = True
778
779 if item_deps:
780 # Ensure all of the items deps are included and, where appropriate,
781 # add this item to their COL_BINB
782 for dep in item_deps.split(" "):
783 # If the contents model doesn't already contain dep, add it
784 dep_path = self.find_path_for_item(dep)
785 if not dep_path:
786 continue
787 dep_included = self.path_included(dep_path)
788
789 if dep_included and not dep in item_bin:
790 # don't set the COL_BINB to this item if the target is an
791 # item in our own COL_BINB
792 dep_bin = self[dep_path][self.COL_BINB].split(', ')
793 if not item_name in dep_bin:
794 dep_bin.append(item_name)
795 self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
796 elif not dep_included:
797 self.include_item(dep_path, binb=item_name, image_contents=image_contents)
798 dep_bin = self[item_path][self.COL_BINB].split(', ')
799 if self[item_path][self.COL_NAME] in dep_bin:
800 dep_bin.remove(self[item_path][self.COL_NAME])
801 self[item_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
802
803 def exclude_item(self, item_path):
804 if not self.path_included(item_path):
805 return
806
807 self[item_path][self.COL_INC] = False
808
809 item_name = self[item_path][self.COL_NAME]
810 item_deps = self[item_path][self.COL_DEPS]
811 if item_deps:
812 for dep in item_deps.split(" "):
813 dep_path = self.find_path_for_item(dep)
814 if not dep_path:
815 continue
816 dep_bin = self[dep_path][self.COL_BINB].split(', ')
817 if item_name in dep_bin:
818 dep_bin.remove(item_name)
819 self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
820
821 item_bin = self[item_path][self.COL_BINB].split(', ')
822 if item_bin:
823 for binb in item_bin:
824 binb_path = self.find_path_for_item(binb)
825 if not binb_path:
826 continue
827 self.exclude_item(binb_path)
828
829 def reset(self):
830 it = self.get_iter_first()
831 while it:
832 self.set(it,
833 self.COL_INC, False,
834 self.COL_BINB, "",
835 self.COL_IMG, False)
836 it = self.iter_next(it)
837
838 self.selection_change_notification()
839
840 """
841 Returns two lists. One of user selected recipes and the other containing
842 all selected recipes
843 """
844 def get_selected_recipes(self):
845 allrecipes = []
846 userrecipes = []
847
848 it = self.get_iter_first()
849 while it:
850 if self.get_value(it, self.COL_INC):
851 name = self.get_value(it, self.COL_PN)
852 type = self.get_value(it, self.COL_TYPE)
853 if type != "image":
854 allrecipes.append(name)
855 sel = "User Selected" in self.get_value(it, self.COL_BINB)
856 if sel:
857 userrecipes.append(name)
858 it = self.iter_next(it)
859
860 return list(set(userrecipes)), list(set(allrecipes))
861
862 def set_selected_recipes(self, recipelist):
863 for pn in recipelist:
864 if pn in self.pn_path.keys():
865 path = self.pn_path[pn]
866 self.include_item(item_path=path,
867 binb="User Selected")
868 self.selection_change_notification()
869
870 def get_selected_image(self):
871 it = self.get_iter_first()
872 while it:
873 if self.get_value(it, self.COL_INC):
874 name = self.get_value(it, self.COL_PN)
875 type = self.get_value(it, self.COL_TYPE)
876 if type == "image":
877 sel = "User Selected" in self.get_value(it, self.COL_BINB)
878 if sel:
879 return name
880 it = self.iter_next(it)
881 return None
882
883 def set_selected_image(self, img):
884 if not img:
885 return
886 self.reset()
887 path = self.find_path_for_item(img)
888 self.include_item(item_path=path,
889 binb="User Selected",
890 image_contents=True)
891 self.selection_change_notification()
892
893 def set_custom_image_version(self, version):
894 self.custom_image_version = version
895
896 def get_custom_image_version(self):
897 return self.custom_image_version
898
899 def is_custom_image(self):
900 return self.get_selected_image() == self.__custom_image__