コード例 #1
0
 def test_mapped_model_values_after_delete_are_correct(self):
     l = ListModel.ListModel("items")
     l.append_item(A("1"))
     l.append_item(A("2"))
     l.append_item(A("3"))
     l2 = ListModel.MappedListModel(container=l, master_items_key="items", items_key="itemsb", map_fn=B)
     l.remove_item(1)
     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("3_B", l2.items[1].s)
コード例 #2
0
 def test_mapped_model_selection_after_delete_are_correct(self):
     l = ListModel.ListModel("items")
     l.append_item(A("1"))
     l.append_item(A("2"))
     l.append_item(A("3"))
     l2 = ListModel.MappedListModel(container=l, master_items_key="items", items_key="itemsb", map_fn=B)
     s = l2.make_selection()
     s.add(0)
     s.add(2)
     l.remove_item(1)
     self.assertEqual({0, 1}, s.indexes)
コード例 #3
0
 def test_initial_mapped_model_values_are_correct(self) -> None:
     l = ListModel.ListModel[typing.Any]("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)
コード例 #4
0
 def test_mapped_model_selection_after_insert_are_correct(self) -> None:
     l = ListModel.ListModel[typing.Any]("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)
コード例 #5
0
    def test_mapped_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")
        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):
            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)
コード例 #6
0
    def show_choose_project_dialog(self) -> None:
        with self.prevent_close():
            u = Declarative.DeclarativeUI()
            button_row = u.create_row(
                u.create_push_button(text=_("New..."),
                                     on_clicked="new_project"),
                u.create_push_button(text=_("Open..."),
                                     on_clicked="open_project"),
                u.create_stretch(),
                u.create_push_button(text=_("Cancel"),
                                     on_clicked="close_window"),
                u.create_push_button(text=_("Open Recent"),
                                     on_clicked="open_recent"),
                spacing=8)

            project_references_model = ListModel.FilteredListModel(
                container=self.__profile, items_key="project_references")
            project_references_model.filter = ListModel.PredicateFilter(
                lambda pr: pr.project_state != "loaded")
            project_references_model.sort_key = lambda pr: pr.last_used
            project_references_model.sort_reverse = True

            class ProjectReferenceItem:
                # provides a str converter and a tool tip.
                def __init__(self,
                             project_reference: Profile.ProjectReference):
                    self.project_reference = project_reference

                def __str__(self) -> str:
                    project_reference = self.project_reference
                    project_title = project_reference.title
                    if project_reference.project_state == "needs_upgrade":
                        project_title += " " + _("(NEEDS UPGRADE)")
                    elif project_reference.project_state != "unloaded" or project_reference.project_version != FileStorageSystem.PROJECT_VERSION:
                        project_title += " " + _("(MISSING OR UNREADABLE)")
                    return project_title

                @property
                def tool_tip(self) -> str:
                    return str(self.project_reference.path)

            project_reference_items_model = ListModel.MappedListModel(
                container=project_references_model,
                master_items_key="project_references",
                items_key="project_reference_items",
                map_fn=ProjectReferenceItem)

            item_list = u.create_list_box(
                items_ref="@binding(list_property_model.value)",
                current_index="@binding(current_index)",
                height=240,
                min_height=180,
                size_policy_horizontal="expanding",
                on_item_selected="recent_item_selected",
                on_item_handle_context_menu="item_handle_context_menu")

            main_column = u.create_column(
                u.create_label(text=_("Recent Projects")),
                item_list,
                u.create_spacing(13),
                button_row,
                spacing=8,
                width=380)
            window = u.create_window(main_column,
                                     title=_("Choose Project"),
                                     margin=12,
                                     window_style="tool")

            def open_project_reference(
                    project_reference: Profile.ProjectReference) -> None:
                self.open_project_reference(project_reference)

            def show_open_project_dialog() -> None:
                self.show_open_project_dialog()

            def show_new_project_dialog() -> None:
                NewProjectAction().invoke(
                    UIWindow.ActionContext(self, None, None))

            from nion.utils import Observable

            class ListPropertyModel(Observable.Observable):
                # copied from nionutils to avoid requiring new version.
                # remove this code once nionutils 0.3.24+ is released.

                def __init__(self, list_model):
                    super().__init__()
                    self.__list_model = list_model
                    self.__item_inserted_event_listener = list_model.item_inserted_event.listen(
                        self.__item_inserted)
                    self.__item_removed_event_listener = list_model.item_removed_event.listen(
                        self.__item_removed)

                def close(self) -> None:
                    self.__list_model = None
                    self.__item_inserted_event_listener = None
                    self.__item_removed_event_listener = None

                def __item_inserted(self, key: str, item,
                                    before_index: int) -> None:
                    self.notify_property_changed("value")

                def __item_removed(self, key: str, item, index: int) -> None:
                    self.notify_property_changed("value")

                @property
                def value(self):
                    return self.__list_model.items

            class ChooseProjectHandler(Declarative.WindowHandler):
                def __init__(self, application: Application):
                    super().__init__()
                    self.__application = application
                    self.current_index = 0
                    self.list_property_model = ListPropertyModel(
                        project_reference_items_model)

                def recent_item_selected(self, widget: Declarative.UIWidget,
                                         current_index: int) -> None:
                    if 0 <= current_index < len(project_reference_items_model.
                                                project_reference_items):
                        # to ensure the application does not close upon closing the last window, force it
                        # to stay open while the window is closed and another reopened.
                        with self.__application.prevent_close():
                            self.close_window()
                            project_reference_item = project_reference_items_model.project_reference_items[
                                current_index]
                            open_project_reference(
                                project_reference_item.project_reference)

                def new_project(self, widget: Declarative.UIWidget) -> None:
                    # to ensure the application does not close upon closing the last window, force it
                    # to stay open while the window is closed and another reopened.
                    with self.__application.prevent_close():
                        show_new_project_dialog()
                        self.close_window()

                def open_project(self, widget: Declarative.UIWidget) -> None:
                    # to ensure the application does not close upon closing the last window, force it
                    # to stay open while the window is closed and another reopened.
                    with self.__application.prevent_close():
                        show_open_project_dialog()
                        self.close_window()

                def open_recent(self, widget: Declarative.UIWidget) -> None:
                    self.recent_item_selected(widget, self.current_index)

                def item_handle_context_menu(self,
                                             widget: Declarative.UIWidget, *,
                                             gx: int, gy: int,
                                             index: typing.Optional[int],
                                             **kwargs) -> bool:
                    if index is not None:
                        project_reference_item = project_reference_items_model.project_reference_items[
                            index]
                        menu = self.window.create_context_menu()
                        menu.add_menu_item(
                            _(f"Open Project Location"),
                            functools.partial(
                                ProjectPanel.reveal_project,
                                project_reference_item.project_reference))
                        menu.add_separator()

                        def remove_project(index: int) -> None:
                            project_reference_item = project_reference_items_model.project_reference_items[
                                index]
                            self.__application.profile.remove_project_reference(
                                project_reference_item.project_reference)

                        menu.add_menu_item(
                            _(f"Remove Project from List"),
                            functools.partial(remove_project, index))
                        menu.popup(gx, gy)
                    return True

            ChooseProjectHandler(self).run(window, app=self)
コード例 #7
0
 def test_refcounts(self) -> None:
     # list model
     model = ListModel.ListModel[typing.Any]("items")
     model_ref = weakref.ref(model)
     del model
     self.assertIsNone(model_ref())
     # filtered model
     l = ListModel.ListModel[typing.Any]("items")
     model2 = ListModel.FilteredListModel(container=l, items_key="items")
     model_ref2 = weakref.ref(model2)
     del model2
     self.assertIsNone(model_ref2())
     # nested filtered model
     l = ListModel.ListModel[typing.Any]("items")
     l2 = ListModel.FilteredListModel(container=l, items_key="items")
     model3 = ListModel.FilteredListModel(container=l2, items_key="items")
     model_ref3 = weakref.ref(model3)
     del model3
     self.assertIsNone(model_ref3())
     # filtered model with item changed event
     l = ListModel.ListModel[typing.Any]("items")
     l.append_item(C())
     model4 = ListModel.FilteredListModel(container=l, items_key="items")
     model_ref4 = weakref.ref(model4)
     del model4
     self.assertIsNone(model_ref4())
     # mapped model
     l = ListModel.ListModel[typing.Any]("items")
     model5 = ListModel.MappedListModel(container=l,
                                        master_items_key="items",
                                        items_key="items")
     model_ref5 = weakref.ref(model5)
     del model5
     self.assertIsNone(model_ref5())
     # mapped model of filtered model
     l = ListModel.ListModel[typing.Any]("items")
     l2 = ListModel.FilteredListModel(container=l, items_key="items")
     model6 = ListModel.MappedListModel(container=l2,
                                        master_items_key="items",
                                        items_key="items")
     model_ref6 = weakref.ref(model6)
     del model6
     self.assertIsNone(model_ref6())
     # flattened model
     l = ListModel.ListModel[typing.Any]("items")
     model7 = ListModel.FlattenedListModel(container=l,
                                           master_items_key="items",
                                           child_items_key="items",
                                           items_key="items")
     model_ref7 = weakref.ref(model7)
     del model7
     self.assertIsNone(model_ref7())
     # flattened model with items
     l = ListModel.ListModel[typing.Any]("items")
     l.append_item(ListModel.ListModel[typing.Any]("items"))
     model8 = ListModel.FlattenedListModel(container=l,
                                           master_items_key="items",
                                           child_items_key="items",
                                           items_key="items")
     model_ref8 = weakref.ref(model8)
     del model8
     self.assertIsNone(model_ref8())
     # list property model
     l = ListModel.ListModel[typing.Any]("items")
     model9 = ListModel.ListPropertyModel(l)
     model_ref9 = weakref.ref(model9)
     del model9
     self.assertIsNone(model_ref9())
コード例 #8
0
ファイル: DataPanel.py プロジェクト: shabihsherjeel/nionswift
    def __init__(self, document_controller: DocumentController.DocumentController, panel_id: str, properties: typing.Dict):
        super().__init__(document_controller, panel_id, _("Data Items"))

        ui = document_controller.ui

        def show_context_menu(display_item: typing.Optional[DisplayItem.DisplayItem], x: int, y: int, gx: int, gy: int) -> bool:
            menu = document_controller.create_context_menu_for_display(display_item, use_selection=True)
            menu.popup(gx, gy)
            return True

        def map_display_item_to_display_item_adapter(display_item: DisplayItem.DisplayItem) -> DisplayItemAdapter:
            return DisplayItemAdapter(display_item, ui)

        def unmap_display_item_to_display_item_adapter(display_item_adapter: DisplayItemAdapter) -> None:
            display_item_adapter.close()

        self.__filtered_display_item_adapters_model = ListModel.MappedListModel(container=document_controller.filtered_display_items_model, master_items_key="display_items", items_key="display_item_adapters", map_fn=map_display_item_to_display_item_adapter, unmap_fn=unmap_display_item_to_display_item_adapter)

        self.__selection = self.document_controller.selection

        self.__focused = False

        def selection_changed() -> None:
            # called when the selection changes; notify selected display item changed if focused.
            self.__notify_focus_changed()

        self.__selection_changed_event_listener = self.__selection.changed_event.listen(selection_changed)

        def display_item_adapter_selection_changed(display_item_adapters: typing.List[DisplayItemAdapter]) -> None:
            indexes = set()
            for index, display_item_adapter in enumerate(self.__filtered_display_item_adapters_model.display_item_adapters):
                if display_item_adapter in display_item_adapters:
                    indexes.add(index)
            self.__selection.set_multiple(indexes)
            self.__notify_focus_changed()

        def focus_changed(focused: bool) -> None:
            self.focused = focused

        def delete_display_item_adapters(display_item_adapters: typing.List[DisplayItemAdapter]) -> None:
            document_controller.delete_display_items([display_item_adapter.display_item for display_item_adapter in display_item_adapters if display_item_adapter.display_item])

        self.data_list_controller = DataListController(document_controller.event_loop, ui, self.__filtered_display_item_adapters_model, self.__selection)
        self.data_list_controller.on_display_item_adapter_selection_changed = display_item_adapter_selection_changed
        self.data_list_controller.on_context_menu_event = show_context_menu
        self.data_list_controller.on_focus_changed = focus_changed
        self.data_list_controller.on_delete_display_item_adapters = delete_display_item_adapters

        self.data_grid_controller = DataGridController(document_controller.event_loop, ui, self.__filtered_display_item_adapters_model, self.__selection)
        self.data_grid_controller.on_display_item_adapter_selection_changed = display_item_adapter_selection_changed
        self.data_grid_controller.on_context_menu_event = show_context_menu
        self.data_grid_controller.on_focus_changed = focus_changed
        self.data_grid_controller.on_delete_display_item_adapters = delete_display_item_adapters

        data_list_widget = DataListWidget(ui, self.data_list_controller)
        data_grid_widget = DataGridWidget(ui, self.data_grid_controller)

        list_icon_button = CanvasItem.BitmapButtonCanvasItem(CanvasItem.load_rgba_data_from_bytes(pkgutil.get_data(__name__, "resources/list_icon_20.png")))
        grid_icon_button = CanvasItem.BitmapButtonCanvasItem(CanvasItem.load_rgba_data_from_bytes(pkgutil.get_data(__name__, "resources/grid_icon_20.png")))

        list_icon_button.sizing.set_fixed_size(Geometry.IntSize(20, 20))
        grid_icon_button.sizing.set_fixed_size(Geometry.IntSize(20, 20))

        button_row = CanvasItem.CanvasItemComposition()
        button_row.layout = CanvasItem.CanvasItemRowLayout(spacing=4)
        button_row.add_canvas_item(list_icon_button)
        button_row.add_canvas_item(grid_icon_button)

        buttons_widget = ui.create_canvas_widget(properties={"height": 20, "width": 44})
        buttons_widget.canvas_item.add_canvas_item(button_row)

        search_widget = ui.create_row_widget()
        search_widget.add_spacing(8)
        search_widget.add(ui.create_label_widget(_("Filter")))
        search_widget.add_spacing(8)
        search_line_edit = ui.create_line_edit_widget()
        search_line_edit.placeholder_text = _("No Filter")
        search_line_edit.clear_button_enabled = True  # Qt 5.3 doesn't signal text edited or editing finished when clearing. useless so disabled.
        search_line_edit.on_text_edited = self.document_controller.filter_controller.text_filter_changed
        search_line_edit.on_editing_finished = self.document_controller.filter_controller.text_filter_changed
        search_widget.add(search_line_edit)
        search_widget.add_spacing(6)
        search_widget.add(buttons_widget)
        search_widget.add_spacing(8)

        self.data_view_widget = ui.create_stack_widget()
        self.data_view_widget.add(data_list_widget)
        self.data_view_widget.add(data_grid_widget)
        self.data_view_widget.current_index = 0

        self.__view_button_group = CanvasItem.RadioButtonGroup([list_icon_button, grid_icon_button])
        self.__view_button_group.current_index = 0
        self.__view_button_group.on_current_index_changed = lambda index: setattr(self.data_view_widget, "current_index", index)

        widget = ui.create_column_widget(properties=properties)
        widget.add(self.data_view_widget)
        widget.add_spacing(6)
        widget.add(search_widget)
        widget.add_spacing(6)

        self.widget = widget

        self._data_list_widget = data_list_widget
        self._data_grid_widget = data_grid_widget