def test_filtered_model_updates_when_source_model_has_data_item_that_updates( self): document_model = DocumentModel.DocumentModel() with contextlib.closing(document_model): filtered_data_items = ListModel.FilteredListModel( items_key="data_items") filtered_data_items.container = document_model for _ in range(4): data_item = DataItem.DataItem( numpy.zeros((16, 16), numpy.uint32)) document_model.append_data_item(data_item) self.assertEqual(len(filtered_data_items.items), 4) selection = Selection.IndexedSelection() filtered_data_items2 = ListModel.FilteredListModel( items_key="data_items", container=filtered_data_items, selection=selection) filtered_data_items2.filter = ListModel.EqFilter("is_live", True) self.assertEqual(len(filtered_data_items2.items), 0) with document_model.data_item_live(document_model.data_items[0]): document_model.data_items[0].data_item_changed_event.fire() self.assertEqual(len(filtered_data_items.items), 4) # verify assumption self.assertEqual(len(filtered_data_items2.items), 1) # verify assumption self.assertTrue( document_model.data_items[0] in filtered_data_items2.items)
def date_browser_selection_changed(self, selected_indexes): """ Called to handle selection changes in the tree widget. This method should be connected to the on_selection_changed event. This method builds a list of keys represented by all selected items. It then provides date_filter to filter data items based on the list of keys. It then sets the filter into the document controller. :param selected_indexes: The selected indexes :type selected_indexes: list of ints """ partial_date_filters = list() for index, parent_row, parent_id in selected_indexes: item_model_controller = self.item_model_controller tree_node = item_model_controller.item_value( "tree_node", index, parent_id) partial_date_filters.append( ListModel.PartialDateFilter("created_local", *tree_node.keys)) if len(partial_date_filters) > 0: self.__date_filter = ListModel.OrFilter(partial_date_filters) else: self.__date_filter = None self.__update_filter()
def test_filtered_list_sends_begin_end_changes_for_grouped_insert_and_remove( self): l = ListModel.ListModel("items") l.append_item("3") l.append_item("1") l.append_item("4") l.append_item("2") l2 = ListModel.FilteredListModel(container=l, items_key="items") l2.sort_key = lambda x: x begin_changes_count = 0 end_changes_count = 0 def begin_changes(key): nonlocal begin_changes_count begin_changes_count += 1 def end_changes(key): nonlocal end_changes_count end_changes_count += 1 with l2.begin_changes_event.listen( begin_changes), l2.end_changes_event.listen(end_changes): with l2.changes(): l.insert_item(0, "5") l.insert_item(0, "6") l.remove_item(0) l.remove_item(0) self.assertEqual(1, begin_changes_count) self.assertEqual(1, end_changes_count)
def test_filtered_list_changing_container_under_changes_retains_order( self): # the bug was that if list model is under a change and items are only # being rearranged (easy to occur with dependent list being sorted differently) # then there is no way to detect that it is not sorted anymore so it proceeds # as if it is already sorted properly. l = ListModel.ListModel("items") l.append_item("3") l.append_item("1") l.append_item("4") l.append_item("2") l2 = ListModel.ListModel("items") l2.append_item("4") l2.append_item("1") l2.append_item("2") l2.append_item("3") l3 = ListModel.FilteredListModel(container=l, items_key="items") self.assertEqual(["3", "1", "4", "2"], l3.items) l4 = ListModel.FilteredListModel(container=l3, items_key="items") self.assertEqual(["3", "1", "4", "2"], l4.items) l4.begin_change() l3.begin_change() l3.filter = ListModel.Filter(True) l3.end_change() l4.end_change() l4.begin_change() l3.begin_change() l3.container = l2 l3.end_change() l4.end_change() self.assertEqual(["4", "1", "2", "3"], l3.items) self.assertEqual(["4", "1", "2", "3"], l4.items)
def test_random_filtered_model_updates(self): list_model = ListModel.ListModel("data_items") filtered_data_items = ListModel.FilteredListModel(items_key="data_items") filtered_data_items.container = list_model data_items = list() cc = 30 for _ in range(cc): data_item = DataItem.DataItem(numpy.zeros((16, 16), numpy.uint32)) list_model.insert_item(0, data_item) data_items.append(data_item) selection = Selection.IndexedSelection() filtered_data_items2 = ListModel.FilteredListModel(items_key="data_items", container=filtered_data_items, selection=selection) import random for xx in range(10): c1 = [n for n in range(cc)] c2 = [n for n in range(cc) if random.randint(0,100) > 20] random.shuffle(c1) random.shuffle(c2) def is_live_filter(data_item): return data_items.index(data_item) in c1 def is_live_filter2(data_item): return data_items.index(data_item) in c2 filtered_data_items.sort_key = lambda x: data_items.index(x) with filtered_data_items.changes(): filtered_data_items.filter = ListModel.PredicateFilter(is_live_filter) filtered_data_items.filter = ListModel.PredicateFilter(is_live_filter2) self.assertEqual(set(c2), set([data_items.index(d) for d in filtered_data_items2.items])) for data_item in data_items: data_item.close()
def slow_test_threaded_filtered_model_updates(self): for _ in range(1000): list_model = ListModel.ListModel("data_items") filtered_data_items = ListModel.FilteredListModel(items_key="data_items") data_items = list() cc = 30 for _ in range(cc): data_item = DataItem.DataItem(numpy.zeros((16, 16), numpy.uint32)) data_items.append(data_item) c1 = [n for n in range(cc) if random.randint(0,100) > 50] def is_live_filter(data_item): return data_items.index(data_item) in c1 filtered_data_items.container = list_model filtered_data_items.sort_key = lambda x: data_items.index(x) selection = Selection.IndexedSelection() filtered_data_items2 = ListModel.FilteredListModel(items_key="data_items", container=filtered_data_items, selection=selection) filtered_data_items2.filter = ListModel.PredicateFilter(is_live_filter) finished = threading.Event() def update_randomly(): for _ in range(cc): data_item = random.choice(filtered_data_items._get_master_items()) data_item.data_item_changed_event.fire() finished.set() list_model.insert_item(0, data_items[0]) threading.Thread(target = update_randomly).start() for index in range(1, cc): list_model.insert_item(index, data_items[index]) finished.wait() filtered_data_items2.close() filtered_data_items.close()
def test_mapped_list_sends_begin_end_changes_for_single_insert_and_remove( self): l = ListModel.ListModel("items") l.append_item("3") l.append_item("1") l.append_item("4") l.append_item("2") l1 = ListModel.FilteredListModel(container=l, master_items_key="items", items_key="mitems") l1.sort_key = lambda x: x l2 = ListModel.MappedListModel(container=l1, master_items_key="mitems", items_key="items") begin_changes_count = 0 end_changes_count = 0 def begin_changes(key): nonlocal begin_changes_count begin_changes_count += 1 def end_changes(key): nonlocal end_changes_count end_changes_count += 1 with l2.begin_changes_event.listen( begin_changes), l2.end_changes_event.listen(end_changes): l.insert_item(0, "5") l.remove_item(0) self.assertEqual(2, begin_changes_count) self.assertEqual(2, end_changes_count)
def test_sorted_filtered_model_updates_when_data_item_enters_filter(self): def sort_by_date_key(data_item): return data_item.created document_model = DocumentModel.DocumentModel() with contextlib.closing(document_model): filtered_data_items = ListModel.FilteredListModel( items_key="data_items") filtered_data_items.container = document_model filtered_data_items.filter = ListModel.EqFilter("is_live", True) filtered_data_items.sort_key = sort_by_date_key for _ in range(4): data_item = DataItem.DataItem( numpy.zeros((16, 16), numpy.uint32)) document_model.append_data_item(data_item) self.assertEqual(len(filtered_data_items.items), 0) with document_model.data_item_live(document_model.data_items[0]): document_model.data_items[0].data_item_changed_event.fire() self.assertEqual(len(filtered_data_items.items), 1) with document_model.data_item_live( document_model.data_items[2]): document_model.data_items[2].data_item_changed_event.fire() self.assertEqual(len(filtered_data_items.items), 2) self.assertTrue( filtered_data_items.items.index( document_model.data_items[0]) < filtered_data_items .items.index(document_model.data_items[2]))
def test_initial_mapped_model_values_are_correct(self): l = ListModel.ListModel("items") l.append_item(A("1")) l.append_item(A("2")) l2 = ListModel.MappedListModel(container=l, master_items_key="items", items_key="itemsb", map_fn=B) self.assertEqual([b.s for b in map(B, l.items)], [b.s for b in l2.items]) self.assertEqual(l2.itemsb, l2.items) self.assertEqual("2_B", l2.items[1].s)
def test_mapped_model_selection_after_insert_are_correct(self): l = ListModel.ListModel("items") l.append_item(A("1")) l.append_item(A("2")) l2 = ListModel.MappedListModel(container=l, master_items_key="items", items_key="itemsb", map_fn=B) s = l2.make_selection() s.add(0) s.add(1) l.insert_item(1, A("1.5")) self.assertEqual({0, 2}, s.indexes)
def test_inserting_items_into_model_index0_without_sort_key_puts_them_in_same_order(self): list_model = ListModel.ListModel("data_items") filtered_data_items = ListModel.FilteredListModel(items_key="data_items") filtered_data_items.container = list_model data_items = list() for index, value in enumerate(TestDataItemsModelModule.values): data_item = DataItem.DataItem(numpy.zeros((16, 16), numpy.uint32)) data_item.title = value list_model.insert_item(TestDataItemsModelModule.indexes[index], data_item) data_items.append(data_item) self.assertEqual([d.title for d in filtered_data_items.items], TestDataItemsModelModule.result) for data_item in data_items: data_item.close()
def test_flattened_model_with_empty_master_item_closes_properly(self): l = ListModel.ListModel("as") bs1 = ListModel.ListModel("bs") bs1.append_item("11") bs2 = ListModel.ListModel("bs") bs3 = ListModel.ListModel("bs") bs3.append_item("31") l.append_item(bs1) l.append_item(bs2) l.append_item(bs3) f = ListModel.FlattenedListModel(container=l, master_items_key="as", child_items_key="bs", items_key="cs") with contextlib.closing(f): pass
def test_inserting_items_into_model_index0_with_sort_key_puts_them_in_correct_order(self): list_model = ListModel.ListModel("data_items") filtered_data_items = ListModel.FilteredListModel(items_key="data_items") filtered_data_items.container = list_model filtered_data_items.sort_key = operator.attrgetter("title") data_items = list() for value in TestDataItemsModelModule.values: data_item = DataItem.DataItem(numpy.zeros((16, 16), numpy.uint32)) data_item.title = value list_model.insert_item(0, data_item) data_items.append(data_item) self.assertEqual([d.title for d in filtered_data_items.items], sorted([d.title for d in filtered_data_items.items])) for data_item in data_items: data_item.close()
def test_filtered_list_changing_from_sorted_to_unsorted_retains_order(self): l = ListModel.ListModel("items") l.append_item("3") l.append_item("1") l.append_item("4") l.append_item("2") l2 = ListModel.FilteredListModel(container=l, items_key="items") l2.sort_key = lambda x: x self.assertEqual(["1", "2", "3", "4"], l2.items) l2.filter = ListModel.PredicateFilter(lambda x: x != "4") l2.sort_key = None self.assertEqual(["3", "1", "2"], l2.items) l.remove_item(1) self.assertEqual(["3", "2"], l2.items)
def test_flattened_model_initializes_properly(self): l = ListModel.ListModel("as") bs1 = ListModel.ListModel("bs") bs1.append_item("11") bs1.append_item("12") bs2 = ListModel.ListModel("bs") bs3 = ListModel.ListModel("bs") bs3.append_item("31") bs3.append_item("32") bs3.append_item("33") l.append_item(bs1) l.append_item(bs2) l.append_item(bs3) f = ListModel.FlattenedListModel(container=l, master_items_key="as", child_items_key="bs", items_key="cs") self.assertEqual(["11", "12", "31", "32", "33"], f.cs)
def test_sorted_filtered_model_updates_when_data_item_exits_filter(self): def sort_by_date_key(data_item): return data_item.created with TestContext.create_memory_context() as test_context: document_model = test_context.create_document_model() filtered_data_items = ListModel.FilteredListModel(items_key="data_items") filtered_data_items.container = document_model filtered_data_items.filter = ListModel.NotFilter(ListModel.EqFilter("is_live", True)) filtered_data_items.sort_key = sort_by_date_key for _ in range(4): data_item = DataItem.DataItem(numpy.zeros((16, 16), numpy.uint32)) document_model.append_data_item(data_item) self.assertEqual(len(filtered_data_items.items), 4) with document_model.data_item_live(document_model.data_items[0]): document_model.data_items[0].data_item_changed_event.fire() self.assertEqual(len(filtered_data_items.items), 3)
def __init__(self, base_title: str, data_group: typing.Optional[DataGroup.DataGroup], filter_id: typing.Optional[str], document_controller: DocumentController.DocumentController): self.__base_title = base_title self.__data_group = data_group self.__filter_id = filter_id self.__filter_predicate = document_controller.get_filter_predicate( filter_id) if self.__filter_id else ListModel.Filter(True) self.on_title_changed: typing.Optional[typing.Callable[[str], None]] = None self.__count = 0 # useful for drag and drop self.document_controller = document_controller self.document_model = document_controller.document_model container = self.__data_group or document_controller.document_model def count_changed(count: Observer.ItemValue) -> None: self.__count = count if callable(self.on_title_changed): self.on_title_changed(self.title) oo = Observer.ObserverBuilder() oo.source(container).sequence_from_array( "display_items", predicate=self.__filter_predicate.matches).len().action_fn( count_changed) self.__count_observer = typing.cast(Observer.AbstractItemSource, oo.make_observable())
def test_filtered_list_sends_begin_end_changes_for_single_insert_and_remove( self) -> None: l = ListModel.ListModel[typing.Any]("items") l.append_item("3") l.append_item("1") l.append_item("4") l.append_item("2") l2 = ListModel.FilteredListModel(container=l, items_key="items") l2.sort_key = lambda x: x begin_changes_count = 0 end_changes_count = 0 def begin_changes(key: str) -> None: nonlocal begin_changes_count begin_changes_count += 1 def end_changes(key: str) -> None: nonlocal end_changes_count end_changes_count += 1 with l2.begin_changes_event.listen( begin_changes), l2.end_changes_event.listen(end_changes): l.insert_item(0, "5") l.remove_item(0) self.assertEqual(2, begin_changes_count) self.assertEqual(2, end_changes_count)
def test_filtered_list_is_sorted(self): l = ListModel.ListModel("items") l.append_item("3") l.append_item("1") l.append_item("4") l.append_item("2") l2 = ListModel.FilteredListModel(container=l, items_key="items") l2.sort_key = lambda x: x l2.mark_changed() self.assertEqual(["1", "2", "3", "4"], l2.items) l.remove_item(1) l.remove_item(1) self.assertEqual(["2", "3"], l2.items) l.insert_item(0, "5") l.insert_item(0, "1") self.assertEqual(["1", "2", "3", "5"], l2.items)
def __init__(self): self.__config_file = None # the active video sources (hardware sources). this list is updated when a video camera device is registered or # unregistered with the hardware source manager. self.video_sources = ListModel.ListModel() # the list of instances of video cameras. this is similar to the video sources but is the devices plus settings # for the device. some devices might not have instances if the factory to create the instance hasn't been # registered yet. self.__instances = list() # the list of video device factories. this is populated by responding to the registry messages. self.__video_device_factories = list() def component_registered(component, component_types): if "video_device_factory" in component_types: if not component in self.__video_device_factories: self.__video_device_factories.append(component) self.__make_video_devices() def component_unregistered(component, component_types): if "video_device_factory" in component_types: if component in self.__video_device_factories: self.__video_device_factories.remove(component) self.__component_registered_listener = Registry.listen_component_registered_event( component_registered) self.__component_unregistered_listener = Registry.listen_component_unregistered_event( component_unregistered) for component in Registry.get_components_by_type( "video_device_factory"): component_registered(component, {"video_device_factory"})
def test_processed_data_items_sorted_by_source_data_modified_date(self): document_model = DocumentModel.DocumentModel() with contextlib.closing(document_model): filtered_data_items = ListModel.FilteredListModel( items_key="data_items") filtered_data_items.container = document_model filtered_data_items.sort_key = DataItem.sort_by_date_key for _ in range(4): data_item = DataItem.DataItem( numpy.zeros((16, 16), numpy.uint32)) document_model.append_data_item(data_item) time.sleep(0.01) data_item = document_model.get_invert_new( document_model.display_items[0]) document_model.recompute_all() self.assertEqual(len(filtered_data_items.items), 5) # new data item should be last self.assertEqual( filtered_data_items.items.index(document_model.data_items[4]), 4) self.assertEqual( filtered_data_items.items.index(document_model.data_items[0]), 0) self.assertEqual( list(document_model.data_items[2:5]), filtered_data_items.items[2:]) # rest of list matches
def test_and_filter(self): f1 = ListModel.Filter(True) f2 = ListModel.Filter(True) f3 = ListModel.Filter(False) f4 = ListModel.Filter(False) self.assertTrue(ListModel.AndFilter([f1, f2]).matches(None)) self.assertFalse(ListModel.AndFilter([f2, f3]).matches(None)) self.assertTrue(ListModel.OrFilter([f2, f3]).matches(None)) self.assertFalse(ListModel.OrFilter([f3, f4]).matches(None))
def test_inserting_items_into_model_index0_without_sort_key__but_with_filter_puts_them_in_same_order(self): values = ["DEF", "ABC", "GHI", "DFG", "ACD", "GIJ"] indexes = [0, 0, 1, 1, 2, 4] result = ["ABC", "DFG", "ACD", "GHI", "GIJ", "DEF"] list_model = ListModel.ListModel("data_items") filtered_data_items = ListModel.FilteredListModel(items_key="data_items") filtered_data_items.container = list_model filtered_data_items.filter = ListModel.NotFilter(ListModel.StartsWithFilter("title", "D")) data_items = list() for index, value in enumerate(values): data_item = DataItem.DataItem(numpy.zeros((16, 16), numpy.uint32)) data_item.title = value list_model.insert_item(indexes[index], data_item) data_items.append(data_item) self.assertEqual([d.title for d in filtered_data_items.items], [v for v in result if not v.startswith("D")]) for data_item in data_items: data_item.close()
def test_filter_model_inits_with_source_model(self): list_model = ListModel.ListModel("data_items") filtered_data_items = ListModel.FilteredListModel(items_key="data_items") filtered_data_items.container = list_model filtered_data_items.sort_key = operator.attrgetter("title") data_items = list() for value in TestDataItemsModelModule.values: data_item = DataItem.DataItem(numpy.zeros((16, 16), numpy.uint32)) data_item.title = value list_model.insert_item(0, data_item) data_items.append(data_item) self.assertEqual([d.title for d in filtered_data_items.items], sorted([d.title for d in filtered_data_items.items])) selection = Selection.IndexedSelection() filtered_data_items2 = ListModel.FilteredListModel(items_key="data_items", container=filtered_data_items, selection=selection) self.assertEqual([d.title for d in filtered_data_items.items], [d.title for d in filtered_data_items2.items]) for data_item in data_items: data_item.close()
def create_objects(self, name: str, items, label: str = None) -> ComputationVariable: list_model = ListModel.ListModel(items=items) variable = ComputationVariable(name, objects=list_model, label=label) self.add_variable(variable) return variable
def project_filter(self) -> ListModel.Filter: def is_display_item_active( project_weak_ref, display_item: DisplayItem.DisplayItem) -> bool: return display_item.project == project_weak_ref() # use a weak reference to avoid circular references loops that prevent garbage collection return ListModel.PredicateFilter( functools.partial(is_display_item_active, weakref.ref(self)))
def test_filtered_list_updates_filtered_selection(self) -> None: l = ListModel.ListModel[typing.Any]("items") l.append_item("A1") l.append_item("B1") l.append_item("A2") l.append_item("B2") l.append_item("A3") l.append_item("B3") l2 = ListModel.FilteredListModel(container=l, items_key="items") s = l2.make_selection() s.set_multiple({0, 1, 2, 3}) l2.filter = ListModel.PredicateFilter( lambda x: bool(x.startswith("A"))) s.set_multiple({0, 1, 2}) l.remove_item(1) # B self.assertEqual({0, 1, 2}, s.indexes) l.remove_item(0) # A self.assertEqual({0, 1}, s.indexes)
def read_from_dict(self, properties: dict) -> None: # used for persistence # ensure that value_type is read first value_type_property = self._get_persistent_property("value_type") value_type_property.read_from_dict(properties) super().read_from_dict(properties) if self.object_specifiers: self.__objects_model = ListModel.ListModel( items=self.object_specifiers)
def __update_filter(self): """ Create a combined filter. Set the resulting filter into the document controller. """ filters = list() if self.__date_filter: filters.append(self.__date_filter) if self.__text_filter: filters.append(self.__text_filter) self.document_controller.display_filter = ListModel.AndFilter(filters)
def test_filtered_list_unsorted_retains_order(self): l = ListModel.ListModel("items") l.append_item("3") l.append_item("1") l.append_item("4") l.append_item("2") l2 = ListModel.FilteredListModel(container=l, items_key="items") l2.filter = ListModel.PredicateFilter(lambda x: x != "4") self.assertEqual(["3", "1", "2"], l2.items) l.remove_item(0) self.assertEqual(["1", "2"], l2.items) l.insert_item(0, "3") l.append_item("44") self.assertEqual(["3", "1", "2", "44"], l2.items) l2.begin_change() l.insert_item(0, "5") l.append_item("6") l2.end_change() self.assertEqual(["5", "3", "1", "2", "44", "6"], l2.items)