コード例 #1
0
class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()

        # Config --------------------------------------
        self.objectList = {}
        self.systemIcon = {
            'folder':
            QIcon(QApplication.style().standardIcon(QStyle.SP_DirIcon)),
            'folderLink':
            QIcon(QApplication.style().standardIcon(QStyle.SP_DirLinkIcon)),
            'file':
            QIcon(QApplication.style().standardIcon(QStyle.SP_FileIcon)),
            'quit':
            QIcon(QApplication.style().standardIcon(
                QStyle.SP_DialogCloseButton))
        }
        self.filetypeIcon = Icons.icon_filetypes_flat(self)
        self.includeExclude = IncludeExclude()
        self.includeExclude.includePaths = ['Examples']
        self.includeExclude.includeExtensions = ['md', 'py', 'png']
        self.includeExclude.excludeFilenames = ['gitignore']
        self.includeExclude.excludePaths = ['git', '__pycache__']

        # --------------------------------------------
        self.create_menu()
        self.add_directory(
            '&Scripts',
            '/media/m/Data/Development/Phyton/TreeViewUltraMenu/Python-UltraMenu'
        )
        self.add_exit()

    def create_menu(self):
        self.menu = QMenu(self)
        # Enable theme, uncomment:
        self.menu.setStyleSheet(appStyle)
        self.menu.setCursor(QtCore.Qt.PointingHandCursor)
        tt1 = self.menu.addAction('Tooltip 1')
        tt1.setToolTip('t1')
        tt2 = self.menu.addAction('Tooltip 2')
        tt2.setToolTip('t2')
        tt3 = self.menu.addAction('Tooltip 3')
        tt3.setWhatsThis('setWhatsThis')
        tt3.setIconText('q')
        tt3.iconText()

        # custom style label
        text = QLabel("Label with custom text", self)
        text.setProperty('class', 'singlestyle')
        styleItem = QWidgetAction(self)
        styleItem.setDefaultWidget(text)
        styleItem.setProperty('class', 'singlestyle')
        tt4 = self.menu.addAction(styleItem)
        # tt4.setProperty('class', 'singlestyle')

        # tt4.Priority
        # tt4.setStyleSheet("QLabel { color: rgb(50, 50, 50); font-size: 11px; background-color: rgba(188, 188, 188, 50); border: 1px solid rgba(188, 188, 188, 250); }")
        self.menu.setToolTipsVisible(True)
        # self.menu.setIcon
        # self.menu.setwha(True)
        # self.menu.hovered.connect(lambda tt1= tt1, tt1())
        # self.menu.keyPressEvent(self.keyPressEvent)
        # pos = tt3.
        self.menu.installEventFilter(self)
        # widgetRect = self.menu.mapToGlobal()
        p = (0, 0)
        # print(self.menu.mapToGlobal(0,0))
        widgetRect = self.geometry()

        print(widgetRect)
        # tt2.hovered.connect(lambda tt2=self.tt2, tt2.tooltip())
        tt3.hovered.connect(lambda pos=[self], parent=self.menu, index=2: self.
                            show_toolTip(pos, parent, index))

    # Listen for All KeyPress/Mouse events
    def eventFilter(self, widget, event):
        if (event.type() == QtCore.QEvent.KeyRelease and widget is self.menu):
            self.menu.toolTip()
            print('all')

            # self.
            key = event.key()
            if key == QtCore.Qt.Key_Escape:
                print('escape')
            else:
                if key == QtCore.Qt.Key_Return:
                    print('escape')
                elif key == QtCore.Qt.Key_Enter:
                    print('escape')
                elif key == QtCore.Qt.Key_C:
                    print('Key - c')
                return True
        # return QtGui.QWidget.eventFilter(self, widget, event)

    def show_toolTip(self, pos, parent, index):
        '''
        **Parameters**
            pos:    list
                list of all parent widget up to the upmost

            parent: PySide.QtGui.QAction
                the parent QAction

            index:  int
                place within the QMenu, beginning with zero
        '''
        position_x = 0
        position_y = 0
        for widget in pos:
            position_x += widget.pos().x()
            position_y += widget.pos().y()

        point = QtCore.QPoint()
        point.setX(position_x)
        point.setY(position_y + index * 22)  # set y Position of QToolTip
        QToolTip.showText(point, parent.toolTip())

    def add_directory(self, label, dir):

        qtParentMenuItem = self.menu.addMenu(self.systemIcon['folder'], label)
        parentMenuClass = FolderItem(qtMenuItem=qtParentMenuItem,
                                     label=label,
                                     iconPath='',
                                     globalHotkey='',
                                     path=Path(dir))
        uid = parentMenuClass.getUid()
        self.objectList[uid] = parentMenuClass
        self.add_directory_submenu(parentMenuClass)

    def add_directory_submenu(self, parentMenuClass: FolderItem):

        qtParentMenuItem = parentMenuClass.getQtMenuItem()

        # Don't add the menu items multiple times, every time you hover a submenu.
        if parentMenuClass.isSubmenuItemsAdded == True:
            return None

        parentMenuClass.isSubmenuItemsAdded = True
        dirPath: str = parentMenuClass.getFullPath()
        osPaths = sorted(Path(dirPath).glob('*'))
        osPaths.sort(key=lambda x: x.is_file())
        filesAndFoldersArr = []

        for item in osPaths:
            # path = dirPath + '/' + item.name
            if item.is_dir(
            ) == True and self.includeExclude.folderIsNotExcluded(item):

                folderIcon = self.systemIcon['folder']

                if item.is_symlink():
                    folderIcon = self.systemIcon['folderLink']

                qtFolderItem = qtParentMenuItem.addMenu(
                    folderIcon, '&' + item.name)
                folderItemClass = FolderItem(qtMenuItem=qtFolderItem,
                                             label=item.name,
                                             iconPath='',
                                             globalHotkey='',
                                             path=item)
                uid = folderItemClass.getUid()
                self.objectList[uid] = folderItemClass
                filesAndFoldersArr.append(folderItemClass)
                qtFolderItem.aboutToShow.connect(
                    lambda folderItemClass=folderItemClass: self.
                    add_directory_submenu(folderItemClass))
                # newFolder.triggered.connect(self.action_directory(item.uid))

            elif item.is_file() and self.includeExclude.fileIsNotExcluded(
                    item):

                fileExt = item.suffix

                qtIcon = self.systemIcon['file']

                # If we have a icon for the filetype, use that instead
                if fileExt in self.filetypeIcon:
                    qtIcon = QIcon(str(self.filetypeIcon[fileExt]))

                qtFileItem = qtParentMenuItem.addAction(qtIcon, item.name)
                folderItemClass = FolderItem(qtMenuItem=qtFileItem,
                                             label=item.name,
                                             iconPath='',
                                             globalHotkey='',
                                             path=item)
                uid = folderItemClass.getUid()
                self.objectList[uid] = folderItemClass
                filesAndFoldersArr.append(folderItemClass)
                # filename
                # item.name
                # extension
                # item.suffix
                # newFile.triggered.connect(self.action_directory(item.uid))
                #         # newFile.hovered.connect(self.exit_app)
                #         # newFile.hovered.connect(lambda:  item.printUid())

                #         # func = self.hover()
                #         # newFile.hovered.connect(lambda f=func,arg=newFile:f(arg))
            else:
                print("It is a special file (socket, FIFO, device file)")

    def action_directory(self, uid):
        print(uid)

    def add_exit(self):
        exit = self.menu.addAction(self.systemIcon['quit'], '&Quit')
        self.menu.insertSeparator(exit)
        exit.triggered.connect(self.exit_app)
        self.menu.exec_(QCursor.pos())

    def exit_app(self):
        self.close()
        sys.exit(0)
コード例 #2
0
class QGraphicsBlockItem(QGraphicsPixmapItem, Block, QObject):

    def __init__(self, _parent, _imgfile: str, _functionname: str, _translations: dict, _vars: list, _connections: dict,
                 _type: BlockType, _typeIMG: BlockImgType, _nameControl: str = "", img=None):
        self._parent = _parent
        self._translations = _translations
        self._vars = _vars
        self.initConections(_connections)
        self._language = Language()
        self.__functionname = _functionname
        self._type = _type
        self._typeImg = _typeIMG
        self._nameControl = _nameControl
        self.c, self.cS = None, None
        # self.timer = QTimer()
        # self.timer.timeout.connect(self.updateSize)
        # self.timer.start(100)
        QObject.__init__(self)

        QGraphicsPixmapItem.__init__(self)
        if img is None:
            img = PILImagetoCV2Image(Image.open(_imgfile))

        _varstext = self.listValuesVars()

        Block.__init__(self, _img=img, _text1="", _text2=self._nameControl, _vars=_varstext, _type=self._type, _typeIMG=self._typeImg)

        self.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.setAcceptHoverEvents(True)
        self.setZValue(1)
        self.initPopUpMenu()
        self._language.changed.connect(self.changeLanguage)
        self.imgchanged.connect(self.repaintImg)
        self.changeLanguage()
        super(QGraphicsBlockItem, self).setPos(QPointF(0, 0))
        # self.setEnabled(False)

    @classmethod
    def fromBlock(cls, block, _functionname, _translations, _imgfileconf):
        _, _connections  = loadConnection(_imgfileconf=_imgfileconf, cls=None)

        return cls(_parent=None, _imgfile="", _functionname=_functionname, _translations=_translations,_vars=[],
                   _connections=_connections,_type=block._type,_typeIMG=block._typeIMG,_nameControl=block.text2,img=block._img)

    def __str__(self):
        return str(self.id)

    @property
    def functionname(self):
        return self.__functionname

    def initConections(self, conf):
        self._connections = {}
        self._typeImg = BlockImgType.fromString(conf["type"])
        for p in conf["points"]:
            _type = ConnectionType.fromString(p["type"])
            self._connections[_type] = Connection(point=Point(p["x"], p["y"]), parent=self, type=_type)

    def initPopUpMenu(self):
        self.popMenu = QMenu()

        scene = self._parent.scene
        self.popMenu.addAction(scene.undoAction)
        self.popMenu.addAction(scene.redoAction)
        self.popMenu.addAction(scene.disableAction)
        self.keyPressEater = KeyPressEater(self.popMenu)
        self.popMenu.installEventFilter(self.keyPressEater)
        action1 = QAction(self.tr('Edit'), self)
        # action1.triggered.connect(self.on_clicked_menu_edit)
        self.popMenu.addAction(action1)
        if self.__functionname not in ["main", "when"]:
            if self._type is BlockType.USERFUNCTION and self._typeIMG is BlockImgType.COMPLEXBLOCK:
                action3 = QAction(self.tr('Export Block'), self)
                action3.triggered.connect(self.on_clicked_menu_export_block)
                self.popMenu.addAction(action3)
            else:
                action0 = QAction(self.tr('Duplicate'), self)
                action0.triggered.connect(self.on_clicked_menu_duplicate)
                self.popMenu.addAction(action0)

        self.popMenu.addSeparator()
        action2 = QAction(self.tr('Delete'), self)
        action2.triggered.connect(self.on_clicked_menu_delete)
        action2.installEventFilter(self.keyPressEater)
        self.popMenu.addAction(action2)
        # self.pos

    def on_clicked_menu_edit(self):
        raise NotImplementedError("on_clicked_menu_export_block")

    def on_clicked_menu_export_block(self):
        raise NotImplementedError("on_clicked_menu_export_block")

    def on_clicked_menu_duplicate(self):
        raise NotImplementedError("on_clicked_menu_export_block")

    def on_clicked_menu_delete(self):
        if self.scene() is not None:
            self.scene().undoStack.push(DeleteCommand(self, self.scene()))
            # self.scene().removeItem(self)

    @Slot()
    def changeLanguage(self):
        self.text1 = self._translations[self._language.language]

    def repaintImg(self):
        self.setPixmap(self.img.toqpixmap())
        for type, c in iter(self._connections.items()):
            otherConnect, otherId = c.connect
            if type is ConnectionType.BOTTOM:
                c.point.move(0, self.pixmap().height() - 5 - c.point.y)
                if otherId is not None:
                    otherConnect.parent.setPos(self.pos() + QPointF(0, self.pixmap().height() - 5), True)
            if type is ConnectionType.RIGHT:
                c.point.move(self.pixmap().width() - 5 - c.point.x, 0)
                if otherId is not None:
                    otherConnect.parent.setPos(self.pos() + QPointF(self.pixmap().width() - 5, 0), True)

    def updateSize(self):
        _, self.block_size = self.getNumSub()
        self._resized()

    def _resized(self):
        if ConnectionType.TOP in self._connections and self._connections[ConnectionType.TOP].connected():
            self._connections[ConnectionType.TOP].connect[0].parent.updateSize()

    def listValuesVars(self):
        return [str(v.value) for v in self._vars]

    def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent):
        selectedItems = self.scene().selectedItems()
        if self in selectedItems:
            for item in selectedItems:
                item.setHover(True)
        else:
            self.setHover(True)

    def hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent):
        selectedItems = self.scene().selectedItems()
        if self in selectedItems:
            for item in selectedItems:
                item.setHover(False)
        else:
            self.setHover(False)

    def setHover(self, hover):
        self.hover = hover
        if ConnectionType.BOTTOM in self._connections and self._connections[ConnectionType.BOTTOM].connected():
            self._connections[ConnectionType.BOTTOM].connect[0].parent.setHover(hover)
        if ConnectionType.RIGHT in self._connections and self._connections[ConnectionType.RIGHT].connected():
            self._connections[ConnectionType.RIGHT].connect[0].parent.setHover(hover)
        if ConnectionType.BOTTOMIN in self._connections and self._connections[ConnectionType.BOTTOMIN].connected():
            self._connections[ConnectionType.BOTTOMIN].connect[0].parent.setHover(hover)

    def setZValue(self, z: float):
        super(QGraphicsBlockItem, self).setZValue(z)
        if ConnectionType.BOTTOM in self._connections and self._connections[ConnectionType.BOTTOM].connected():
            self._connections[ConnectionType.BOTTOM].connect[0].parent.setZValue(z)
        if ConnectionType.RIGHT in self._connections and self._connections[ConnectionType.RIGHT].connected():
            self._connections[ConnectionType.RIGHT].connect[0].parent.setZValue(z)
        if ConnectionType.BOTTOMIN in self._connections and self._connections[ConnectionType.BOTTOMIN].connected():
            self._connections[ConnectionType.BOTTOMIN].connect[0].parent.setZValue(z)

    def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
        if self.isEnabled():
            self.setZValue(1)
            if event.button() is Qt.MouseButton.LeftButton:
                pass
                # self.posmouseinItem = event.scenePos() - self.pos()
                # items = self.scene().selectedItems()
                # if self not in items:
                #     self.scene().clearSelection()
                # if self.DialogVar is not None:
                #     self.DialogVar.close()
            if event.button() is Qt.MouseButton.RightButton:
                self.popMenu.exec_(event.screenPos())

    def setPos(self, pos: QPointF, connect=False):
        super(QGraphicsBlockItem, self).setPos(pos)
        for type, c in iter(self._connections.items()):
            otherConnect, otherId = c.connect
            if otherId is not None:
                if type in [ConnectionType.TOP, ConnectionType.LEFT] and not connect:
                    c.connect = None
                    otherConnect.connect = None
                    otherConnect.parent.updateSize()
                elif c.type is ConnectionType.BOTTOM:
                    otherConnect.parent.setPos(self.pos() + QPointF(0, self.pixmap().height() - 5), True)
                elif c.type is ConnectionType.BOTTOMIN:
                    otherConnect.parent.setPos(self.pos() + QPointF(17, 33), True)
                elif c.type is ConnectionType.RIGHT:
                    otherConnect.parent.setPos(self.pos() + QPointF(self.pixmap().width() - 5, 0), True)

    def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent):
        self.setZValue(-1)
        self.scene().imgPosibleConnectH.setVisible(False)
        self.scene().imgPosibleConnectV.setVisible(False)
        self.connecting()

    def getLastItem(self):
        if ConnectionType.BOTTOM in self._connections:
            c = self._connections[ConnectionType.BOTTOM]
            if c.connect[0] is None:
                return c
            else:
                return c.connect[0].parent.getLastItem()
        return None

    def getLastRightItem(self):
        if ConnectionType.RIGHT in self._connections:
            c = self._connections[ConnectionType.RIGHT]
            if c.connect[0] is None:
                return c
            else:
                return c.connect[0].parent.getLastRightItem()
        return None

    def connecting(self):
        if self.c is None or self.cS is None:
            return
        if self.cS.connect[0] is self.c:
            return
        if self.c.connect[0] is not None:
            if self.c.type is ConnectionType.TOP:
                pass
            elif self.c.type in [ConnectionType.BOTTOM, ConnectionType.BOTTOMIN]:
                cNext, _ = self.c.connect
                cLastIt = self.getLastItem()
                if cLastIt is not None:
                    cLastIt.connect = cNext
                    cNext.connect = cLastIt
            elif self.c.type is ConnectionType.RIGHT:
                cNext, _ = self.c.connect
                cLastIt = self.getLastRightItem()
                if cLastIt is not None:
                    cLastIt.connect = cNext
                    cNext.connect = cLastIt
        self.c.connect = self.cS
        self.cS.connect = self.c
        otherBlock = self.c.parent
        if self.c.type is ConnectionType.TOP:
            self.setPos(otherBlock.pos() + QPointF(0, - otherBlock.pixmap().height() + 5), True)
        elif self.c.type is ConnectionType.BOTTOM:
            self.setPos(otherBlock.pos() + QPointF(0, otherBlock.pixmap().height() - 5), True)
        elif self.c.type is ConnectionType.RIGHT:
            self.setPos(otherBlock.pos() + QPointF(otherBlock.pixmap().width() - 5, 0), True)
        elif self.c.type is ConnectionType.LEFT:
            self.setPos(otherBlock.pos() + QPointF(-otherBlock.pixmap().width() + 5, 0), True)
        elif self.c.type is ConnectionType.BOTTOMIN:
            self.setPos(otherBlock.pos() + QPointF(17, 33), True)
        self.updateSize()

    def getNumSubBottom(self, n=0, size=0):
        size += self.pixmap().height() - 5
        if ConnectionType.BOTTOM in self._connections:
            c = self._connections[ConnectionType.BOTTOM]
            if c.connect[1] is None:
                return n + 1, size + 1
            else:
                return c.connect[0].parent.getNumSubBottom(n + 1, size)
        return n + 1, size + 1

    def getDependsItems(self):
        items = [self]
        for type in [ConnectionType.BOTTOMIN, ConnectionType.BOTTOM]:
            if type in self._connections:
                item,_ = self._connections[ConnectionType.BOTTOMIN].connect
                if item is not None:
                    items += item.parent.getDependsItems()
        return items


    def getNumSub(self, n=0):
        if ConnectionType.BOTTOMIN in self._connections:
            c = self._connections[ConnectionType.BOTTOMIN]
            if c.connect[1] is None:
                return 0, 34
            else:
                return c.connect[0].parent.getNumSubBottom()
        return 0, 34

    def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent):
        super(QGraphicsBlockItem, self).mouseMoveEvent(event)
        self.setPos(event.scenePos() - event.buttonDownPos(Qt.MouseButton.LeftButton))
        self.c, self.cS = self.closestItem()
        imgPosibleConnectH = self.scene().imgPosibleConnectH
        imgPosibleConnectV = self.scene().imgPosibleConnectV
        if self.c is not None:
            if self.c.type is ConnectionType.TOP:
                imgPosibleConnectH.setPos(self.c.parent.pos())
                imgPosibleConnectH.setVisible(True)
                imgPosibleConnectH.setZValue(1)
            elif self.c.type is ConnectionType.BOTTOM:
                imgPosibleConnectH.setPos(self.c.parent.pos() + QPointF(0, self.c.parent.pixmap().height() - 5))
                imgPosibleConnectH.setVisible(True)
                imgPosibleConnectH.setZValue(1)
            elif self.c.type is ConnectionType.RIGHT:
                imgPosibleConnectV.setPos(
                    self.c.parent.pos() + QPointF(self.c.parent.pixmap().width() - 5, 0) + QPointF(0, 5))
                imgPosibleConnectV.setVisible(True)
                imgPosibleConnectV.setZValue(1)
            elif self.c.type is ConnectionType.LEFT:
                imgPosibleConnectV.setPos(self.c.parent.pos() + QPointF(0, 5))
                imgPosibleConnectV.setVisible(True)
                imgPosibleConnectV.setZValue(1)
            elif self.c.type is ConnectionType.BOTTOMIN:
                imgPosibleConnectH.setPos(self.c.parent.pos() + QPointF(16, 38))
                imgPosibleConnectH.setVisible(True)
                imgPosibleConnectH.setZValue(1)
        else:
            imgPosibleConnectH.setVisible(False)
            imgPosibleConnectV.setVisible(False)

    def closestItem(self):
        min_dist = None
        min_c = None
        min_cS = None
        if self.scene() is not None:
            sceneitems = self.scene().items()
        else:
            sceneitems = []
        sceneitems = [x for x in sceneitems if isinstance(x, QGraphicsBlockItem)]
        for type, c in iter(self._connections.items()):
            for otherItem in sceneitems:
                if self is not otherItem and otherItem.isEnabled():
                    for othertype, otherc in iter(otherItem._connections.items()):
                        if (type is ConnectionType.TOP and othertype in [ConnectionType.BOTTOMIN,
                                                                         ConnectionType.BOTTOM]) or \
                                (type is ConnectionType.LEFT and othertype is ConnectionType.RIGHT):
                            dist = c.pos.distance(otherc.pos)
                            if min_dist is None or dist < min_dist:
                                min_c = otherc
                                min_cS = c
                                min_dist = dist
        self.setZValue(1)
        if min_dist is not None and min_dist < 30:
            return min_c, min_cS
        return None, None

    def getInstructionsByType(self, type: ConnectionType):
        if type in self._connections and self._connections[type].connected():
            inst = self._connections[type].connect[0].parent.getInstructions()
            return inst
        return None

    def getInstructions(self):
        instRight = self.getInstructionsByType(ConnectionType.RIGHT)
        instBottom = self.getInstructionsByType(ConnectionType.BOTTOM)
        instBottomIn = self.getInstructionsByType(ConnectionType.BOTTOMIN)
        nameControl = self._nameControl
        if nameControl is "":
            nameControl = None
        dic = dict(NAMECONTROL=nameControl, RIGHT=instRight, BOTTOM=instBottom, BOTTOMIN=instBottomIn, VARIABLES=self.getVars(), TYPE=self._type)
        return self.__functionname, dic

    def getVars(self):
        vars = []
        for var in self._vars:
            value = str(var.value)
            if var.type in [VariableType.APRILTEXT, VariableType.STRING]:
                value = '"' + value + '"'
            vars.append(value)
        if len(vars) is 0:
            vars = None
        return vars

    def isBlockDef(self):
        return (self.__functionname == "when") or (
                    len(self._connections) is 1 and ConnectionType.BOTTOMIN in self._connections)

    def setEnabled(self, enabled:bool):
        super(QGraphicsBlockItem, self).setEnabled(enabled)
        if not enabled:
            _, _, _, a = self.img.split()
            img = self.img.convert('L').convert('RGB')
            img.putalpha(a)
        else:
            img = self.img
        self.setPixmap(img.toqpixmap())
        for _type in [ConnectionType.BOTTOMIN, ConnectionType.BOTTOM, ConnectionType.RIGHT]:
            if _type in self._connections and self._connections[_type].connected():
                self._connections[_type].connect[0].parent.setEnabled(enabled)