def buildRangeRestrictionNodeMenu(self, diagram, node): """ Build and return a QMenu instance for range restriction nodes. :type diagram: Diagram :type node: RangeRestrictionNode :rtype: QMenu """ f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.identity() is Identity.Attribute f3 = lambda x: x.type() is Item.InclusionEdge f4 = lambda x: x.identity() is Identity.ValueDomain attribute_in_input = first(node.incomingNodes(filter_on_edges=f1, filter_on_nodes=f2)) valuedomain_in_isa = first(node.outgoingNodes(filter_on_edges=f3, filter_on_nodes=f4)) menu = self.buildGenericNodeMenu(diagram, node) menu.addSeparator() menu.insertMenu(self.session.action('node_properties'), self.session.menu('switch_restriction')) for action in self.session.action('switch_restriction').actions(): action.setChecked(node.type() is action.data()) action.setVisible(node.type() is action.data() or not attribute_in_input and not valuedomain_in_isa) if not attribute_in_input and not valuedomain_in_isa: qualified = node.isRestrictionQualified() menu.insertMenu(self.session.action('node_properties'), self.session.menu('property_restriction')) for action in self.session.action('restriction').actions(): action.setChecked(node.restriction() is action.data()) action.setVisible(action.data() is not Restriction.Self or not qualified) menu.insertSeparator(self.session.action('node_properties')) self.insertLabelActions(menu, node) menu.insertSeparator(self.session.action('node_properties')) return menu
def test_insert_edge_with_missing_endpoint(self): # GIVEN view = self.session.mdi.activeView() diagram = self.session.mdi.activeDiagram() diagram.setMode(DiagramMode.EdgeAdd, Item.InclusionEdge) num_edges_in_diagram = len(diagram.edges()) num_items_in_project = len(self.project.items()) num_edges_in_project = len(self.project.edges()) node1 = first( self.project.predicates(Item.ConceptNode, 'Male', diagram)) node2 = first( self.project.predicates(Item.ConceptNode, 'Person', diagram)) pos1 = view.mapFromScene(node1.pos()) pos2 = view.mapFromScene(node2.pos() - QtCore.QPointF(-200, 0)) # WHEN QtTest.QTest.mousePress(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos1) QtTest.QTest.mouseMove(view.viewport(), pos2) # THEN self.assertTrue(diagram.isEdgeAdd()) # WHEN QtTest.QTest.mouseRelease(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos2) # THEN self.assertFalse(diagram.isEdgeAdd()) self.assertEqual(num_edges_in_diagram, len(diagram.edges())) self.assertEqual(num_items_in_project, len(self.project.items())) self.assertEqual(num_edges_in_project, len(self.project.edges()))
def buildFacetNodeMenu(self, diagram, node): """ Build and return a QMenu instance for facet nodes. :type diagram: Diagram :type node: FacetNode :rtype: QMenu """ menu = self.buildGenericNodeMenu(diagram, node) menu.insertMenu(self.session.action('node_properties'), self.session.menu('facet')) menu.insertSeparator(self.session.action('node_properties')) ############################################# # BEGIN CONSTRAIN FACET SWITCH ################################# f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.type() is Item.DatatypeRestrictionNode f3 = lambda x: x.type() is Item.ValueDomainNode facet = node.facet admissible = [x for x in Facet] restriction = first(node.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2)) if restriction: valuedomain = first(restriction.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) if valuedomain: admissible = Facet.forDatatype(valuedomain.datatype) for action in self.session.action('facet').actions(): action.setChecked(action.data() is facet) action.setVisible(action.data() in admissible) ############################################# # END CONSTRAIN FACET SWITCH ################################# return menu
def test_insert_edge_with_missing_endpoint(self, session, qtbot): # GIVEN project = session.project view = session.mdi.activeView() diagram = session.mdi.activeDiagram() diagram.setMode(DiagramMode.EdgeAdd, Item.InclusionEdge) num_edges_in_diagram = len(diagram.edges()) num_items_in_project = len(project.items()) num_edges_in_project = len(project.edges()) iri1 = project.getIRI('http://www.dis.uniroma1.it/~graphol/test_project/Male') node1 = first(project.iriOccurrences(Item.ConceptIRINode, iri1, diagram)) iri2 = project.getIRI('http://www.dis.uniroma1.it/~graphol/test_project/Person') node2 = first(project.iriOccurrences(Item.ConceptIRINode, iri2, diagram)) pos1 = view.mapFromScene(node1.pos()) pos2 = view.mapFromScene(node2.pos() - QtCore.QPointF(-200, 0)) # WHEN qtbot.mousePress(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos1) qtbot.mouseMove(view.viewport(), pos2) # THEN assert diagram.isEdgeAdd() # WHEN qtbot.mouseRelease(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos2) # THEN assert not diagram.isEdgeAdd() assert num_edges_in_diagram == len(diagram.edges()) assert num_items_in_project == len(project.items()) assert num_edges_in_project == len(project.edges())
def identify(self): """ Perform the node identification step for this Union node. Because this node can assume a Concept identity, whenever this node is being targeted by an Individual node using a Membership edge, we set the identity and move this node in the STRONG set. We'll also make sure to remove from the STRONG set the individual node used to compute the identity of this very node since Individual nodes do not contribute with inheritance to the computation of the final identity for all the WEAK nodes being examined during the identification process. Similarly we do the same if the node is targeted by a RoleInstance or an AttributeInstance :rtype: tuple """ f1 = lambda x: x.type() is Item.MembershipEdge f2 = lambda x: x.identity() is Identity.Individual f3 = lambda x: x.identity() in {Identity.RoleInstance, Identity.AttributeInstance} f4 = lambda x: Identity.Role if x.identity() is Identity.RoleInstance else Identity.Attribute incoming = self.incomingNodes(filter_on_edges=f1, filter_on_nodes=f2) if incoming: computed = Identity.Unknown identities = set(x.identity() for x in incoming) if len(identities) == 1 and first(identities) is Identity.Individual: computed = Identity.Concept self.setIdentity(computed) return {self}, incoming, set() incoming = self.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3) if incoming: computed = Identity.Unknown identities = set(map(f4, incoming)) if len(identities) == 1: computed = first(identities) self.setIdentity(computed) return {self}, incoming, set() return None
def test_insert_edge_with_missing_endpoint(self, session, qtbot): # GIVEN project = session.project view = session.mdi.activeView() diagram = session.mdi.activeDiagram() diagram.setMode(DiagramMode.EdgeAdd, Item.InclusionEdge) num_edges_in_diagram = len(diagram.edges()) num_items_in_project = len(project.items()) num_edges_in_project = len(project.edges()) node1 = first( project.predicates(Item.ConceptNode, 'test:Male', diagram)) node2 = first( project.predicates(Item.ConceptNode, 'test:Person', diagram)) pos1 = view.mapFromScene(node1.pos()) pos2 = view.mapFromScene(node2.pos() - QtCore.QPointF(-200, 0)) # WHEN qtbot.mousePress(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos1) qtbot.mouseMove(view.viewport(), pos2) # THEN assert diagram.isEdgeAdd() # WHEN qtbot.mouseRelease(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos2) # THEN assert not diagram.isEdgeAdd() assert num_edges_in_diagram == len(diagram.edges()) assert num_items_in_project == len(project.items()) assert num_edges_in_project == len(project.edges())
def test_insert_edge_with_control_modifier(session, qtbot): # GIVEN project = session.project diagram = session.mdi.activeDiagram() view = session.mdi.activeView() plugin = session.plugin('palette') palette = plugin.widget('palette') button = palette.button(Item.InclusionEdge) node1 = first(project.predicates(Item.ConceptNode, 'test:Male', diagram)) node2 = first(project.predicates(Item.ConceptNode, 'test:Person', diagram)) pos1 = view.mapFromScene(node1.pos()) pos2 = view.mapFromScene(node2.pos()) # WHEN qtbot.mouseClick(button, QtCore.Qt.LeftButton) # THEN assert button.isChecked() assert diagram.mode is DiagramMode.EdgeAdd assert diagram.modeParam is Item.InclusionEdge # WHEN qtbot.mousePress(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.ControlModifier, pos1) qtbot.mouseMove(view.viewport(), pos2) # THEN assert button.isChecked() # WHEN qtbot.mouseRelease(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.ControlModifier, pos2) # THEN assert button.isChecked() assert diagram.mode is DiagramMode.EdgeAdd assert diagram.modeParam is Item.InclusionEdge
def test_change_diagram_font(self, session): # GIVEN project = session.project diagram = session.mdi.activeDiagram() node1 = first( project.predicates(Item.ConceptNode, 'test:Male', diagram)) node2 = first( project.predicates(Item.ConceptNode, 'test:Person', diagram)) node3 = first( project.predicates(Item.RoleNode, 'test:hasMother', diagram)) node4 = first( project.predicates(Item.RoleNode, 'test:hasFather', diagram)) pos1 = node1.textPos() pos2 = node2.textPos() pos3 = node3.textPos() pos4 = node4.textPos() font = diagram.font() # WHEN diagram.setFont(Font(font=font, pixelSize=font.pixelSize() * 2)) # THEN assert pos1 == node1.textPos() assert pos2 == node2.textPos() assert pos3 == node3.textPos() assert pos4 == node4.textPos() # WHEN diagram.setFont(font) # THEN assert pos1 == node1.textPos() assert pos2 == node2.textPos() assert pos3 == node3.textPos() assert pos4 == node4.textPos()
def test_insert_edge_with_control_modifier(self): # GIVEN diagram = self.session.mdi.activeDiagram() view = self.session.mdi.activeView() plugin = self.session.plugin('palette') palette = plugin.widget('palette') button = palette.button(Item.InclusionEdge) node1 = first(self.project.predicates(Item.ConceptNode, 'Male', diagram)) node2 = first(self.project.predicates(Item.ConceptNode, 'Person', diagram)) pos1 = view.mapFromScene(node1.pos()) pos2 = view.mapFromScene(node2.pos()) # WHEN QtTest.QTest.mouseClick(button, QtCore.Qt.LeftButton) # THEN self.assertTrue(button.isChecked()) self.assertIs(diagram.mode, DiagramMode.EdgeAdd) self.assertIs(diagram.modeParam, Item.InclusionEdge) # WHEN QtTest.QTest.mousePress(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.ControlModifier, pos1) QtTest.QTest.mouseMove(view.viewport(), pos2) # THEN self.assertTrue(button.isChecked()) # WHEN QtTest.QTest.mouseRelease(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.ControlModifier, pos2) # THEN self.assertTrue(button.isChecked()) self.assertIs(diagram.mode, DiagramMode.EdgeAdd) self.assertIs(diagram.modeParam, Item.InclusionEdge)
def test_insert_edge(self): # GIVEN view = self.session.mdi.activeView() diagram = self.session.mdi.activeDiagram() diagram.setMode(DiagramMode.EdgeAdd, Item.InclusionEdge) num_edges_in_diagram = len(diagram.edges()) num_items_in_project = len(self.project.items()) num_edges_in_project = len(self.project.edges()) node1 = first(self.project.predicates(Item.ConceptNode, 'Male', diagram)) node2 = first(self.project.predicates(Item.ConceptNode, 'Person', diagram)) num_edges_in_node1 = len(node1.edges) num_edges_in_node2 = len(node2.edges) pos1 = view.mapFromScene(node1.pos()) pos2 = view.mapFromScene(node2.pos()) # WHEN QtTest.QTest.mousePress(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos1) QtTest.QTest.mouseMove(view.viewport(), pos2) # THEN self.assertTrue(diagram.isEdgeAdd()) # WHEN QtTest.QTest.mouseRelease(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos2) # THEN self.assertFalse(diagram.isEdgeAdd()) self.assertEqual(num_edges_in_diagram, len(diagram.edges()) - 1) self.assertEqual(num_items_in_project, len(self.project.items()) - 1) self.assertEqual(num_edges_in_project, len(self.project.edges()) - 1) self.assertEqual(num_edges_in_node1, len(node1.edges) - 1) self.assertEqual(num_edges_in_node2, len(node2.edges) - 1)
def test_insert_edge(self): # GIVEN diagram = self.session.mdi.activeDiagram() view = self.session.mdi.activeView() plugin = self.session.plugin('palette') palette = plugin.widget('palette') button = palette.button(Item.InclusionEdge) node1 = first( self.project.predicates(Item.ConceptNode, 'test:Male', diagram)) node2 = first( self.project.predicates(Item.ConceptNode, 'test:Person', diagram)) pos1 = view.mapFromScene(node1.pos()) pos2 = view.mapFromScene(node2.pos()) # WHEN QtTest.QTest.mouseClick(button, QtCore.Qt.LeftButton) # THEN self.assertTrue(button.isChecked()) self.assertIs(diagram.mode, DiagramMode.EdgeAdd) self.assertIs(diagram.modeParam, Item.InclusionEdge) # WHEN QtTest.QTest.mousePress(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos1) QtTest.QTest.mouseMove(view.viewport(), pos2) # THEN self.assertTrue(button.isChecked()) # WHEN QtTest.QTest.mouseRelease(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.NoModifier, pos2) # THEN self.assertFalse(button.isChecked()) self.assertIs(diagram.mode, DiagramMode.Idle) self.assertIsNone(diagram.modeParam)
def test_action_cut_and_paste_multiple_predicate_nodes_with_shared_edges_on_the_same_diagram( session): # GIVEN project = session.project diagram = session.mdi.activeDiagram() action_cut = session.action('cut') action_paste = session.action('paste') iri1 = project.getIRI( 'http://www.dis.uniroma1.it/~graphol/test_project/hasParent') node1 = first(project.iriOccurrences(Item.RoleIRINode, iri1, diagram)) iri2 = project.getIRI( 'http://www.dis.uniroma1.it/~graphol/test_project/hasAncestor') node2 = first(project.iriOccurrences(Item.RoleIRINode, iri2, diagram)) iri3 = project.getIRI( 'http://www.dis.uniroma1.it/~graphol/test_project/hasFather') node3 = first(project.iriOccurrences(Item.RoleIRINode, iri3, diagram)) iri4 = project.getIRI( 'http://www.dis.uniroma1.it/~graphol/test_project/hasMother') node4 = first(project.iriOccurrences(Item.RoleIRINode, iri4, diagram)) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) num_items_in_project = len(project.items()) num_nodes_in_project = len(project.nodes()) num_edges_in_project = len(project.edges()) diagram.clearSelection() node1.setSelected(True) for edge in node1.edges: edge.setSelected(True) edge.other(node1).setSelected(True) # WHEN action_cut.trigger() action_paste.trigger() # THEN assert num_nodes_in_diagram == len(diagram.nodes()) assert num_edges_in_diagram == len(diagram.edges()) + 5 assert num_items_in_project == len(project.items()) + 5 assert num_nodes_in_project == len(project.nodes()) assert num_edges_in_project == len(project.edges()) + 5 assert num_items_in_project == len(project.items(diagram)) + 5 assert num_nodes_in_project == len(project.nodes(diagram)) assert num_edges_in_project == len(project.edges(diagram)) + 5 assert len(project.iriOccurrences(Item.RoleIRINode, iri1, diagram)) == 1 assert len(project.iriOccurrences(Item.RoleIRINode, iri1)) == 1 assert len(project.iriOccurrences(Item.RoleIRINode, iri2, diagram)) == 1 assert len(project.iriOccurrences(Item.RoleIRINode, iri2)) == 1 assert len(project.iriOccurrences(Item.RoleIRINode, iri3, diagram)) == 1 assert len(project.iriOccurrences(Item.RoleIRINode, iri3)) == 1 assert len(project.iriOccurrences(Item.RoleIRINode, iri4, diagram)) == 1 assert len(project.iriOccurrences(Item.RoleIRINode, iri4)) == 1 assert not session.clipboard.empty() assert session.clipboard.size() == 7 assert not session.undostack.isClean()
def __init__(self, diagram, node, session): """ Initialize the node properties dialog. :type diagram: Diagram :type node: AbstractNode :type session: Session """ super().__init__(diagram, node, session) ############################################# # FACET TAB ################################# f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.type() is Item.DatatypeRestrictionNode f3 = lambda x: x.type() is Item.ValueDomainNode admissible = [x for x in Facet] restriction = first( self.node.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2)) if restriction: valuedomain = first( restriction.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) if valuedomain: admissible = Facet.forDatatype(valuedomain.datatype) self.facetLabel = QtWidgets.QLabel(self) self.facetLabel.setFont(Font('Roboto', 12)) self.facetLabel.setText('Facet') self.facetField = ComboBox(self) self.facetField.setFixedWidth(200) self.facetField.setFocusPolicy(QtCore.Qt.StrongFocus) self.facetField.setFont(Font('Roboto', 12)) for facet in admissible: self.facetField.addItem(facet.value, facet) facet = self.node.facet for i in range(self.facetField.count()): if self.facetField.itemData(i) is facet: self.facetField.setCurrentIndex(i) break else: self.facetField.setCurrentIndex(0) self.valueLabel = QtWidgets.QLabel(self) self.valueLabel.setFont(Font('Roboto', 12)) self.valueLabel.setText('Value') self.valueField = StringField(self) self.valueField.setFixedWidth(200) self.valueField.setFont(Font('Roboto', 12)) self.valueField.setValue(self.node.value) self.facetWidget = QtWidgets.QWidget() self.facetLayout = QtWidgets.QFormLayout(self.facetWidget) self.facetLayout.addRow(self.facetLabel, self.facetField) self.facetLayout.addRow(self.valueLabel, self.valueField) self.mainWidget.addTab(self.facetWidget, 'Facet')
def test_action_cut_and_paste_multiple_predicate_nodes_on_the_same_diagram( self): # GIVEN diagram = self.session.mdi.activeDiagram() action_cut = self.session.action('cut') action_paste = self.session.action('paste') node1 = first( self.project.predicates(Item.RoleNode, 'hasParent', diagram)) node2 = first( self.project.predicates(Item.RoleNode, 'hasAncestor', diagram)) node3 = first( self.project.predicates(Item.RoleNode, 'hasFather', diagram)) node4 = first( self.project.predicates(Item.RoleNode, 'hasMother', diagram)) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) num_edges_in_project = len(self.project.edges()) diagram.clearSelection() node1.setSelected(True) node2.setSelected(True) node3.setSelected(True) node4.setSelected(True) # WHEN action_cut.trigger() action_paste.trigger() # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes())) self.assertEqual(num_edges_in_diagram, len(diagram.edges()) + 8) self.assertEqual(num_items_in_project, len(self.project.items()) + 8) self.assertEqual(num_nodes_in_project, len(self.project.nodes())) self.assertEqual(num_edges_in_project, len(self.project.edges()) + 8) self.assertEqual(num_items_in_project, len(self.project.items(diagram)) + 8) self.assertEqual(num_nodes_in_project, len(self.project.nodes(diagram))) self.assertEqual(num_edges_in_project, len(self.project.edges(diagram)) + 8) self.assertLen( 1, self.project.predicates(Item.RoleNode, 'hasParent', diagram)) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasParent')) self.assertLen( 1, self.project.predicates(Item.RoleNode, 'hasAncestor', diagram)) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasAncestor')) self.assertLen( 1, self.project.predicates(Item.RoleNode, 'hasFather', diagram)) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasFather')) self.assertLen( 1, self.project.predicates(Item.RoleNode, 'hasMother', diagram)) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasMother')) self.assertFalse(self.session.clipboard.empty()) self.assertEqual(self.session.clipboard.size(), 4) self.assertFalse(self.session.undostack.isClean())
def __init__(self, diagram, node, session): """ Initialize the node properties dialog. :type diagram: Diagram :type node: AbstractNode :type session: Session """ super().__init__(diagram, node, session) ############################################# # FACET TAB ################################# f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.type() is Item.DatatypeRestrictionNode f3 = lambda x: x.type() is Item.ValueDomainNode admissible = [x for x in Facet] restriction = first(self.node.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2)) if restriction: valuedomain = first(restriction.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) if valuedomain: admissible = Facet.forDatatype(valuedomain.datatype) self.facetLabel = QtWidgets.QLabel(self) self.facetLabel.setFont(Font('Roboto', 12)) self.facetLabel.setText('Facet') self.facetField = ComboBox(self) self.facetField.setFixedWidth(200) self.facetField.setFocusPolicy(QtCore.Qt.StrongFocus) self.facetField.setFont(Font('Roboto', 12)) for facet in admissible: self.facetField.addItem(facet.value, facet) facet = self.node.facet for i in range(self.facetField.count()): if self.facetField.itemData(i) is facet: self.facetField.setCurrentIndex(i) break else: self.facetField.setCurrentIndex(0) self.valueLabel = QtWidgets.QLabel(self) self.valueLabel.setFont(Font('Roboto', 12)) self.valueLabel.setText('Value') self.valueField = StringField(self) self.valueField.setFixedWidth(200) self.valueField.setFont(Font('Roboto', 12)) self.valueField.setValue(self.node.value) self.facetWidget = QtWidgets.QWidget() self.facetLayout = QtWidgets.QFormLayout(self.facetWidget) self.facetLayout.addRow(self.facetLabel, self.facetField) self.facetLayout.addRow(self.valueLabel, self.valueField) self.mainWidget.addTab(self.facetWidget, 'Facet')
def buildIndividualNodeMenu(self, diagram, node): """ Build and return a QMenu instance for individual nodes. :type diagram: Diagram :type node: IndividualNode :rtype: QMenu """ menu = self.buildGenericNodeMenu(diagram, node) menu.insertMenu(self.session.action('node_properties'), self.session.menu('refactor')) menu.insertMenu(self.session.action('node_properties'), self.session.menu('brush')) menu.insertMenu(self.session.action('node_properties'), self.session.menu('switch_individual')) self.insertLabelActions(menu, node) menu.insertSeparator(self.session.action('node_properties')) ############################################# # BEGIN CONSTRAIN IDENTITY SWITCH ################################# instance = True value = True f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.type() is Item.EnumerationNode f3 = lambda x: x.type() is Item.IndividualNode f4 = lambda x: x.type() is Item.PropertyAssertionNode f5 = lambda x: x.type() is Item.MembershipEdge f6 = lambda x: x.identity() in {Identity.Attribute, Identity.Role} enumeration = first(node.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2)) if enumeration: num = len(enumeration.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) instance = enumeration.identity() is Identity.Concept or num < 2 value = enumeration.identity() is Identity.ValueDomain or num < 2 assertion = first(node.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f4)) if assertion: operand = first(assertion.outgoingNodes(filter_on_edges=f5, filter_on_nodes=f6)) if operand: if operand.identity() is Identity.Role: value = False elif operand.identity() is Identity.Attribute: num = len(assertion.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) instance = instance and (node.identity() is Identity.Individual or num < 2) value = value and (node.identity() is Identity.Value or num < 2) for a in self.session.action('switch_individual').actions(): a.setChecked(a.data() is node.identity()) a.setVisible(a.data() is Identity.Individual and instance or a.data() is Identity.Value and value) ############################################# # END CONSTRAIN IDENTITY SWITCH ################################# return menu
def datatype(self): """ Returns the datatype this facet is restricting, or None if the node is isolated. :rtype: Datatype """ f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.type() is Item.DatatypeRestrictionNode f3 = lambda x: x.type() is Item.ValueDomainNode outgoing = first(self.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2)) if outgoing: incoming = first(outgoing.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) if incoming: return incoming.datatype return None
def test_action_cut_and_paste_multiple_predicate_nodes_on_the_same_diagram( session): # GIVEN project = session.project diagram = session.mdi.activeDiagram() action_cut = session.action('cut') action_paste = session.action('paste') node1 = first(project.predicates(Item.RoleNode, 'test:hasParent', diagram)) node2 = first( project.predicates(Item.RoleNode, 'test:hasAncestor', diagram)) node3 = first(project.predicates(Item.RoleNode, 'test:hasFather', diagram)) node4 = first(project.predicates(Item.RoleNode, 'test:hasMother', diagram)) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) num_items_in_project = len(project.items()) num_nodes_in_project = len(project.nodes()) num_edges_in_project = len(project.edges()) diagram.clearSelection() node1.setSelected(True) node2.setSelected(True) node3.setSelected(True) node4.setSelected(True) # WHEN action_cut.trigger() action_paste.trigger() # THEN assert num_nodes_in_diagram == len(diagram.nodes()) assert num_edges_in_diagram == len(diagram.edges()) + 8 assert num_items_in_project == len(project.items()) + 8 assert num_nodes_in_project == len(project.nodes()) assert num_edges_in_project == len(project.edges()) + 8 assert num_items_in_project == len(project.items(diagram)) + 8 assert num_nodes_in_project == len(project.nodes(diagram)) assert num_edges_in_project == len(project.edges(diagram)) + 8 assert len(project.predicates(Item.RoleNode, 'test:hasParent', diagram)) == 1 assert len(project.predicates(Item.RoleNode, 'test:hasParent')) == 1 assert len(project.predicates(Item.RoleNode, 'test:hasAncestor', diagram)) == 1 assert len(project.predicates(Item.RoleNode, 'test:hasAncestor')) == 1 assert len(project.predicates(Item.RoleNode, 'test:hasFather', diagram)) == 1 assert len(project.predicates(Item.RoleNode, 'test:hasFather')) == 1 assert len(project.predicates(Item.RoleNode, 'test:hasMother', diagram)) == 1 assert len(project.predicates(Item.RoleNode, 'test:hasMother')) == 1 assert not session.clipboard.empty() assert session.clipboard.size() == 4 assert not session.undostack.isClean()
def mouseReleaseEvent(self, mouseEvent): """ Executed when the mouse is released from the tree view. :type mouseEvent: QMouseEvent """ if mouseEvent.button() == QtCore.Qt.RightButton: index = first(self.selectedIndexes()) if index: model = self.model().sourceModel() index = self.model().mapToSource(index) item = model.itemFromIndex(index) data = item.data(OntologyExplorerView.IRIRole) if isinstance(data, IRI): self.widget.sgnIRIItemRightClicked.emit(data) if item in self.parent().unsatisfiableItems: self.session.currentEmptyEntityIRI = data if item in self.parent().unsatisfiableClasses: self.session.currentEmptyEntityType = Item.ConceptIRINode elif item in self.parent().unsatisfiableObjProps: self.session.currentEmptyEntityType = Item.RoleIRINode elif item in self.parent().unsatisfiableDataProps: self.session.currentEmptyEntityType = Item.AttributeIRINode menu = self.session.mf.buildEmptyEntityMenu() menu.exec_(mouseEvent.screenPos().toPoint()) elif isinstance(data, AbstractNode): node = item.data(OntologyExplorerView.IRIRole) self.widget.sgnItemRightClicked.emit(node) menu = self.session.mf.create(node.diagram, [node]) menu.exec_(mouseEvent.screenPos().toPoint()) super().mouseReleaseEvent(mouseEvent)
def test_action_copy_and_paste_single_predicate_node_on_the_same_diagram(self): # GIVEN diagram = self.session.mdi.activeDiagram() action_copy = self.session.action('copy') action_paste = self.session.action('paste') node = first(self.project.predicates(Item.RoleNode, 'hasParent', diagram)) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) num_edges_in_project = len(self.project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) diagram.clearSelection() node.setSelected(True) # WHEN action_copy.trigger() action_paste.trigger() # THEN self.assertEqual(num_nodes_in_diagram + 1, len(diagram.nodes())) self.assertEqual(num_edges_in_diagram, len(diagram.edges())) self.assertEqual(num_items_in_project + 1, len(self.project.items())) self.assertEqual(num_nodes_in_project + 1, len(self.project.nodes())) self.assertEqual(num_edges_in_project, len(self.project.edges())) self.assertEqual(num_items_in_project + 1, len(self.project.items(diagram))) self.assertEqual(num_nodes_in_project + 1, len(self.project.nodes(diagram))) self.assertEqual(num_edges_in_project, len(self.project.edges(diagram))) self.assertLen(2, self.project.predicates(Item.RoleNode, 'hasParent', diagram)) self.assertLen(2, self.project.predicates(Item.RoleNode, 'hasParent')) self.assertFalse(self.session.clipboard.empty()) self.assertEqual(self.session.clipboard.size(), 1) self.assertFalse(self.session.undostack.isClean())
def doNodeIdentification(self, node): """ Perform node identification. :type node: AbstractNode """ if Identity.Neutral in node.identities(): func = lambda x: Identity.Neutral in x.identities() collection = bfs(source=node, filter_on_visit=func) generators = partition(func, collection) excluded = set() strong = set(generators[1]) weak = set(generators[0]) for node in weak: identification = node.identify() if identification: strong = set.union(strong, identification[0]) strong = set.difference(strong, identification[1]) excluded = set.union(excluded, identification[2]) computed = Identity.Neutral identities = set(x.identity() for x in strong) if identities: computed = first(identities) if len(identities) > 1: computed = Identity.Unknown for node in weak - strong - excluded: node.setIdentity(computed)
def mouseReleaseEvent(self, mouseEvent): """ Executed when the mouse is released from the tree view. :type mouseEvent: QMouseEvent """ if mouseEvent.button() == QtCore.Qt.RightButton: index = first(self.selectedIndexes()) if index: model = self.model().sourceModel() index = self.model().mapToSource(index) item = model.itemFromIndex(index) diagram = item.data() if diagram: menu = QtWidgets.QMenu() menu.addAction(self.session.action('new_diagram')) menu.addSeparator() menu.addAction(self.session.action('rename_diagram')) menu.addAction(self.session.action('remove_diagram')) menu.addSeparator() menu.addAction(self.session.action('diagram_properties')) self.session.action('rename_diagram').setData(diagram) self.session.action('remove_diagram').setData(diagram) self.session.action('diagram_properties').setData(diagram) menu.exec_(mouseEvent.screenPos().toPoint()) super().mouseReleaseEvent(mouseEvent)
def identify(self): """ Perform the node identification step for this Union node. Because this node can assume a Concept identity, whenever this node is being targeted by an Individual node using a Membership edge, we set the identity and move this node in the STRONG set. We'll also make sure to remove from the STRONG set the individual node used to compute the identity of this very node since Individual nodes do not contribute with inheritance to the computation of the final identity for all the WEAK nodes being examined during the identification process. :rtype: tuple """ f1 = lambda x: x.type() is Item.MembershipEdge f2 = lambda x: x.identity() is Identity.Individual incoming = self.incomingNodes(filter_on_edges=f1, filter_on_nodes=f2) if incoming: computed = Identity.Unknown identities = set(x.identity() for x in incoming) if len(identities ) == 1 and first(identities) is Identity.Individual: computed = Identity.Concept self.setIdentity(computed) return {self}, incoming, set() f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.identity() is Identity.Neutral and isinstance( x, HasKeyNode) outgoing = self.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2) if outgoing: self.setIdentity(Identity.Concept) return {self}, outgoing, set() return None
def test_action_cut(session): # GIVEN project = session.project diagram = session.mdi.activeDiagram() action = session.action('cut') iri = project.getIRI( 'http://www.dis.uniroma1.it/~graphol/test_project/hasParent') node = first(project.iriOccurrences(Item.RoleIRINode, iri, diagram)) num_items_in_project = len(project.items()) num_nodes_in_project = len(project.nodes()) num_edges_in_project = len(project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) # WHEN diagram.clearSelection() node.setSelected(True) action.trigger() # THEN assert num_nodes_in_diagram == len(diagram.nodes()) + 1 assert num_edges_in_diagram == len(diagram.edges()) + 3 assert num_items_in_project == len(project.items()) + 4 assert num_nodes_in_project == len(project.nodes()) + 1 assert num_edges_in_project == len(project.edges()) + 3 assert num_items_in_project == len(project.items(diagram)) + 4 assert num_nodes_in_project == len(project.nodes(diagram)) + 1 assert num_edges_in_project == len(project.edges(diagram)) + 3 assert len(project.iriOccurrences(Item.RoleIRINode, iri, diagram)) == 0 assert len(project.iriOccurrences(Item.RoleIRINode, iri)) == 0 assert not session.clipboard.empty() assert session.clipboard.size() == 1 assert not session.undostack.isClean()
def test_action_cut(self): # GIVEN diagram = self.session.mdi.activeDiagram() action = self.session.action('cut') node = first(self.project.predicates(Item.RoleNode, 'hasParent', diagram)) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) num_edges_in_project = len(self.project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) # WHEN diagram.clearSelection() node.setSelected(True) action.trigger() # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes()) + 1) self.assertEqual(num_edges_in_diagram, len(diagram.edges()) + 3) self.assertEqual(num_items_in_project, len(self.project.items()) + 4) self.assertEqual(num_nodes_in_project, len(self.project.nodes()) + 1) self.assertEqual(num_edges_in_project, len(self.project.edges()) + 3) self.assertEqual(num_items_in_project, len(self.project.items(diagram)) + 4) self.assertEqual(num_nodes_in_project, len(self.project.nodes(diagram)) + 1) self.assertEqual(num_edges_in_project, len(self.project.edges(diagram)) + 3) self.assertEmpty(self.project.predicates(Item.RoleNode, 'hasParent', diagram)) self.assertEmpty(self.project.predicates(Item.RoleNode, 'hasParent')) self.assertFalse(self.session.clipboard.empty()) self.assertEqual(self.session.clipboard.size(), 1) self.assertFalse(self.session.undostack.isClean())
def test_action_purge_role_node(session): # GIVEN project = session.project diagram = session.mdi.activeDiagram() action = session.action('purge') iri = project.getIRI( 'http://www.dis.uniroma1.it/~graphol/test_project/hasAncestor') node = first(project.iriOccurrences(Item.RoleIRINode, iri, diagram)) num_items_in_project = len(project.items()) num_nodes_in_project = len(project.nodes()) num_edges_in_project = len(project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) diagram.clearSelection() node.setSelected(True) # WHEN action.trigger() # THEN assert num_nodes_in_diagram == len(diagram.nodes()) + 3 assert num_edges_in_diagram == len(diagram.edges()) + 6 assert num_items_in_project == len(project.items()) + 9 assert num_nodes_in_project == len(project.nodes()) + 3 assert num_edges_in_project == len(project.edges()) + 6 assert num_items_in_project == len(project.items(diagram)) + 9 assert num_nodes_in_project == len(project.nodes(diagram)) + 3 assert num_edges_in_project == len(project.edges(diagram)) + 6 assert len(project.iriOccurrences(Item.RoleIRINode, iri, diagram)) == 0 assert len(project.iriOccurrences(Item.RoleIRINode, iri)) == 0 assert not session.undostack.isClean()
def test_action_cut(self): # GIVEN diagram = self.session.mdi.activeDiagram() action = self.session.action('cut') node = first( self.project.predicates(Item.RoleNode, 'hasParent', diagram)) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) num_edges_in_project = len(self.project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) # WHEN diagram.clearSelection() node.setSelected(True) action.trigger() # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes()) + 1) self.assertEqual(num_edges_in_diagram, len(diagram.edges()) + 3) self.assertEqual(num_items_in_project, len(self.project.items()) + 4) self.assertEqual(num_nodes_in_project, len(self.project.nodes()) + 1) self.assertEqual(num_edges_in_project, len(self.project.edges()) + 3) self.assertEqual(num_items_in_project, len(self.project.items(diagram)) + 4) self.assertEqual(num_nodes_in_project, len(self.project.nodes(diagram)) + 1) self.assertEqual(num_edges_in_project, len(self.project.edges(diagram)) + 3) self.assertEmpty( self.project.predicates(Item.RoleNode, 'hasParent', diagram)) self.assertEmpty(self.project.predicates(Item.RoleNode, 'hasParent')) self.assertFalse(self.session.clipboard.empty()) self.assertEqual(self.session.clipboard.size(), 1) self.assertFalse(self.session.undostack.isClean())
def test_action_delete_multiple_edges(self): # GIVEN diagram = self.session.mdi.activeDiagram() action = self.session.action('delete') node = first( self.project.predicates(Item.RoleNode, 'hasParent', diagram)) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) num_edges_in_project = len(self.project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) diagram.clearSelection() for edge in node.edges: edge.setSelected(True) # WHEN action.trigger() # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes())) self.assertEqual(num_edges_in_diagram, len(diagram.edges()) + 3) self.assertEqual(num_items_in_project, len(self.project.items()) + 3) self.assertEqual(num_nodes_in_project, len(self.project.nodes())) self.assertEqual(num_edges_in_project, len(self.project.edges()) + 3) self.assertEqual(num_items_in_project, len(self.project.items(diagram)) + 3) self.assertEqual(num_nodes_in_project, len(self.project.nodes(diagram))) self.assertEqual(num_edges_in_project, len(self.project.edges(diagram)) + 3) self.assertFalse(self.session.undostack.isClean())
def isRestrictionQualified(self): """ Returna True if this node expresses a qualified restriction (exists R.C), False otherwise. :rtype: bool """ f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.identity() in {Identity.Concept, Identity.Role} f3 = lambda x: x.identity( ) in {Identity.Attribute, Identity.ValueDomain} f4 = lambda x: x.identity() is Identity.Concept if self.restriction() in { Restriction.Cardinality, Restriction.Exists, Restriction.Forall }: # CHECK FOR ROLE QUALIFIED RESTRICTION collection = self.incomingNodes(filter_on_edges=f1, filter_on_nodes=f2) if len(collection) >= 2: node = first(collection, filter_on_item=f4) if node and Special.valueOf(node.text()) is not Special.Top: return True # CHECK FOR ATTRIBUTE QUALIFIED RESTRICTION return len( self.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) >= 2 return False
def test_action_delete_multiple_edges(session): # GIVEN project = session.project diagram = session.mdi.activeDiagram() action = session.action('delete') iri = project.getIRI( 'http://www.dis.uniroma1.it/~graphol/test_project/hasParent') node = first(project.iriOccurrences(Item.RoleIRINode, iri, diagram)) num_items_in_project = len(project.items()) num_nodes_in_project = len(project.nodes()) num_edges_in_project = len(project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) diagram.clearSelection() for edge in node.edges: edge.setSelected(True) # WHEN action.trigger() # THEN assert num_nodes_in_diagram == len(diagram.nodes()) assert num_edges_in_diagram == len(diagram.edges()) + 3 assert num_items_in_project == len(project.items()) + 3 assert num_nodes_in_project == len(project.nodes()) assert num_edges_in_project == len(project.edges()) + 3 assert num_items_in_project == len(project.items(diagram)) + 3 assert num_nodes_in_project == len(project.nodes(diagram)) assert num_edges_in_project == len(project.edges(diagram)) + 3 assert not session.undostack.isClean()
def __init__(self, diagram, items): """ Initialize the command. :type diagram: Diagram :type items: T <= tuple|list|set """ self.diagram = diagram self.nodes = {item for item in items if item.isNode()} self.edges = {item for item in items if item.isEdge()} self.inputs = {n: { 'undo': n.inputs[:], 'redo': n.inputs[:], } for edge in self.edges \ if edge.type() is Item.InputEdge \ for n in {edge.source, edge.target} \ if n.type() in {Item.RoleChainNode, Item.PropertyAssertionNode} and \ n not in self.nodes} for node in self.inputs: for edge in node.edges: if edge.type() is Item.InputEdge and edge in self.edges and edge.target is node: self.inputs[node]['redo'].remove(edge.id) if len(items) == 1: name = 'remove {0}'.format(first(items).name) else: name = 'remove {0} items'.format(len(items)) super().__init__(name)
def test_action_delete_multiple_edges(self): # GIVEN diagram = self.session.mdi.activeDiagram() action = self.session.action('delete') node = first(self.project.predicates(Item.RoleNode, 'hasParent', diagram)) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) num_edges_in_project = len(self.project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) diagram.clearSelection() for edge in node.edges: edge.setSelected(True) # WHEN action.trigger() # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes())) self.assertEqual(num_edges_in_diagram, len(diagram.edges()) + 3) self.assertEqual(num_items_in_project, len(self.project.items()) + 3) self.assertEqual(num_nodes_in_project, len(self.project.nodes())) self.assertEqual(num_edges_in_project, len(self.project.edges()) + 3) self.assertEqual(num_items_in_project, len(self.project.items(diagram)) + 3) self.assertEqual(num_nodes_in_project, len(self.project.nodes(diagram))) self.assertEqual(num_edges_in_project, len(self.project.edges(diagram)) + 3) self.assertFalse(self.session.undostack.isClean())
def test_action_purge_role_node(self): # GIVEN diagram = self.session.mdi.activeDiagram() action = self.session.action('purge') node = first( self.project.predicates(Item.RoleNode, 'hasAncestor', diagram)) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) num_edges_in_project = len(self.project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) diagram.clearSelection() node.setSelected(True) # WHEN action.trigger() # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes()) + 3) self.assertEqual(num_edges_in_diagram, len(diagram.edges()) + 6) self.assertEqual(num_items_in_project, len(self.project.items()) + 9) self.assertEqual(num_nodes_in_project, len(self.project.nodes()) + 3) self.assertEqual(num_edges_in_project, len(self.project.edges()) + 6) self.assertEqual(num_items_in_project, len(self.project.items(diagram)) + 9) self.assertEqual(num_nodes_in_project, len(self.project.nodes(diagram)) + 3) self.assertEqual(num_edges_in_project, len(self.project.edges(diagram)) + 6) self.assertEmpty( self.project.predicates(Item.RoleNode, 'hasAncestor', diagram)) self.assertEmpty(self.project.predicates(Item.RoleNode, 'hasAncestor')) self.assertFalse(self.session.undostack.isClean())
def __init__(self, diagram, edges): """ Initialize the command. :type diagram: Diagram :type edges: T <= tuple|list|set """ self.diagram = diagram self.edges = edges self.inputs = {n: { 'undo': n.inputs[:], 'redo': n.inputs[:], } for edge in self.edges \ if edge.type() is Item.InputEdge \ for n in {edge.source, edge.target} \ if n.type() in {Item.RoleChainNode, Item.PropertyAssertionNode}} for edge in self.edges: if edge.type() is Item.InputEdge and edge.target in self.inputs: self.inputs[edge.target]['redo'].doRemoveNode(edge.id) for edge in self.edges: if edge.type() is Item.InputEdge and edge.source in self.inputs: self.inputs[edge.source]['redo'].append(edge.id) if len(edges) == 1: name = 'swap {0}'.format(first(edges).name) else: name = 'swap {0} edges'.format(len(edges)) super().__init__(name)
def buildDomainRestrictionNodeMenu(self, diagram, node): """ Build and return a QMenu instance for domain restriction nodes. :type diagram: Diagram :type node: DomainRestrictionNode :rtype: QMenu """ menu = self.buildGenericNodeMenu(diagram, node) menu.addSeparator() menu.insertMenu(self.session.action('node_properties'), self.session.menu('switch_restriction')) for action in self.session.action('switch_restriction').actions(): action.setChecked(node.type() is action.data()) action.setVisible(True) menu.insertMenu(self.session.action('node_properties'), self.session.menu('property_restriction')) f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.identity() is Identity.Attribute qualified = node.isRestrictionQualified() attribute = first( node.incomingNodes(filter_on_edges=f1, filter_on_nodes=f2)) for action in self.session.action('restriction').actions(): action.setChecked(node.restriction() is action.data()) action.setVisible(action.data() is not Restriction.Self or not qualified and not attribute) menu.insertSeparator(self.session.action('node_properties')) self.insertLabelActions(menu, node) menu.insertSeparator(self.session.action('node_properties')) return menu
def identify(self): """ Perform the node identification step for this Enumeration node. The identity of the node is calculated as follows: * If the node has Individuals as inputs => Identity == Concept * If the node has Values as inputs => Identity == ValueDomain After establishing the identity for this node, we remove all the nodes we used to compute such identity from the STRONG set and make sure this enumeration node is added to the STRONG set, so it will contribute to the computation of the final identity for all the WEAK nodes being examined during the identification process. :rtype: tuple """ f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.type() is Item.IndividualNode f3 = lambda x: Identity.Concept if x.identity( ) is Identity.Individual else Identity.ValueDomain inputs = self.incomingNodes(filter_on_edges=f1, filter_on_nodes=f2) identities = set(map(f3, inputs)) computed = Identity.Neutral if identities: computed = first(identities) if len(identities) > 1: computed = Identity.Unknown self.setIdentity(computed) strong_add = set() if self.identity() is not Identity.Neutral: strong_add.add(self) return strong_add, inputs, set()
def identify(self): """ Perform the node identification step for this Enumeration node. The identity of the node is calculated as follows: * If the node has Individuals as inputs => Identity == Concept * If the node has Values as inputs => Identity == ValueDomain After establishing the identity for this node, we remove all the nodes we used to compute such identity from the STRONG set and make sure this enumeration node is added to the STRONG set, so it will contribute to the computation of the final identity for all the WEAK nodes being examined during the identification process. :rtype: tuple """ f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.type() is Item.IndividualNode f3 = lambda x: Identity.Concept if x.identity() is Identity.Individual else Identity.ValueDomain inputs = self.incomingNodes(filter_on_edges=f1, filter_on_nodes=f2) identities = set(map(f3, inputs)) computed = Identity.Neutral if identities: computed = first(identities) if len(identities) > 1: computed = Identity.Unknown self.setIdentity(computed) strong_add = set() if self.identity() is not Identity.Neutral: strong_add.add(self) return strong_add, inputs, set()
def test_action_purge_role_node(self): # GIVEN diagram = self.session.mdi.activeDiagram() action = self.session.action('purge') node = first(self.project.predicates(Item.RoleNode, 'hasAncestor', diagram)) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) num_edges_in_project = len(self.project.edges()) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) diagram.clearSelection() node.setSelected(True) # WHEN action.trigger() # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes()) + 3) self.assertEqual(num_edges_in_diagram, len(diagram.edges()) + 6) self.assertEqual(num_items_in_project, len(self.project.items()) + 9) self.assertEqual(num_nodes_in_project, len(self.project.nodes()) + 3) self.assertEqual(num_edges_in_project, len(self.project.edges()) + 6) self.assertEqual(num_items_in_project, len(self.project.items(diagram)) + 9) self.assertEqual(num_nodes_in_project, len(self.project.nodes(diagram)) + 3) self.assertEqual(num_edges_in_project, len(self.project.edges(diagram)) + 6) self.assertEmpty(self.project.predicates(Item.RoleNode, 'hasAncestor', diagram)) self.assertEmpty(self.project.predicates(Item.RoleNode, 'hasAncestor')) self.assertFalse(self.session.undostack.isClean())
def buildDomainRestrictionNodeMenu(self, diagram, node): """ Build and return a QMenu instance for domain restriction nodes. :type diagram: Diagram :type node: DomainRestrictionNode :rtype: QMenu """ menu = self.buildGenericNodeMenu(diagram, node) menu.addSeparator() menu.insertMenu(self.session.action('node_properties'), self.session.menu('switch_restriction')) for action in self.session.action('switch_restriction').actions(): action.setChecked(node.type() is action.data()) action.setVisible(True) menu.insertMenu(self.session.action('node_properties'), self.session.menu('property_restriction')) f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.identity() is Identity.Attribute qualified = node.isRestrictionQualified() attribute = first(node.incomingNodes(filter_on_edges=f1, filter_on_nodes=f2)) for action in self.session.action('restriction').actions(): action.setChecked(node.restriction() is action.data()) action.setVisible(action.data() is not Restriction.Self or not qualified and not attribute) menu.insertSeparator(self.session.action('node_properties')) self.insertLabelActions(menu, node) menu.insertSeparator(self.session.action('node_properties')) return menu
def path(self): """ Returns the path to the the plugin (either a directory of a ZIP file). :rtype: str """ path = lstrip(inspect.getfile(self.__class__), expandPath('@plugins/'), expandPath('@home/plugins/')) home = first(filter(None, path.split(os.path.sep))) root = expandPath('@plugins/' if self.isBuiltIn() else '@home/plugins/') return os.path.join(root, home)
def test_action_cut_and_paste_multiple_predicate_nodes_on_the_same_diagram(self): # GIVEN diagram = self.session.mdi.activeDiagram() action_cut = self.session.action('cut') action_paste = self.session.action('paste') node1 = first(self.project.predicates(Item.RoleNode, 'hasParent', diagram)) node2 = first(self.project.predicates(Item.RoleNode, 'hasAncestor', diagram)) node3 = first(self.project.predicates(Item.RoleNode, 'hasFather', diagram)) node4 = first(self.project.predicates(Item.RoleNode, 'hasMother', diagram)) num_nodes_in_diagram = len(diagram.nodes()) num_edges_in_diagram = len(diagram.edges()) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) num_edges_in_project = len(self.project.edges()) diagram.clearSelection() node1.setSelected(True) node2.setSelected(True) node3.setSelected(True) node4.setSelected(True) # WHEN action_cut.trigger() action_paste.trigger() # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes())) self.assertEqual(num_edges_in_diagram, len(diagram.edges()) + 8) self.assertEqual(num_items_in_project, len(self.project.items()) + 8) self.assertEqual(num_nodes_in_project, len(self.project.nodes())) self.assertEqual(num_edges_in_project, len(self.project.edges()) + 8) self.assertEqual(num_items_in_project, len(self.project.items(diagram)) + 8) self.assertEqual(num_nodes_in_project, len(self.project.nodes(diagram))) self.assertEqual(num_edges_in_project, len(self.project.edges(diagram)) + 8) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasParent', diagram)) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasParent')) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasAncestor', diagram)) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasAncestor')) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasFather', diagram)) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasFather')) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasMother', diagram)) self.assertLen(1, self.project.predicates(Item.RoleNode, 'hasMother')) self.assertFalse(self.session.clipboard.empty()) self.assertEqual(self.session.clipboard.size(), 4) self.assertFalse(self.session.undostack.isClean())
def doOpenProject(self): """ Bring up a modal window used to open a project. """ dialog = QtWidgets.QFileDialog(self) dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptOpen) dialog.setDirectory(expandPath(self.workspace)) dialog.setFileMode(QtWidgets.QFileDialog.Directory) dialog.setOption(QtWidgets.QFileDialog.ShowDirsOnly, True) dialog.setViewMode(QtWidgets.QFileDialog.Detail) if dialog.exec_() == QtWidgets.QFileDialog.Accepted: self.sgnCreateSession.emit(expandPath(first(dialog.selectedFiles())))
def __init__(self, diagram, items): """ Initialize the command. :type diagram: Diagram :type items: T <= tuple|list|set """ self.items = items self.diagram = diagram self.selected = diagram.selectedItems() if len(items) == 1: name = 'add {0}'.format(first(items).name) else: name = 'add {0} items'.format(len(items)) super().__init__(name)
def test_insert_single_concept_node_with_control_modifier(self): # GIVEN view = self.session.mdi.activeView() diagram = self.session.mdi.activeDiagram() diagram.setMode(DiagramMode.NodeAdd, Item.ConceptNode) num_nodes_in_diagram = len(diagram.nodes()) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) node = first(self.project.predicates(Item.ConceptNode, 'Person', diagram)) position = view.mapFromScene(node.pos() - QtCore.QPointF(-200, 0)) # WHEN QtTest.QTest.mousePress(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.ControlModifier, position) # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes()) - 1) self.assertEqual(num_items_in_project, len(self.project.items()) - 1) self.assertEqual(num_nodes_in_project, len(self.project.nodes()) - 1) self.assertLen(1, self.project.predicates(Item.ConceptNode, 'concept'))
def choosePath(self): """ Bring up a modal window that allows the user to choose a valid workspace path. """ path = self.workspaceField.value() if not isPathValid(path): path = expandPath('~') dialog = QtWidgets.QFileDialog(self) dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptOpen) dialog.setDirectory(path) dialog.setFileMode(QtWidgets.QFileDialog.Directory) dialog.setOption(QtWidgets.QFileDialog.ShowDirsOnly, True) dialog.setViewMode(QtWidgets.QFileDialog.Detail) if dialog.exec_() == QtWidgets.QFileDialog.Accepted: self.workspaceField.setValue(first(dialog.selectedFiles()))
def cardinality(self, *args): """ Returns the cardinality of the node. :rtype: T <= int|dict """ cardinality = {'min': None, 'max': None} match = RE_CARDINALITY.match(self.text()) if match: if match.group('min') != '-': cardinality['min'] = int(match.group('min')) if match.group('max') != '-': cardinality['max'] = int(match.group('max')) if args: cardinality = {k:v for k, v in cardinality.items() if k in args} if len(cardinality) == 1: cardinality = first(cardinality.values()) return cardinality
def selectPlugin(self): """ Bring up a modal window that allows the user to choose a valid plugin archive. """ path = os.path.dirname(self.pluginField.value()) if not isPathValid(path): path = expandPath('~') dialog = QtWidgets.QFileDialog(self) dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptOpen) dialog.setDirectory(path) dialog.setFileMode(QtWidgets.QFileDialog.ExistingFile) dialog.setViewMode(QtWidgets.QFileDialog.Detail) dialog.setNameFilters([File.Zip.value]) if dialog.exec_() == QtWidgets.QFileDialog.Accepted: self.pluginField.setValue(first(dialog.selectedFiles())) self.confirmationBox.setEnabled(not isEmpty(self.pluginField.value()))
def mouseReleaseEvent(self, mouseEvent): """ Executed when the mouse is released from the tree view. :type mouseEvent: QMouseEvent """ if mouseEvent.button() == QtCore.Qt.RightButton: index = first(self.selectedIndexes()) if index: model = self.model().sourceModel() index = self.model().mapToSource(index) item = model.itemFromIndex(index) node = item.data() if node: self.widget.sgnItemRightClicked.emit(node) menu = self.session.mf.create(node.diagram, [node]) menu.exec_(mouseEvent.screenPos().toPoint()) super().mouseReleaseEvent(mouseEvent)
def identify(self): """ Perform the node identification step for this PropertyAssertion node. The identity of the node is calculated as follows: * If the node is targeting a Role with a membership edge => Identity == RoleInstance * If the node is targeting an Attribute with a membership edge => Identity == AttributeInstance else * If the node has 2 individuals as inputs => Identity == RoleInstance * If the node has 1 individual and 1 value as inputs => Identity == AttributeInstance In both the cases, whether we establish or not an idendity for this node, we mark it for EXCLUSION from the STRONG and WEAK sets. This is due to the PropertyAssertion node being used to perform assertions at ABox level while every other node in the graph is used at TBox level. Additionally we discard the inputs of this node from the STRONG set because they are either Individual or Value nodes and they are not needed to compute the final identity for all the WEAK nodes being examined during the identification process. :rtype: tuple """ f1 = lambda x: x.type() is Item.MembershipEdge f2 = lambda x: x.type() in {Item.RoleNode, Item.RoleInverseNode, Item.AttributeNode} f3 = lambda x: x.type() is Item.InputEdge f4 = lambda x: x.type() is Item.IndividualNode f5 = lambda x: Identity.RoleInstance if x.identity() is Identity.Role else Identity.AttributeInstance f6 = lambda x: x.identity() is Identity.Value outgoing = self.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2) incoming = self.incomingNodes(filter_on_edges=f3, filter_on_nodes=f4) computed = Identity.Neutral # 1) USE MEMBERSHIP EDGE identities = set(map(f5, outgoing)) if identities: computed = first(identities) if len(identities) > 1: computed = Identity.Unknown # 2) USE INPUT EDGES if computed is Identity.Neutral and len(incoming) >= 2: computed = Identity.RoleInstance if sum(map(f6, incoming)): computed = Identity.AttributeInstance self.setIdentity(computed) return set(), incoming, {self}
def test_insert_multiple_concept_nodes_with_control_modifier_released_after_insertion(self): # GIVEN view = self.session.mdi.activeView() diagram = self.session.mdi.activeDiagram() diagram.setMode(DiagramMode.NodeAdd, Item.ConceptNode) num_nodes_in_diagram = len(diagram.nodes()) num_items_in_project = len(self.project.items()) num_nodes_in_project = len(self.project.nodes()) node = first(self.project.predicates(Item.ConceptNode, 'Person', diagram)) positions = (view.mapFromScene(node.pos() - QtCore.QPointF(-300, x)) for x in (0, +200, -200)) # WHEN for position in positions: QtTest.QTest.mousePress(view.viewport(), QtCore.Qt.LeftButton, QtCore.Qt.ControlModifier, position) QtTest.QTest.keyRelease(self.session, QtCore.Qt.Key_Control) # THEN self.assertEqual(num_nodes_in_diagram, len(diagram.nodes()) - 3) self.assertEqual(num_items_in_project, len(self.project.items()) - 3) self.assertEqual(num_nodes_in_project, len(self.project.nodes()) - 3) self.assertLen(3, self.project.predicates(Item.ConceptNode, 'concept'))
def isRestrictionQualified(self): """ Returna True if this node expresses a qualified restriction (exists R.C), False otherwise. :rtype: bool """ f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.identity() in {Identity.Concept, Identity.Role} f3 = lambda x: x.identity() in {Identity.Attribute, Identity.ValueDomain} f4 = lambda x: x.identity() is Identity.Concept if self.restriction() in {Restriction.Cardinality, Restriction.Exists, Restriction.Forall}: # CHECK FOR ROLE QUALIFIED RESTRICTION collection = self.incomingNodes(filter_on_edges=f1, filter_on_nodes=f2) if len(collection) >= 2: node = first(collection, filter_on_item=f4) if node and Special.forValue(node.text()) is not Special.Top: return True # CHECK FOR ATTRIBUTE QUALIFIED RESTRICTION return len(self.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) >= 2 return False