<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def on_button_release(self, event):
 """Write back changes If one or more items have been moved, the new position are stored in the corresponding meta data and a signal notifying the change is emitted. :param event: The button event """

        affected_models = {}

        for inmotion in self._movable_items:
            inmotion.move((event.x, event.y))
            rel_pos = gap_helper.calc_rel_pos_to_parent(self.view.canvas, inmotion.item,
                                                        inmotion.item.handles()[NW])
            if isinstance(inmotion.item, StateView):
                state_v = inmotion.item
                state_m = state_v.model
                self.view.canvas.request_update(state_v)
                if state_m.get_meta_data_editor()['rel_pos'] != rel_pos:
                    state_m.set_meta_data_editor('rel_pos', rel_pos)
                    affected_models[state_m] = ("position", True, state_v)
            elif isinstance(inmotion.item, NameView):
                state_v = inmotion.item
                state_m = self.view.canvas.get_parent(state_v).model
                self.view.canvas.request_update(state_v)
                if state_m.get_meta_data_editor()['name']['rel_pos'] != rel_pos:
                    state_m.set_meta_data_editor('name.rel_pos', rel_pos)
                    affected_models[state_m] = ("name_position", False, state_v)
            elif isinstance(inmotion.item, TransitionView):
                transition_v = inmotion.item
                transition_m = transition_v.model
                self.view.canvas.request_update(transition_v)
                current_waypoints = gap_helper.get_relative_positions_of_waypoints(transition_v)
                old_waypoints = transition_m.get_meta_data_editor()['waypoints']
                if current_waypoints != old_waypoints:
                    transition_m.set_meta_data_editor('waypoints', current_waypoints)
                    affected_models[transition_m] = ("waypoints", False, transition_v)

        if len(affected_models) == 1:
            model = next(iter(affected_models))
            change, affects_children, view = affected_models[model]
            self.view.graphical_editor.emit('meta_data_changed', model, change, affects_children)
        elif len(affected_models) > 1:
            # if more than one item has been moved, we need to call the meta_data_changed signal on a common parent
            common_parents = None
            for change, affects_children, view in affected_models.values():
                parents_of_view = set(self.view.canvas.get_ancestors(view))
                if common_parents is None:
                    common_parents = parents_of_view
                else:
                    common_parents = common_parents.intersection(parents_of_view)
            assert len(common_parents) > 0, "The selected elements do not have common parent element"
            for state_v in common_parents:
                # Find most nested state_v
                children_of_state_v = self.view.canvas.get_all_children(state_v)
                if any(common_parent in children_of_state_v for common_parent in common_parents):
                    continue
                self.view.graphical_editor.emit('meta_data_changed', state_v.model, "positions", True)
                break

        if not affected_models and self._old_selection is not None:
            # The selection is handled differently depending on whether states were moved or not
            # If no move operation was performed, we reset the selection to that is was before the button-press event
            # and let the state machine selection handle the selection
            self.view.unselect_all()
            self.view.select_item(self._old_selection)
            self.view.handle_new_selection(self._item)

        self._move_name_v = False
        self._old_selection = None
        return super(MoveItemTool, self).on_button_release(event)