diff options
| author | Cristiana Voicu <cristiana.voicu@intel.com> | 2013-03-20 14:35:06 +0200 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2013-03-22 16:54:39 +0000 |
| commit | 860f826753cab81b1d1d9b2ecafa630a96676d9e (patch) | |
| tree | 6f5da66864b05ded2f96c76ce9299a3386fa9c1f /bitbake/lib | |
| parent | ab7d8bd172f61e14266a020bd6633d33d79e3d8f (diff) | |
| download | poky-860f826753cab81b1d1d9b2ecafa630a96676d9e.tar.gz | |
bitbake: hob: implementation of search functionality in Hob
Implemented the search functionality for recipes and packages using
filters on the listmodel. I have used the design which can be found in
bugzilla.
[YOCTO #3529]
(Bitbake rev: b77166ad7b8571895f73a84f7789d93fbd4f6d04)
Signed-off-by: Cristiana Voicu <cristiana.voicu@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib')
| -rw-r--r-- | bitbake/lib/bb/ui/crumbs/hoblistmodel.py | 118 | ||||
| -rw-r--r-- | bitbake/lib/bb/ui/crumbs/hobwidget.py | 75 | ||||
| -rwxr-xr-x | bitbake/lib/bb/ui/crumbs/packageselectionpage.py | 57 | ||||
| -rwxr-xr-x | bitbake/lib/bb/ui/crumbs/recipeselectionpage.py | 67 |
4 files changed, 234 insertions, 83 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/hoblistmodel.py b/bitbake/lib/bb/ui/crumbs/hoblistmodel.py index 0f37a068c6..9b8db23c79 100644 --- a/bitbake/lib/bb/ui/crumbs/hoblistmodel.py +++ b/bitbake/lib/bb/ui/crumbs/hoblistmodel.py | |||
| @@ -85,34 +85,67 @@ class PackageListModel(gtk.ListStore): | |||
| 85 | Helper function to determine whether an item is an item specified by filter | 85 | Helper function to determine whether an item is an item specified by filter |
| 86 | """ | 86 | """ |
| 87 | def tree_model_filter(self, model, it, filter): | 87 | def tree_model_filter(self, model, it, filter): |
| 88 | for key in filter.keys(): | 88 | name = model.get_value(it, self.COL_NAME) |
| 89 | if model.get_value(it, key) not in filter[key]: | ||
| 90 | return False | ||
| 91 | 89 | ||
| 90 | for key in filter.keys(): | ||
| 91 | if key == self.COL_NAME: | ||
| 92 | if filter[key] != 'Search packages by name': | ||
| 93 | if filter[key] not in name: | ||
| 94 | return False | ||
| 95 | else: | ||
| 96 | if model.get_value(it, key) not in filter[key]: | ||
| 97 | return False | ||
| 98 | self.filtered_nb += 1 | ||
| 92 | return True | 99 | return True |
| 93 | 100 | ||
| 94 | """ | 101 | """ |
| 95 | Create, if required, and return a filtered gtk.TreeModelSort | 102 | Create, if required, and return a filtered gtk.TreeModelSort |
| 96 | containing only the items specified by filter | 103 | containing only the items specified by filter |
| 97 | """ | 104 | """ |
| 98 | def tree_model(self, filter): | 105 | def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=True, search_data=None): |
| 99 | model = self.filter_new() | 106 | model = self.filter_new() |
| 107 | self.filtered_nb = 0 | ||
| 100 | model.set_visible_func(self.tree_model_filter, filter) | 108 | model.set_visible_func(self.tree_model_filter, filter) |
| 101 | 109 | ||
| 102 | sort = gtk.TreeModelSort(model) | 110 | sort = gtk.TreeModelSort(model) |
| 103 | sort.set_sort_column_id(RecipeListModel.COL_NAME, gtk.SORT_ASCENDING) | 111 | if excluded_items_ahead: |
| 104 | sort.set_default_sort_func(None) | 112 | sort.set_default_sort_func(self.exclude_item_sort_func, search_data) |
| 113 | elif included_items_ahead: | ||
| 114 | sort.set_default_sort_func(self.include_item_sort_func, search_data) | ||
| 115 | else: | ||
| 116 | sort.set_sort_column_id(RecipeListModel.COL_NAME, gtk.SORT_ASCENDING) | ||
| 117 | sort.set_default_sort_func(None) | ||
| 105 | return sort | 118 | return sort |
| 106 | 119 | ||
| 107 | def exclude_item_sort_func(self, model, iter1, iter2): | 120 | def exclude_item_sort_func(self, model, iter1, iter2, user_data=None): |
| 108 | val1 = model.get_value(iter1, RecipeListModel.COL_FADE_INC) | 121 | if user_data: |
| 109 | val2 = model.get_value(iter2, RecipeListModel.COL_INC) | 122 | val1 = model.get_value(iter1, RecipeListModel.COL_NAME) |
| 110 | return ((val1 == True) and (val2 == False)) | 123 | val2 = model.get_value(iter2, RecipeListModel.COL_NAME) |
| 111 | 124 | if val1.startswith(user_data) and not val2.startswith(user_data): | |
| 112 | def include_item_sort_func(self, model, iter1, iter2): | 125 | return -1 |
| 113 | val1 = model.get_value(iter1, RecipeListModel.COL_INC) | 126 | elif not val1.startswith(user_data) and val2.startswith(user_data): |
| 114 | val2 = model.get_value(iter2, RecipeListModel.COL_INC) | 127 | return 1 |
| 115 | return ((val1 == False) and (val2 == True)) | 128 | else: |
| 129 | return 0 | ||
| 130 | else: | ||
| 131 | val1 = model.get_value(iter1, RecipeListModel.COL_FADE_INC) | ||
| 132 | val2 = model.get_value(iter2, RecipeListModel.COL_INC) | ||
| 133 | return ((val1 == True) and (val2 == False)) | ||
| 134 | |||
| 135 | def include_item_sort_func(self, model, iter1, iter2, user_data=None): | ||
| 136 | if user_data: | ||
| 137 | val1 = model.get_value(iter1, RecipeListModel.COL_NAME) | ||
| 138 | val2 = model.get_value(iter2, RecipeListModel.COL_NAME) | ||
| 139 | if val1.startswith(user_data) and not val2.startswith(user_data): | ||
| 140 | return -1 | ||
| 141 | elif not val1.startswith(user_data) and val2.startswith(user_data): | ||
| 142 | return 1 | ||
| 143 | else: | ||
| 144 | return 0 | ||
| 145 | else: | ||
| 146 | val1 = model.get_value(iter1, RecipeListModel.COL_INC) | ||
| 147 | val2 = model.get_value(iter2, RecipeListModel.COL_INC) | ||
| 148 | return ((val1 == False) and (val2 == True)) | ||
| 116 | 149 | ||
| 117 | def convert_vpath_to_path(self, view_model, view_path): | 150 | def convert_vpath_to_path(self, view_model, view_path): |
| 118 | # view_model is the model sorted | 151 | # view_model is the model sorted |
| @@ -444,34 +477,61 @@ class RecipeListModel(gtk.ListStore): | |||
| 444 | return False | 477 | return False |
| 445 | 478 | ||
| 446 | for key in filter.keys(): | 479 | for key in filter.keys(): |
| 447 | if model.get_value(it, key) not in filter[key]: | 480 | if key == self.COL_NAME: |
| 448 | return False | 481 | if filter[key] != 'Search recipes by name' and filter[key] != 'Search package groups by name': |
| 482 | if filter[key] not in name: | ||
| 483 | return False | ||
| 484 | else: | ||
| 485 | if model.get_value(it, key) not in filter[key]: | ||
| 486 | return False | ||
| 487 | self.filtered_nb += 1 | ||
| 449 | 488 | ||
| 450 | return True | 489 | return True |
| 451 | 490 | ||
| 452 | def exclude_item_sort_func(self, model, iter1, iter2): | 491 | def exclude_item_sort_func(self, model, iter1, iter2, user_data=None): |
| 453 | val1 = model.get_value(iter1, RecipeListModel.COL_FADE_INC) | 492 | if user_data: |
| 454 | val2 = model.get_value(iter2, RecipeListModel.COL_INC) | 493 | val1 = model.get_value(iter1, RecipeListModel.COL_NAME) |
| 455 | return ((val1 == True) and (val2 == False)) | 494 | val2 = model.get_value(iter2, RecipeListModel.COL_NAME) |
| 456 | 495 | if val1.startswith(user_data) and not val2.startswith(user_data): | |
| 457 | def include_item_sort_func(self, model, iter1, iter2): | 496 | return -1 |
| 458 | val1 = model.get_value(iter1, RecipeListModel.COL_INC) | 497 | elif not val1.startswith(user_data) and val2.startswith(user_data): |
| 459 | val2 = model.get_value(iter2, RecipeListModel.COL_INC) | 498 | return 1 |
| 460 | return ((val1 == False) and (val2 == True)) | 499 | else: |
| 500 | return 0 | ||
| 501 | else: | ||
| 502 | val1 = model.get_value(iter1, RecipeListModel.COL_FADE_INC) | ||
| 503 | val2 = model.get_value(iter2, RecipeListModel.COL_INC) | ||
| 504 | return ((val1 == True) and (val2 == False)) | ||
| 505 | |||
| 506 | def include_item_sort_func(self, model, iter1, iter2, user_data=None): | ||
| 507 | if user_data: | ||
| 508 | val1 = model.get_value(iter1, RecipeListModel.COL_NAME) | ||
| 509 | val2 = model.get_value(iter2, RecipeListModel.COL_NAME) | ||
| 510 | if val1.startswith(user_data) and not val2.startswith(user_data): | ||
| 511 | return -1 | ||
| 512 | elif not val1.startswith(user_data) and val2.startswith(user_data): | ||
| 513 | return 1 | ||
| 514 | else: | ||
| 515 | return 0 | ||
| 516 | else: | ||
| 517 | val1 = model.get_value(iter1, RecipeListModel.COL_INC) | ||
| 518 | val2 = model.get_value(iter2, RecipeListModel.COL_INC) | ||
| 519 | return ((val1 == False) and (val2 == True)) | ||
| 461 | 520 | ||
| 462 | """ | 521 | """ |
| 463 | Create, if required, and return a filtered gtk.TreeModelSort | 522 | Create, if required, and return a filtered gtk.TreeModelSort |
| 464 | containing only the items specified by filter | 523 | containing only the items specified by filter |
| 465 | """ | 524 | """ |
| 466 | def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=True): | 525 | def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=True, search_data=None): |
| 467 | model = self.filter_new() | 526 | model = self.filter_new() |
| 527 | self.filtered_nb = 0 | ||
| 468 | model.set_visible_func(self.tree_model_filter, filter) | 528 | model.set_visible_func(self.tree_model_filter, filter) |
| 469 | 529 | ||
| 470 | sort = gtk.TreeModelSort(model) | 530 | sort = gtk.TreeModelSort(model) |
| 471 | if excluded_items_ahead: | 531 | if excluded_items_ahead: |
| 472 | sort.set_default_sort_func(self.exclude_item_sort_func) | 532 | sort.set_default_sort_func(self.exclude_item_sort_func, search_data) |
| 473 | elif included_items_ahead: | 533 | elif included_items_ahead: |
| 474 | sort.set_default_sort_func(self.include_item_sort_func) | 534 | sort.set_default_sort_func(self.include_item_sort_func, search_data) |
| 475 | else: | 535 | else: |
| 476 | sort.set_sort_column_id(RecipeListModel.COL_NAME, gtk.SORT_ASCENDING) | 536 | sort.set_sort_column_id(RecipeListModel.COL_NAME, gtk.SORT_ASCENDING) |
| 477 | sort.set_default_sort_func(None) | 537 | sort.set_default_sort_func(None) |
diff --git a/bitbake/lib/bb/ui/crumbs/hobwidget.py b/bitbake/lib/bb/ui/crumbs/hobwidget.py index 9a00e941e9..17d9cee138 100644 --- a/bitbake/lib/bb/ui/crumbs/hobwidget.py +++ b/bitbake/lib/bb/ui/crumbs/hobwidget.py | |||
| @@ -88,12 +88,12 @@ class HobViewTable (gtk.VBox): | |||
| 88 | self.table_tree = gtk.TreeView() | 88 | self.table_tree = gtk.TreeView() |
| 89 | self.table_tree.set_headers_visible(True) | 89 | self.table_tree.set_headers_visible(True) |
| 90 | self.table_tree.set_headers_clickable(True) | 90 | self.table_tree.set_headers_clickable(True) |
| 91 | self.table_tree.set_enable_search(True) | ||
| 92 | self.table_tree.set_rules_hint(True) | 91 | self.table_tree.set_rules_hint(True) |
| 93 | self.table_tree.set_enable_tree_lines(True) | 92 | self.table_tree.set_enable_tree_lines(True) |
| 94 | self.table_tree.get_selection().set_mode(gtk.SELECTION_SINGLE) | 93 | self.table_tree.get_selection().set_mode(gtk.SELECTION_SINGLE) |
| 95 | self.toggle_columns = [] | 94 | self.toggle_columns = [] |
| 96 | self.table_tree.connect("row-activated", self.row_activated_cb) | 95 | self.table_tree.connect("row-activated", self.row_activated_cb) |
| 96 | self.top_bar = None | ||
| 97 | 97 | ||
| 98 | for i, column in enumerate(columns): | 98 | for i, column in enumerate(columns): |
| 99 | col = gtk.TreeViewColumn(column['col_name']) | 99 | col = gtk.TreeViewColumn(column['col_name']) |
| @@ -141,10 +141,41 @@ class HobViewTable (gtk.VBox): | |||
| 141 | if 'col_t_id' in column.keys(): | 141 | if 'col_t_id' in column.keys(): |
| 142 | col.add_attribute(cell, 'font', column['col_t_id']) | 142 | col.add_attribute(cell, 'font', column['col_t_id']) |
| 143 | 143 | ||
| 144 | scroll = gtk.ScrolledWindow() | 144 | self.scroll = gtk.ScrolledWindow() |
| 145 | scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) | 145 | self.scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) |
| 146 | scroll.add(self.table_tree) | 146 | self.scroll.add(self.table_tree) |
| 147 | self.pack_start(scroll, True, True, 0) | 147 | |
| 148 | self.pack_end(self.scroll, True, True, 0) | ||
| 149 | |||
| 150 | def add_no_result_bar(self, entry): | ||
| 151 | color = HobColors.KHAKI | ||
| 152 | self.top_bar = gtk.EventBox() | ||
| 153 | self.top_bar.set_size_request(-1, 70) | ||
| 154 | self.top_bar.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) | ||
| 155 | self.top_bar.set_flags(gtk.CAN_DEFAULT) | ||
| 156 | self.top_bar.grab_default() | ||
| 157 | |||
| 158 | no_result_tab = gtk.Table(5, 20, True) | ||
| 159 | self.top_bar.add(no_result_tab) | ||
| 160 | |||
| 161 | label = gtk.Label() | ||
| 162 | label.set_alignment(0.0, 0.5) | ||
| 163 | title = "No results matching your search" | ||
| 164 | label.set_markup("<span size='x-large'><b>%s</b></span>" % title) | ||
| 165 | no_result_tab.attach(label, 1, 14, 1, 4) | ||
| 166 | |||
| 167 | clear_button = HobButton("Clear search") | ||
| 168 | clear_button.connect('clicked', self.set_search_entry_clear_cb, entry) | ||
| 169 | no_result_tab.attach(clear_button, 16, 19, 1, 4) | ||
| 170 | |||
| 171 | self.pack_start(self.top_bar, False, True, 12) | ||
| 172 | self.top_bar.show_all() | ||
| 173 | |||
| 174 | def set_search_entry_clear_cb(self, button, search): | ||
| 175 | if search.get_editable() == True: | ||
| 176 | search.set_text("") | ||
| 177 | search.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False) | ||
| 178 | search.grab_focus() | ||
| 148 | 179 | ||
| 149 | def display_binb_cb(self, col, cell, model, it, col_id): | 180 | def display_binb_cb(self, col, cell, model, it, col_id): |
| 150 | binb = model.get_value(it, col_id) | 181 | binb = model.get_value(it, col_id) |
| @@ -170,10 +201,6 @@ class HobViewTable (gtk.VBox): | |||
| 170 | def set_model(self, tree_model): | 201 | def set_model(self, tree_model): |
| 171 | self.table_tree.set_model(tree_model) | 202 | self.table_tree.set_model(tree_model) |
| 172 | 203 | ||
| 173 | def set_search_entry(self, search_column_id, entry): | ||
| 174 | self.table_tree.set_search_column(search_column_id) | ||
| 175 | self.table_tree.set_search_entry(entry) | ||
| 176 | |||
| 177 | def toggle_default(self): | 204 | def toggle_default(self): |
| 178 | model = self.table_tree.get_model() | 205 | model = self.table_tree.get_model() |
| 179 | if not model: | 206 | if not model: |
| @@ -453,7 +480,6 @@ class HobNotebook(gtk.Notebook): | |||
| 453 | self.pages = [] | 480 | self.pages = [] |
| 454 | 481 | ||
| 455 | self.search = None | 482 | self.search = None |
| 456 | self.search_name = "" | ||
| 457 | 483 | ||
| 458 | self.connect("switch-page", self.page_changed_cb) | 484 | self.connect("switch-page", self.page_changed_cb) |
| 459 | 485 | ||
| @@ -466,6 +492,9 @@ class HobNotebook(gtk.Notebook): | |||
| 466 | else: | 492 | else: |
| 467 | lbl.set_active(False) | 493 | lbl.set_active(False) |
| 468 | 494 | ||
| 495 | if self.search: | ||
| 496 | self.reset_entry(self.search, page_num) | ||
| 497 | |||
| 469 | def append_page(self, child, tab_label, tab_tooltip=None): | 498 | def append_page(self, child, tab_label, tab_tooltip=None): |
| 470 | label = HobTabLabel(tab_label) | 499 | label = HobTabLabel(tab_label) |
| 471 | if tab_tooltip: | 500 | if tab_tooltip: |
| @@ -474,16 +503,22 @@ class HobNotebook(gtk.Notebook): | |||
| 474 | self.pages.append(label) | 503 | self.pages.append(label) |
| 475 | gtk.Notebook.append_page(self, child, label) | 504 | gtk.Notebook.append_page(self, child, label) |
| 476 | 505 | ||
| 477 | def set_entry(self, name="Search:"): | 506 | def set_entry(self, names, tips): |
| 478 | self.search = gtk.Entry() | 507 | self.search = gtk.Entry() |
| 479 | self.search_name = name | 508 | self.search_names = names |
| 509 | self.search_tips = tips | ||
| 480 | style = self.search.get_style() | 510 | style = self.search.get_style() |
| 481 | style.text[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(HobColors.GRAY, False, False) | 511 | style.text[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(HobColors.GRAY, False, False) |
| 482 | self.search.set_style(style) | 512 | self.search.set_style(style) |
| 483 | self.search.set_text(name) | 513 | self.search.set_text(names[0]) |
| 514 | self.search.set_tooltip_text(self.search_tips[0]) | ||
| 515 | self.search.props.has_tooltip = True | ||
| 516 | |||
| 484 | self.search.set_editable(False) | 517 | self.search.set_editable(False) |
| 485 | self.search.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, gtk.STOCK_CLEAR) | 518 | self.search.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, gtk.STOCK_CLEAR) |
| 519 | self.search.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False) | ||
| 486 | self.search.connect("icon-release", self.set_search_entry_clear_cb) | 520 | self.search.connect("icon-release", self.set_search_entry_clear_cb) |
| 521 | self.search.set_width_chars(30) | ||
| 487 | self.search.show() | 522 | self.search.show() |
| 488 | 523 | ||
| 489 | self.search.connect("focus-in-event", self.set_search_entry_editable_cb) | 524 | self.search.connect("focus-in-event", self.set_search_entry_editable_cb) |
| @@ -507,19 +542,23 @@ class HobNotebook(gtk.Notebook): | |||
| 507 | style.text[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(HobColors.BLACK, False, False) | 542 | style.text[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(HobColors.BLACK, False, False) |
| 508 | search.set_style(style) | 543 | search.set_style(style) |
| 509 | 544 | ||
| 510 | def reset_entry(self, entry): | 545 | def set_search_entry_reset_cb(self, search, event): |
| 546 | page_num = self.get_current_page() | ||
| 547 | self.reset_entry(search, page_num) | ||
| 548 | |||
| 549 | def reset_entry(self, entry, page_num): | ||
| 511 | style = entry.get_style() | 550 | style = entry.get_style() |
| 512 | style.text[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(HobColors.GRAY, False, False) | 551 | style.text[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(HobColors.GRAY, False, False) |
| 513 | entry.set_style(style) | 552 | entry.set_style(style) |
| 514 | entry.set_text(self.search_name) | 553 | entry.set_text(self.search_names[page_num]) |
| 554 | entry.set_tooltip_text(self.search_tips[page_num]) | ||
| 515 | entry.set_editable(False) | 555 | entry.set_editable(False) |
| 516 | 556 | entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False) | |
| 517 | def set_search_entry_reset_cb(self, search, event): | ||
| 518 | self.reset_entry(search) | ||
| 519 | 557 | ||
| 520 | def set_search_entry_clear_cb(self, search, icon_pos, event): | 558 | def set_search_entry_clear_cb(self, search, icon_pos, event): |
| 521 | if search.get_editable() == True: | 559 | if search.get_editable() == True: |
| 522 | search.set_text("") | 560 | search.set_text("") |
| 561 | search.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False) | ||
| 523 | 562 | ||
| 524 | def set_page(self, title): | 563 | def set_page(self, title): |
| 525 | for child in self.pages: | 564 | for child in self.pages: |
diff --git a/bitbake/lib/bb/ui/crumbs/packageselectionpage.py b/bitbake/lib/bb/ui/crumbs/packageselectionpage.py index 6f9a4e2a7a..ce2deabb89 100755 --- a/bitbake/lib/bb/ui/crumbs/packageselectionpage.py +++ b/bitbake/lib/bb/ui/crumbs/packageselectionpage.py | |||
| @@ -34,10 +34,12 @@ class PackageSelectionPage (HobPage): | |||
| 34 | 34 | ||
| 35 | pages = [ | 35 | pages = [ |
| 36 | { | 36 | { |
| 37 | 'name' : 'Included packages', | 37 | 'name' : 'Included packages', |
| 38 | 'tooltip' : 'The packages currently included for your image', | 38 | 'tooltip' : 'The packages currently included for your image', |
| 39 | 'filter' : { PackageListModel.COL_INC : [True] }, | 39 | 'filter' : { PackageListModel.COL_INC : [True] }, |
| 40 | 'columns' : [{ | 40 | 'search' : 'Search packages by name', |
| 41 | 'searchtip' : 'Enter a package name to find it', | ||
| 42 | 'columns' : [{ | ||
| 41 | 'col_name' : 'Package name', | 43 | 'col_name' : 'Package name', |
| 42 | 'col_id' : PackageListModel.COL_NAME, | 44 | 'col_id' : PackageListModel.COL_NAME, |
| 43 | 'col_style': 'text', | 45 | 'col_style': 'text', |
| @@ -73,10 +75,12 @@ class PackageSelectionPage (HobPage): | |||
| 73 | 'col_max' : 100 | 75 | 'col_max' : 100 |
| 74 | }] | 76 | }] |
| 75 | }, { | 77 | }, { |
| 76 | 'name' : 'All packages', | 78 | 'name' : 'All packages', |
| 77 | 'tooltip' : 'All packages that have been built', | 79 | 'tooltip' : 'All packages that have been built', |
| 78 | 'filter' : {}, | 80 | 'filter' : {}, |
| 79 | 'columns' : [{ | 81 | 'search' : 'Search packages by name', |
| 82 | 'searchtip' : 'Enter a package name to find it', | ||
| 83 | 'columns' : [{ | ||
| 80 | 'col_name' : 'Package name', | 84 | 'col_name' : 'Package name', |
| 81 | 'col_id' : PackageListModel.COL_NAME, | 85 | 'col_id' : PackageListModel.COL_NAME, |
| 82 | 'col_style': 'text', | 86 | 'col_style': 'text', |
| @@ -132,12 +136,18 @@ class PackageSelectionPage (HobPage): | |||
| 132 | # set visible members | 136 | # set visible members |
| 133 | self.ins = HobNotebook() | 137 | self.ins = HobNotebook() |
| 134 | self.tables = [] # we need to modify table when the dialog is shown | 138 | self.tables = [] # we need to modify table when the dialog is shown |
| 139 | |||
| 140 | search_names = [] | ||
| 141 | search_tips = [] | ||
| 135 | # append the tab | 142 | # append the tab |
| 136 | for page in self.pages: | 143 | for page in self.pages: |
| 137 | columns = page['columns'] | 144 | columns = page['columns'] |
| 138 | tab = HobViewTable(columns) | 145 | tab = HobViewTable(columns) |
| 146 | search_names.append(page['search']) | ||
| 147 | search_tips.append(page['searchtip']) | ||
| 139 | filter = page['filter'] | 148 | filter = page['filter'] |
| 140 | tab.set_model(self.package_model.tree_model(filter)) | 149 | sort_model = self.package_model.tree_model(filter) |
| 150 | tab.set_model(sort_model) | ||
| 141 | tab.connect("toggled", self.table_toggled_cb, page['name']) | 151 | tab.connect("toggled", self.table_toggled_cb, page['name']) |
| 142 | if page['name'] == "Included packages": | 152 | if page['name'] == "Included packages": |
| 143 | tab.connect("button-release-event", self.button_click_cb) | 153 | tab.connect("button-release-event", self.button_click_cb) |
| @@ -148,13 +158,8 @@ class PackageSelectionPage (HobPage): | |||
| 148 | self.ins.append_page(tab, page['name'], page['tooltip']) | 158 | self.ins.append_page(tab, page['name'], page['tooltip']) |
| 149 | self.tables.append(tab) | 159 | self.tables.append(tab) |
| 150 | 160 | ||
| 151 | self.ins.set_entry("Search packages:") | 161 | self.ins.set_entry(search_names, search_tips) |
| 152 | # set the search entry for each table | 162 | self.ins.search.connect("changed", self.search_entry_changed) |
| 153 | for tab in self.tables: | ||
| 154 | search_tip = "Enter a package name to find it" | ||
| 155 | self.ins.search.set_tooltip_text(search_tip) | ||
| 156 | self.ins.search.props.has_tooltip = True | ||
| 157 | tab.set_search_entry(0, self.ins.search) | ||
| 158 | 163 | ||
| 159 | # add all into the dialog | 164 | # add all into the dialog |
| 160 | self.box_group_area.pack_start(self.ins, expand=True, fill=True) | 165 | self.box_group_area.pack_start(self.ins, expand=True, fill=True) |
| @@ -174,6 +179,26 @@ class PackageSelectionPage (HobPage): | |||
| 174 | self.back_button.connect("clicked", self.back_button_clicked_cb) | 179 | self.back_button.connect("clicked", self.back_button_clicked_cb) |
| 175 | self.button_box.pack_end(self.back_button, expand=False, fill=False) | 180 | self.button_box.pack_end(self.back_button, expand=False, fill=False) |
| 176 | 181 | ||
| 182 | def search_entry_changed(self, entry): | ||
| 183 | current_tab = self.ins.get_current_page() | ||
| 184 | filter = self.pages[current_tab]['filter'] | ||
| 185 | text = entry.get_text() | ||
| 186 | filter[PackageListModel.COL_NAME] = text | ||
| 187 | self.tables[current_tab].set_model(self.package_model.tree_model(filter, search_data=text)) | ||
| 188 | if self.package_model.filtered_nb == 0: | ||
| 189 | if not self.ins.get_nth_page(current_tab).top_bar: | ||
| 190 | self.ins.get_nth_page(current_tab).add_no_result_bar(entry) | ||
| 191 | self.ins.get_nth_page(current_tab).top_bar.show() | ||
| 192 | self.ins.get_nth_page(current_tab).scroll.hide() | ||
| 193 | else: | ||
| 194 | if self.ins.get_nth_page(current_tab).top_bar: | ||
| 195 | self.ins.get_nth_page(current_tab).top_bar.hide() | ||
| 196 | self.ins.get_nth_page(current_tab).scroll.show() | ||
| 197 | if entry.get_text() == '': | ||
| 198 | entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False) | ||
| 199 | else: | ||
| 200 | entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, True) | ||
| 201 | |||
| 177 | def button_click_cb(self, widget, event): | 202 | def button_click_cb(self, widget, event): |
| 178 | path, col = widget.table_tree.get_cursor() | 203 | path, col = widget.table_tree.get_cursor() |
| 179 | tree_model = widget.table_tree.get_model() | 204 | tree_model = widget.table_tree.get_model() |
diff --git a/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py b/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py index 636762e40c..aa0cd60c3f 100755 --- a/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py +++ b/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py | |||
| @@ -33,11 +33,13 @@ from bb.ui.crumbs.hobpages import HobPage | |||
| 33 | class RecipeSelectionPage (HobPage): | 33 | class RecipeSelectionPage (HobPage): |
| 34 | pages = [ | 34 | pages = [ |
| 35 | { | 35 | { |
| 36 | 'name' : 'Included recipes', | 36 | 'name' : 'Included recipes', |
| 37 | 'tooltip' : 'The recipes currently included for your image', | 37 | 'tooltip' : 'The recipes currently included for your image', |
| 38 | 'filter' : { RecipeListModel.COL_INC : [True], | 38 | 'filter' : { RecipeListModel.COL_INC : [True], |
| 39 | RecipeListModel.COL_TYPE : ['recipe', 'packagegroup'] }, | 39 | RecipeListModel.COL_TYPE : ['recipe', 'packagegroup'] }, |
| 40 | 'columns' : [{ | 40 | 'search' : 'Search recipes by name', |
| 41 | 'searchtip' : 'Enter a recipe name to find it', | ||
| 42 | 'columns' : [{ | ||
| 41 | 'col_name' : 'Recipe name', | 43 | 'col_name' : 'Recipe name', |
| 42 | 'col_id' : RecipeListModel.COL_NAME, | 44 | 'col_id' : RecipeListModel.COL_NAME, |
| 43 | 'col_style': 'text', | 45 | 'col_style': 'text', |
| @@ -66,10 +68,12 @@ class RecipeSelectionPage (HobPage): | |||
| 66 | 'col_max' : 100 | 68 | 'col_max' : 100 |
| 67 | }] | 69 | }] |
| 68 | }, { | 70 | }, { |
| 69 | 'name' : 'All recipes', | 71 | 'name' : 'All recipes', |
| 70 | 'tooltip' : 'All recipes in your configured layers', | 72 | 'tooltip' : 'All recipes in your configured layers', |
| 71 | 'filter' : { RecipeListModel.COL_TYPE : ['recipe'] }, | 73 | 'filter' : { RecipeListModel.COL_TYPE : ['recipe'] }, |
| 72 | 'columns' : [{ | 74 | 'search' : 'Search recipes by name', |
| 75 | 'searchtip' : 'Enter a recipe name to find it', | ||
| 76 | 'columns' : [{ | ||
| 73 | 'col_name' : 'Recipe name', | 77 | 'col_name' : 'Recipe name', |
| 74 | 'col_id' : RecipeListModel.COL_NAME, | 78 | 'col_id' : RecipeListModel.COL_NAME, |
| 75 | 'col_style': 'text', | 79 | 'col_style': 'text', |
| @@ -98,10 +102,12 @@ class RecipeSelectionPage (HobPage): | |||
| 98 | 'col_max' : 100 | 102 | 'col_max' : 100 |
| 99 | }] | 103 | }] |
| 100 | }, { | 104 | }, { |
| 101 | 'name' : 'Package Groups', | 105 | 'name' : 'Package Groups', |
| 102 | 'tooltip' : 'All package groups in your configured layers', | 106 | 'tooltip' : 'All package groups in your configured layers', |
| 103 | 'filter' : { RecipeListModel.COL_TYPE : ['packagegroup'] }, | 107 | 'filter' : { RecipeListModel.COL_TYPE : ['packagegroup'] }, |
| 104 | 'columns' : [{ | 108 | 'search' : 'Search package groups by name', |
| 109 | 'searchtip' : 'Enter a package group name to find it', | ||
| 110 | 'columns' : [{ | ||
| 105 | 'col_name' : 'Package group name', | 111 | 'col_name' : 'Package group name', |
| 106 | 'col_id' : RecipeListModel.COL_NAME, | 112 | 'col_id' : RecipeListModel.COL_NAME, |
| 107 | 'col_style': 'text', | 113 | 'col_style': 'text', |
| @@ -142,12 +148,18 @@ class RecipeSelectionPage (HobPage): | |||
| 142 | # set visible members | 148 | # set visible members |
| 143 | self.ins = HobNotebook() | 149 | self.ins = HobNotebook() |
| 144 | self.tables = [] # we need modify table when the dialog is shown | 150 | self.tables = [] # we need modify table when the dialog is shown |
| 151 | |||
| 152 | search_names = [] | ||
| 153 | search_tips = [] | ||
| 145 | # append the tabs in order | 154 | # append the tabs in order |
| 146 | for page in self.pages: | 155 | for page in self.pages: |
| 147 | columns = page['columns'] | 156 | columns = page['columns'] |
| 148 | tab = HobViewTable(columns) | 157 | tab = HobViewTable(columns) |
| 158 | search_names.append(page['search']) | ||
| 159 | search_tips.append(page['searchtip']) | ||
| 149 | filter = page['filter'] | 160 | filter = page['filter'] |
| 150 | tab.set_model(self.recipe_model.tree_model(filter)) | 161 | sort_model = self.recipe_model.tree_model(filter) |
| 162 | tab.set_model(sort_model) | ||
| 151 | tab.connect("toggled", self.table_toggled_cb, page['name']) | 163 | tab.connect("toggled", self.table_toggled_cb, page['name']) |
| 152 | if page['name'] == "Included recipes": | 164 | if page['name'] == "Included recipes": |
| 153 | tab.connect("button-release-event", self.button_click_cb) | 165 | tab.connect("button-release-event", self.button_click_cb) |
| @@ -161,13 +173,8 @@ class RecipeSelectionPage (HobPage): | |||
| 161 | self.ins.append_page(tab, page['name'], page['tooltip']) | 173 | self.ins.append_page(tab, page['name'], page['tooltip']) |
| 162 | self.tables.append(tab) | 174 | self.tables.append(tab) |
| 163 | 175 | ||
| 164 | self.ins.set_entry("Search recipes:") | 176 | self.ins.set_entry(search_names, search_tips) |
| 165 | # set the search entry for each table | 177 | self.ins.search.connect("changed", self.search_entry_changed) |
| 166 | for tab in self.tables: | ||
| 167 | search_tip = "Enter a recipe's or task's name to find it" | ||
| 168 | self.ins.search.set_tooltip_text(search_tip) | ||
| 169 | self.ins.search.props.has_tooltip = True | ||
| 170 | tab.set_search_entry(0, self.ins.search) | ||
| 171 | 178 | ||
| 172 | # add all into the window | 179 | # add all into the window |
| 173 | self.box_group_area.pack_start(self.ins, expand=True, fill=True) | 180 | self.box_group_area.pack_start(self.ins, expand=True, fill=True) |
| @@ -187,6 +194,26 @@ class RecipeSelectionPage (HobPage): | |||
| 187 | self.back_button.connect("clicked", self.back_button_clicked_cb) | 194 | self.back_button.connect("clicked", self.back_button_clicked_cb) |
| 188 | button_box.pack_end(self.back_button, expand=False, fill=False) | 195 | button_box.pack_end(self.back_button, expand=False, fill=False) |
| 189 | 196 | ||
| 197 | def search_entry_changed(self, entry): | ||
| 198 | current_tab = self.ins.get_current_page() | ||
| 199 | filter = self.pages[current_tab]['filter'] | ||
| 200 | text = entry.get_text() | ||
| 201 | filter[RecipeListModel.COL_NAME] = text | ||
| 202 | self.tables[current_tab].set_model(self.recipe_model.tree_model(filter, search_data=text)) | ||
| 203 | if self.recipe_model.filtered_nb == 0: | ||
| 204 | if not self.ins.get_nth_page(current_tab).top_bar: | ||
| 205 | self.ins.get_nth_page(current_tab).add_no_result_bar(entry) | ||
| 206 | self.ins.get_nth_page(current_tab).top_bar.show() | ||
| 207 | self.ins.get_nth_page(current_tab).scroll.hide() | ||
| 208 | else: | ||
| 209 | if self.ins.get_nth_page(current_tab).top_bar: | ||
| 210 | self.ins.get_nth_page(current_tab).top_bar.hide() | ||
| 211 | self.ins.get_nth_page(current_tab).scroll.show() | ||
| 212 | if entry.get_text() == '': | ||
| 213 | entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False) | ||
| 214 | else: | ||
| 215 | entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, True) | ||
| 216 | |||
| 190 | def button_click_cb(self, widget, event): | 217 | def button_click_cb(self, widget, event): |
| 191 | path, col = widget.table_tree.get_cursor() | 218 | path, col = widget.table_tree.get_cursor() |
| 192 | tree_model = widget.table_tree.get_model() | 219 | tree_model = widget.table_tree.get_model() |
