Exemple #1
0
class EditableNodeProperty(PredicateNodeProperty):
    """
    This class implements the property dialog for label editable predicate nodes.
    """
    def __init__(self, scene, node, parent=None):
        """
        Initialize the editable node properties dialog.
        :type scene: DiagramScene
        :type node: AbstractNode
        :type parent: QWidget
        """
        super().__init__(scene, node, parent)

        ################################################################################################################
        #                                                                                                              #
        #   LABEL TAB                                                                                                  #
        #                                                                                                              #
        ################################################################################################################

        self.labelWidget = QWidget()
        self.labelLayout = QFormLayout(self.labelWidget)

        self.textField = StringField(self.labelWidget)
        self.textField.setFixedWidth(300)
        self.textField.setValue(self.node.text())
        self.textField.setEnabled(self.node.label.editable)

        self.labelLayout.addRow('Text', self.textField)

        self.mainWidget.addTab(self.labelWidget, 'Label')

    ####################################################################################################################
    #                                                                                                                  #
    #   SLOTS                                                                                                          #
    #                                                                                                                  #
    ####################################################################################################################

    def completed(self, code):
        """
        Executed when the dialog is terminated.
        :type code: int
        """
        if code == QDialog.Accepted:
            super().completed(code)
            self.labelEdited()

    def labelEdited(self):
        """
        Change the label of the node.
        """
        data = self.textField.value().strip()
        data = data if not isEmpty(data) else self.node.label.template
        if self.node.text() != data:
            command = CommandNodeLabelChange(self.scene, self.node,
                                             self.node.text(), data)
            self.scene.undostack.push(command)
Exemple #2
0
class PredicateNodeProperty(NodeProperty):
    """
    This class implements the property dialog for predicate nodes.
    """
    def __init__(self, scene, node, parent=None):
        """
        Initialize the predicate node properties dialog.
        :type scene: DiagramScene
        :type node: AbstractNode
        :type parent: QWidget
        """
        super().__init__(scene, node, parent)

        meta = scene.meta.metaFor(node.item, node.text())

        self.urlField = StringField(self.generalWidget)
        self.urlField.setFixedWidth(300)
        self.urlField.setValue(meta.url)

        self.descriptionField = TextField(self.generalWidget)
        self.descriptionField.setFixedSize(300, 160)
        self.descriptionField.setValue(meta.description)

        self.generalLayout.addRow('URL', self.urlField)
        self.generalLayout.addRow('Description', self.descriptionField)

    ####################################################################################################################
    #                                                                                                                  #
    #   SLOTS                                                                                                          #
    #                                                                                                                  #
    ####################################################################################################################

    @pyqtSlot(int)
    def completed(self, code):
        """
        Executed when the dialog is terminated.
        :type code: int
        """
        if code == QDialog.Accepted:
            super().completed(code)
            self.metaDataChanged()

    def metaDataChanged(self):
        """
        Change the url and description of the node.
        """
        meta = self.scene.meta.metaFor(self.node.item, self.node.text())

        copy = meta.copy()
        copy.description = self.descriptionField.value()
        copy.url = self.urlField.value()

        if copy != meta:
            command = CommandNodeChangeMeta(self.scene, self.node, meta, copy)
            self.scene.undostack.push(command)
Exemple #3
0
class NewProjectDialog(QtWidgets.QDialog):
    """
    This class is used to display a modal window to enter new project specific data.
    """
    def __init__(self, parent=None):
        """
        Initialize the project dialog.
        :type parent: QWidget
        """
        super().__init__(parent)

        #############################################
        # FORM AREA
        #################################

        settings = QtCore.QSettings(ORGANIZATION, APPNAME)

        self.workspace = expandPath(
            settings.value('workspace/home', WORKSPACE, str))
        self.workspace = '{0}{1}'.format(rstrip(self.workspace, os.path.sep),
                                         os.path.sep)

        self.nameLabel = QtWidgets.QLabel(self)
        self.nameLabel.setFont(Font('Roboto', 12))
        self.nameLabel.setText('Name')
        self.nameField = StringField(self)
        self.nameField.setFont(Font('Roboto', 12))
        self.nameField.setMinimumWidth(400)
        self.nameField.setMaxLength(64)

        self.prefixLabel = QtWidgets.QLabel(self)
        self.prefixLabel.setFont(Font('Roboto', 12))
        self.prefixLabel.setText('Prefix')
        self.prefixField = StringField(self)
        self.prefixField.setFont(Font('Roboto', 12))
        self.prefixField.setMinimumWidth(400)

        self.iriLabel = QtWidgets.QLabel(self)
        self.iriLabel.setFont(Font('Roboto', 12))
        self.iriLabel.setText('IRI')
        self.iriField = StringField(self)
        self.iriField.setFont(Font('Roboto', 12))
        self.iriField.setMinimumWidth(400)

        connect(self.prefixField.textChanged, self.doAcceptForm)
        connect(self.iriField.textChanged, self.doAcceptForm)
        connect(self.nameField.textChanged, self.doAcceptForm)
        connect(self.nameField.textChanged, self.onNameFieldChanged)

        self.pathLabel = QtWidgets.QLabel(self)
        self.pathLabel.setFont(Font('Roboto', 12))
        self.pathLabel.setText('Location')
        self.pathField = StringField(self)
        self.pathField.setFont(Font('Roboto', 12))
        self.pathField.setMinimumWidth(400)
        self.pathField.setReadOnly(True)
        self.pathField.setFocusPolicy(QtCore.Qt.NoFocus)
        self.pathField.setValue(self.workspace)

        spacer = QtWidgets.QFrame()
        spacer.setFrameShape(QtWidgets.QFrame.HLine)
        spacer.setFrameShadow(QtWidgets.QFrame.Sunken)

        self.formWidget = QtWidgets.QWidget(self)
        self.formLayout = QtWidgets.QFormLayout(self.formWidget)
        self.formLayout.addRow(self.nameLabel, self.nameField)
        self.formLayout.addRow(self.prefixLabel, self.prefixField)
        self.formLayout.addRow(self.iriLabel, self.iriField)
        self.formLayout.addWidget(spacer)
        self.formLayout.addRow(self.pathLabel, self.pathField)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(
            QtCore.Qt.Horizontal, self)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)
        self.confirmationBox.setFont(Font('Roboto', 12))
        self.confirmationBox.button(
            QtWidgets.QDialogButtonBox.Ok).setEnabled(False)

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.caption = QtWidgets.QLabel(self)
        self.caption.setFont(Font('Roboto', 12))
        self.caption.setContentsMargins(8, 0, 8, 0)
        self.caption.setProperty('class', 'invalid')
        self.caption.setVisible(False)

        self.gridLayout = QtWidgets.QVBoxLayout(self)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.addWidget(self.formWidget)
        self.gridLayout.addWidget(self.caption)
        self.gridLayout.addWidget(self.confirmationBox, 0,
                                  QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('New project')

        connect(self.confirmationBox.accepted, self.accept)
        connect(self.confirmationBox.rejected, self.reject)

    #############################################
    #   INTERFACE
    #################################

    def iri(self):
        """
        Returns the value of the iri field (trimmed).
        :rtype: str
        """
        return self.iriField.value()

    def name(self):
        """
        Returns the value of the name field (trimmed).
        :rtype: str
        """
        return self.nameField.value()

    def path(self):
        """
        Returns the value of the path field (expanded).
        :rtype: str
        """
        return expandPath(self.pathField.value())

    def prefix(self):
        """
        Returns the value of the prefix field (trimmed).
        :rtype: str
        """
        return self.prefixField.value()

    #############################################
    # SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Accept the project form and creates a new empty project.
        """
        project = Project(name=self.name(),
                          path=self.path(),
                          prefix=self.prefix(),
                          iri=self.iri(),
                          profile=OWL2Profile())
        worker = GrapholProjectExporter(project)
        worker.run()
        super().accept()

    @QtCore.pyqtSlot()
    def doAcceptForm(self):
        """
        Validate project settings.
        """
        caption = ''
        enabled = True

        #############################################
        # CHECK NAME
        #################################

        if not self.name():
            caption = ''
            enabled = False
        else:
            if isdir(self.path()):
                caption = "Project '{0}' already exists!".format(self.name())
                enabled = False
            elif not isPathValid(self.path()):
                caption = "'{0}' is not a valid project name!".format(
                    self.name())
                enabled = False

        #############################################
        # CHECK PREFIX
        #################################

        if enabled:
            if not self.prefix():
                caption = ''
                enabled = False

        #############################################
        # CHECK IRI
        #################################

        if enabled:
            if not self.iri():
                caption = ''
                enabled = False

        self.caption.setText(caption)
        self.caption.setVisible(not isEmpty(caption))
        self.confirmationBox.button(
            QtWidgets.QDialogButtonBox.Ok).setEnabled(enabled)
        self.setFixedSize(self.sizeHint())

    @QtCore.pyqtSlot(str)
    def onNameFieldChanged(self, name):
        """
        Update the project location field to reflect the new project name.
        :type name: str
        """
        self.pathField.setValue('{0}{1}'.format(self.workspace, name.strip()))
Exemple #4
0
class ValueNodeProperty(NodeProperty):
    """
    This class implements the property dialog for value nodes.
    """
    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)

        #############################################
        # VALUE TAB
        #################################

        self.datatypeLabel = QtWidgets.QLabel(self)
        self.datatypeLabel.setFont(Font('Roboto', 12))
        self.datatypeLabel.setText('Datatype')
        self.datatypeField = ComboBox(self)
        self.datatypeField.setFixedWidth(200)
        self.datatypeField.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.datatypeField.setFont(Font('Roboto', 12))

        for datatype in Datatype:
            self.datatypeField.addItem(datatype.value, datatype)
        datatype = self.node.datatype
        for i in range(self.datatypeField.count()):
            if self.datatypeField.itemData(i) is datatype:
                self.datatypeField.setCurrentIndex(i)
                break
        else:
            self.datatypeField.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.valueWidget = QtWidgets.QWidget()
        self.valueLayout = QtWidgets.QFormLayout(self.valueWidget)
        self.valueLayout.addRow(self.datatypeLabel, self.datatypeField)
        self.valueLayout.addRow(self.valueLabel, self.valueField)

        self.mainWidget.addTab(self.valueWidget, 'Datatype')

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def complete(self):
        """
        Executed when the dialog is accepted.
        """
        commands = [self.positionChanged(), self.valueChanged()]
        if any(commands):
            self.session.undostack.beginMacro('edit {0} properties'.format(
                self.node.name))
            for command in commands:
                if command:
                    self.session.undostack.push(command)
            self.session.undostack.endMacro()
        super().accept()

    #############################################
    #   AUXILIARY METHODS
    #################################

    def valueChanged(self):
        """
        Change the value of the node.
        :rtype: QUndoCommand
        """
        datatype = self.datatypeField.currentData()
        value = self.valueField.value()
        data = self.node.compose(value, datatype)
        if self.node.text() != data:
            return CommandLabelChange(self.diagram, self.node,
                                      self.node.text(), data)
        return None
Exemple #5
0
class PredicateNodeProperty(NodeProperty):
    """
    This class implements the property dialog for predicate nodes.
    Note that this dialog window is not used for value-domain nodes even though they are predicate nodes.
    """
    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)

        meta = diagram.project.meta(node.type(), node.text())

        self.urlLabel = QtWidgets.QLabel(self)
        self.urlLabel.setFont(Font('Roboto', 12))
        self.urlLabel.setText('URL')
        self.urlField = StringField(self)
        self.urlField.setFixedWidth(300)
        self.urlField.setFont(Font('Roboto', 12))
        self.urlField.setValue(meta.get(K_URL, ''))

        self.descriptionLabel = QtWidgets.QLabel(self)
        self.descriptionLabel.setFont(Font('Roboto', 12))
        self.descriptionLabel.setText('Description')
        self.descriptionField = TextField(self)
        self.descriptionField.setFixedSize(300, 160)
        self.descriptionField.setFont(Font('Roboto', 12))
        self.descriptionField.setValue(meta.get(K_DESCRIPTION, ''))

        self.generalLayout.addRow(self.urlLabel, self.urlField)
        self.generalLayout.addRow(self.descriptionLabel, self.descriptionField)

        #############################################
        # LABEL TAB
        #################################

        self.textLabel = QtWidgets.QLabel(self)
        self.textLabel.setFont(Font('Roboto', 12))
        self.textLabel.setText('Text')
        self.textField = StringField(self)
        self.textField.setFixedWidth(300)
        self.textField.setFont(Font('Roboto', 12))
        self.textField.setValue(self.node.text())

        self.refactorLabel = QtWidgets.QLabel(self)
        self.refactorLabel.setFont(Font('Roboto', 12))
        self.refactorLabel.setText('Refactor')
        self.refactorField = CheckBox(self)
        self.refactorField.setFont(Font('Roboto', 12))
        self.refactorField.setChecked(False)

        if node.type() in {
                Item.AttributeNode, Item.ConceptNode, Item.RoleNode
        }:
            if node.special() is not None:
                self.refactorField.setEnabled(False)

        self.labelWidget = QtWidgets.QWidget()
        self.labelLayout = QtWidgets.QFormLayout(self.labelWidget)
        self.labelLayout.addRow(self.textLabel, self.textField)
        self.labelLayout.addRow(self.refactorLabel, self.refactorField)

        self.mainWidget.addTab(self.labelWidget, 'Label')

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def complete(self):
        """
        Executed when the dialog is accepted.
        """
        commands = [self.positionChanged(), self.metaDataChanged()]
        commands.extend(self.textChanged())
        if any(commands):
            self.session.undostack.beginMacro('edit {0} properties'.format(
                self.node.name))
            for command in commands:
                if command:
                    self.session.undostack.push(command)
            self.session.undostack.endMacro()
        super().accept()

    #############################################
    #   AUXILIARY METHODS
    #################################

    def metaDataChanged(self):
        """
        Change the url and description of the node.
        :rtype: QUndoCommand
        """
        undo = self.diagram.project.meta(self.node.type(), self.node.text())
        redo = undo.copy()
        redo[K_DESCRIPTION] = self.descriptionField.value()
        redo[K_URL] = self.urlField.value()
        if redo != undo:
            return CommandNodeSetMeta(self.diagram.project, self.node.type(),
                                      self.node.text(), undo, redo)
        return None

    def textChanged(self):
        """
        Change the label of the node.
        :rtype: list
        """
        data = self.textField.value().strip()
        data = data if not isEmpty(data) else self.node.label.template
        if self.node.text() != data:
            if self.refactorField.isChecked():
                item = self.node.type()
                name = self.node.text()
                project = self.diagram.project
                return [
                    CommandLabelChange(n.diagram, n, n.text(), data)
                    for n in project.predicates(item, name)
                ]
            return [
                CommandLabelChange(self.diagram, self.node, self.node.text(),
                                   data)
            ]
        return [None]
Exemple #6
0
class ValueForm(QtWidgets.QDialog):
    """
    This class implements the form used to select the Value of an Individual node.
    """
    def __init__(self, node, session):
        """
        Initialize the form dialog.
        :type node: IndividualNode
        :type session: Session
        """
        super().__init__(session)

        self.node = node

        #############################################
        # FORM AREA
        #################################

        self.datatypeLabel = QtWidgets.QLabel(self)
        self.datatypeLabel.setText('Datatype')
        self.datatypeField = ComboBox(self)
        self.datatypeField.setFixedWidth(300)
        for datatype in sorted(Datatype.forProfile(
                self.project.profile.type()),
                               key=attrgetter('value')):
            self.datatypeField.addItem(datatype.value, datatype)

        self.valueLabel = QtWidgets.QLabel(self)
        self.valueLabel.setText('Value')
        self.valueField = StringField(self)
        self.valueField.setFixedWidth(300)

        if node.identity() is Identity.Value:
            self.valueField.setValue(node.value)
            datatype = node.datatype
            for i in range(self.datatypeField.count()):
                if self.datatypeField.itemData(i) is datatype:
                    self.datatypeField.setCurrentIndex(i)
                    break
        else:
            self.valueField.setValue('')
            self.datatypeField.setCurrentIndex(0)

        self.formWidget = QtWidgets.QWidget(self)
        self.formLayout = QtWidgets.QFormLayout(self.formWidget)
        self.formLayout.addRow(self.datatypeLabel, self.datatypeField)
        self.formLayout.addRow(self.valueLabel, self.valueField)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(
            QtCore.Qt.Horizontal, self)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.formWidget)
        self.mainLayout.addWidget(self.confirmationBox, 0,
                                  QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('Compose value')

        connect(self.confirmationBox.accepted, self.accept)
        connect(self.confirmationBox.rejected, self.reject)

    #############################################
    #   PROPERTIES
    #################################

    @property
    def project(self):
        """
        Returns the reference to the active project.
        :rtype: Project
        """
        return self.session.project

    @property
    def session(self):
        """
        Returns the reference to the active session (alias for RefactorNameForm.parent()).
        :rtype: Session
        """
        return self.parent()

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Accepts the form and set the new value.
        """
        # print('>>>          ValueForm (accept)')
        node = self.node
        diagram = node.diagram
        datatype = self.datatypeField.currentData()
        value = self.valueField.value()
        data = node.compose(value, datatype)

        if node.text() != data:
            name = 'change {0} to {1}'.format(node.text(), data)

            new_prefix = datatype.value[0:datatype.value.index(':')]
            new_remaining_characters = datatype.value[datatype.value.index(':'
                                                                           ) +
                                                      1:len(datatype.value)]
            new_iri = None

            for namespace in Namespace:
                if namespace.name.lower() == new_prefix:
                    new_iri = namespace.value

            if new_iri is None:
                LOGGER.error(
                    '*****************   failed to assign iri to node   *******************'
                )
                return

            Duplicate_dict_1 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                self.project.IRI_prefixes_nodes_dict, dict())
            Duplicate_dict_2 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                self.project.IRI_prefixes_nodes_dict, dict())

            old_iri = self.project.get_iri_of_node(node)

            Duplicate_dict_1[old_iri][1].remove(node)
            Duplicate_dict_1[new_iri][1].add(node)

            commands = []

            commands.append(
                CommandProjectDisconnectSpecificSignals(self.project))
            commands.append(
                CommandLabelChange(diagram, self.node, self.node.text(), data))
            commands.append(
                CommandNodeSetRemainingCharacters(node.remaining_characters,
                                                  new_remaining_characters,
                                                  node, self.project))
            commands.append(
                CommandLabelChange(diagram, self.node, self.node.text(), data))
            commands.append(CommandProjectConnectSpecificSignals(self.project))

            if any(commands):
                self.session.undostack.beginMacro(
                    'edit Forms >> accept() {0}'.format(node))
                for command in commands:
                    if command:
                        self.session.undostack.push(command)
                self.session.undostack.endMacro()

        super().accept()
Exemple #7
0
class FacetNodeProperty(NodeProperty):
    """
    This class implements the property dialog for facet nodes.
    """
    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.setText('Facet')
        self.facetField = ComboBox(self)
        self.facetField.setFixedWidth(200)
        self.facetField.setFocusPolicy(QtCore.Qt.StrongFocus)
        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.setText('Value')
        self.valueField = StringField(self)
        self.valueField.setFixedWidth(200)
        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')

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def complete(self):
        """
        Executed when the dialog is accepted.
        """
        commands = [self.positionChanged(), self.facetChanged()]
        if any(commands):
            self.session.undostack.beginMacro('edit {0} properties'.format(
                self.node.name))
            for command in commands:
                if command:
                    self.session.undostack.push(command)
            self.session.undostack.endMacro()
        super().accept()

    #############################################
    #   AUXILIARY METHODS
    #################################

    def facetChanged(self):
        """
        Change the facet value of the node of the node.
        :rtype: QUndoCommand
        """
        data = self.node.compose(self.facetField.currentData(),
                                 self.valueField.value())
        if self.node.text() != data:
            return CommandLabelChange(self.diagram, self.node,
                                      self.node.text(), data)
        return None
Exemple #8
0
class ValueNodeProperty(NodeProperty):
    """
    This class implements the property dialog for value nodes.
    """
    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)

        self.node = node

        #############################################
        # VALUE TAB
        #################################

        self.datatypeLabel = QtWidgets.QLabel(self)
        self.datatypeLabel.setText('Datatype')
        self.datatypeField = ComboBox(self)
        self.datatypeField.setFixedWidth(200)
        self.datatypeField.setFocusPolicy(QtCore.Qt.StrongFocus)

        for datatype in Datatype:
            self.datatypeField.addItem(datatype.value, datatype)
        datatype = self.node.datatype
        for i in range(self.datatypeField.count()):
            if self.datatypeField.itemData(i) is datatype:
                self.datatypeField.setCurrentIndex(i)
                break
        else:
            self.datatypeField.setCurrentIndex(0)

        self.valueLabel = QtWidgets.QLabel(self)
        self.valueLabel.setText('Value')
        self.valueField = StringField(self)
        self.valueField.setFixedWidth(200)
        self.valueField.setValue(self.node.value)

        self.valueWidget = QtWidgets.QWidget()
        self.valueLayout = QtWidgets.QFormLayout(self.valueWidget)
        self.valueLayout.addRow(self.datatypeLabel, self.datatypeField)
        self.valueLayout.addRow(self.valueLabel, self.valueField)

        self.mainWidget.addTab(self.valueWidget, 'Datatype')

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def complete(self):
        """
        Executed when the dialog is accepted.
        """
        commands = [self.positionChanged()]
        commands_value_changed = self.valueChanged()

        if commands_value_changed is not None:
            commands.extend(commands_value_changed)

        if any(commands):
            self.session.undostack.beginMacro('edit {0} properties'.format(
                self.node.name))
            for command in commands:
                if command:
                    self.session.undostack.push(command)
            self.session.undostack.endMacro()
        super().accept()

    #############################################
    #   AUXILIARY METHODS
    #################################

    def valueChanged(self):
        """
        Change the value of the node.
        :rtype: QUndoCommand
        """
        datatype = self.datatypeField.currentData()
        value = self.valueField.value()
        data = self.node.compose(value, datatype)
        if self.node.text() != data:
            new_prefix = datatype.value[0:datatype.value.index(':')]
            new_remaining_characters = datatype.value[datatype.value.index(':'
                                                                           ) +
                                                      1:len(datatype.value)]
            new_iri = None

            for namespace in Namespace:
                if namespace.name.lower() == new_prefix:
                    new_iri = namespace.value

            Duplicate_dict_1 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                self.project.IRI_prefixes_nodes_dict, dict())
            Duplicate_dict_2 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                self.project.IRI_prefixes_nodes_dict, dict())

            old_iri = self.project.get_iri_of_node(self.node)

            Duplicate_dict_1[old_iri][1].remove(self.node)
            Duplicate_dict_1[new_iri][1].add(self.node)

            commands = [
                CommandLabelChange(self.diagram, self.node, self.node.text(),
                                   data),
                CommandNodeSetRemainingCharacters(
                    self.node.remaining_characters, new_remaining_characters,
                    self.node, self.project),
                CommandLabelChange(self.diagram, self.node, self.node.text(),
                                   data)
            ]

            return commands

        return None
Exemple #9
0
class ValueNodeProperty(NodeProperty):
    """
    This class implements the property dialog for value nodes.
    """
    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)

        #############################################
        # VALUE TAB
        #################################

        self.datatypeLabel = QtWidgets.QLabel(self)
        self.datatypeLabel.setFont(Font('Roboto', 12))
        self.datatypeLabel.setText('Datatype')
        self.datatypeField = ComboBox(self)
        self.datatypeField.setFixedWidth(200)
        self.datatypeField.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.datatypeField.setFont(Font('Roboto', 12))

        for datatype in Datatype:
            self.datatypeField.addItem(datatype.value, datatype)
        datatype = self.node.datatype
        for i in range(self.datatypeField.count()):
            if self.datatypeField.itemData(i) is datatype:
                self.datatypeField.setCurrentIndex(i)
                break
        else:
            self.datatypeField.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.valueWidget = QtWidgets.QWidget()
        self.valueLayout = QtWidgets.QFormLayout(self.valueWidget)
        self.valueLayout.addRow(self.datatypeLabel, self.datatypeField)
        self.valueLayout.addRow(self.valueLabel, self.valueField)

        self.mainWidget.addTab(self.valueWidget, 'Datatype')

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def complete(self):
        """
        Executed when the dialog is accepted.
        """
        commands = [self.positionChanged(), self.valueChanged()]
        if any(commands):
            self.session.undostack.beginMacro('edit {0} properties'.format(self.node.name))
            for command in commands:
                if command:
                    self.session.undostack.push(command)
            self.session.undostack.endMacro()
        super().accept()

    #############################################
    #   AUXILIARY METHODS
    #################################

    def valueChanged(self):
        """
        Change the value of the node.
        :rtype: QUndoCommand
        """
        datatype = self.datatypeField.currentData()
        value = self.valueField.value()
        data = self.node.compose(value, datatype)
        if self.node.text() != data:
            return CommandLabelChange(self.diagram, self.node, self.node.text(), data)
        return None
Exemple #10
0
class FacetNodeProperty(NodeProperty):
    """
    This class implements the property dialog for facet nodes.
    """
    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')

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def complete(self):
        """
        Executed when the dialog is accepted.
        """
        commands = [self.positionChanged(), self.facetChanged()]
        if any(commands):
            self.session.undostack.beginMacro('edit {0} properties'.format(self.node.name))
            for command in commands:
                if command:
                    self.session.undostack.push(command)
            self.session.undostack.endMacro()
        super().accept()

    #############################################
    #   AUXILIARY METHODS
    #################################

    def facetChanged(self):
        """
        Change the facet value of the node of the node.
        :rtype: QUndoCommand
        """
        data = self.node.compose(self.facetField.currentData(), self.valueField.value())
        if self.node.text() != data:
            return CommandLabelChange(self.diagram, self.node, self.node.text(), data)
        return None
Exemple #11
0
class PredicateNodeProperty(NodeProperty):
    """
    This class implements the property dialog for predicate nodes.
    Note that this dialog window is not used for value-domain nodes even though they are predicate nodes.
    """
    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)

        meta = diagram.project.meta(node.type(), node.text())

        self.urlLabel = QtWidgets.QLabel(self)
        self.urlLabel.setFont(Font('Roboto', 12))
        self.urlLabel.setText('URL')
        self.urlField = StringField(self)
        self.urlField.setFixedWidth(300)
        self.urlField.setFont(Font('Roboto', 12))
        self.urlField.setValue(meta.get('url', ''))

        self.descriptionLabel = QtWidgets.QLabel(self)
        self.descriptionLabel.setFont(Font('Roboto', 12))
        self.descriptionLabel.setText('Description')
        self.descriptionField = TextField(self)
        self.descriptionField.setFixedSize(300, 160)
        self.descriptionField.setFont(Font('Roboto', 12))
        self.descriptionField.setValue(meta.get('description', ''))

        self.generalLayout.addRow(self.urlLabel, self.urlField)
        self.generalLayout.addRow(self.descriptionLabel, self.descriptionField)

        #############################################
        # LABEL TAB
        #################################

        self.textLabel = QtWidgets.QLabel(self)
        self.textLabel.setFont(Font('Roboto', 12))
        self.textLabel.setText('Text')
        self.textField = StringField(self)
        self.textField.setFixedWidth(300)
        self.textField.setFont(Font('Roboto', 12))
        self.textField.setValue(self.node.text())

        self.refactorLabel = QtWidgets.QLabel(self)
        self.refactorLabel.setFont(Font('Roboto', 12))
        self.refactorLabel.setText('Refactor')
        self.refactorField = CheckBox(self)
        self.refactorField.setFont(Font('Roboto', 12))
        self.refactorField.setChecked(False)

        if node.type() in {Item.AttributeNode, Item.ConceptNode, Item.RoleNode}:
            if node.special() is not None:
                self.refactorField.setEnabled(False)

        self.labelWidget = QtWidgets.QWidget()
        self.labelLayout = QtWidgets.QFormLayout(self.labelWidget)
        self.labelLayout.addRow(self.textLabel, self.textField)
        self.labelLayout.addRow(self.refactorLabel, self.refactorField)

        self.mainWidget.addTab(self.labelWidget, 'Label')

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def complete(self):
        """
        Executed when the dialog is accepted.
        """
        commands = [self.positionChanged(), self.metaDataChanged()]
        commands.extend(self.textChanged())
        if any(commands):
            self.session.undostack.beginMacro('edit {0} properties'.format(self.node.name))
            for command in commands:
                if command:
                    self.session.undostack.push(command)
            self.session.undostack.endMacro()
        super().accept()

    #############################################
    #   AUXILIARY METHODS
    #################################

    def metaDataChanged(self):
        """
        Change the url and description of the node.
        :rtype: QUndoCommand
        """
        meta = self.diagram.project.meta(self.node.type(), self.node.text())
        copy = meta.copy()
        copy['description'] = self.descriptionField.value()
        copy['url'] = self.urlField.value()
        if copy != meta:
            return CommandNodeChangeMeta(self.diagram, self.node, meta, copy)
        return None

    def textChanged(self):
        """
        Change the label of the node.
        :rtype: list
        """
        data = self.textField.value().strip()
        data = data if not isEmpty(data) else self.node.label.template
        if self.node.text() != data:
            if self.refactorField.isChecked():
                item = self.node.type()
                name = self.node.text()
                project = self.diagram.project
                return [CommandLabelChange(n.diagram, n, n.text(), data) for n in project.predicates(item, name)]
            return [CommandLabelChange(self.diagram, self.node, self.node.text(), data)]
        return [None]
Exemple #12
0
class ValueForm(QtWidgets.QDialog):
    """
    This class implements the form used to select the Value of an Individual node.
    """
    def __init__(self, node, session):
        """
        Initialize the form dialog.
        :type node: IndividualNode
        :type session: Session
        """
        super().__init__(session)

        self.node = node

        #############################################
        # FORM AREA
        #################################

        self.datatypeLabel = QtWidgets.QLabel(self)
        self.datatypeLabel.setFont(Font('Roboto', 12))
        self.datatypeLabel.setText('Datatype')
        self.datatypeField = ComboBox(self)
        self.datatypeField.setFont(Font('Roboto', 12))
        self.datatypeField.setFixedWidth(300)
        for datatype in sorted(Datatype.forProfile(
                self.project.profile.type()),
                               key=attrgetter('value')):
            self.datatypeField.addItem(datatype.value, datatype)

        self.valueLabel = QtWidgets.QLabel(self)
        self.valueLabel.setFont(Font('Roboto', 12))
        self.valueLabel.setText('Value')
        self.valueField = StringField(self)
        self.valueField.setFixedWidth(300)

        if node.identity() is Identity.Value:
            self.valueField.setValue(node.value)
            datatype = node.datatype
            for i in range(self.datatypeField.count()):
                if self.datatypeField.itemData(i) is datatype:
                    self.datatypeField.setCurrentIndex(i)
                    break
        else:
            self.valueField.setValue('')
            self.datatypeField.setCurrentIndex(0)

        self.formWidget = QtWidgets.QWidget(self)
        self.formLayout = QtWidgets.QFormLayout(self.formWidget)
        self.formLayout.addRow(self.datatypeLabel, self.datatypeField)
        self.formLayout.addRow(self.valueLabel, self.valueField)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(
            QtCore.Qt.Horizontal, self)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)
        self.confirmationBox.setFont(Font('Roboto', 12))

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.formWidget)
        self.mainLayout.addWidget(self.confirmationBox, 0,
                                  QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('Compose value')

        connect(self.confirmationBox.accepted, self.accept)
        connect(self.confirmationBox.rejected, self.reject)

    #############################################
    #   PROPERTIES
    #################################

    @property
    def project(self):
        """
        Returns the reference to the active project.
        :rtype: Project
        """
        return self.session.project

    @property
    def session(self):
        """
        Returns the reference to the active session (alias for RefactorNameForm.parent()).
        :rtype: Session
        """
        return self.parent()

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Accepts the form and set the new value.
        """
        node = self.node
        diagram = node.diagram
        datatype = self.datatypeField.currentData()
        value = self.valueField.value()
        data = node.compose(value, datatype)
        if node.text() != data:
            name = 'change {0} to {1}'.format(node.text(), data)
            self.session.undostack.push(
                CommandLabelChange(diagram, node, node.text(), data,
                                   name=name))
        super().accept()
Exemple #13
0
class RefactorNameForm(QtWidgets.QDialog):
    """
    This class implements the form used to rename nodes during refactor operations.
    """
    def __init__(self, node, session):
        """
        Initialize the form dialog.
        :type node: AbstractNode
        :type session: Session
        """
        super().__init__(session)

        self.node = node

        #############################################
        # FORM AREA
        #################################

        self.renameLabel = QtWidgets.QLabel(self)
        self.renameLabel.setFont(Font('Roboto', 12))
        self.renameLabel.setText('Name')
        self.renameField = StringField(self)
        self.renameField.setFixedWidth(200)
        self.renameField.setFont(Font('Roboto', 12))
        self.renameField.setValue(self.node.text())
        connect(self.renameField.textChanged, self.nameChanged)

        self.formWidget = QtWidgets.QWidget(self)
        self.formLayout = QtWidgets.QFormLayout(self.formWidget)
        self.formLayout.addRow(self.renameLabel, self.renameField)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(
            QtCore.Qt.Horizontal, self)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)
        self.confirmationBox.setFont(Font('Roboto', 12))

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.caption = QtWidgets.QLabel(self)
        self.caption.setFont(Font('Roboto', 12))
        self.caption.setContentsMargins(8, 0, 8, 0)
        self.caption.setProperty('class', 'invalid')
        self.caption.setVisible(False)

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.formWidget)
        self.mainLayout.addWidget(self.caption)
        self.mainLayout.addWidget(self.confirmationBox, 0,
                                  QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('Rename')

        connect(self.confirmationBox.accepted, self.accept)
        connect(self.confirmationBox.rejected, self.reject)

    #############################################
    #   PROPERTIES
    #################################

    @property
    def project(self):
        """
        Returns the reference to the active project.
        :rtype: Project
        """
        return self.session.project

    @property
    def session(self):
        """
        Returns the reference to the active session (alias for RefactorNameForm.parent()).
        :rtype: Session
        """
        return self.parent()

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Accepts the rename form and perform refactoring.
        """
        name = self.renameField.value()
        self.session.undostack.beginMacro(
            'change predicate "{0}" to "{1}"'.format(self.node.text(), name))
        for node in self.project.predicates(self.node.type(),
                                            self.node.text()):
            command = CommandLabelChange(node.diagram,
                                         node,
                                         node.text(),
                                         name,
                                         refactor=True)
            self.session.undostack.push(command)
        self.session.undostack.endMacro()
        super().accept()

    @QtCore.pyqtSlot()
    def nameChanged(self):
        """
        Executed whenever the text in the rename field changes.
        """
        caption = ''
        enabled = True

        if isEmpty(self.renameField.value()):
            caption = "\'{0}\' is not a valid predicate name".format(
                self.renameField.value())
            enabled = False

        self.caption.setText(caption)
        self.caption.setVisible(not isEmpty(caption))
        self.confirmationBox.button(
            QtWidgets.QDialogButtonBox.Ok).setEnabled(enabled)
        self.setFixedSize(self.sizeHint())
Exemple #14
0
class PluginInstallDialog(QtWidgets.QDialog):
    """
    Extends QtWidgets.QDialog providing an interface to install plugins.
    """
    def __init__(self, session):
        """
        Initialize the plugin install dialog.
        :type session: Session
        """
        super().__init__(session)

        #############################################
        # HEAD AREA
        #################################

        self.headTitle = QtWidgets.QLabel('Install a plugin', self)
        self.headTitle.setFont(Font('Roboto', 12, bold=True))
        self.headDescription = QtWidgets.QLabel(dedent("""
        Plugins are software components that add specific features to {0}.<br/>
        Please select the plugin you wish to install.""".format(APPNAME)), self)
        self.headDescription.setFont(Font('Roboto', 12))
        self.headPix = QtWidgets.QLabel(self)
        self.headPix.setPixmap(QtGui.QIcon(':/icons/48/ic_extension_black').pixmap(48))
        self.headPix.setContentsMargins(0, 0, 0, 0)
        self.headWidget = QtWidgets.QWidget(self)
        self.headWidget.setProperty('class', 'head')
        self.headWidget.setContentsMargins(10, 10, 10, 10)

        self.headLayoutL = QtWidgets.QVBoxLayout()
        self.headLayoutL.addWidget(self.headTitle)
        self.headLayoutL.addWidget(self.headDescription)
        self.headLayoutL.setContentsMargins(0, 0, 0, 0)
        self.headLayoutR = QtWidgets.QVBoxLayout()
        self.headLayoutR.addWidget(self.headPix, 0, QtCore.Qt.AlignRight)
        self.headLayoutR.setContentsMargins(0, 0, 0, 0)
        self.headLayoutM = QtWidgets.QHBoxLayout(self.headWidget)
        self.headLayoutM.addLayout(self.headLayoutL)
        self.headLayoutM.addLayout(self.headLayoutR)
        self.headLayoutM.setContentsMargins(0, 0, 0, 0)

        #############################################
        # SELECTION AREA
        #################################

        self.pluginField = StringField(self)
        self.pluginField.setFont(Font('Roboto', 12))
        self.pluginField.setFixedWidth(400)
        self.pluginField.setReadOnly(True)

        self.btnBrowse = QtWidgets.QPushButton(self)
        self.btnBrowse.setFont(Font('Roboto', 12))
        self.btnBrowse.setFixedWidth(30)
        self.btnBrowse.setText('...')

        self.editLayout = QtWidgets.QHBoxLayout()
        self.editLayout.setContentsMargins(10, 10, 10, 10)
        self.editLayout.addWidget(self.pluginField)
        self.editLayout.addWidget(self.btnBrowse)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok, self)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)
        self.confirmationBox.setEnabled(False)
        self.confirmationBox.setFont(Font('Roboto', 12))

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.headWidget)
        self.mainLayout.addLayout(self.editLayout)
        self.mainLayout.addWidget(self.confirmationBox, 0, QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('Install a plugin')

        connect(self.btnBrowse.clicked, self.selectPlugin)
        connect(self.confirmationBox.accepted, self.accept)

    #############################################
    #   PROPERTIES
    #################################

    @property
    def session(self):
        """
        Returns the reference to the main session (alias for PluginInstallDialog.parent()).
        :rtype: Session
        """
        return self.parent()

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Trigger the install of the selected plugin.
        """
        try:
            spec = self.session.pmanager.install(self.pluginField.value())
        except Exception as e:
            msgbox = QtWidgets.QMessageBox(self)
            msgbox.setIconPixmap(QtGui.QIcon(':/icons/48/ic_error_outline_black').pixmap(48))
            msgbox.setStandardButtons(QtWidgets.QMessageBox.Close)
            msgbox.setText('{0} could not install plugin archive <b>{1}</b>: {2}'.format(APPNAME, self.pluginField.value(), e))
            msgbox.setDetailedText(format_exception(e))
            msgbox.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
            msgbox.setWindowTitle('Plugin install failed!')
            msgbox.exec_()
        else:
            plugin_name = spec.get('plugin', 'name')
            plugin_version = spec.get('plugin', 'version')
            plugin_author = spec.get('plugin', 'author', fallback='<unknown>')
            message = dedent("""Successfully installed plugin <b>{0} v{1}</b> by <b>{2}</b>.
            Please reboot {3} for the plugin to work.""".format(plugin_name, plugin_version, plugin_author, APPNAME))
            msgbox = QtWidgets.QMessageBox(self)
            msgbox.setIconPixmap(QtGui.QIcon(':/icons/48/ic_done_black').pixmap(48))
            msgbox.setStandardButtons(QtWidgets.QMessageBox.Close)
            msgbox.setText(message)
            msgbox.setTextFormat(QtCore.Qt.RichText)
            msgbox.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
            msgbox.setWindowTitle('Plugin installed!')
            msgbox.exec_()
            super().accept()

    @QtCore.pyqtSlot()
    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()))
Exemple #15
0
class RefactorNameForm(QtWidgets.QDialog):
    """
    This class implements the form used to rename nodes during refactor operations.
    """
    def __init__(self, node, session):
        """
        Initialize the form dialog.
        :type node: AbstractNode
        :type session: Session
        """
        super().__init__(session)

        self.node = node

        #############################################
        # FORM AREA
        #################################

        self.renameLabel = QtWidgets.QLabel(self)
        self.renameLabel.setFont(Font('Roboto', 12))
        self.renameLabel.setText('Name')
        self.renameField = StringField(self)
        self.renameField.setFixedWidth(200)
        self.renameField.setFont(Font('Roboto', 12))
        self.renameField.setValue(self.node.text())
        connect(self.renameField.textChanged, self.nameChanged)

        self.formWidget = QtWidgets.QWidget(self)
        self.formLayout = QtWidgets.QFormLayout(self.formWidget)
        self.formLayout.addRow(self.renameLabel, self.renameField)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(QtCore.Qt.Horizontal, self)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)
        self.confirmationBox.setFont(Font('Roboto', 12))

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.caption = QtWidgets.QLabel(self)
        self.caption.setFont(Font('Roboto', 12))
        self.caption.setContentsMargins(8, 0, 8, 0)
        self.caption.setProperty('class', 'invalid')
        self.caption.setVisible(False)

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.formWidget)
        self.mainLayout.addWidget(self.caption)
        self.mainLayout.addWidget(self.confirmationBox, 0, QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('Rename')

        connect(self.confirmationBox.accepted, self.accept)
        connect(self.confirmationBox.rejected, self.reject)

    #############################################
    #   PROPERTIES
    #################################

    @property
    def project(self):
        """
        Returns the reference to the active project.
        :rtype: Project
        """
        return self.session.project

    @property
    def session(self):
        """
        Returns the reference to the active session (alias for RefactorNameForm.parent()).
        :rtype: Session
        """
        return self.parent()

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Accepts the rename form and perform refactoring.
        """
        name = self.renameField.value()
        self.session.undostack.beginMacro('change predicate "{0}" to "{1}"'.format(self.node.text(), name))
        for node in self.project.predicates(self.node.type(), self.node.text()):
            command = CommandLabelChange(node.diagram, node, node.text(), name, refactor=True)
            self.session.undostack.push(command)
        self.session.undostack.endMacro()
        super().accept()

    @QtCore.pyqtSlot()
    def nameChanged(self):
        """
        Executed whenever the text in the rename field changes.
        """
        caption = ''
        enabled = True

        if isEmpty(self.renameField.value()):
            caption = "\'{0}\' is not a valid predicate name".format(self.renameField.value())
            enabled = False

        self.caption.setText(caption)
        self.caption.setVisible(not isEmpty(caption))
        self.confirmationBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(enabled)
        self.setFixedSize(self.sizeHint())
Exemple #16
0
class ValueForm(QtWidgets.QDialog):
    """
    This class implements the form used to select the Value of an Individual node.
    """
    def __init__(self, node, session):
        """
        Initialize the form dialog.
        :type node: IndividualNode
        :type session: Session
        """
        super().__init__(session)

        self.node = node

        #############################################
        # FORM AREA
        #################################

        self.datatypeLabel = QtWidgets.QLabel(self)
        self.datatypeLabel.setFont(Font('Roboto', 12))
        self.datatypeLabel.setText('Datatype')
        self.datatypeField = ComboBox(self)
        self.datatypeField.setFont(Font('Roboto', 12))
        self.datatypeField.setFixedWidth(300)
        for datatype in sorted(Datatype.forProfile(self.project.profile.type()), key=attrgetter('value')):
            self.datatypeField.addItem(datatype.value, datatype)

        self.valueLabel = QtWidgets.QLabel(self)
        self.valueLabel.setFont(Font('Roboto', 12))
        self.valueLabel.setText('Value')
        self.valueField = StringField(self)
        self.valueField.setFixedWidth(300)

        if node.identity() is Identity.Value:
            self.valueField.setValue(node.value)
            datatype = node.datatype
            for i in range(self.datatypeField.count()):
                if self.datatypeField.itemData(i) is datatype:
                    self.datatypeField.setCurrentIndex(i)
                    break
        else:
            self.valueField.setValue('')
            self.datatypeField.setCurrentIndex(0)

        self.formWidget = QtWidgets.QWidget(self)
        self.formLayout = QtWidgets.QFormLayout(self.formWidget)
        self.formLayout.addRow(self.datatypeLabel, self.datatypeField)
        self.formLayout.addRow(self.valueLabel, self.valueField)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(QtCore.Qt.Horizontal, self)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)
        self.confirmationBox.setFont(Font('Roboto', 12))

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.formWidget)
        self.mainLayout.addWidget(self.confirmationBox, 0, QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('Compose value')

        connect(self.confirmationBox.accepted, self.accept)
        connect(self.confirmationBox.rejected, self.reject)

    #############################################
    #   PROPERTIES
    #################################

    @property
    def project(self):
        """
        Returns the reference to the active project.
        :rtype: Project
        """
        return self.session.project

    @property
    def session(self):
        """
        Returns the reference to the active session (alias for RefactorNameForm.parent()).
        :rtype: Session
        """
        return self.parent()

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Accepts the form and set the new value.
        """
        node = self.node
        diagram = node.diagram
        datatype = self.datatypeField.currentData()
        value = self.valueField.value()
        data = node.compose(value, datatype)
        if node.text() != data:
            name = 'change {0} to {1}'.format(node.text(), data)
            self.session.undostack.push(CommandLabelChange(diagram, node, node.text(), data, name=name))
        super().accept()
Exemple #17
0
class ProjectDialog(QtWidgets.QDialog):
    """
    This class is used to display a modal window to enter project specific data.
    """
    def __init__(self, parent=None):
        """
        Initialize the project dialog.
        :type parent: QtWidgets.QWidget
        """
        super().__init__(parent)

        #############################################
        # FORM AREA
        #################################

        settings = QtCore.QSettings(ORGANIZATION, APPNAME)

        self.workspace = expandPath(settings.value('workspace/home', WORKSPACE, str))
        self.workspace = '{0}{1}'.format(rstrip(self.workspace, os.path.sep), os.path.sep)

        self.nameLabel = QtWidgets.QLabel(self)
        self.nameLabel.setFont(Font('Roboto', 12))
        self.nameLabel.setText('Name')
        self.nameField = StringField(self)
        self.nameField.setFont(Font('Roboto', 12))
        self.nameField.setMinimumWidth(400)
        self.nameField.setMaxLength(64)
        connect(self.nameField.textChanged, self.onNameFieldChanged)

        self.prefixLabel = QtWidgets.QLabel(self)
        self.prefixLabel.setFont(Font('Roboto', 12))
        self.prefixLabel.setText('Prefix')
        self.prefixField = StringField(self)
        self.prefixField.setFont(Font('Roboto', 12))
        self.prefixField.setMinimumWidth(400)

        self.iriLabel = QtWidgets.QLabel(self)
        self.iriLabel.setFont(Font('Roboto', 12))
        self.iriLabel.setText('IRI')
        self.iriField = StringField(self)
        self.iriField.setFont(Font('Roboto', 12))
        self.iriField.setMinimumWidth(400)

        connect(self.iriField.textChanged, self.doProjectPathValidate)
        connect(self.nameField.textChanged, self.doProjectPathValidate)
        connect(self.prefixField.textChanged, self.doProjectPathValidate)

        self.pathLabel = QtWidgets.QLabel(self)
        self.pathLabel.setFont(Font('Roboto', 12))
        self.pathLabel.setText('Location')
        self.pathField = StringField(self)
        self.pathField.setFont(Font('Roboto', 12))
        self.pathField.setMinimumWidth(400)
        self.pathField.setReadOnly(True)
        self.pathField.setFocusPolicy(QtCore.Qt.NoFocus)
        self.pathField.setValue(self.workspace)

        spacer = QtWidgets.QFrame()
        spacer.setFrameShape(QtWidgets.QFrame.HLine)
        spacer.setFrameShadow(QtWidgets.QFrame.Sunken)

        self.formWidget = QtWidgets.QWidget(self)
        self.formLayout = QtWidgets.QFormLayout(self.formWidget)
        self.formLayout.addRow(self.nameLabel, self.nameField)
        self.formLayout.addRow(self.prefixLabel, self.prefixField)
        self.formLayout.addRow(self.iriLabel, self.iriField)
        self.formLayout.addWidget(spacer)
        self.formLayout.addRow(self.pathLabel, self.pathField)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(QtCore.Qt.Horizontal, self)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)
        self.confirmationBox.setFont(Font('Roboto', 12))
        self.confirmationBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False)

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.caption = QtWidgets.QLabel(self)
        self.caption.setFont(Font('Roboto', 12))
        self.caption.setContentsMargins(8, 0, 8, 0)
        self.caption.setProperty('class', 'invalid')
        self.caption.setVisible(False)

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.formWidget)
        self.mainLayout.addWidget(self.caption)
        self.mainLayout.addWidget(self.confirmationBox, 0, QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('New project')

        connect(self.confirmationBox.accepted, self.accept)
        connect(self.confirmationBox.rejected, self.reject)

    #############################################
    #   INTERFACE
    #################################

    def iri(self):
        """
        Returns the value of the iri field (trimmed).
        :rtype: str
        """
        return self.iriField.value()

    def path(self):
        """
        Returns the value of the path field (expanded).
        :rtype: str
        """
        return expandPath(self.pathField.value())

    def prefix(self):
        """
        Returns the value of the prefix field (trimmed).
        :rtype: str
        """
        return self.prefixField.value()

    #############################################
    # SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Accept the project form and creates a new empty project.
        """
        project = Project(self.path(), self.prefix(), self.iri(), OWL2Profile())
        worker = GrapholProjectExporter(project)
        worker.run()
        super().accept()

    @QtCore.pyqtSlot()
    def doProjectPathValidate(self):
        """
        Validate project settings.
        """
        caption = ''
        enabled = True

        #############################################
        # CHECK NAME
        #################################

        name = self.nameField.value()
        path = self.pathField.value()

        if not name:
            caption = ''
            enabled = False
        else:
            if isdir(path):
                caption = "Project '{0}' already exists!".format(name)
                enabled = False
            elif not isPathValid(path):
                caption = "'{0}' is not a valid project name!".format(name)
                enabled = False

        #############################################
        # CHECK PREFIX
        #################################

        if enabled:
            if not self.prefixField.value():
                caption = ''
                enabled = False

        #############################################
        # CHECK IRI
        #################################

        if enabled:
            if not self.iriField.value():
                caption = ''
                enabled = False

        self.caption.setText(caption)
        self.caption.setVisible(not isEmpty(caption))
        self.confirmationBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(enabled)
        self.setFixedSize(self.sizeHint())

    @QtCore.pyqtSlot(str)
    def onNameFieldChanged(self, name):
        """
        Update the project location field to reflect the new project name.
        :type name: str
        """
        self.pathField.setValue('{0}{1}'.format(self.workspace, name.strip()))
Exemple #18
0
class PredicateNodeProperty(NodeProperty):
    """
    This class implements the property dialog for predicate nodes.
    Note that this dialog window is not used for value-domain nodes even though they are predicate nodes.
    """
    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)

        meta = diagram.project.meta(node.type(), node.text())

        self.iriLabel = QtWidgets.QLabel(self)
        self.iriLabel.setText('IRI')
        self.iriField = StringField(self)
        self.iriField.setFixedWidth(300)

        self.iriField.setValue(self.diagram.project.get_iri_of_node(node))
        """
        self.iriversionLabel = QtWidgets.QLabel(self)
        self.iriversionLabel.setText('IRI version')
        self.iriversionField = StringField(self)
        self.iriversionField.setFixedWidth(300)

        self.iriversionField.setValue(self.node.IRI_version(diagram.project))
        """
        #############################################
        # LABEL TAB
        #################################

        self.textLabel = QtWidgets.QLabel(self)
        self.textLabel.setText('IRI Label')
        self.textField = StringField(self)
        self.textField.setFixedWidth(300)
        # if node.type() in {Item.AttributeNode, Item.ConceptNode, Item.RoleNode, Item.IndividualNode}:
        if (('AttributeNode' in str(type(node)))
                or ('ConceptNode' in str(type(node)))
                or ('IndividualNode' in str(type(node)))
                or ('RoleNode' in str(type(node)))):
            self.textField.setValue(self.node.remaining_characters)
        else:
            self.textField.setValue(self.node.text().replace('\n', ''))

        # if ((node.type() is Item.IndividualNode) and (node.identity() is Identity.Value)) or \
        if (('IndividualNode' in str(type(node))) and (node.identity() is Identity.Value)) or \
                (('IndividualNode' not in str(type(node))) and (node.special() is not None)):
            self.textField.setReadOnly(True)
            self.iriField.setReadOnly(True)

        self.refactorLabel = QtWidgets.QLabel(self)
        self.refactorLabel.setText('Refactor')
        self.refactorField = CheckBox(self)
        self.refactorField.setChecked(False)

        # if node.type() in {Item.AttributeNode, Item.ConceptNode, Item.RoleNode}:
        if (('AttributeNode' in str(type(node)))
                or ('ConceptNode' in str(type(node)))
                or ('RoleNode' in str(type(node)))):
            if node.special() is not None:
                self.refactorField.setEnabled(False)

        self.FulliriLabel = QtWidgets.QLabel(self)
        self.FulliriLabel.setText('Full IRI')
        self.FulliriField = StringField(self)
        self.FulliriField.setFixedWidth(300)
        full_iri = self.project.get_full_IRI(self.iriField.value(), None,
                                             self.textField.value().strip())
        self.FulliriField.setValue(full_iri)
        # self.FulliriField.setValue(self.iriField.value()+'#'+self.textField.value().strip())
        self.FulliriField.setReadOnly(True)

        self.labelWidget = QtWidgets.QWidget()
        self.labelLayout = QtWidgets.QFormLayout(self.labelWidget)
        self.labelLayout.addRow(self.iriLabel, self.iriField)
        self.labelLayout.addRow(self.textLabel, self.textField)
        self.labelLayout.addRow(self.FulliriLabel, self.FulliriField)
        self.labelLayout.addRow(self.refactorLabel, self.refactorField)

        self.mainWidget.addTab(self.labelWidget, 'IRI')

        self.metaDataChanged_ADD_OK_var = None
        self.metaDataChanged_REMOVE_OK_var = None
        self.metaDataChanged_IGNORE_var = None

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def complete(self):
        """
        Executed when the dialog is accepted.
        """
        commands = [self.positionChanged()]

        iri_changed_result = self.IRIChanged()

        if iri_changed_result is not None:
            if (str(type(iri_changed_result)) is
                    '<class \'str\'>') and ('Error in' in iri_changed_result):
                super().reject()
                return
            else:

                commands.extend(iri_changed_result)

        text_changed_result = self.textChanged()
        if text_changed_result is not None:
            commands.extend(text_changed_result)

        if any(commands):
            self.session.undostack.beginMacro('edit {0} properties'.format(
                self.node.name))
            for command in commands:
                if command:
                    self.session.undostack.push(command)
            self.session.undostack.endMacro()
        super().accept()

    #############################################
    #   AUXILIARY METHODS
    #################################
    def textChanged(self):

        unprocessed_new_text = self.textField.value().strip()
        unprocessed_new_text = unprocessed_new_text if not isEmpty(
            unprocessed_new_text) else self.node.label.template

        exception_list = ['-', '_', '.', '~', '\n']
        new_rc = ''

        flag = False

        for i, c in enumerate(unprocessed_new_text):
            if c == '':
                pass
            elif i < (len(unprocessed_new_text) - 1) and (
                    c == '\\' and unprocessed_new_text[i + 1] == 'n'):
                new_rc = new_rc + '\n'
            elif i > 0 and (c == 'n' and unprocessed_new_text[i - 1] == '\\'):
                pass
            elif (not c.isalnum()) and (c not in exception_list):
                new_rc = new_rc + '_'
                flag = True
            else:
                new_rc = new_rc + c

        # new_rc = new_rc.replace('\n','')

        if flag is True:
            self.session.statusBar().showMessage(
                'Spaces in between alphanumeric characters and special characters were replaced by an underscore character.',
                15000)

        return_list = []

        if (unprocessed_new_text != self.node.remaining_characters):

            # print('unprocessed_new_text',unprocessed_new_text)
            # print('self.node.remaining_characters',self.node.remaining_characters)
            # print(NewlineFeedInsensitive(new_rc, self.node.remaining_characters).result())

            return_list.append(
                CommandProjectDisconnectSpecificSignals(self.project))

            if self.refactorField.isChecked():
                for n in self.project.nodes():
                    if n.text() == self.node.text():
                        return_list.append(
                            CommandNodeSetRemainingCharacters(
                                n.remaining_characters,
                                new_rc,
                                n,
                                self.project,
                                refactor=True))
            else:
                # refactor_var = NewlineFeedInsensitive(new_rc, self.node.remaining_characters).result()

                # return_list.append(
                #        CommandNodeSetRemainingCharacters(self.node.remaining_characters, new_rc, self.node, self.project, refactor=refactor_var))
                return_list.append(
                    CommandNodeSetRemainingCharacters(
                        self.node.remaining_characters, new_rc, self.node,
                        self.project))

            return_list.append(
                CommandProjectConnectSpecificSignals(self.project))

            return return_list

        return None

    def IRIChanged(self):
        # Change the iri of the node.
        #:rtype: Command

        IRI_valid = self.project.check_validity_of_IRI(self.iriField.value())

        if IRI_valid is False:
            self.session.statusBar().showMessage('Invalid IRI.', 15000)
            return None
        else:

            old_iri = self.project.get_iri_of_node(self.node)
            new_iri = self.iriField.value()

            # if (self.iriField.value() != self.project.get_iri_of_node(node)) or (self.iriversionField.value() != self.node.IRI_version(self.project)):
            if new_iri != old_iri:
                connect(self.project.sgnIRINodeEntryAdded,
                        self.metaDataChanged_ADD_OK)
                connect(self.project.sgnIRINodeEntryRemoved,
                        self.metaDataChanged_REMOVE_OK)
                connect(self.project.sgnIRINodeEntryIgnored,
                        self.metaDataChanged_IGNORE)

                # check for conflict in prefixes
                # transaction = remove(old) + add(new)
                # perform transaction on duplicate dict.
                # if successful, original_dict = duplicate_dict
                # else duplicate_dict = original_dict

                Duplicate_dict_1 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                    self.project.IRI_prefixes_nodes_dict, dict())
                Duplicate_dict_2 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                    self.project.IRI_prefixes_nodes_dict, dict())

                list_of_nodes_to_process = []

                if self.refactorField.isChecked():
                    for n in self.project.nodes():
                        if (('AttributeNode' in str(type(n)))
                                or ('ConceptNode' in str(type(n)))
                                or ('IndividualNode' in str(type(n)))
                                or ('RoleNode' in str(type(n)))):

                            if (self.project.get_iri_of_node(n) == old_iri
                                ) and (n.remaining_characters
                                       == self.node.remaining_characters):
                                list_of_nodes_to_process.append(n)
                else:
                    list_of_nodes_to_process.append(self.node)

                commands = []

                for nd in list_of_nodes_to_process:

                    self.project.removeIRINodeEntry(Duplicate_dict_1, old_iri,
                                                    nd)
                    self.project.addIRINodeEntry(Duplicate_dict_1, new_iri, nd)

                    if (self.metaDataChanged_REMOVE_OK_var is True) and (
                            self.metaDataChanged_ADD_OK_var is True):
                        self.metaDataChanged_REMOVE_OK_var = False
                        self.metaDataChanged_ADD_OK_var = False
                        self.metaDataChanged_IGNORE_var = False
                    else:
                        LOGGER.warning(
                            'redo != undo but transaction was not executed correctly'
                        )
                        self.metaDataChanged_REMOVE_OK_var = False
                        self.metaDataChanged_ADD_OK_var = False
                        self.metaDataChanged_IGNORE_var = False
                        return str('Error in ' + str(nd))

                if len(Duplicate_dict_1[new_iri][0]) == 0:
                    ###
                    if 'display_in_widget' in Duplicate_dict_1[new_iri][2]:
                        new_label = ':' + self.node.remaining_characters
                    else:
                        new_label = self.project.get_full_IRI(
                            new_iri, None, self.node.remaining_characters)
                else:
                    new_label = str(Duplicate_dict_1[new_iri][0][
                        len(Duplicate_dict_1[new_iri][0]) - 1] + ':' +
                                    self.node.remaining_characters)

                commands.append(
                    CommandProjectDisconnectSpecificSignals(self.project))

                for nd in list_of_nodes_to_process:
                    commands.append(
                        CommandLabelChange(nd.diagram, nd, nd.text(),
                                           new_label))

                for nd in list_of_nodes_to_process:
                    commands.append(
                        CommandLabelChange(nd.diagram, nd, nd.text(),
                                           new_label))

                commands.append(
                    CommandProjectConnectSpecificSignals(self.project))

                return commands

            self.metaDataChanged_REMOVE_OK_var = False
            self.metaDataChanged_ADD_OK_var = False
            self.metaDataChanged_IGNORE_var = False

            return None

    @QtCore.pyqtSlot(str, str, str)
    def metaDataChanged_REMOVE_OK(self, iri, node, message):

        # print('metaDataChanged_REMOVE_OK -', iri, ',', node, ',', message)
        self.metaDataChanged_REMOVE_OK_var = True

    @QtCore.pyqtSlot(str, str, str)
    def metaDataChanged_ADD_OK(self, iri, node, message):

        # print('metaDataChanged_ADD_OK -', iri, ',', node, ',', message)
        self.metaDataChanged_ADD_OK_var = True

    @QtCore.pyqtSlot(str, str, str)
    def metaDataChanged_IGNORE(self, iri, node, message):

        # if node.id is None:
        # print('metaDataChanged_IGNORE >', iri, '-', 'None', '-', message)
        # else:
        # print('metaDataChanged_IGNORE >', iri, '-', node, '-', message)
        self.metaDataChanged_IGNORE_var = True
Exemple #19
0
class RenameForm(QDialog):
    """
    This class implements the form used to rename nodes during refactor operations.
    """
    def __init__(self, node, parent=None):
        """
        Initialize the form dialog.
        :type node: AbstractNode
        :type parent: QWidget
        """
        super().__init__(parent)
        self.node = node
        self.renameField = StringField(self)
        self.renameField.setFixedWidth(200)
        self.renameField.setValue(self.node.text())
        self.invalidName = QLabel('\'\' is not a valid predicate name', self)
        self.invalidName.setProperty('class', 'invalid')
        self.invalidName.setVisible(False)
        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        self.mainLayout = QFormLayout(self)
        self.mainLayout.addRow('Name', self.renameField)
        self.mainLayout.addRow(self.invalidName)
        self.mainLayout.addRow(self.buttonBox)
        self.setWindowTitle('Rename')
        self.setWindowIcon(QIcon(':/images/eddy'))
        self.setFixedSize(self.sizeHint())

        connect(self.buttonBox.accepted, self.validate)
        connect(self.buttonBox.rejected, self.reject)
        connect(self.renameField.textChanged, self.nameChanged)

    ####################################################################################################################
    #                                                                                                                  #
    #   SLOTS                                                                                                          #
    #                                                                                                                  #
    ####################################################################################################################

    @pyqtSlot()
    def nameChanged(self):
        """
        Executed whenever the text in the rename field changes.
        """
        button = self.buttonBox.button(QDialogButtonBox.Ok)
        empty = isEmpty(self.renameField.value())
        button.setDisabled(empty)
        self.invalidName.setVisible(empty)
        self.setFixedSize(self.sizeHint())

    @pyqtSlot()
    def validate(self):
        """
        Validate the form and trigger accept() if the form is valid.
        """
        if isEmpty(self.renameField.value()):
            msgbox = QMessageBox(self)
            msgbox.setIconPixmap(QPixmap(':/icons/warning'))
            msgbox.setWindowIcon(QIcon(':/images/eddy'))
            msgbox.setWindowTitle('Invalid predicate')
            msgbox.setText('You specified an invalid predicate name!')
            msgbox.setStandardButtons(QMessageBox.Ok)
            msgbox.exec_()
            return

        # This will strip out leading/trailing whitespaces.
        self.renameField.setValue(self.renameField.value())
        self.accept()
Exemple #20
0
class RefactorNameForm(QtWidgets.QDialog):
    """
    This class implements the form used to rename nodes during refactor operations.
    """
    def __init__(self, node, session):
        """
        Initialize the form dialog.
        :type node: AbstractNode
        :type session: Session
        """
        super().__init__(session)

        self.node = node

        #############################################
        # FORM AREA
        #################################

        self.renameLabel = QtWidgets.QLabel(self)
        self.renameLabel.setText('IRI label')
        self.renameField = StringField(self)
        self.renameField.setFixedWidth(200)
        self.renameLabel.setWordWrap(True)

        match = RE_VALUE.match(self.node.text())
        if match:
            self.renameField.setValue(self.node.text())

        else:
            self.renameField.setValue(self.node.remaining_characters)

        self.old_text = self.node.text()

        connect(self.renameField.textChanged, self.nameChanged)

        self.formWidget = QtWidgets.QWidget(self)
        self.formLayout = QtWidgets.QFormLayout(self.formWidget)
        self.formLayout.addRow(self.renameLabel, self.renameField)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(
            QtCore.Qt.Horizontal, self)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok)
        self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.caption = QtWidgets.QLabel(self)
        self.caption.setContentsMargins(8, 0, 8, 0)
        self.caption.setProperty('class', 'invalid')
        self.caption.setVisible(False)

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.formWidget)
        self.mainLayout.addWidget(self.caption)
        self.mainLayout.addWidget(self.confirmationBox, 0,
                                  QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('Rename')

        connect(self.confirmationBox.accepted, self.accept)
        connect(self.confirmationBox.rejected, self.reject)

    #############################################
    #   PROPERTIES
    #################################

    @property
    def project(self):
        """
        Returns the reference to the active project.
        :rtype: Project
        """
        return self.session.project

    @property
    def session(self):
        """
        Returns the reference to the active session (alias for RefactorNameForm.parent()).
        :rtype: Session
        """
        return self.parent()

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Accepts the rename form and perform refactoring.
        """
        currentData = self.renameField.value()

        if currentData and currentData != self.old_text:

            match = RE_VALUE.match(currentData)
            match_old = RE_VALUE.match(self.old_text)

            commands = []

            if match:
                new_prefix = match.group(
                    'datatype')[0:match.group('datatype').index(':')]
                new_remaining_characters = match.group(
                    'datatype')[match.group('datatype').index(':') +
                                1:len(match.group('datatype'))]
                new_iri = None

                for namespace in Namespace:
                    if namespace.name.lower() == new_prefix:
                        new_iri = namespace.value

                Duplicate_dict_1 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                    self.project.IRI_prefixes_nodes_dict, dict())
                Duplicate_dict_2 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                    self.project.IRI_prefixes_nodes_dict, dict())

                old_iri = self.project.get_iri_of_node(self.node)

                list_of_nodes_to_process = []

                commands_label_change_list_1 = []
                commands_label_change_list_2 = []
                commands_rc_change = []

                for node in self.project.predicates(self.node.type(),
                                                    self.node.text()):
                    list_of_nodes_to_process.append(node)

                    Duplicate_dict_1[old_iri][1].remove(node)
                    Duplicate_dict_1[new_iri][1].add(node)

                    commands_label_change_list_1.append(
                        CommandLabelChange(node.diagram,
                                           node,
                                           self.old_text,
                                           currentData,
                                           refactor=True))
                    commands_rc_change.append(
                        CommandNodeSetRemainingCharacters(
                            node.remaining_characters,
                            new_remaining_characters,
                            node,
                            self.project,
                            refactor=True))
                    commands_label_change_list_2.append(
                        CommandLabelChange(node.diagram,
                                           node,
                                           self.old_text,
                                           currentData,
                                           refactor=True))

                commands.append(
                    CommandProjectDisconnectSpecificSignals(self.project))

                commands.extend(commands_label_change_list_1)
                commands.extend(commands_rc_change)
                commands.extend(commands_label_change_list_2)

                commands.append(
                    CommandProjectConnectSpecificSignals(self.project))

            else:
                exception_list = ['-', '_', '.', '~', '\n']
                currentData_processed = ''
                flag = False

                for i, c in enumerate(currentData):
                    if c == '':
                        pass
                    elif i < (len(currentData) - 1) and (
                            c == '\\' and currentData[i + 1] == 'n'):
                        currentData_processed = currentData_processed + '\n'
                    elif i > 0 and (c == 'n' and currentData[i - 1] == '\\'):
                        pass
                    elif (not c.isalnum()) and (c not in exception_list):
                        currentData_processed = currentData_processed + '_'
                        flag = True
                    else:
                        currentData_processed = currentData_processed + c

                if flag is True:
                    self.session.statusBar().showMessage(
                        'Spaces in between alphanumeric characters and special characters were replaced by an '
                        'underscore character.', 15000)

                if match_old:
                    new_remaining_characters = currentData_processed
                    new_iri = self.project.ontologyIRIString

                    Duplicate_dict_1 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                        self.project.IRI_prefixes_nodes_dict, dict())
                    Duplicate_dict_2 = self.project.copy_IRI_prefixes_nodes_dictionaries(
                        self.project.IRI_prefixes_nodes_dict, dict())

                    old_iri = self.project.get_iri_of_node(self.node)

                    list_of_nodes_to_process = []

                    commands_label_change_list_1 = []
                    commands_label_change_list_2 = []
                    commands_rc_change = []

                    for node in self.project.predicates(
                            self.node.type(), self.node.text()):
                        list_of_nodes_to_process.append(node)

                        Duplicate_dict_1[old_iri][1].remove(node)
                        Duplicate_dict_1[new_iri][1].add(node)

                        if len(Duplicate_dict_1[new_iri][0]) == 0:
                            new_label = self.project.get_full_IRI(
                                new_iri, None, new_remaining_characters)
                        else:
                            new_label = str(Duplicate_dict_1[new_iri][0][
                                len(Duplicate_dict_1[new_iri][0]) - 1] + ':' +
                                            new_remaining_characters)

                        commands_label_change_list_1.append(
                            CommandLabelChange(node.diagram,
                                               node,
                                               self.old_text,
                                               new_label,
                                               refactor=True))
                        commands_rc_change.append(
                            CommandNodeSetRemainingCharacters(
                                node.remaining_characters,
                                new_remaining_characters,
                                node,
                                self.project,
                                refactor=True))
                        commands_label_change_list_2.append(
                            CommandLabelChange(node.diagram,
                                               node,
                                               self.old_text,
                                               new_label,
                                               refactor=True))

                    command_dict_change = CommandProjetSetIRIPrefixesNodesDict(
                        self.project, Duplicate_dict_2, Duplicate_dict_1,
                        [old_iri, new_iri], list_of_nodes_to_process)

                    commands.append(
                        CommandProjectDisconnectSpecificSignals(self.project))

                    commands.extend(commands_label_change_list_1)
                    commands.append(command_dict_change)
                    commands.extend(commands_rc_change)
                    commands.extend(commands_label_change_list_2)

                    commands.append(
                        CommandProjectConnectSpecificSignals(self.project))

                else:

                    commands.append(
                        CommandProjectDisconnectSpecificSignals(self.project))

                    for node in self.project.predicates(
                            self.node.type(), self.node.text()):
                        commands.append(
                            CommandNodeSetRemainingCharacters(
                                node.remaining_characters,
                                currentData_processed,
                                node,
                                self.project,
                                refactor=True))

                    commands.append(
                        CommandProjectConnectSpecificSignals(self.project))

            if any(commands):
                self.session.undostack.beginMacro(
                    'change predicate "{0}" to "{1}"'.format(
                        self.node.text(), currentData))
                for command in commands:
                    if command:
                        self.session.undostack.push(command)
                self.session.undostack.endMacro()

        else:
            pass

        super().accept()

    # not used
    @QtCore.pyqtSlot()
    def accept_2(self):
        """
        Accepts the rename form and perform refactoring.
        """
        name = self.renameField.value()
        self.session.undostack.beginMacro(
            'change predicate "{0}" to "{1}"'.format(self.node.text(), name))
        for node in self.project.predicates(self.node.type(),
                                            self.node.text()):
            command = CommandLabelChange(node.diagram,
                                         node,
                                         node.text(),
                                         name,
                                         refactor=True)
            self.session.undostack.push(command)
        self.session.undostack.endMacro()
        super().accept()

    @QtCore.pyqtSlot()
    def nameChanged(self):
        """
        Executed whenever the text in the rename field changes.
        """
        caption = ''
        enabled = True

        if isEmpty(self.renameField.value()):
            caption = "\'{0}\' is not a valid predicate name".format(
                self.renameField.value())
            enabled = False

        self.caption.setText(caption)
        self.caption.setVisible(not isEmpty(caption))
        self.confirmationBox.button(
            QtWidgets.QDialogButtonBox.Ok).setEnabled(enabled)
        self.setFixedSize(self.sizeHint())
Exemple #21
0
class WorkspaceDialog(QtWidgets.QDialog):
    """
    This class can be used to setup the workspace path.
    """
    def __init__(self, parent=None):
        """
        Initialize the workspace dialog.
        :type parent: QtWidgets.QWidget
        """
        super().__init__(parent)

        #############################################
        # HEAD AREA
        #################################

        self.headTitle = QtWidgets.QLabel('Select a workspace', self)
        self.headTitle.setFont(Font('Roboto', 12, bold=True))
        self.headDescription = QtWidgets.QLabel(dedent("""
        {0} stores your projects in a directory called workspace.<br/>
        Please choose a workspace directory to use.""".format(APPNAME)), self)
        self.headDescription.setFont(Font('Roboto', 12))
        self.headPix = QtWidgets.QLabel(self)
        self.headPix.setPixmap(QtGui.QIcon(':/icons/128/ic_eddy').pixmap(48))
        self.headPix.setContentsMargins(0, 0, 0, 0)
        self.headWidget = QtWidgets.QWidget(self)
        self.headWidget.setProperty('class', 'head')
        self.headWidget.setContentsMargins(10, 10, 10, 10)
        self.headLayoutL = QtWidgets.QVBoxLayout()
        self.headLayoutL.addWidget(self.headTitle)
        self.headLayoutL.addWidget(self.headDescription)
        self.headLayoutL.setContentsMargins(0, 0, 0, 0)
        self.headLayoutR = QtWidgets.QVBoxLayout()
        self.headLayoutR.addWidget(self.headPix, 0, QtCore.Qt.AlignRight)
        self.headLayoutR.setContentsMargins(0, 0, 0, 0)
        self.headLayoutM = QtWidgets.QHBoxLayout(self.headWidget)
        self.headLayoutM.addLayout(self.headLayoutL)
        self.headLayoutM.addLayout(self.headLayoutR)
        self.headLayoutM.setContentsMargins(0, 0, 0, 0)

        #############################################
        # EDIT AREA
        #################################

        self.workspaceField = StringField(self)
        self.workspaceField.setFont(Font('Roboto', 12))
        self.workspaceField.setFixedWidth(400)
        self.workspaceField.setReadOnly(True)
        self.workspaceField.setText(expandPath(WORKSPACE))

        self.btnBrowse = QtWidgets.QPushButton(self)
        self.btnBrowse.setFont(Font('Roboto', 12))
        self.btnBrowse.setFixedWidth(30)
        self.btnBrowse.setText('...')

        self.editLayout = QtWidgets.QHBoxLayout()
        self.editLayout.setContentsMargins(10, 10, 10, 10)
        self.editLayout.addWidget(self.workspaceField)
        self.editLayout.addWidget(self.btnBrowse)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok, self)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)
        self.confirmationBox.setFont(Font('Roboto', 12))

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.headWidget)
        self.mainLayout.addLayout(self.editLayout)
        self.mainLayout.addWidget(self.confirmationBox, 0, QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('Configure workspace')

        connect(self.btnBrowse.clicked, self.choosePath)
        connect(self.confirmationBox.accepted, self.accept)

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Create Eddy workspace (if necessary).
        """
        path = self.workspaceField.value()

        try:
            mkdir(path)
        except Exception as e:
            msgbox = QtWidgets.QMessageBox(self)
            msgbox.setDetailedText(format_exception(e))
            msgbox.setIconPixmap(QtGui.QIcon(':/icons/48/ic_error_outline_black').pixmap(48))
            msgbox.setStandardButtons(QtWidgets.QMessageBox.Close)
            msgbox.setText('{0} could not create the specified workspace: {1}!'.format(APPNAME, path))
            msgbox.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
            msgbox.setWindowTitle('Workspace setup failed!')
            msgbox.exec_()
            super().reject()
        else:
            settings = QtCore.QSettings(ORGANIZATION, APPNAME)
            settings.setValue('workspace/home', path)
            settings.sync()
            super().accept()

    @QtCore.pyqtSlot()
    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()))
Exemple #22
0
class PluginInstallDialog(QtWidgets.QDialog):
    """
    Extends QtWidgets.QDialog providing an interface to install plugins.
    """
    def __init__(self, session):
        """
        Initialize the plugin install dialog.
        :type session: Session
        """
        super().__init__(session)

        #############################################
        # HEAD AREA
        #################################

        self.headTitle = QtWidgets.QLabel('Install a plugin', self)
        self.headTitle.setFont(Font('Roboto', 12, bold=True))
        self.headDescription = QtWidgets.QLabel(
            dedent("""
        Plugins are software components that add specific features to {0}.<br/>
        Please select the plugin you wish to install.""".format(APPNAME)),
            self)
        self.headDescription.setFont(Font('Roboto', 12))
        self.headPix = QtWidgets.QLabel(self)
        self.headPix.setPixmap(
            QtGui.QIcon(':/icons/48/ic_extension_black').pixmap(48))
        self.headPix.setContentsMargins(0, 0, 0, 0)
        self.headWidget = QtWidgets.QWidget(self)
        self.headWidget.setProperty('class', 'head')
        self.headWidget.setContentsMargins(10, 10, 10, 10)

        self.headLayoutL = QtWidgets.QVBoxLayout()
        self.headLayoutL.addWidget(self.headTitle)
        self.headLayoutL.addWidget(self.headDescription)
        self.headLayoutL.setContentsMargins(0, 0, 0, 0)
        self.headLayoutR = QtWidgets.QVBoxLayout()
        self.headLayoutR.addWidget(self.headPix, 0, QtCore.Qt.AlignRight)
        self.headLayoutR.setContentsMargins(0, 0, 0, 0)
        self.headLayoutM = QtWidgets.QHBoxLayout(self.headWidget)
        self.headLayoutM.addLayout(self.headLayoutL)
        self.headLayoutM.addLayout(self.headLayoutR)
        self.headLayoutM.setContentsMargins(0, 0, 0, 0)

        #############################################
        # SELECTION AREA
        #################################

        self.pluginField = StringField(self)
        self.pluginField.setFont(Font('Roboto', 12))
        self.pluginField.setFixedWidth(400)
        self.pluginField.setReadOnly(True)

        self.btnBrowse = QtWidgets.QPushButton(self)
        self.btnBrowse.setFont(Font('Roboto', 12))
        self.btnBrowse.setFixedWidth(30)
        self.btnBrowse.setText('...')

        self.editLayout = QtWidgets.QHBoxLayout()
        self.editLayout.setContentsMargins(10, 10, 10, 10)
        self.editLayout.addWidget(self.pluginField)
        self.editLayout.addWidget(self.btnBrowse)

        #############################################
        # CONFIRMATION AREA
        #################################

        self.confirmationBox = QtWidgets.QDialogButtonBox(
            QtWidgets.QDialogButtonBox.Ok, self)
        self.confirmationBox.setContentsMargins(10, 0, 10, 10)
        self.confirmationBox.setEnabled(False)
        self.confirmationBox.setFont(Font('Roboto', 12))

        #############################################
        # SETUP DIALOG LAYOUT
        #################################

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.headWidget)
        self.mainLayout.addLayout(self.editLayout)
        self.mainLayout.addWidget(self.confirmationBox, 0,
                                  QtCore.Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
        self.setWindowTitle('Install a plugin')

        connect(self.btnBrowse.clicked, self.selectPlugin)
        connect(self.confirmationBox.accepted, self.accept)

    #############################################
    #   PROPERTIES
    #################################

    @property
    def session(self):
        """
        Returns the reference to the main session (alias for PluginInstallDialog.parent()).
        :rtype: Session
        """
        return self.parent()

    #############################################
    #   SLOTS
    #################################

    @QtCore.pyqtSlot()
    def accept(self):
        """
        Trigger the install of the selected plugin.
        """
        try:
            spec = self.session.pmanager.install(self.pluginField.value())
        except Exception as e:
            msgbox = QtWidgets.QMessageBox(self)
            msgbox.setIconPixmap(
                QtGui.QIcon(':/icons/48/ic_error_outline_black').pixmap(48))
            msgbox.setStandardButtons(QtWidgets.QMessageBox.Close)
            msgbox.setText(
                '{0} could not install plugin archive <b>{1}</b>: {2}'.format(
                    APPNAME, self.pluginField.value(), e))
            msgbox.setDetailedText(format_exception(e))
            msgbox.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
            msgbox.setWindowTitle('Plugin install failed!')
            msgbox.exec_()
        else:
            plugin_name = spec.get('plugin', 'name')
            plugin_version = spec.get('plugin', 'version')
            plugin_author = spec.get('plugin', 'author', fallback='<unknown>')
            message = dedent(
                """Successfully installed plugin <b>{0} v{1}</b> by <b>{2}</b>.
            Please reboot {3} for the plugin to work.""".format(
                    plugin_name, plugin_version, plugin_author, APPNAME))
            msgbox = QtWidgets.QMessageBox(self)
            msgbox.setIconPixmap(
                QtGui.QIcon(':/icons/48/ic_done_black').pixmap(48))
            msgbox.setStandardButtons(QtWidgets.QMessageBox.Close)
            msgbox.setText(message)
            msgbox.setTextFormat(QtCore.Qt.RichText)
            msgbox.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy'))
            msgbox.setWindowTitle('Plugin installed!')
            msgbox.exec_()
            super().accept()

    @QtCore.pyqtSlot()
    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()))
Exemple #23
0
class OWLTranslationForm(QDialog):
    """
    This class implements the form used to perform Graphol -> OWL ontology translation.
    """
    def __init__(self, scene, filepath, parent=None):
        """
        Initialize the form dialog.
        :type scene: DiagramScene
        :type filepath: str
        :type parent: QWidget
        """
        super().__init__(parent)

        self.scene = scene
        self.filepath = filepath
        self.worker = None
        self.workerThread = None

        self.iriField = StringField(self)
        self.iriField.setFixedWidth(300)
        self.iriField.setValidator(QRegExpValidator(QRegExp('[\w:\/\[\]=?%#~\.\-\+]*'), self))

        self.prefixField = StringField(self)
        self.prefixField.setFixedWidth(300)
        self.prefixField.setValidator(QRegExpValidator(QRegExp('[\w]*'), self))

        self.syntaxField = ComboBox(self)
        for syntax in OWLSyntax:
            self.syntaxField.addItem(syntax.value, syntax)
        self.syntaxField.setCurrentIndex(0)

        self.progressBar = QProgressBar(self)
        self.progressBar.setAlignment(Qt.AlignHCenter)
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(0)

        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        self.buttonBox.button(QDialogButtonBox.Ok).setDisabled(True)

        self.mainLayout = QFormLayout(self)
        self.mainLayout.addRow('IRI', self.iriField)
        self.mainLayout.addRow('Prefix', self.prefixField)
        self.mainLayout.addRow('Syntax', self.syntaxField)
        self.mainLayout.addRow(self.progressBar)
        self.mainLayout.addRow(self.buttonBox)

        self.setWindowTitle('OWL Translation')
        self.setWindowIcon(QIcon(':/images/eddy'))
        self.setFixedSize(self.sizeHint())

        connect(self.buttonBox.accepted, self.run)
        connect(self.buttonBox.rejected, self.reject)
        connect(self.iriField.textChanged, self.iriChanged)

    ####################################################################################################################
    #                                                                                                                  #
    #   SLOTS                                                                                                          #
    #                                                                                                                  #
    ####################################################################################################################

    @pyqtSlot(Exception)
    def errored(self, exception):
        """
        Executed whenever the translation errors.
        :type exception: Exception
        """
        if isinstance(exception, MalformedDiagramError):

            msgbox = QMessageBox(self)
            msgbox.setIconPixmap(QPixmap(':/icons/warning'))
            msgbox.setWindowIcon(QIcon(':/images/eddy'))
            msgbox.setWindowTitle('Malformed Diagram')
            msgbox.setText('Malformed expression detected on {}: {}'.format(exception.item, exception))
            msgbox.setInformativeText('Do you want to see the error in the diagram?')
            msgbox.setStandardButtons(QMessageBox.Yes|QMessageBox.No)
            S = QSpacerItem(400, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
            L = msgbox.layout()
            L.addItem(S, L.rowCount(), 0, 1, L.columnCount())
            msgbox.exec_()

            if msgbox.result() == QMessageBox.Yes:
                for view in self.scene.views():
                    if isinstance(view, MainView):
                        view.centerOn(exception.item)

        else:

            msgbox = QMessageBox(self)
            msgbox.setIconPixmap(QPixmap(':/icons/error'))
            msgbox.setWindowIcon(QIcon(':/images/eddy'))
            msgbox.setWindowTitle('Unhandled exception!')
            msgbox.setStandardButtons(QMessageBox.Close)
            msgbox.setText('Diagram translation could not be completed!')
            msgbox.setInformativeText('Please <a href="{}">submit a bug report</a> with detailed information.'.format(BUG_TRACKER))
            msgbox.setDetailedText(''.join(traceback.format_exception(type(exception), exception, exception.__traceback__)))
            S = QSpacerItem(400, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
            L = msgbox.layout()
            L.addItem(S, L.rowCount(), 0, 1, L.columnCount())
            msgbox.exec_()

        self.workerThread.quit()
        self.reject()

    @pyqtSlot()
    def completed(self):
        """
        Executed whenever the translation completes.
        """
        self.workerThread.quit()

        file = File(path=self.filepath)
        file.write(string=self.worker.export(syntax=self.syntaxField.currentData()))

        msgbox = QMessageBox(self)
        msgbox.setIconPixmap(QPixmap(':/icons/info'))
        msgbox.setWindowIcon(QIcon(':/images/eddy'))
        msgbox.setText('Translation completed!')
        msgbox.setInformativeText('Do you want to open the OWL ontology?')
        msgbox.setStandardButtons(QMessageBox.Yes|QMessageBox.No)
        S = QSpacerItem(400, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
        L = msgbox.layout()
        L.addItem(S, L.rowCount(), 0, 1, L.columnCount())
        msgbox.exec_()

        if msgbox.result() == QMessageBox.Yes:
            openPath(self.filepath)

        self.accept()

    @pyqtSlot(int, int)
    def progress(self, current, total):
        """
        Update the progress bar showing the translation advancement.
        :type current: int
        :type total: int
        """
        self.progressBar.setRange(0, total)
        self.progressBar.setValue(current)

    @pyqtSlot()
    def iriChanged(self):
        """
        Executed whenever the value of the prefix field changes.
        """
        button = self.buttonBox.button(QDialogButtonBox.Ok)
        button.setEnabled(not isEmpty(self.iriField.value()))

    @pyqtSlot()
    def run(self):
        """
        Perform the Graphol -> OWL translation in a separate thread.
        """
        ontoIRI = self.iriField.value()
        ontoPrefix = self.prefixField.value()

        self.buttonBox.setEnabled(False)
        self.syntaxField.setEnabled(False)

        if not ontoIRI.endswith('#'):
            ontoIRI = '{0}#'.format(ontoIRI)

        self.workerThread = QThread()
        self.worker = OWLExporter(scene=self.scene, ontoIRI=ontoIRI, ontoPrefix=ontoPrefix)
        self.worker.moveToThread(self.workerThread)

        connect(self.worker.completed, self.completed)
        connect(self.worker.errored, self.errored)
        connect(self.worker.progress, self.progress)
        connect(self.workerThread.started, self.worker.work)

        self.workerThread.start()