Пример #1
0
    def P07(self, obj, event):  # LEFTMOUSEPRESSED + MOUSERELEASED
        self.redrawSelectedItems()
        self.redrawNodes()

        item = self.itemAt(event.scenePos())
        if self.scene.currentItem != None:
            self.scene.currentItem = None
            self.deselect_all()
            try:
                item.setSelected(True)
                self.scene.currentItem = item
            except:
                pass

        if self.scene.selectedItems():
            self.state = ITEMSELECTED
        else:
            self.state = IDLE

        item = self.findOutPortAt(event.scenePos())
        if isinstance(item, OutPort):
            self.scene.DgmToUndo()
            self.state = DRAWFROMOUTPORT
            self.conn = Connection(None, self.scene)
            self.conn.port1 = item
            self.conn.pos1 = item.scenePos()
            self.conn.pos2 = item.scenePos()
Пример #2
0
    def addConn(self):
        self.scene.DgmToUndo()
        c = self.scene.item
        posMouse = self.gridPos(self.scene.evpos)
        self.conn = Connection(None, self.scene)
        self.conn.port1 = c.port1
        self.conn.pos1 = c.pos1

        try:
            npos, pos = self.find_exact_pos(c, posMouse)
        except:
            return
        N = len(c.connPoints)

        if npos == 0:
            pos = posMouse
            npt = 0
        elif npos == N:
            pos = posMouse
            npt = N
        else:
            npt = npos

        for n in range(0, npt):
            self.conn.connPoints.append(c.connPoints[n])
        self.conn.connPoints.append(pos)
        self.state = DRAWFROMOUTPORT
Пример #3
0
 def P11(self, obj, event):
     item = self.itemAt(event.scenePos())
     if isinstance(item, Node):
         self.scene.DmgToUndo()
         self.state = DRAWFROMOUTPORT
         #self.scene.mainw.status.showMessage('DRAWFROMOUTPORT')
         self.conn = Connection(None, self.scene)
         self.conn.port1 = item.port_out
         self.conn.pos1 = item.scenePos()
         self.conn.pos2 = item.scenePos()
Пример #4
0
 def newConn(self):
     self.scene.DgmToUndo()
     if not self.conn:
         self.insertConnection(self.event)
         item = self.lastNode
         self.scene.DgmToUndo()
         self.state = DRAWFROMOUTPORT
         self.scene.mainw.status.showMessage('DRAWFROMOUTPORT')
         self.conn = Connection(None, self.scene)
         self.conn.port1 = item.port_out
         self.conn.pos1 = item.scenePos()
         self.conn.pos2 = item.scenePos()
     else:
         self.scene.clearLastUndo()
Пример #5
0
    def P08(self, obj, event):
        item = self.itemAt(event.scenePos())
        if isinstance(item, InPort):
            if len(item.connections) == 0:
                self.scene.DgmToUndo()
                self.conn.port2 = item
                self.conn.pos2 = item.scenePos()
                self.conn.port1.connections.append(self.conn)
                self.conn.port2.connections.append(self.conn)
                if isinstance(self.conn.port1, OutPort):
                    pos = QtCore.QPointF(
                        (self.conn.pos2.x() + self.conn.pos1.x()) / 2,
                        self.conn.pos1.y())
                    self.newNode(self.conn, pos)

                self.conn.update_path()
                self.conn = None
                self.state = IDLE
                #self.scene.mainw.status.showMessage('IDLE')

        if isinstance(item, Node):
            if item.port_in.connections == []:
                self.scene.DgmToUndo()
                self.conn.port2 = item.port_in
                self.conn.pos2 = item.scenePos()
                self.conn.port1.connections.append(self.conn)
                self.conn.port2.connections.append(self.conn)  # Problema qui!

                self.conn.update_path()
                self.conn = None
                self.state = IDLE
                #self.scene.mainw.status.showMessage('IDLE')

        if item == None:
            pt = self.genInterPoint(event.scenePos())
            b = Node(None, self.scene)
            b.setPos(pt)
            self.conn.port2 = b.port_in
            self.conn.pos2 = b.scenePos()
            self.conn.port1.connections.append(self.conn)
            self.conn.port2.connections.append(self.conn)
            self.conn.update_path()

            self.conn = Connection(None, self.scene)
            self.conn.port1 = b.port_out
            self.conn.pos1 = b.scenePos()
            self.conn.pos2 = b.scenePos()
Пример #6
0
 def connectionInsertNode(self, conn, pos):
     newnode = self.createNode(pos)
     p = conn.port[1]
     conn.attach(1, newnode)
     conn.update_path()
     newconn = Connection(None, self.scene)
     newconn.attach(0, newnode)
     newconn.attach(1, p)
     newconn.update_path()
     return newconn
Пример #7
0
    def pasteAct(self):
        if self.scene.selection != []:
            block_tr = dict()
            port_tr = dict()
            conn_list = []
            dx, dy = 100, 100
            for item in self.scene.selection:
                newitem = None
                if isinstance(item, Block):
                    b = item.clone(QtCore.QPointF(dx, dy))
                    b.setSelected(True)
                    block_tr[item.label.text()] = b
                elif isConnection(item):
                    conn_list.append(item)
                elif isPort(item, 'pin') or isPort(item, 'node'):
                    newitem = Port(None, self.scene)
                    port_tr[item] = newitem
                elif isComment(item):
                    newitem = Comment('')
                    self.scene.addItem(newitem)
#                else:
#                    print ('skipping paste of ', item.toData())

                item.setSelected(False)
                if newitem:
                    data = item.toData()
                    data['x'] += dx
                    data['y'] += dy
                    newitem.fromData(data)
                    newitem.setSelected(True)

            for c in conn_list:
                data = c.toData()
                conn = Connection(None, scene=self.scene)
                conn.pos[0] = QtCore.QPointF(data['x0'] + dx, data['y0'] + dy)
                conn.pos[1] = QtCore.QPointF(data['x1'] + dx, data['y1'] + dy)
                for ix, p in [(0, 'p0'), (1, 'p1')]:
                    if p in data:  # translate blocknames
                        (blkname, pinname) = data[p]  # update to new blockname
                        if blkname in block_tr:
                            b = block_tr[blkname]
                            conn.attach(ix, b.ports(retDict=True)[pinname])
                    elif c.port[ix]:
                        port = c.port[ix]
                        if port in port_tr:
                            conn.port[ix] = port_tr[port]
                conn.update_path()
Пример #8
0
    def recreateBlock(self, item, scene=None):
        if scene is None:
            scene = self.scene
        pp = dict()
        for port in item.ports():
            portname = port.label.text()
            pp[portname] = []
            for c in port.connections:
                if c.port[0] == port and c.port[1] != port:
                    pp[portname].append((0, c.port[1]))
                elif c.port[0] != port and c.port[1] == port:
                    pp[portname].append((1, c.port[0]))

        data = item.toData()  # store blk
        item.remove()  # also removes connections

        # recreate with new parameters
        par = item.parameters
        prop = item.properties
        b = getBlock(data['libname'],
                     data['blockname'],
                     scene=scene,
                     param=par,
                     properties=prop,
                     name=data['blockname'])
        b.fromData(data)
        b.setLabel()

        # restore connections to block
        for port in b.ports():
            portname = port.label.text()
            if portname in pp:
                for (ix, p) in pp[portname]:
                    if ix == 0:
                        c = Connection(None, scene, port)
                        c.attach(1, p)
                    else:
                        c = Connection(None, scene, p)
                        c.attach(1, port)
                    c.update_path()
Пример #9
0
 def loadConn(self, item):
     c = Connection(None, self)
     pt1 = QtCore.QPointF(float(item.findtext('pos1X')),
                          float(item.findtext('pos1Y')))
     pt2 = QtCore.QPointF(float(item.findtext('pos2X')),
                          float(item.findtext('pos2Y')))
     c.pos1 = pt1
     c.pos2 = pt2
     c.update_ports_from_pos()
Пример #10
0
    def P07(self, obj, event):
        item = self.itemAt(event.scenePos())
        if self.scene.currentItem != None:
            self.deselect_all()
            try:
                item.setSelected(True)
                self.scene.currentItem = item
            except:
                pass

        if self.scene.selectedItems():
            self.state = ITEMSELECTED
            #self.scene.mainw.status.showMessage('ITEMSELECTED')
        else:
            self.state = IDLE
            #self.scene.mainw.status.showMessage('IDLE')

        if isinstance(item, OutPort):
            self.scene.DgmToUndo()
            self.state = DRAWFROMOUTPORT
            #self.scene.mainw.status.showMessage('DRAWFROMOUTPORT')
            if len(item.connections) == 0:
                self.conn = Connection(None, self.scene)
                self.conn.port1 = item
                self.conn.pos1 = item.scenePos()
                self.conn.pos2 = item.scenePos()

        if isinstance(item, Node):
            self.scene.DgmToUndo()
            self.state = DRAWFROMOUTPORT
            #self.scene.mainw.status.showMessage('DRAWFROMOUTPORT')
            self.conn = Connection(None, self.scene)
            self.conn.port1 = item.port_out
            self.conn.pos1 = item.scenePos()
            self.conn.pos2 = item.scenePos()
        self.scene.updateDgm()
Пример #11
0
 def newNode(self, item, pos):
     port2 = item.port2
     pos2 = item.pos2
     c = Connection(None, self.scene)
     b = Node(None, self.scene)
     b.setPos(pos)
     self.lastNode = b
     item.port2.connections.remove(item)
     item.port2.connections.append(c)
     item.port2 = b.port_in
     item.port2.connections.append(item)
     item.pos2 = b.pos()
     c.port1 = b.port_out
     c.port2 = port2
     c.port1.connections.append(c)
     c.pos1 = b.pos()
     c.pos2 = pos2
     item.update_path()
     c.update_path()
     self.scene.isInsConn = False
     self.scene.isConnecting = True
Пример #12
0
 def bindNode(self):
     self.scene.DgmToUndo()
     item = self.scene.item
     if len(item.port_out.connections) == 1:
         c1 = item.port_in.connections[0]
         c2 = item.port_out.connections[0]
         c = Connection(None, self.scene)
         c.pos1 = c1.pos1
         c.pos2 = c2.pos2
         item.remove()
         c.update_ports_from_pos()
         if isinstance(c.port1, OutPort) and isinstance(c.port2, InPort):
             pos = QtCore.QPointF((c.pos2.x() + c.pos1.x()) / 2, c.pos1.y())
             self.newNode(c, pos)
     else:
         self.scene.clearLastUndo()
Пример #13
0
 def connectionNext(self, pos):
     newnode = self.createNode(pos)
     self.conn.update_path(newnode)  # last point
     self.conn = Connection(None, self.scene, newnode)  #new Connection
Пример #14
0
 def connectionStart(self, p):
     self.conn = Connection(None, self.scene, p)
Пример #15
0
class Editor(QtCore.QObject):
    """ Editor to handles events"""
    def __init__(self, parent):
        super(Editor, self).__init__(parent)
        self.conn = None
        self.move = None
        self.scene = None
        self.status = parent.status
        self.movBlk = False
        self.event = None
        self.connFromNode = False

        self.menuIOBlk = QtWidgets.QMenu()
        #parBlkAction = self.menuIOBlk.addAction('Block I/Os')
        paramsBlkAction = self.menuIOBlk.addAction('Parameters')
        propertiesBlkAction = self.menuIOBlk.addAction('Properties')
        flpBlkAction = self.menuIOBlk.addAction('Flip')
        nameBlkAction = self.menuIOBlk.addAction('Change Name')
        cloneBlkAction = self.menuIOBlk.addAction('Clone Block')
        deleteBlkAction = self.menuIOBlk.addAction('Delete Block')
        #        self.netlistMenu = QtWidgets.QMenu('Netlist')
        #        self.menuIOBlk.addMenu(self.netlistMenu)
        #        netListAction = self.menuIOBlk.addAction('Netlist')

        #parBlkAction.triggered.connect(self.parBlock)
        flpBlkAction.triggered.connect(self.flipBlock)
        nameBlkAction.triggered.connect(self.nameBlock)
        paramsBlkAction.triggered.connect(self.blockParams)
        propertiesBlkAction.triggered.connect(self.blockProperties)
        cloneBlkAction.triggered.connect(self.cloneBlock)
        deleteBlkAction.triggered.connect(self.deleteBlock)
        #        netListAction.triggered.connect(self.netList)

        self.subMenuPort = QtWidgets.QMenu()
        portEditAction = self.subMenuPort.addAction('Edit')
        portFlipAction = self.subMenuPort.addAction('Flip')
        portDelAction = self.subMenuPort.addAction('Delete')
        portTypeAction = self.subMenuPort.addAction('Add/Edit signal type')
        portEditAction.triggered.connect(self.portEdit)
        portFlipAction.triggered.connect(self.flipBlock)
        portDelAction.triggered.connect(self.portDelete)
        portTypeAction.triggered.connect(self.portAddType)

        self.subMenuConn = QtWidgets.QMenu()
        connDelAction = self.subMenuConn.addAction('Delete connection')
        connInsAction = self.subMenuConn.addAction('Insert node')
        connLabelAction = self.subMenuConn.addAction('Add/Edit label')
        connDelAction.triggered.connect(self.deleteConn)
        connInsAction.triggered.connect(self.insConn)
        connLabelAction.triggered.connect(self.addConnLabel)

        self.subMenuText = QtWidgets.QMenu()
        textCloneAction = self.subMenuText.addAction('Clone')
        textCloneAction.triggered.connect(self.cloneText)

        self.subMenuNothing = QtWidgets.QMenu(
        )  # right mouse menu when nothing on pos
        nodeInsAction = self.subMenuNothing.addAction('Insert node')
        nodeInsAction.triggered.connect(self.createNode)

    def addConnLabel(self):
        conn = self.scene.item
        if conn.label:
            dialog = textLineDialog('Label: ', content=conn.label.text())
        else:
            dialog = textLineDialog('Label: ')
        ret = dialog.getLabel()
        if ret:
            if conn.label:
                conn.label.setText(ret)
            else:
                conn.label = textItem(ret, anchor=3, parent=conn)
                conn.label.setPos(conn.pos2.x(), conn.pos2.y())

    def cloneBlock(self):
        item = self.scene.item
        b = item.clone(QtCore.QPointF(100, 100))
        #        b.name = self.scene.setUniqueName(b)
        b.setup()

    def cloneText(self):
        item = self.scene.item
        c = Comment('')
        c.fromData(item.toData())
        c.setPos(c.pos() + QtCore.QPointF(100, 100))
        self.scene.addItem(c)

    def deleteBlock(self):
        item = self.scene.item
        item.remove()

    def portDelete(self):
        self.scene.item.remove()

    def deleteConn(self):
        self.scene.item.remove()

    def flipBlock(self):
        item = self.scene.item
        item.flip = not item.flip
        item.setFlip()

    def insConn(self):
        if not self.conn:
            self.insertConnection(self.event)

    def install(self, scene):
        scene.installEventFilter(self)
        self.scene = scene

    def itemAt(self, pos, exclude=[], single=True):
        items = []
        radius = 4 * DB / self.parent().view.currentscale
        allitems = self.scene.items(
            QtCore.QRectF(pos - QtCore.QPointF(radius, radius),
                          QtCore.QSizeF(2 * radius, 2 * radius)))
        for item in allitems:
            if isinstance(item, QtWidgets.QGraphicsItem):
                items.append(item)
                for testfunc in exclude:
                    if testfunc(item):
                        items.pop()  # remove
                        break
            if single and items:
                return items[0]
        return items

    def sortedItemsAt(self, pos):
        blocks, ports, nodes, connections, labels = [], [], [], [], []
        radius = 4 * DB / self.parent().view.currentscale
        allitems = self.scene.items(
            QtCore.QRectF(pos - QtCore.QPointF(radius, radius),
                          QtCore.QSizeF(2 * radius, 2 * radius)))
        for item in allitems:
            for cat, test in [(blocks, isBlock), (nodes, isNode),
                              (connections, isConnection),
                              (labels, isTextItem)]:
                if test(item):
                    cat.append(item)
                elif isPort(item):  # all ports except nodes
                    ports.append(item)
        return blocks, ports, nodes, connections, labels

    def ConnectionAt(self, pos):
        return self.itemAt(pos, exclude=[isNode, isPort, isBlock], single=True)

    def nameBlock(self):
        item = self.scene.item
        dialog = BlockName_Dialog(self.scene.mainw)
        dialog.name.setText(item.name)
        res = dialog.exec_()
        if res == 1:
            #            item.name = str(dialog.name.text())
            item.setLabel(dialog.name.text())
#            item.label.setNormal()
#            w = item.label.boundingRect().width()
#            item.label.setPos(-w/2, item.h/2+5)

        self.scene.isInsConn = False
        self.scene.isConnecting = True

    def netList(self, type):
        try:
            item = self.scene.item
            fname = 'libraries.library_{}.{}'.format(item.libname,
                                                     item.blockname)
            exec('import ' + fname)
            func = eval(fname + '.netlist' + type)
            func(item)

        except:
            if type == 'myhdl':
                item = self.scene.item

                if item.hasDiagram():
                    views = libraries.getViews(item.blockname, item.libname)
                    fname = 'libraries/library_{}/{}_myhdl.py'.format(
                        item.libname, item.blockname)
                    overwrite = True
                    if 'myhdl' in views:
                        dialog = overWriteNetlist()
                        ret = dialog.exec_()
                        if ret == 0:
                            fname = views['myhdl']
                        else:
                            overwrite = False
                    if overwrite:
                        import supsisim.netlist
                        content = supsisim.netlist.netlistMyHdl(
                            item.blockname, item.libname, item.properties)
                        if content == False:
                            error('More than 1 label on signal')
                            return
                        f = open(fname, 'w+')
                        f.write(content)
                        f.close()
                        if not 'myhdl' in views:
                            self.addView(item.blockname, item.libname, 'myhdl')
                        self.parent().library.openView('myhdl', item)
                else:
                    error("file doesn't have a diagram")
            else:
                error('netlist not found')

    def parBlock(self):
        self.scene.mainw.parBlock()

    def portAddType(self, event):
        item = self.scene.item
        if not isPort(item):
            error('use on nodes/pins')
            return
        if item.signalType:
            dialog = textLineDialog('Signal type: ', 'Signal type',
                                    item.signalType.text())
        else:
            dialog = textLineDialog('Signal type: ', 'Signal type')
        ret = dialog.getLabel()
        if ret:
            item.signalType = textItem(ret, anchor=8, parent=item)
            item.signalType.setBrush(colors['signalType'])
            font = item.signalType.font()
            font.setItalic(True)
            item.signalType.setFont(font)

#            item.signalType.setPos(item.pos2.x(),item.pos2.y())

    def portEdit(self):
        item = self.scene.item
        if not isPort(item):
            error('not a pin')
        dd = OrderedDict()
        dd['Pin_label'] = item.label.text() if item.label else ''

        options = 'ipin opin iopin node'.split()
        dd['Pin_type'] = (item.porttype, options)
        properties = item.properties
        title = 'Edit Node' if isNode(item) else 'Edit Pin'
        dialog = propertiesDialog(self.scene.mainw,
                                  dd,
                                  properties,
                                  title=title)
        dd = dialog.getRet()
        if dd:
            item.setType(dd.pop('Pin_type')[0])
            item.setLabel(dd.pop('Pin_label'))
            if dd:
                item.properties = dd
            item.setup()

    def blockProperties(self):
        item = self.scene.item
        dialog = propertiesDialog(self.scene.mainw,
                                  item.properties,
                                  addButton=False)
        dd = dialog.getRet()
        if dd:
            item.properties = dd
            self.recreateBlock(item)

    def recreateBlock(self, item, scene=None):
        if scene is None:
            scene = self.scene
        pp = dict()
        for port in item.ports():
            portname = port.label.text()
            pp[portname] = []
            for c in port.connections:
                if c.port[0] == port and c.port[1] != port:
                    pp[portname].append((0, c.port[1]))
                elif c.port[0] != port and c.port[1] == port:
                    pp[portname].append((1, c.port[0]))

        data = item.toData()  # store blk
        item.remove()  # also removes connections

        # recreate with new parameters
        par = item.parameters
        prop = item.properties
        b = getBlock(data['libname'],
                     data['blockname'],
                     scene=scene,
                     param=par,
                     properties=prop,
                     name=data['blockname'])
        b.fromData(data)
        b.setLabel()

        # restore connections to block
        for port in b.ports():
            portname = port.label.text()
            if portname in pp:
                for (ix, p) in pp[portname]:
                    if ix == 0:
                        c = Connection(None, scene, port)
                        c.attach(1, p)
                    else:
                        c = Connection(None, scene, p)
                        c.attach(1, port)
                    c.update_path()

    def blockParams(self):
        item = self.scene.item
        dialog = propertiesDialog(self.scene.mainw,
                                  item.parameters,
                                  addButton=False)
        ret = dialog.getRet()
        if ret:
            # store connections to ports
            item.parameters = ret  # apply new parameters (no effect)
            self.recreateBlock(item)

    def insertConnection(self, event):
        pos = gridPos(event.scenePos())
        item = self.ConnectionAt(pos)
        if item and isConnection(item):
            self.connectionInsertNode(item, pos)

    def createNode(self, pos=None):
        if not isinstance(pos, (QtCore.QPoint, QtCore.QPointF)):
            pos = gridPos(self.event.scenePos())
        newnode = Port(None, self.scene, porttype='node')
        newnode.setPos(pos)
        return newnode

    def connectionStart(self, p):
        self.conn = Connection(None, self.scene, p)

    def connectionNext(self, pos):
        newnode = self.createNode(pos)
        self.conn.update_path(newnode)  # last point
        self.conn = Connection(None, self.scene, newnode)  #new Connection

    def connectionFinish(self, port):
        self.conn.update_path(port)
        self.conn = None
        self.scene.mainw.view.setCursor(QtCore.Qt.ArrowCursor)
        self.scene.update()

    def connectionInsertNode(self, conn, pos):
        newnode = self.createNode(pos)
        p = conn.port[1]
        conn.attach(1, newnode)
        conn.update_path()
        newconn = Connection(None, self.scene)
        newconn.attach(0, newnode)
        newconn.attach(1, p)
        newconn.update_path()
        return newconn

    def addNetlistMenu(self):
        blockname = self.scene.item.blockname
        libname = self.scene.item.libname
        fname = 'libraries.library_{}.{}'.format(libname, blockname)
        exec('import ' + fname) in globals(), locals()
        reload(eval(fname))
        attributes = dir(eval(fname))
        netlistFunctions = []
        for attribute in attributes:
            if attribute.startswith('netlist'):
                netlistFunctions.append(attribute.replace('netlist', ''))
        if not 'myhdl' in netlistFunctions:
            netlistFunctions.append('myhdl')
        for type in netlistFunctions:

            def getFunction(type):
                def netlistAction():
                    self.netList(type)

                return netlistAction

            netlistAction = getFunction(type)
            action = self.netlistMenu.addAction(type + " netlist")
            action.triggered.connect(netlistAction)

    def mouseDoubleClicked(self, obj, event):
        pos = gridPos(event.scenePos())
        item = self.itemAt(pos, exclude=[isConnection])
        if isBlock(item):
            if 'diagram' in item.getViews():
                self.scene.mainw.descend(item)
            else:
                views = item.getViews()
                fname = None
                if len(views) == 1:
                    viewtype, fname = views.items()[0]
                elif len(views) > 1:
                    d = selectionDialog(views.keys(), title='Select view')
                    ret = d.getRet()
                    if ret:
                        fname = views[ret]
                if fname:
                    for tp, (editor, extension) in viewTypes.items():
                        if fname.endswith(extension):
                            cmd = editor
                            break
                    if cmd:
                        os.system(cmd + " " + fname)
                    else:
                        error(
                            "{} is unkown type\nplease see viewTypes in menu Settings -> Edit settings"
                            .format(source))
                        return

        elif isPort(item, tp='ipin opin iopin node'.split()):
            self.scene.item = item
            self.portEdit()
            if self.conn:
                self.conn.remove()
                self.conn = None
                self.scene.mainw.view.setCursor(QtCore.Qt.ArrowCursor)
        elif isTextItem(item):
            font, ok = QtWidgets.QFontDialog.getFont(item.font())
            if ok:
                item.setFont(font)

    def mouseLeftButtonPressed(self, obj, event):
        pos = gridPos(event.scenePos())
        blocks, ports, nodes, connections, labels = self.sortedItemsAt(pos)
        if self.conn:  # connection mode
            while ports:  # try to find in-port
                port = ports.pop()
                if isInPort(port):
                    self.connectionFinish(port)
                    return
            while nodes:  # else try to find node
                node = nodes.pop()
                self.connectionFinish(node)
                return
#            while connections:
#                conn = connections.pop()
#                if conn != self.conn:
#                    node = self.connectionInsertNode(conn, pos)
#                    self.connectionFinish(node)
#                    return
            self.connectionNext(pos)

        else:  # not in connection mode
            while ports:
                port = ports.pop()
                if isOutPort(port) and not port.connections:
                    # Try to create new connection starting at selected output port
                    self.connectionStart(port)
                    return

            while nodes:
                node = nodes.pop()

                if node in self.scene.selectedItems():
                    node.setFlag(node.ItemIsMovable)
                else:
                    #starting the connection
                    self.connectionStart(node)
                    self.connFromNode = True

    def moveMouse(self, obj, event):
        if self.connFromNode:
            return
        pos = gridPos(event.scenePos())
        item = self.itemAt(pos)

        if self.conn:
            self.scene.mainw.view.setCursor(QtCore.Qt.ArrowCursor)
            if item and isInPort(item) or isNode(item):
                if len(item.connections) == 0:
                    self.scene.mainw.view.setCursor(QtCore.Qt.CrossCursor)
                else:
                    self.scene.mainw.view.setCursor(QtCore.Qt.ArrowCursor)
            elif item and isNode(item):
                if len(item.connections) == 0:
                    self.scene.mainw.view.setCursor(QtCore.Qt.CrossCursor)
                else:
                    self.scene.mainw.view.setCursor(QtCore.Qt.ArrowCursor)
            self.conn.update_path(pos)
            #return True
        elif item:
            if isBlock(item):
                items = self.scene.selectedItems()

                for item in items:
                    if isBlock(item):
                        for thing in item.childItems():
                            if isPort(thing, 'block'):
                                for conn in thing.connections:
                                    conn.update_path()

            #elif isConnection(item):
            #self.scene.mainw.view.setCursor(QtCore.Qt.PointingHandCursor)
            elif isOutPort(item):
                self.scene.mainw.view.setCursor(QtCore.Qt.CrossCursor)
            elif isNode(item):
                if item in self.scene.selectedItems():
                    self.scene.mainw.view.setCursor(
                        QtCore.Qt.PointingHandCursor)
                else:
                    self.scene.mainw.view.setCursor(QtCore.Qt.CrossCursor)
            else:
                self.scene.mainw.view.setCursor(QtCore.Qt.ArrowCursor)

    def mouseReleased(self, obj, event):
        self.connFromNode = False
        items = self.scene.selectedItems()
        for item in items:
            if isBlock(item) or isPort(item) or isComment(item):
                item.setPos(gridPos(item.pos()))
                for thing in item.childItems():
                    if isPort(thing, 'block'):
                        for conn in thing.connections:
                            conn.update_path()

    def mouseRightButtonPressed(self, obj, event):
        if self.conn == None:
            b, p, c, t = [], [], [], []
            for i in self.itemAt(event.scenePos(), single=False):
                if isBlock(i):
                    b.append(i)
                elif isPort(i):
                    p.append(i)
                elif isConnection(i):
                    c.append(i)
                elif isComment(i):
                    t.append(i)
            item = p.pop() if p else b.pop() if b else c.pop() if c else t.pop(
            ) if t else None
            if isBlock(item):
                self.scene.item = item
                #                self.netlistMenu.clear()
                #                self.addNetlistMenu()
                self.menuIOBlk.exec_(event.screenPos())
            elif isPort(item, ['node', 'ipin', 'opin', 'iopin']):
                self.scene.item = item
                self.subMenuPort.exec_(event.screenPos())
            elif isConnection(item):
                self.scene.item = item
                self.event = event
                self.subMenuConn.exec_(event.screenPos())
            elif isComment(item):
                self.scene.item = item
                self.event = event
                self.subMenuText.exec_(event.screenPos())
            else:
                self.event = event
                self.subMenuNothing.exec_(event.screenPos())

    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.GraphicsSceneMouseMove:
            self.moveMouse(obj, event)
            self.status.showMessage('{:.1f}, {:.1f}'.format(
                event.scenePos().x(),
                event.scenePos().y()))

        elif event.type() == QtCore.QEvent.GraphicsSceneMousePress:
            if event.button() == QtCore.Qt.LeftButton:
                self.mouseLeftButtonPressed(obj, event)
            elif event.button() == QtCore.Qt.RightButton:
                self.mouseRightButtonPressed(obj, event)

        elif event.type() == QtCore.QEvent.GraphicsSceneMouseRelease:
            self.mouseReleased(obj, event)

        elif event.type() == QtCore.QEvent.GraphicsSceneMouseDoubleClick:
            self.mouseDoubleClicked(obj, event)

        if event.type() == QtCore.QEvent.KeyPress:
            if event.key() == QtCore.Qt.Key_Delete:
                items = self.scene.selectedItems()
                for item in items:
                    try:
                        item.remove()
                    except:
                        try:
                            if isComment(item):
                                self.scene.removeItem(item)
                        except:
                            pass
                if self.conn:
                    self.conn.remove()
                #self.conn = None

            if event.key() == QtCore.Qt.Key_Escape:
                if self.conn != None:
                    self.conn.remove()
                self.conn = None
                self.scene.mainw.view.setCursor(QtCore.Qt.ArrowCursor)
            if event.key() == QtCore.Qt.Key_Control:
                self.scene.mainw.view.setDragMode(
                    QtWidgets.QGraphicsView.ScrollHandDrag)
        if event.type() == QtCore.QEvent.KeyRelease and event.key(
        ) == QtCore.Qt.Key_Control:
            self.scene.mainw.view.setDragMode(
                QtWidgets.QGraphicsView.RubberBandDrag)
        return super(Editor, self).eventFilter(obj, event)
Пример #16
0
 def loadConn(self, item, dx=0.0, dy=0.0):
     c = Connection(None, self)
     c.load(item, dx, dy)
Пример #17
0
class Editor(QObject):
    """ Editor to handles events"""
    def __init__(self, parent):
        super(Editor, self).__init__(parent)
        self.mainw = parent
        self.conn = None
        self.scene = None
        self.movBlk = False
        self.event = None
        self.state = IDLE

        self.menuIOBlk = QMenu()
        parBlkAction = self.menuIOBlk.addAction('Block I/Os')
        paramsBlkAction = self.menuIOBlk.addAction('Block Parameters')
        flpBlkAction = self.menuIOBlk.addAction('Flip Block')
        nameBlkAction = self.menuIOBlk.addAction('Change Name')
        cloneBlkAction = self.menuIOBlk.addAction('Clone Block')
        copyBlkAction = self.menuIOBlk.addAction('Copy Block')
        deleteBlkAction = self.menuIOBlk.addAction('Delete Block')

        parBlkAction.triggered.connect(self.parBlock)
        flpBlkAction.triggered.connect(self.flipBlock)
        nameBlkAction.triggered.connect(self.nameBlock)
        paramsBlkAction.triggered.connect(self.paramsBlock)
        cloneBlkAction.triggered.connect(self.cloneBlock)
        copyBlkAction.triggered.connect(self.copyBlock)
        deleteBlkAction.triggered.connect(self.deleteBlock)

        self.subMenuConn = QMenu()
        connAddAction = self.subMenuConn.addAction('Add connection')
        connDelAction = self.subMenuConn.addAction('Delete connection')
        connAddAction.triggered.connect(self.addConn)
        connDelAction.triggered.connect(self.deleteConn)

        self.subMenuEditor = QMenu()
        pasteAction = self.subMenuEditor.addAction('Paste')
        pasteAction.triggered.connect(self.pasteBlock)

        # Matrix has two index [state, event]
        # States:
        # IDLE                                  0
        # LEFTMOUSEPRESSED       1
        # ITEMSELECTED                 2
        # DRAWFROMOUTPORT      3
        # MOVECONN                      4

        # Events
        # MOUSEMOVE                    0
        # LEFTMOUSEPRESSED        1
        # RIGHTMOUSEPRESSED     2
        # MOUSERELEASED             3
        # MOUSEDOUBLECLICK       4
        # KEY_DEL                            5
        # KEY_ESC                            6

        self.Fun = [[
            self.P00, self.P01, self.P02, self.PDM, self.P03, self.P04,
            self.P05
        ],
                    [
                        self.P06, self.PDM, self.PDM, self.P07, self.PDM,
                        self.PDM, self.PDM
                    ],
                    [
                        self.P11, self.P01, self.P02, self.PDM, self.P03,
                        self.P04, self.P05
                    ],
                    [
                        self.P10, self.P08, self.P09, self.PDM, self.PDM,
                        self.PDM, self.P09
                    ],
                    [
                        self.P12, self.PDM, self.PDM, self.P13, self.PDM,
                        self.PDM, self.PDM
                    ]]

    def install(self, scene):
        scene.installEventFilter(self)
        self.scene = scene

    def parBlock(self):
        self.scene.DgmToUndo()
        ok = self.scene.mainw.parBlock()
        if not ok:
            self.scene.clearLastUndo()

    def flipBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        item.flip = not item.flip
        item.setFlip()

    def nameBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        dialog = BlockName_Dialog(self.scene.mainw)
        dialog.name.setText(item.name)
        res = dialog.exec_()
        if res == 1:
            item.name = str(dialog.name.text())
            item.label.setPlainText(item.name)
            w = item.label.boundingRect().width()
            item.label.setPos(-w / 2, item.h / 2 + 5)
        else:
            self.scene.clearLastUndo()

    def paramsBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        params = item.params.split('|')
        blk = params[0]
        blk = blk.replace('Blk', 'Dlg')

        streV = 'import ' + blk + ' as dlg'
        try:
            exec(streV)
            name = item.name.replace(' ', '_')
            cmd = 'dlg.' + blk + '(' + str(item.inp) + ',' + str(
                item.outp) + ',"' + item.params + '"' + ',"' + name + '")'
            pars = eval(cmd)

        except:
            pars = pDlg.parsDialog(item.params)

        if pars != item.params:
            item.params = pars
        else:
            self.scene.clearLastUndo()

    def cloneBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        item.clone(QPointF(DP, DP))

    def copyBlock(self):
        root = etree.Element('root')
        item = self.scene.item
        item.save(root)
        msg = etree.tostring(root, pretty_print=True)
        clipboard = QApplication.clipboard()
        mimeData = QMimeData()
        mimeData.setText(msg.decode())
        clipboard.setMimeData(mimeData)

    def pasteBlock(self):
        self.scene.DgmToUndo()
        try:
            msg = QApplication.clipboard().text()
            root = etree.fromstring(msg)
            blocks = root.findall('block')
            meanPosX = 0.0
            meanPosY = 0.0
            numBlk = 0
            for item in blocks:
                pBlkX = float(item.findtext('posX'))
                pBlkY = float(item.findtext('posY'))
                meanPosX = meanPosX + pBlkX
                meanPosY = meanPosY + pBlkY
                numBlk += 1
            deltaPosX = self.scene.evpos.x() - meanPosX / numBlk
            deltaPosY = self.scene.evpos.y() - meanPosY / numBlk
            blocks = root.findall('block')
            for item in blocks:
                self.scene.loadBlock(item, deltaPosX, deltaPosY)
            connections = root.findall('connection')
            for item in connections:
                self.scene.loadConn(item, deltaPosX, deltaPosY)
            try:
                self.editor.redrawNodes()
            except:
                pass
        except:
            pass

    def deleteBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        item.remove()
        self.removeNodes()
        self.redrawNodes()

    def connectInPort(self, item):
        if len(item.connections) == 0:
            self.conn.port2 = item
            self.conn.pos2 = item.scenePos()
            self.conn.port1.connections.append(self.conn)
            self.conn.port2.connections.append(self.conn)
            if len(self.conn.connPoints) == 0:
                pos1 = QPointF((self.conn.pos2.x() + self.conn.pos1.x()) / 2,
                               self.conn.pos1.y())
                pos2 = QPointF((self.conn.pos2.x() + self.conn.pos1.x()) / 2,
                               self.conn.pos2.y())
                self.conn.connPoints.append(self.gridPos(pos1))
                self.conn.connPoints.append(self.gridPos(pos2))
            else:
                pt = self.conn.connPoints[-1]
                pos1 = QPointF(pt.x(), self.conn.pos2.y())
                self.conn.connPoints.append(self.gridPos(pos1))
        self.conn.clean()
        self.conn.update_path()
        self.conn = None

    def deleteConn(self):
        self.scene.DgmToUndo()
        self.scene.item.remove()
        self.removeNodes()
        self.redrawNodes()

    def find_exact_pos(self, c, pos):
        # Find exact point on connection c
        points = [c.pos1]
        for el in c.connPoints:
            points.append(el)
        points.append(c.pos2)
        N = len(points)
        for n in range(0, N - 1):
            p1 = points[n]
            p2 = points[n + 1]
            rect = QRectF(p1 - QPointF(DB, DB), p2 + QPointF(DB, DB))
            if rect.contains(pos):
                if p1.x() == p2.x():
                    pos.setX(p1.x())
                if p1.y() == p2.y():
                    pos.setY(p1.y())
                return n, pos

    def addConn(self):
        self.scene.DgmToUndo()
        c = self.scene.item
        posMouse = self.gridPos(self.scene.evpos)
        self.conn = Connection(None, self.scene)
        self.conn.port1 = c.port1
        self.conn.pos1 = c.pos1

        try:
            npos, pos = self.find_exact_pos(c, posMouse)
        except:
            return
        N = len(c.connPoints)

        if npos == 0:
            pos = posMouse
            npt = 0
        elif npos == N:
            pos = posMouse
            npt = N
        else:
            npt = npos

        for n in range(0, npt):
            self.conn.connPoints.append(c.connPoints[n])
        self.conn.connPoints.append(pos)
        self.state = DRAWFROMOUTPORT

    def redrawSelectedItems(self):
        for item in self.scene.selectedItems():
            if isinstance(item, Block):
                item.setPos(item.scenePos())
                for el in item.childItems():
                    try:
                        for conn in el.connections:
                            conn.update_pos_from_ports()
                    except:
                        pass

    def clean_points(self, pts, m):
        N = len(pts)
        remPt = []
        for n in range(1, N - 1):
            if m == 'x':
                if pts[n - 1].x() == pts[n].x() == pts[n + 1].x():
                    remPt.append(pts[n])
            elif m == 'y':
                if pts[n - 1].y() == pts[n].y() == pts[n + 1].y():
                    remPt.append(pts[n])

        for el in remPt:
            pts.remove(el)
        return pts

    def ptInLine(self, pt, p1, p2):
        rect = QRectF(p1 - QPointF(0.5, 0.5), p2 + QPointF(0.5, 0.5))
        if rect.contains(pt):
            return True
        else:
            return False

    def setNode(self, pts1, pts2):
        pts1 = self.clean_points(pts1, 'x')
        pts1 = self.clean_points(pts1, 'y')
        pts2 = self.clean_points(pts2, 'x')
        pts2 = self.clean_points(pts2, 'y')

        n = 0
        N = min(len(pts1), len(pts2))
        try:
            while pts1[n] == pts2[n] and n < N:
                n += 1
            p1_prev = pts1[n - 1]
            p1 = pts1[n]
            p2_prev = pts2[n - 1]
            p2 = pts2[n]

            if self.ptInLine(p1, p2_prev, p2):
                pos = p1
            elif self.ptInLine(p2, p1_prev, p1):
                pos = p2
            else:
                pos = p1_prev

            node = Node(None, self.scene)
            node.setPos(pos)
        except:
            pass

    def redrawNodesFromPort(self, p):
        N = len(p.connections)
        for n in range(0, N):
            pts1 = [p.connections[n].pos1]
            for el in p.connections[n].connPoints:
                pts1.append(el)
            pts1.append(p.connections[n].pos2)
            for m in range(n + 1, N):
                pts2 = [p.connections[m].pos1]
                for el in p.connections[m].connPoints:
                    pts2.append(el)
                pts2.append(p.connections[m].pos2)

                self.setNode(pts1, pts2)

    def redrawNodes(self):
        for el in self.scene.items():
            if isinstance(el, Node):
                el.remove()
        for item in self.scene.items():
            if isinstance(item, Block):
                for p in item.childItems():
                    if isinstance(p, OutPort):
                        if len(p.connections) > 1:
                            self.redrawNodesFromPort(p)

    def removeNodes(self):
        for el in self.scene.items():
            if isinstance(el, Node):
                el.remove()

    def itemAt(self, pos):
        rect = QRectF(pos + QPointF(-DB, -DB), QSizeF(2 * DB, 2 * DB))
        items = self.scene.items(rect)

        for item in items:
            if isinstance(self.findBlockAt(pos), Block):
                return item
        for item in items:
            if isinstance(self.findOutPortAt(pos), OutPort):
                return item
        for item in items:
            if isinstance(self.findInPortAt(pos), InPort):
                return (item)
        for item in items:
            if isinstance(self.findConnectionAt(pos), Connection):
                return (item)
        return None

    def itemByDraw(self, pos):
        rect = QRectF(pos - QPointF(DB, DB), QSizeF(2 * DB, 2 * DB))
        items = self.scene.items(
            QRectF(pos - QPointF(DB, DB), QSizeF(2 * DB, 2 * DB)))
        for item in items:
            if isinstance(item, InPort):
                return (item)
        return None

    def findInPortAt(self, pos):
        items = self.scene.items(
            QRectF(pos - QPointF(DB, DB), QSizeF(2 * DB, 2 * DB)))
        for el in items:
            if isinstance(el, InPort):
                return el
        return None

    def findOutPortAt(self, pos):
        items = self.scene.items(
            QRectF(pos - QPointF(DB, DB), QSizeF(2 * DB, 2 * DB)))
        for el in items:
            if isinstance(el, OutPort):
                return el
        return None

    def findBlockAt(self, pos):
        items = self.scene.items(
            QRectF(pos - QPointF(DB, DB), QSizeF(2 * DB, 2 * DB)))
        for el in items:
            if isinstance(el, Block):
                return el
        return None

    def findConnectionAt(self, pos):
        items = self.scene.items(
            QRectF(pos - QPointF(DB, DB), QSizeF(2 * DB, 2 * DB)))
        for c in items:
            if isinstance(c, Connection):
                points = [c.pos1]
                for el in c.connPoints:
                    points.append(el)
                points.append(c.pos2)
                N = len(points)
                for n in range(0, N - 1):
                    p1 = points[n]
                    p2 = points[n + 1]
                    rect = QRectF(p1 - QPointF(DB, DB), p2 + QPointF(DB, DB))
                    if rect.contains(pos):
                        return c
        return None

    def deleteSelected(self):
        items = self.scene.selectedItems()
        self.scene.DgmToUndo()
        for item in items:
            try:
                item.remove()
                self.editor.removeNodes()
                self.editor.redrawNodes()
            except:
                pass

    def deselect_all(self):
        for el in self.scene.items():
            el.setSelected(False)

    def setMouseInitDraw(self, pos):
        pointer = Qt.ArrowCursor
        if isinstance(self.findBlockAt(pos), Block):
            pointer = Qt.ArrowCursor
        elif isinstance(self.findOutPortAt(pos), OutPort):
            pointer = Qt.CrossCursor
        elif isinstance(self.findConnectionAt(pos), Connection):
            pointer = Qt.PointingHandCursor
        else:
            pointer = Qt.ArrowCursor
        self.scene.mainw.view.setCursor(pointer)

    def setMouseByDraw(self, item):
        if isinstance(item, InPort) and len(item.connections) == 0:
            pointer = Qt.CrossCursor
        else:
            pointer = Qt.DragLinkCursor
        self.scene.mainw.view.setCursor(pointer)

    def PDM(self, obj, event):  # Dummy function - No action
        pass

    def P00(self, obj, event):  # IDLE + MOUSEMOVE
        self.setMouseInitDraw(event.scenePos())

        item = self.itemAt(event.scenePos())
        if item == None:
            self.deselect_all()
        else:
            try:
                item.setSelected(True)
            except:
                pass
        self.scene.updateDgm()

    def P01(self, obj, event):  # IDLE, ITEMSELECTED + LEFTMOUSEPRESSED
        item = self.findConnectionAt(event.scenePos())
        if item != None:
            self.scene.currentItem = item
            self.currentPos = event.scenePos()
            self.deselect_all()
            self.scene.DgmToUndo()
            self.state = MOVECONN
        else:
            self.state = LEFTMOUSEPRESSED

    def P02(self, obj, event):  # IDLE, ITEMSELECTED + RIGHTMOUSEPRESSED
        item = self.findBlockAt(event.scenePos())
        self.deselect_all()
        if isinstance(item, Block):
            item.setSelected(True)
            self.scene.item = item
            self.scene.evpos = event.scenePos()
            try:
                self.menuIOBlk.exec_(event.screenPos())
            except:
                pass
        else:
            item = self.findConnectionAt(event.scenePos())
            if isinstance(item, Connection):
                self.scene.item = item
                self.scene.evpos = event.scenePos()
                try:
                    self.subMenuConn.exec_(event.screenPos())
                except:
                    pass

        if item == None:
            self.scene.evpos = event.scenePos()
            self.subMenuEditor.exec_(event.screenPos())

    def P03(self, obj, event):  # IDLE, ITEMSELECTED + MOUSEDOUBLECLICK
        item = self.findBlockAt(event.scenePos())
        self.deselect_all()
        if isinstance(item, Block):
            item.setSelected(True)
            self.scene.item = item
            self.scene.evpos = event.scenePos()
            self.paramsBlock()

    def P04(self, obj, event):  # ITEMSELECTED + KEY_DEL
        self.deleteSelected()
        self.state = IDLE
        self.redrawNodes()

    def P05(self, obj, event):  # ITEMSELECTED + KEY_ESC
        self.state = IDLE

    def P06(self, obj, event):  # LEFTMOUSEPRESSED + MOUSEMOVE
        self.redrawSelectedItems()
        self.removeNodes()
        item = self.itemAt(event.scenePos())

    def P07(self, obj, event):  # LEFTMOUSEPRESSED + MOUSERELEASED
        self.redrawSelectedItems()
        self.redrawNodes()

        item = self.itemAt(event.scenePos())
        if self.scene.currentItem != None:
            self.scene.currentItem = None
            self.deselect_all()
            try:
                item.setSelected(True)
                self.scene.currentItem = item
            except:
                pass

        if self.scene.selectedItems():
            self.state = ITEMSELECTED
        else:
            self.state = IDLE

        item = self.findOutPortAt(event.scenePos())
        if isinstance(item, OutPort):
            self.scene.DgmToUndo()
            self.state = DRAWFROMOUTPORT
            self.conn = Connection(None, self.scene)
            self.conn.port1 = item
            self.conn.pos1 = item.scenePos()
            self.conn.pos2 = item.scenePos()

    def P08(self, obj, event):  # DRAWFROMOUTPORT + LEFTMOUSEPRESSED
        item = self.findInPortAt(event.scenePos())
        if isinstance(item, InPort):
            self.connectInPort(item)
            self.redrawNodes()
            self.state = IDLE
        else:
            pt = self.gridPos(event.scenePos())
            self.conn.addPoint(pt)
            self.conn.pos2 = pt
            self.conn.update_path()

    def P09(self, obj, event):  # DRAWFROMOUTPORT + RIGHTMOUSEPRESSED, KEY_ESC
        try:
            self.conn.remove()
            self.scene.undoDgm()
        except:
            pass
        self.conn = None
        self.state = IDLE

    def P10(self, obj, event):  # DRAWFROMOUTPORT + MOUSEMOVE
        item = self.itemByDraw(event.scenePos())
        self.setMouseByDraw(item)
        self.conn.pos2 = event.scenePos()
        if isinstance(item, InPort):
            self.conn.update_path_draw2Port()
        else:
            self.conn.update_path_draw2Pt()

    def P11(self, obj, event):  # ITEMSELECTED + MOUSEMOVE
        self.setMouseInitDraw(event.scenePos())

    def P12(self, obj, event):  # MOVECONN + MOUSEMOVE
        item = self.scene.currentItem
        N = len(item.connPoints)
        oldPos = self.currentPos
        newPos = self.gridPos(event.scenePos())
        try:
            npos, pos = self.find_exact_pos(item, oldPos)
        except:
            return

        if npos != 0 and npos != N:
            ok = item.move(npos, newPos)
            if ok:
                self.currentPos = newPos

    def P13(self, obj, event):  # MOVECONN + MOUSERELEASE
        item = self.scene.currentItem
        N = len(item.connPoints)
        oldPos = self.currentPos
        newPos = self.gridPos(event.scenePos())
        try:
            npos, pos = self.find_exact_pos(item, oldPos)
        except:
            return

        if npos != 0 and npos != N:
            ok = item.move(npos, newPos)
            if ok:
                self.currentPos = newPos

        self.redrawNodes()
        self.scene.currentItem = None
        self.state = IDLE

    def eventFilter(self, obj, event):
        ev = -1
        if event.type() == QEvent.GraphicsSceneMouseMove:
            ev = 0

        if event.type() == QEvent.GraphicsSceneMousePress:
            self.mainw.statusLabel.setText('')
            if event.button() == Qt.LeftButton:
                ev = 1
            if event.button() == Qt.RightButton:
                ev = 2

        if event.type() == QEvent.GraphicsSceneMouseRelease:
            ev = 3

        if event.type() == QEvent.GraphicsSceneMouseDoubleClick:
            self.mainw.statusLabel.setText('')
            ev = 4

        if event.type() == QEvent.KeyPress:
            self.mainw.statusLabel.setText('')
            if event.key() == Qt.Key_Delete:
                ev = 5
            if event.key() == Qt.Key_Escape:
                ev = 6
        if ev != -1:
            #if ev != 0:
            #print('state->', self.state, 'event->',ev)
            fun = self.Fun[self.state][ev]
            fun(obj, event)

        return False

    def gridPos(self, pt):
        gr = GRID
        x = gr * ((pt.x() + gr / 2) // gr)
        y = gr * ((pt.y() + gr / 2) // gr)
        return QPointF(x, y)
Пример #18
0
    def dataToDiagram(self,
                      blocks,
                      connections,
                      nodes,
                      comments,
                      center=True,
                      undo=False):
        errors = []

        for data in blocks:
            prop = data['properties'] if 'properties' in data else dict()
            if 'parameters' in data:
                #getBlock(libname, blockname, parent=None, scene=None, param=dict(), name=None, flip=False)
                b = getBlock(data['libname'],
                             data['blockname'],
                             scene=self.scene,
                             param=data['parameters'],
                             properties=prop,
                             errors=errors)
            else:
                b = getBlock(data['libname'],
                             data['blockname'],
                             scene=self.scene,
                             properties=prop,
                             errors=errors)

            if b:
                b.fromData(data)

        for item in nodes:
            pos = QtCore.QPointF(item['x'], item['y'])
            if self.scene.find_itemAt(pos):
                print('discarding overlapping node at x={}, y={}'.format(
                    item['x'], item['y']))
            else:
                p = Port(None, self.scene)
                p.fromData(item)

        for data in connections:
            pos = [QtCore.QPointF(data['x0'], data['y0'])]
            pos.append(QtCore.QPointF(data['x1'], data['y1']))
            if pos[0] == pos[1]:
                print('discarding zero length segment x={}, y={}'.format(
                    data['x0'], data['y0']))
            else:
                conn = Connection(None, self.scene)
                for ix in [0, 1]:
                    port = self.scene.find_itemAt(pos[ix],
                                                  exclude=(Block, Connection,
                                                           textItem))
                    if isPort(port):
                        conn.attach(ix, port)
                    else:
                        conn.pos[ix] = pos[ix]
                        print('no port at ', pos[ix])
                conn.update_path()

                if 'label' in data:
                    conn.label = textItem(data['label'], anchor=3, parent=conn)
                    conn.label.setPos(conn.pos2.x(), conn.pos2.y())
                if 'signalType' in data:
                    conn.signalType = textItem(data['signalType'],
                                               anchor=3,
                                               parent=conn)
                    conn.signalType.setPos(conn.pos2.x(), conn.pos2.y())

        for data in comments:
            comment = Comment('')
            comment.fromData(data)
            self.scene.addItem(comment)

        if center:
            self.scene.mainw.view.centerOn(self.scene.getCenter()[0],
                                           self.scene.getCenter()[1])

        if errors:
            error('\n'.join(errors))
Пример #19
0
class Editor(QtCore.QObject):
    """ Editor to handles events"""
    def __init__(self, parent):
        super(Editor, self).__init__(parent)
        self.conn = None
        self.scene = None
        self.movBlk = False
        self.event = None
        self.connFromNode = False
        self.state = IDLE

        self.menuIOBlk = QMenu()
        parBlkAction = self.menuIOBlk.addAction('Block I/Os')
        paramsBlkAction = self.menuIOBlk.addAction('Block Parameters')
        flpBlkAction = self.menuIOBlk.addAction('Flip Block')
        nameBlkAction = self.menuIOBlk.addAction('Change Name')
        cloneBlkAction = self.menuIOBlk.addAction('Clone Block')
        deleteBlkAction = self.menuIOBlk.addAction('Delete Block')

        parBlkAction.triggered.connect(self.parBlock)
        flpBlkAction.triggered.connect(self.flipBlock)
        nameBlkAction.triggered.connect(self.nameBlock)
        paramsBlkAction.triggered.connect(self.paramsBlock)
        cloneBlkAction.triggered.connect(self.cloneBlock)
        deleteBlkAction.triggered.connect(self.deleteBlock)

        self.subMenuNode = QMenu()
        nodeDelAction = self.subMenuNode.addAction('Delete node')
        nodeBindAction = self.subMenuNode.addAction('Bind node')
        nodeDelAction.triggered.connect(self.deleteNode)
        nodeBindAction.triggered.connect(self.bindNode)

        self.subMenuConn = QMenu()
        connConnectAction = self.subMenuConn.addAction('Start connection')
        connDelAction = self.subMenuConn.addAction('Delete connection')
        connInsAction = self.subMenuConn.addAction('Insert node')
        connConnectAction.triggered.connect(self.newConn)
        connDelAction.triggered.connect(self.deleteConn)
        connInsAction.triggered.connect(self.insConn)

        # Matrix has two index [state, event]
        # States:
        # IDLE                                  0
        # LEFTMOUSEPRESSED       1
        # ITEMSELECTED                 2
        #DRAWFROMOUTPORT       3

        # Events
        # MOUSEMOVE                    0
        # LEFTMOUSEPRESSED        1
        # RIGHTMOUSEPRESSED     2
        # MOUSERELEASED             3
        # MOUSEDOUBLECLICK       4
        # KEY_DEL                            5
        # KEY_ESC                            6

        self.Fun = [[
            self.P00, self.P01, self.P02, self.PDM, self.P03, self.P04,
            self.P05
        ],
                    [
                        self.P06, self.PDM, self.PDM, self.P07, self.PDM,
                        self.PDM, self.PDM
                    ],
                    [
                        self.P12, self.P01, self.P02, self.P11, self.P03,
                        self.P04, self.P05
                    ],
                    [
                        self.P10, self.P08, self.P09, self.PDM, self.PDM,
                        self.PDM, self.P09
                    ]]

    def parBlock(self):
        self.scene.DgmToUndo()
        ok = self.scene.mainw.parBlock()
        if not ok:
            self.scene.clearLastUndo()

    def flipBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        item.flip = not item.flip
        item.setFlip()

    def nameBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        dialog = BlockName_Dialog(self.scene.mainw)
        dialog.name.setText(item.name)
        res = dialog.exec_()
        if res == 1:
            item.name = str(dialog.name.text())
            item.label.setPlainText(item.name)
            w = item.label.boundingRect().width()
            item.label.setPos(-w / 2, item.h / 2 + 5)
        else:
            self.scene.clearLastUndo()

    def paramsBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        params = item.params.split('|')
        blk = params[0]
        blk = blk.replace('Blk', 'Dlg')
        if blk in dir(pDlg):
            name = item.name.replace(' ', '_')
            cmd = 'pDlg.' + blk + '(' + str(item.inp) + ',' + str(
                item.outp) + ',"' + item.params + '"' + ',"' + name + '")'
            pars = eval(cmd)
        else:
            pars = pDlg.parsDialog(item.params)
        if pars != item.params:
            item.params = pars
        else:
            self.scene.clearLastUndo()

    def cloneBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        item.clone(QtCore.QPointF(100, 100))

    def deleteBlock(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        item.remove()

    def newNode(self, item, pos):
        port2 = item.port2
        pos2 = item.pos2
        c = Connection(None, self.scene)
        b = Node(None, self.scene)
        b.setPos(pos)
        self.lastNode = b
        item.port2.connections.remove(item)
        item.port2.connections.append(c)
        item.port2 = b.port_in
        item.port2.connections.append(item)
        item.pos2 = b.pos()
        c.port1 = b.port_out
        c.port2 = port2
        c.port1.connections.append(c)
        c.pos1 = b.pos()
        c.pos2 = pos2
        item.update_path()
        c.update_path()
        self.scene.isInsConn = False
        self.scene.isConnecting = True

    def insertConnection(self, event):
        item = self.itemAt(self.scene.evpos)
        self.newNode(item, self.scene.evpos)

    def genInterPoint(self, p2):
        p1 = self.conn.pos1
        dx = np.abs(p2.x() - p1.x())
        dy = np.abs(p2.y() - p1.y())
        if isinstance(self.conn.port1, OutPort):
            pt = QtCore.QPointF(p2.x(), p1.y())
        else:
            if dx > dy:
                pt = QtCore.QPointF(p2.x(), p1.y())
            else:
                pt = QtCore.QPointF(p1.x(), p2.y())
        return pt

    def deleteNode(self):
        self.scene.DgmToUndo()
        self.scene.item.remove()

    def bindNode(self):
        self.scene.DgmToUndo()
        item = self.scene.item
        if len(item.port_out.connections) == 1:
            c1 = item.port_in.connections[0]
            c2 = item.port_out.connections[0]
            c = Connection(None, self.scene)
            c.pos1 = c1.pos1
            c.pos2 = c2.pos2
            item.remove()
            c.update_ports_from_pos()
            if isinstance(c.port1, OutPort) and isinstance(c.port2, InPort):
                pos = QtCore.QPointF((c.pos2.x() + c.pos1.x()) / 2, c.pos1.y())
                self.newNode(c, pos)
        else:
            self.scene.clearLastUndo()

    def newConn(self):
        self.scene.DgmToUndo()
        if not self.conn:
            self.insertConnection(self.event)
            item = self.lastNode
            self.scene.DgmToUndo()
            self.state = DRAWFROMOUTPORT
            self.scene.mainw.status.showMessage('DRAWFROMOUTPORT')
            self.conn = Connection(None, self.scene)
            self.conn.port1 = item.port_out
            self.conn.pos1 = item.scenePos()
            self.conn.pos2 = item.scenePos()
        else:
            self.scene.clearLastUndo()

    def deleteConn(self):
        self.scene.DgmToUndo()
        self.scene.item.remove()

    def insConn(self):
        self.scene.DgmToUndo()
        if not self.conn:
            self.insertConnection(self.event)
        else:
            self.scene.clearLastUndo()

    def install(self, scene):
        scene.installEventFilter(self)
        self.scene = scene

    def itemAt(self, pos):
        items = self.scene.items(
            QtCore.QRectF(pos - QtCore.QPointF(DB, DB),
                          QtCore.QSizeF(2 * DB, 2 * DB)))
        for item in items:
            if isinstance(item, QGraphicsItem):
                return item
        return None

    def deselect_all(self):
        for el in self.scene.items():
            el.setSelected(False)

    def setMouseInitDraw(self, item):
        if isinstance(item, Block):
            pointer = QtCore.Qt.ArrowCursor
        elif isinstance(item, OutPort) and len(item.connections) == 0:
            pointer = QtCore.Qt.CrossCursor
        elif isinstance(item, Node):
            pointer = QtCore.Qt.CrossCursor
        elif isinstance(item, Connection):
            pointer = QtCore.Qt.PointingHandCursor
        else:
            pointer = QtCore.Qt.ArrowCursor
        self.scene.mainw.view.setCursor(pointer)

    def setMouseByDraw(self, item):
        if isinstance(item, Block):
            pointer = QtCore.Qt.ArrowCursor
        elif isinstance(item, InPort) and len(item.connections) == 0:
            pointer = QtCore.Qt.CrossCursor
        elif isinstance(item, Node) and len(item.port_in.connections) == 0:
            pointer = QtCore.Qt.CrossCursor
        elif isinstance(item, Connection):
            pointer = QtCore.Qt.PointingHandCursor
        else:
            pointer = QtCore.Qt.ArrowCursor
        self.scene.mainw.view.setCursor(pointer)

    def PDM(self, obj, event):  # Dummy function - No action
        pass

    def P00(self, obj, event):
        item = self.itemAt(event.scenePos())
        self.setMouseInitDraw(item)

        item = self.itemAt(event.scenePos())
        if item == None:
            self.deselect_all()
        else:
            try:
                item.setSelected(True)
            except:
                pass
        self.scene.updateDgm()

    def P01(self, obj, event):
        self.scene.currentItem = self.itemAt(event.scenePos())
        self.state = LEFTMOUSEPRESSED
        #self.scene.mainw.status.showMessage('LEFTMOUSEPRESSED')

    def P02(self, obj, event):
        item = self.itemAt(event.scenePos())
        self.deselect_all()
        if isinstance(item, Block):
            item.setSelected(True)
            self.scene.item = item
            self.scene.evpos = event.scenePos()
            try:
                self.menuIOBlk.exec_(event.screenPos())
            except:
                pass

        if isinstance(item, Node):
            self.scene.item = item
            try:
                self.subMenuNode.exec_(event.screenPos())
            except:
                pass

        if isinstance(item, Connection):
            self.scene.item = item
            self.scene.evpos = event.scenePos()
            try:
                self.subMenuConn.exec_(event.screenPos())
            except:
                pass

    def P03(self, obj, event):
        item = self.itemAt(event.scenePos())
        self.deselect_all()
        if isinstance(item, Block):
            item.setSelected(True)
            self.scene.item = item
            self.scene.evpos = event.scenePos()
            self.paramsBlock()

    def P04(self, obj, event):
        items = self.scene.selectedItems()
        for item in items:
            self.scene.DgmToUndo()
            try:
                item.remove()
            except:
                pass
        self.state = IDLE
        #self.scene.mainw.status.showMessage('IDLE')

    def P05(self, obj, event):
        self.state = IDLE
        #self.scene.mainw.status.showMessage('IDLE')

    def P06(self, obj, event):
        item = self.itemAt(event.scenePos())
        #self.state = IDLE
        #self.scene.mainw.status.showMessage('IDLE')
        if isinstance(item, Block) or isinstance(item, Node):
            self.scene.DgmToUndo()

    def P07(self, obj, event):
        item = self.itemAt(event.scenePos())
        if self.scene.currentItem != None:
            self.deselect_all()
            try:
                item.setSelected(True)
                self.scene.currentItem = item
            except:
                pass

        if self.scene.selectedItems():
            self.state = ITEMSELECTED
            #self.scene.mainw.status.showMessage('ITEMSELECTED')
        else:
            self.state = IDLE
            #self.scene.mainw.status.showMessage('IDLE')

        if isinstance(item, OutPort):
            self.scene.DgmToUndo()
            self.state = DRAWFROMOUTPORT
            #self.scene.mainw.status.showMessage('DRAWFROMOUTPORT')
            if len(item.connections) == 0:
                self.conn = Connection(None, self.scene)
                self.conn.port1 = item
                self.conn.pos1 = item.scenePos()
                self.conn.pos2 = item.scenePos()

        if isinstance(item, Node):
            self.scene.DgmToUndo()
            self.state = DRAWFROMOUTPORT
            #self.scene.mainw.status.showMessage('DRAWFROMOUTPORT')
            self.conn = Connection(None, self.scene)
            self.conn.port1 = item.port_out
            self.conn.pos1 = item.scenePos()
            self.conn.pos2 = item.scenePos()
        self.scene.updateDgm()

    def P08(self, obj, event):
        item = self.itemAt(event.scenePos())
        if isinstance(item, InPort):
            if len(item.connections) == 0:
                self.scene.DgmToUndo()
                self.conn.port2 = item
                self.conn.pos2 = item.scenePos()
                self.conn.port1.connections.append(self.conn)
                self.conn.port2.connections.append(self.conn)
                if isinstance(self.conn.port1, OutPort):
                    pos = QtCore.QPointF(
                        (self.conn.pos2.x() + self.conn.pos1.x()) / 2,
                        self.conn.pos1.y())
                    self.newNode(self.conn, pos)

                self.conn.update_path()
                self.conn = None
                self.state = IDLE
                #self.scene.mainw.status.showMessage('IDLE')

        if isinstance(item, Node):
            if item.port_in.connections == []:
                self.scene.DgmToUndo()
                self.conn.port2 = item.port_in
                self.conn.pos2 = item.scenePos()
                self.conn.port1.connections.append(self.conn)
                self.conn.port2.connections.append(self.conn)  # Problema qui!

                self.conn.update_path()
                self.conn = None
                self.state = IDLE
                #self.scene.mainw.status.showMessage('IDLE')

        if item == None:
            pt = self.genInterPoint(event.scenePos())
            b = Node(None, self.scene)
            b.setPos(pt)
            self.conn.port2 = b.port_in
            self.conn.pos2 = b.scenePos()
            self.conn.port1.connections.append(self.conn)
            self.conn.port2.connections.append(self.conn)
            self.conn.update_path()

            self.conn = Connection(None, self.scene)
            self.conn.port1 = b.port_out
            self.conn.pos1 = b.scenePos()
            self.conn.pos2 = b.scenePos()

    def P09(self, obj, event):
        try:
            item = self.itemAt(event.scenePos())
        except:
            item = None
        if isinstance(item, InPort):
            if len(item.connections) == 0:
                self.scene.DgmToUndo()
                self.conn.port2 = item
                self.conn.pos2 = item.scenePos()
                self.conn.port1.connections.append(self.conn)
                self.conn.port2.connections.append(self.conn)
                if isinstance(self.conn.port1, OutPort):
                    pos = QtCore.QPointF(
                        (self.conn.pos2.x() + self.conn.pos1.x()) / 2,
                        self.conn.pos1.y())
                    self.newNode(self.conn, pos)

                self.conn.update_path()
                self.conn = None
                self.state = IDLE
                #self.scene.mainw.status.showMessage('IDLE')
        else:
            pt = self.genInterPoint(self.conn.pos2)
            b = Node(None, self.scene)
            b.setPos(pt)
            self.conn.port2 = b.port_in
            self.conn.pos2 = b.scenePos()
            self.conn.port1.connections.append(self.conn)
            self.conn.port2.connections.append(self.conn)
            self.conn.update_path()
            self.conn = None
            self.state = IDLE
            #self.scene.mainw.status.showMessage('IDLE')

    def P10(self, obj, event):
        item = self.itemAt(event.scenePos())
        self.setMouseByDraw(item)
        pt = self.genInterPoint(event.scenePos())
        self.conn.pos2 = pt
        self.conn.update_path()

    def P11(self, obj, event):
        item = self.itemAt(event.scenePos())
        if isinstance(item, Node):
            self.scene.DmgToUndo()
            self.state = DRAWFROMOUTPORT
            #self.scene.mainw.status.showMessage('DRAWFROMOUTPORT')
            self.conn = Connection(None, self.scene)
            self.conn.port1 = item.port_out
            self.conn.pos1 = item.scenePos()
            self.conn.pos2 = item.scenePos()

    def P12(self, obj, event):
        item = self.itemAt(event.scenePos())
        self.setMouseInitDraw(item)

    def eventFilter(self, obj, event):
        ev = -1
        if event.type() == QtCore.QEvent.GraphicsSceneMouseMove:
            ev = 0

        if event.type() == QtCore.QEvent.GraphicsSceneMousePress:
            if event.button() == QtCore.Qt.LeftButton:
                ev = 1
            if event.button() == QtCore.Qt.RightButton:
                ev = 2

        if event.type() == QtCore.QEvent.GraphicsSceneMouseRelease:
            ev = 3

        if event.type() == QtCore.QEvent.GraphicsSceneMouseDoubleClick:
            ev = 4

        if event.type() == QtCore.QEvent.KeyPress:
            if event.key() == QtCore.Qt.Key_Delete:
                ev = 5
            if event.key() == QtCore.Qt.Key_Escape:
                ev = 6
        if ev != -1:
            fun = self.Fun[self.state][ev]
            fun(obj, event)

        return False

    def gridPos(self, pt):
        gr = GRID
        x = gr * ((pt.x() + gr / 2) // gr)
        y = gr * ((pt.y() + gr / 2) // gr)
        return QtCore.QPointF(x, y)