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_layout_size_maintains_height_with_no_items_when_not_wrapped(self) -> None: selection = Selection.IndexedSelection() delegate = GridCanvasItemDelegate(0) canvas_item = GridCanvasItem.GridCanvasItem(delegate, selection, wrap=False) canvas_item.update_layout(Geometry.IntPoint(), Geometry.IntSize.make((40, 500))) canvas_bounds = canvas_item.canvas_bounds or Geometry.IntRect.empty_rect() self.assertEqual(canvas_bounds.height, 40)
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 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 test_layout_size_maintains_height_with_no_items_when_not_wrapped(self): selection = Selection.IndexedSelection() delegate = GridCanvasItemDelegate(0) canvas_item = GridCanvasItem.GridCanvasItem(delegate, selection, wrap=False) canvas_item.update_layout((0, 0), (40, 500)) self.assertEqual(canvas_item.canvas_bounds.height, 40)
def test_start_drag_does_not_change_selection(self) -> None: selection = Selection.IndexedSelection() delegate = GridCanvasItemDelegate() canvas_item = GridCanvasItem.GridCanvasItem(delegate, selection) canvas_item.update_layout(Geometry.IntPoint(), Geometry.IntSize.make((320, 100))) self.assertEqual(selection.indexes, set()) canvas_item.simulate_drag(Geometry.IntPoint(y=120, x=50), Geometry.IntPoint(y=120, x=500)) self.assertEqual(selection.indexes, set())
def test_start_drag_does_not_change_selection(self): selection = Selection.IndexedSelection() delegate = ListCanvasItemDelegate() canvas_item = ListCanvasItem.ListCanvasItem(delegate, selection) canvas_item.update_layout((0, 0), (320, 100)) self.assertEqual(selection.indexes, set()) canvas_item.simulate_drag(Geometry.IntPoint(y=120, x=50), Geometry.IntPoint(y=120, x=500)) self.assertEqual(selection.indexes, set())
def test_shift_click_extends_selection(self): selection = Selection.IndexedSelection() delegate = GridCanvasItemDelegate() canvas_item = GridCanvasItem.GridCanvasItem(delegate, selection) canvas_item.update_layout((0, 0), (320, 100)) self.assertEqual(selection.indexes, set()) canvas_item.simulate_click(Geometry.IntPoint(y=120, x=50)) self.assertEqual(selection.indexes, {1}) modifiers = CanvasItem.KeyboardModifiers(shift=True) canvas_item.simulate_click(Geometry.IntPoint(y=200, x=50), modifiers) self.assertEqual(selection.indexes, {1, 2})
def __init__(self, window: Window.Window, profile: Profile.Profile): content_widget = window.ui.create_column_widget() super().__init__(content_widget) ui = window.ui self._tree_model = TreeModel(profile) def closed_items_changed(closed_items: typing.Set[str]) -> None: profile.closed_items = list(closed_items) self._tree_model.on_closed_items_changed = closed_items_changed self._tree_selection = Selection.IndexedSelection( Selection.Style.multiple) projects_list_widget = Widgets.ListWidget( ui, ProjectTreeCanvasItemDelegate(window, self._tree_model), selection=self._tree_selection, v_scroll_enabled=False, v_auto_resize=True) projects_list_widget.wants_drag_events = True projects_list_widget.bind_items( Binding.PropertyBinding(self._tree_model, "value")) projects_section = Widgets.SectionWidget(ui, _("Projects"), projects_list_widget) projects_section.expanded = True content_widget.add(projects_section) # configure an observer for watching for project references changes. # this serves as the master updater for changes. move to document controller? def project_references_changed(item: Observer.ItemValue) -> None: # update the tree model. project_references = typing.cast( typing.Sequence[Profile.ProjectReference], item) self._tree_model.update_project_references(project_references) oo = Observer.ObserverBuilder() oo.source(profile).ordered_sequence_from_array( "project_references").collect_list().action_fn( project_references_changed) self.__projects_model_observer = typing.cast( Observer.AbstractItemSource, oo.make_observable())
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 test_extending_selection_with_no_anchor_behaves_sensibly(self): s = Selection.IndexedSelection() s.extend(0) self.assertEqual({0}, s.indexes) self.assertEqual(0, s.anchor_index)
def test_inserting_index_into_non_empty_selection_adjusts_indexes(self) -> None: s = Selection.IndexedSelection() s.set_multiple({0, 2, 4}) s.insert_index(1) self.assertEqual({0, 3, 5}, s.indexes)
def test_inserting_index_into_empty_selection_results_in_empty_index(self) -> None: s = Selection.IndexedSelection() s.insert_index(0) self.assertEqual(set(), s.indexes)
def __init__( self, ui: UserInterface.UserInterface, document_controller: DocumentController.DocumentController ) -> None: content_widget = ui.create_column_widget() super().__init__(content_widget) document_model = document_controller.document_model all_items_controller = CollectionDisplayItemCounter( _("All"), None, "all", document_controller) persistent_items_controller = CollectionDisplayItemCounter( _("Persistent"), None, "persistent", document_controller) live_items_controller = CollectionDisplayItemCounter( _("Live"), None, "temporary", document_controller) latest_items_controller = CollectionDisplayItemCounter( _("Latest Session"), None, "latest-session", document_controller) self.__item_controllers = [ all_items_controller, persistent_items_controller, live_items_controller, latest_items_controller ] self.__data_group_controllers: typing.List[ CollectionDisplayItemCounter] = list() collection_selection = Selection.IndexedSelection( Selection.Style.single_or_none) collections_list_widget = Widgets.ListWidget( ui, CollectionListCanvasItemDelegate(collection_selection), selection=collection_selection, v_scroll_enabled=False, v_auto_resize=True) collections_list_widget.wants_drag_events = True def filter_changed(data_group: typing.Optional[DataGroup.DataGroup], filter_id: typing.Optional[str]) -> None: if data_group: for index, controller in enumerate( collections_list_widget.items): if data_group == controller.data_group: collection_selection.set(index) break else: if filter_id == "latest-session": collection_selection.set(3) elif filter_id == "temporary": collection_selection.set(2) elif filter_id == "persistent": collection_selection.set(1) else: collection_selection.set(0) self.__filter_changed_event_listener = document_controller.filter_changed_event.listen( filter_changed) def collections_changed(t: str) -> None: collections_list_widget.items = [ all_items_controller, persistent_items_controller, live_items_controller, latest_items_controller, ] + self.__data_group_controllers all_items_controller.on_title_changed = collections_changed persistent_items_controller.on_title_changed = collections_changed live_items_controller.on_title_changed = collections_changed latest_items_controller.on_title_changed = collections_changed def document_model_item_inserted(key: str, value: typing.Any, before_index: int) -> None: if key == "data_groups": data_group = value controller = CollectionDisplayItemCounter( data_group.title, data_group, None, document_controller) self.__data_group_controllers.insert(before_index, controller) controller.on_title_changed = collections_changed collections_changed(str()) def document_model_item_removed(key: str, value: typing.Any, index: int) -> None: if key == "data_groups": controller = self.__data_group_controllers.pop(index) controller.close() collections_changed(str()) self.__document_model_item_inserted_listener = document_model.item_inserted_event.listen( document_model_item_inserted) self.__document_model_item_removed_listener = document_model.item_removed_event.listen( document_model_item_removed) data_group, filter_id = document_controller.get_data_group_and_filter_id( ) filter_changed(data_group, filter_id) for index, data_group in enumerate(document_model.data_groups): document_model_item_inserted("data_groups", data_group, index) collections_changed(str()) def collections_selection_changed( indexes: typing.AbstractSet[int]) -> None: if len(indexes) == 0: controller = collections_list_widget.items[0] document_controller.set_filter(controller.filter_id) elif len(indexes) == 1: controller = collections_list_widget.items[list(indexes)[0]] if controller.is_smart_collection: document_controller.set_filter(controller.filter_id) document_controller.set_data_group(None) else: document_controller.set_filter(None) document_controller.set_data_group(controller.data_group) collections_list_widget.on_selection_changed = collections_selection_changed collections_column = ui.create_column_widget() collections_column.add(collections_list_widget) collections_section = Widgets.SectionWidget(ui, _("Collections"), collections_column) collections_section.expanded = True content_widget.add(collections_section) content_widget.add_stretch() # for testing self._collection_selection = collection_selection
def make_selection(self): selection = Selection.IndexedSelection() self.__selections.append(selection) return selection
def __init__(self, ui, list_item_delegate, *, items=None, selection_style=None, properties=None, selection=None, border_color=None, v_scroll_enabled: bool=True, v_auto_resize: bool=False): super().__init__(ui.create_column_widget()) self.property_changed_event = Event.Event() items = items or list() self.__items: typing.List = list() self.on_selection_changed = None self.on_item_selected = None self.on_cancel = None self.on_item_handle_context_menu = None # used for declarative self.__items_binding = None self.__current_index_binding = None self.__on_current_index_changed = None self.__v_auto_resize = v_auto_resize self.on_escape_pressed : typing.Optional[typing.Callable[[], bool]] = None self.on_return_pressed : typing.Optional[typing.Callable[[], bool]] = None self.__selection = selection if selection else Selection.IndexedSelection(selection_style) def selection_changed(): on_selection_changed = self.on_selection_changed if callable(on_selection_changed): on_selection_changed(self.__selection.indexes) if callable(self.__on_current_index_changed): self.__on_current_index_changed(self.current_index) def handle_delegate_cancel(): if callable(self.on_cancel): self.on_cancel() if callable(self.on_escape_pressed): self.on_escape_pressed() def handle_delegate_item_selected(index): if callable(self.on_item_selected): self.on_item_selected(index) if callable(self.on_return_pressed): self.on_return_pressed() self.__selection_changed_event_listener = self.__selection.changed_event.listen(selection_changed) self.__list_canvas_item_delegate = list_item_delegate self.__list_canvas_item_delegate.on_cancel = handle_delegate_cancel self.__list_canvas_item_delegate.on_item_selected = handle_delegate_item_selected self.__list_canvas_item = ListCanvasItem.ListCanvasItem(self.__list_canvas_item_delegate, self.__selection, 20) scroll_area_canvas_item = CanvasItem.ScrollAreaCanvasItem(self.__list_canvas_item) scroll_area_canvas_item.auto_resize_contents = True scroll_group_canvas_item = CanvasItem.CanvasItemComposition() if border_color is not None: scroll_group_canvas_item.border_color = border_color scroll_group_canvas_item.layout = CanvasItem.CanvasItemRowLayout() scroll_group_canvas_item.add_canvas_item(scroll_area_canvas_item) if v_scroll_enabled: scroll_bar_canvas_item = CanvasItem.ScrollBarCanvasItem(scroll_area_canvas_item) scroll_group_canvas_item.add_canvas_item(scroll_bar_canvas_item) canvas_widget = ui.create_canvas_widget(properties=properties) canvas_widget.canvas_item.add_canvas_item(scroll_group_canvas_item) self.content_widget.add(canvas_widget) self.__canvas_widget = canvas_widget self.items = items
def __init__(self, ui: UserInterface.UserInterface, list_item_delegate: ListCanvasItem.ListCanvasItemDelegate, *, items: typing.Optional[typing.Sequence[typing.Any]] = None, selection_style: typing.Optional[Selection.Style] = None, properties: typing.Optional[typing.Mapping[ str, typing.Any]] = None, selection: typing.Optional[Selection.IndexedSelection] = None, border_color: typing.Optional[str] = None, v_scroll_enabled: bool = True, v_auto_resize: bool = False) -> None: column_widget = ui.create_column_widget() super().__init__(column_widget) self.property_changed_event = Event.Event() items = items or list() self.__items: typing.List[typing.Any] = list() self.on_selection_changed: typing.Optional[typing.Callable[ [typing.AbstractSet[int]], None]] = None self.on_item_selected: typing.Optional[typing.Callable[[int], bool]] = None self.on_cancel: typing.Optional[typing.Callable[[], None]] = None self.on_item_handle_context_menu: typing.Optional[typing.Callable[ ..., bool]] = None # used for declarative self.__items_binding: typing.Optional[Binding.Binding] = None self.__current_index_binding: typing.Optional[Binding.Binding] = None self.__on_current_index_changed: typing.Optional[typing.Callable[ [int], None]] = None self.__v_auto_resize = v_auto_resize self.on_escape_pressed: typing.Optional[typing.Callable[[], bool]] = None self.on_return_pressed: typing.Optional[typing.Callable[[], bool]] = None self.__selection = selection if selection else Selection.IndexedSelection( selection_style) def selection_changed() -> None: on_selection_changed = self.on_selection_changed if callable(on_selection_changed): on_selection_changed(self.__selection.indexes) if callable(self.__on_current_index_changed): self.__on_current_index_changed(self.current_index) def handle_delegate_cancel() -> None: if callable(self.on_cancel): self.on_cancel() if callable(self.on_escape_pressed): self.on_escape_pressed() def handle_delegate_item_selected(index: int) -> None: if callable(self.on_item_selected): self.on_item_selected(index) if callable(self.on_return_pressed): self.on_return_pressed() self.__selection_changed_event_listener = self.__selection.changed_event.listen( selection_changed) self.__list_canvas_item_delegate = list_item_delegate self.__list_canvas_item_delegate.on_cancel = handle_delegate_cancel self.__list_canvas_item_delegate.on_item_selected = handle_delegate_item_selected self.__list_canvas_item = ListCanvasItem.ListCanvasItem( self.__list_canvas_item_delegate, self.__selection, 20) scroll_area_canvas_item = CanvasItem.ScrollAreaCanvasItem( self.__list_canvas_item) scroll_area_canvas_item.auto_resize_contents = True scroll_group_canvas_item = CanvasItem.CanvasItemComposition() if border_color is not None: scroll_group_canvas_item.border_color = border_color scroll_group_canvas_item.layout = CanvasItem.CanvasItemRowLayout() scroll_group_canvas_item.add_canvas_item(scroll_area_canvas_item) if v_scroll_enabled: scroll_bar_canvas_item = CanvasItem.ScrollBarCanvasItem( scroll_area_canvas_item) scroll_group_canvas_item.add_canvas_item(scroll_bar_canvas_item) canvas_widget = ui.create_canvas_widget(properties=properties) canvas_widget.canvas_item.add_canvas_item(scroll_group_canvas_item) column_widget.add(canvas_widget) self.__canvas_widget = canvas_widget self.items = list(items)