def onExportToPackage(self):
        # check if category is not empty
        if self._rawNode._rawGraph.category == '':
            QMessageBox.information(
                None, "Warning",
                "Category is not set! Please step into compound and type category name."
            )
            return

        packageNames = list(GET_PACKAGES().keys())
        selectedPackageName, accepted = QInputDialog.getItem(None,
                                                             "Select",
                                                             "Select package",
                                                             packageNames,
                                                             editable=False)
        if accepted:
            packagePath = GET_PACKAGE_PATH(selectedPackageName)
            compoundsDir = os.path.join(packagePath, "Compounds")
            if not os.path.isdir(compoundsDir):
                os.mkdir(compoundsDir)
            self.onExport(root=compoundsDir)
            # refresh node box
            app = self.canvasRef().getApp()
            nodeBoxes = app.getRegisteredTools(
                classNameFilters=["NodeBoxTool"])
            for nodeBox in nodeBoxes:
                nodeBox.refresh()
Esempio n. 2
0
    def populateMenu(self):
        fileMenu = self.menuBar.addMenu("File")
        newFileAction = fileMenu.addAction("New file")
        newFileAction.setIcon(QtGui.QIcon(":/new_file_icon.png"))
        newFileAction.triggered.connect(self.newFile)

        loadAction = fileMenu.addAction("Load")
        loadAction.setIcon(QtGui.QIcon(":/folder_open_icon.png"))
        loadAction.triggered.connect(self.load)

        saveAction = fileMenu.addAction("Save")
        saveAction.setIcon(QtGui.QIcon(":/save_icon.png"))
        saveAction.triggered.connect(self.save)

        saveAsAction = fileMenu.addAction("Save as")
        saveAsAction.setIcon(QtGui.QIcon(":/save_as_icon.png"))
        saveAsAction.triggered.connect(lambda: self.save(True))

        IOMenu = fileMenu.addMenu("Custom IO")
        for packageName, package in GET_PACKAGES().items():
            # exporters
            exporters = None
            try:
                exporters = package.GetExporters()
            except:
                continue
            pkgMenu = IOMenu.addMenu(packageName)
            for exporterName, exporterClass in exporters.items():
                fileFormatMenu = pkgMenu.addMenu(exporterClass.displayName())
                fileFormatMenu.setToolTip(exporterClass.toolTip())
                if exporterClass.createExporterMenu():
                    exportAction = fileFormatMenu.addAction("Export")
                    exportAction.triggered.connect(
                        lambda checked=False, app=self, exporter=exporterClass:
                        exporter.doExport(app))
                if exporterClass.createImporterMenu():
                    importAction = fileFormatMenu.addAction("Import")
                    importAction.triggered.connect(
                        lambda checked=False, app=self, exporter=exporterClass:
                        exporter.doImport(app))

        editMenu = self.menuBar.addMenu("Edit")
        preferencesAction = editMenu.addAction("Preferences")
        preferencesAction.setIcon(QtGui.QIcon(":/options_icon.png"))
        preferencesAction.triggered.connect(self.showPreferencesWindow)

        pluginsMenu = self.menuBar.addMenu("Plugins")
        packagePlugin = pluginsMenu.addAction("Create package...")
        packagePlugin.triggered.connect(PackageWizard.run)

        helpMenu = self.menuBar.addMenu("Help")
        helpMenu.addAction("Homepage").triggered.connect(
            lambda _=False, url=
            "https://wonderworks-software.github.io/PyFlow/": QtGui.
            QDesktopServices.openUrl(url))
        helpMenu.addAction("Docs").triggered.connect(
            lambda _=False, url="https://pyflow.readthedocs.io/en/latest/":
            QtGui.QDesktopServices.openUrl(url))
Esempio n. 3
0
    def populateMenu(self):
        fileMenu = self.menuBar.addMenu("File")
        newFileAction = fileMenu.addAction("New file")
        newFileAction.setIcon(QtGui.QIcon(":/new_file_icon.png"))
        newFileAction.triggered.connect(self.newFile)

        loadAction = fileMenu.addAction("Load")
        loadAction.setIcon(QtGui.QIcon(":/folder_open_icon.png"))
        loadAction.triggered.connect(self.load)

        saveAction = fileMenu.addAction("Save")
        saveAction.setIcon(QtGui.QIcon(":/save_icon.png"))
        saveAction.triggered.connect(self.save)

        saveAsAction = fileMenu.addAction("Save as")
        saveAsAction.setIcon(QtGui.QIcon(":/save_as_icon.png"))
        saveAsAction.triggered.connect(lambda: self.save(True))

        IOMenu = fileMenu.addMenu("Custom IO")
        for packageName, package in GET_PACKAGES().items():
            # exporters
            exporters = None
            try:
                exporters = package.GetExporters()
            except:
                continue
            pkgMenu = IOMenu.addMenu(packageName)
            for exporterName, exporterClass in exporters.items():
                fileFormatMenu = pkgMenu.addMenu(exporterClass.displayName())
                fileFormatMenu.setToolTip(exporterClass.toolTip())
                if exporterClass.createExporterMenu():
                    exportAction = fileFormatMenu.addAction("Export")
                    exportAction.triggered.connect(
                        lambda checked=False, app=self, exporter=exporterClass:
                        exporter.doExport(app))
                if exporterClass.createImporterMenu():
                    importAction = fileFormatMenu.addAction("Import")
                    importAction.triggered.connect(
                        lambda checked=False, app=self, exporter=exporterClass:
                        exporter.doImport(app))

        editMenu = self.menuBar.addMenu("Edit")
        preferencesAction = editMenu.addAction("Preferences")
        preferencesAction.setIcon(QtGui.QIcon(":/options_icon.png"))
        preferencesAction.triggered.connect(self.showPreferencesWindow)

        pluginsMenu = self.menuBar.addMenu("Plugins")
        packagePlugin = pluginsMenu.addAction("Create package...")
        packagePlugin.triggered.connect(PackageWizard.run)

        helpMenu = self.menuBar.addMenu("Help")
        shortcutsAction = helpMenu.addAction("Shortcuts")
        shortcutsAction.setIcon(QtGui.QIcon(":/shortcuts_icon.png"))
        shortcutsAction.triggered.connect(self.shortcuts_info)
Esempio n. 4
0
 def onExportToPackage(self):
     packageNames = list(GET_PACKAGES().keys())
     selectedPackageName, accepted = QInputDialog.getItem(None, "Select", "Select package", packageNames, editable=False)
     if accepted:
         packagePath = GET_PACKAGE_PATH(selectedPackageName)
         pyNodesDir = os.path.join(packagePath, "PyNodes")
         if not os.path.isdir(pyNodesDir):
             os.mkdir(pyNodesDir)
         self.onExport(root=pyNodesDir)
         # refresh node boxes
         app = self.canvasRef().getApp()
         nodeBoxes = app.getRegisteredTools(classNameFilters=["NodeBoxTool"])
         for nodeBox in nodeBoxes:
             nodeBox.refresh()
def getInputWidget(dataType, dataSetter, defaultValue, widgetVariant=DEFAULT_WIDGET_VARIANT, **kwds):
    '''
    factory method
    '''

    # try to find factory in other packages first
    for pkgName, pkg in GET_PACKAGES().items():
        # skip self
        if pkgName == PACKAGE_NAME:
            continue

        try:
            widget = pkg.PinsInputWidgetFactory()(dataType, dataSetter, defaultValue, widgetVariant=widgetVariant, **kwds)
            if widget is not None:
                return widget
        except Exception as e:
            print("Failed to override input widget. Package - {0}".format(pkgName), e)
            continue

    if dataType == 'FloatPin':
        if kwds is not None and "pinAnnotations" in kwds:
            if kwds["pinAnnotations"] is not None and "ValueRange" in kwds["pinAnnotations"]:
                return FloatInputWidget(dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
        return FloatInputWidgetSimple(dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
    if dataType == 'IntPin':
        if kwds is not None and "pinAnnotations" in kwds:
            if kwds["pinAnnotations"] is not None and "ValueRange" in kwds["pinAnnotations"]:
                return IntInputWidget(dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
        return IntInputWidgetSimple(dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
    if dataType == 'StringPin':
        if widgetVariant == DEFAULT_WIDGET_VARIANT:
            return StringInputWidget(dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
        elif widgetVariant == "PathWidget":
            return PathInputWidget(mode="all", dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
        elif widgetVariant == "FilePathWidget":
            return PathInputWidget(mode="file", dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
        elif widgetVariant == "FolderPathWidget":
            return PathInputWidget(mode="directory", dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)            
        elif widgetVariant == "EnumWidget":
            return EnumInputWidget(dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
        elif widgetVariant == "ObjectPathWIdget":
            return ObjectPathWIdget(dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
    if dataType == 'BoolPin':
        return BoolInputWidget(dataSetCallback=dataSetter, defaultValue=defaultValue, **kwds)
    if dataType == 'ExecPin':
        return ExecInputWidget(dataSetCallback=dataSetter, defaultValue=None, **kwds)
    if dataType == 'AnyPin':
        return NoneInputWidget(dataSetCallback=dataSetter, defaultValue=None, **kwds)
Esempio n. 6
0
def validateGraphDataPackages(graphData, missedPackages=set()):
    """Checks if packages used in serialized data accessible

    Missed packages will be added to output set

    :param graphData: Serialized graph
    :type graphData: dict
    :param missedPackages: Package names that missed
    :type missedPackages: str
    :rtype: bool
    """
    existingPackages = GET_PACKAGES().keys()
    graphPackages = fetchPackageNames(graphData)
    for pkg in graphPackages:
        if pkg not in existingPackages:
            missedPackages.add(pkg)
    return len(missedPackages) == 0
Esempio n. 7
0
    def loadFromData(self, data, fpath=""):

        # check first if all packages we are trying to load are legal
        existingPackages = GET_PACKAGES().keys()
        graphPackages = PyFlow.fetchPackageNames(data)
        missedPackages = set()
        for pkg in graphPackages:
            if pkg not in existingPackages:
                missedPackages.add(pkg)
        if len(missedPackages) > 0:
            msg = "This graph can not be loaded. Following packages not found:\n\n"
            index = 1
            for missedPackageName in missedPackages:
                msg += "{0}. {1}\n".format(index, missedPackageName)
                index += 1
            QMessageBox.critical(self, "Missing dependencies", msg)
            return

        self.newFile(keepRoot=False)
        # load raw data
        self.graphManager.get().deserialize(data)
        self.fileBeenLoaded.emit()
        self.graphManager.get().selectGraphByName(data["activeGraph"])
Esempio n. 8
0
    def instance(parent=None):
        if PyFlow.appInstance is not None:
            return PyFlow.appInstance

        settings = ConfigManager().getSettings("APP_STATE")

        instance = PyFlow(parent)
        REGISTER_TOOL("PyFlowBase", LoggerTool)
        a = GET_TOOLS()["PyFlowBase"][0]()
        a.setAppInstance(instance)
        instance.registerToolInstance(a)
        instance.addDockWidget(a.defaultDockArea(), a)
        a.setAppInstance(instance)
        a.onShow()

        try:
            extraPackagePaths = []
            extraPathsString = ConfigManager().getPrefsValue(
                "PREFS", "General/ExtraPackageDirs")
            if extraPathsString is not None:
                extraPathsString = extraPathsString.rstrip(";")
                extraPathsRaw = extraPathsString.split(";")
                for rawPath in extraPathsRaw:
                    if os.path.exists(rawPath):
                        extraPackagePaths.append(os.path.normpath(rawPath))
            INITIALIZE(additionalPackageLocations=extraPackagePaths)
        except Exception as e:
            QMessageBox.critical(None, "Fatal error", str(e))
            return

        instance.startMainLoop()

        # populate tools
        canvas = instance.getCanvas()
        toolbar = instance.getToolbar()

        geo = settings.value('Editor/geometry')
        if geo is not None:
            instance.restoreGeometry(geo)
        state = settings.value('Editor/state')
        if state is not None:
            instance.restoreState(state)
        settings.beginGroup("Tools")
        for packageName, registeredToolSet in GET_TOOLS().items():
            for ToolClass in registeredToolSet:
                if issubclass(ToolClass, ShelfTool):
                    ToolInstance = ToolClass()
                    # prevent to be garbage collected
                    instance.registerToolInstance(ToolInstance)
                    ToolInstance.setAppInstance(instance)
                    action = QAction(instance)
                    action.setIcon(ToolInstance.getIcon())
                    action.setText(ToolInstance.name())
                    action.setToolTip(ToolInstance.toolTip())
                    action.setObjectName(ToolInstance.name())
                    action.triggered.connect(ToolInstance.do)
                    # check if context menu data available
                    menuBuilder = ToolInstance.contextMenuBuilder()
                    if menuBuilder:
                        menuGenerator = ContextMenuGenerator(menuBuilder)
                        menu = menuGenerator.generate()
                        action.setMenu(menu)
                    toolbar.addAction(action)

                    # step to ShelfTools/ToolName group and pass settings inside
                    settings.beginGroup("ShelfTools")
                    settings.beginGroup(ToolClass.name())
                    ToolInstance.restoreState(settings)
                    settings.endGroup()
                    settings.endGroup()

                if issubclass(ToolClass, DockTool):
                    menus = instance.menuBar.findChildren(QMenu)
                    pluginsMenuAction = [
                        m for m in menus if m.title() == "Plugins"
                    ][0].menuAction()
                    toolsMenu = getOrCreateMenu(instance.menuBar, "Tools")
                    instance.menuBar.insertMenu(pluginsMenuAction, toolsMenu)
                    packageSubMenu = getOrCreateMenu(toolsMenu, packageName)
                    toolsMenu.addMenu(packageSubMenu)
                    showToolAction = packageSubMenu.addAction(ToolClass.name())
                    icon = ToolClass.getIcon()
                    if icon:
                        showToolAction.setIcon(icon)
                    showToolAction.triggered.connect(
                        lambda pkgName=packageName, toolName=ToolClass.name(
                        ): instance.invokeDockToolByName(pkgName, toolName))

                    settings.beginGroup("DockTools")
                    childGroups = settings.childGroups()
                    for dockToolGroupName in childGroups:
                        # This dock tool data been saved on last shutdown
                        settings.beginGroup(dockToolGroupName)
                        if dockToolGroupName in [
                                t.uniqueName() for t in instance._tools
                        ]:
                            continue
                        toolName = dockToolGroupName.split("::")[0]
                        instance.invokeDockToolByName(packageName, toolName,
                                                      settings)
                        settings.endGroup()
                    settings.endGroup()

        PyFlow.appInstance = instance
        EditorHistory().saveState("New file")

        for name, package in GET_PACKAGES().items():
            prefsWidgets = package.PrefsWidgets()
            if prefsWidgets is not None:
                for categoryName, widgetClass in prefsWidgets.items():
                    PreferencesWindow().addCategory(categoryName,
                                                    widgetClass())
                PreferencesWindow().selectByName("General")

        return instance
Esempio n. 9
0
    def instance(parent=None, software=""):
        assert (
            software != ""
        ), "Invalid arguments. Please pass you software name as second argument!"

        instance = PyFlow(parent)
        settings = ConfigManager().getSettings("APP_STATE")
        instance.currentSoftware = software
        SessionDescriptor().software = instance.currentSoftware

        if software == "standalone":
            editableStyleSheet(instance)

        try:
            extraPackagePaths = []
            extraPathsString = ConfigManager().getPrefsValue(
                "PREFS", "General/ExtraPackageDirs")
            if extraPathsString is not None:
                extraPathsString = extraPathsString.rstrip(";")
                extraPathsRaw = extraPathsString.split(";")
                for rawPath in extraPathsRaw:
                    if os.path.exists(rawPath):
                        extraPackagePaths.append(os.path.normpath(rawPath))
            INITIALIZE(additionalPackageLocations=extraPackagePaths,
                       software=software)
        except Exception as e:
            QMessageBox.critical(None, "Fatal error", str(e))
            return

        instance.startMainLoop()

        # populate tools
        canvas = instance.getCanvas()
        toolbar = instance.getToolbar()

        # populate menus
        instance.populateMenu()

        geo = settings.value('Editor/geometry')
        if geo is not None:
            instance.restoreGeometry(geo)
        state = settings.value('Editor/state')
        if state is not None:
            instance.restoreState(state)
        settings.beginGroup("Tools")
        for packageName, registeredToolSet in GET_TOOLS().items():
            for ToolClass in registeredToolSet:
                if issubclass(ToolClass, ShelfTool):
                    ToolInstance = ToolClass()
                    # prevent to be garbage collected
                    instance.registerToolInstance(ToolInstance)
                    ToolInstance.setAppInstance(instance)
                    action = QAction(instance)
                    action.setIcon(ToolInstance.getIcon())
                    action.setText(ToolInstance.name())
                    action.setToolTip(ToolInstance.toolTip())
                    action.setObjectName(ToolInstance.name())
                    action.triggered.connect(ToolInstance.do)
                    # check if context menu data available
                    menuBuilder = ToolInstance.contextMenuBuilder()
                    if menuBuilder:
                        menuGenerator = ContextMenuGenerator(menuBuilder)
                        menu = menuGenerator.generate()
                        action.setMenu(menu)
                    toolbar.addAction(action)

                    # step to ShelfTools/ToolName group and pass settings inside
                    settings.beginGroup("ShelfTools")
                    settings.beginGroup(ToolClass.name())
                    ToolInstance.restoreState(settings)
                    settings.endGroup()
                    settings.endGroup()

                if issubclass(ToolClass, DockTool):
                    menus = instance.menuBar.findChildren(QMenu)
                    pluginsMenuAction = [
                        m for m in menus if m.title() == "Plugins"
                    ][0].menuAction()
                    toolsMenu = getOrCreateMenu(instance.menuBar, "Tools")
                    instance.menuBar.insertMenu(pluginsMenuAction, toolsMenu)
                    packageSubMenu = getOrCreateMenu(toolsMenu, packageName)
                    toolsMenu.addMenu(packageSubMenu)
                    showToolAction = packageSubMenu.addAction(ToolClass.name())
                    icon = ToolClass.getIcon()
                    if icon:
                        showToolAction.setIcon(icon)
                    showToolAction.triggered.connect(
                        lambda pkgName=packageName, toolName=ToolClass.name(
                        ): instance.invokeDockToolByName(pkgName, toolName))

                    settings.beginGroup("DockTools")
                    childGroups = settings.childGroups()
                    for dockToolGroupName in childGroups:
                        # This dock tool data been saved on last shutdown
                        settings.beginGroup(dockToolGroupName)
                        if dockToolGroupName in [
                                t.uniqueName() for t in instance._tools
                        ]:
                            settings.endGroup()
                            continue
                        toolName = dockToolGroupName.split("::")[0]
                        instance.invokeDockToolByName(packageName, toolName,
                                                      settings)
                        settings.endGroup()
                    settings.endGroup()

        PyFlow.appInstance = instance
        EditorHistory().saveState("New file")

        for name, package in GET_PACKAGES().items():
            prefsWidgets = package.PrefsWidgets()
            if prefsWidgets is not None:
                for categoryName, widgetClass in prefsWidgets.items():
                    PreferencesWindow().addCategory(categoryName,
                                                    widgetClass())
                PreferencesWindow().selectByName("General")

        if ConfigManager().loadedDefaults:
            QMessageBox.information(
                None, "First-time tips",
                "Welcome to DepthAI GUI. To use this tool efficiently, please do the following:\n\n1. Maximize the window\n2. Enable NodeBox widget (Tools > PyFlowBase > NodeBox)\n3. Enable Properties widget (Tools > PyFlowBase > Properties)\n\nHave fun!"
            )
        return instance
Esempio n. 10
0
    def refresh(self,
                pattern='',
                pinDirection=None,
                pinStructure=PinStructure.Single):
        self.clear()
        self.categoryPaths = {}

        dataType = None
        if self.canvas.pressedPin is not None:
            dataType = self.canvas.pressedPin.dataType

        for package_name, package in GET_PACKAGES().items():
            # annotated functions
            for libName, lib in package.GetFunctionLibraries().items():
                foos = lib.getFunctions()
                for name, foo in foos.items():
                    foo = foo
                    libName = foo.__annotations__["lib"]
                    fooArgNames = getargspec(foo).args
                    fooInpTypes = set()
                    fooOutTypes = set()
                    fooInpStructs = set()
                    fooOutStructs = set()
                    if foo.__annotations__['nodeType'] == NodeTypes.Callable:
                        fooInpTypes.add('ExecPin')
                        fooOutTypes.add('ExecPin')
                        fooInpStructs.add(PinStructure.Single)
                        fooOutStructs.add(PinStructure.Single)

                    # consider return type if not None
                    if foo.__annotations__['return'] is not None:
                        fooOutTypes.add(foo.__annotations__['return'][0])
                        fooOutStructs.add(
                            findStructFromValue(
                                foo.__annotations__['return'][1]))

                    for index in range(len(fooArgNames)):
                        dType = foo.__annotations__[fooArgNames[index]]
                        # if tuple - this means ref pin type (output) + default value
                        # eg: (3, True) - bool with True default val
                        fooInpTypes.add(dType[0])
                        fooInpStructs.add(findStructFromValue(dType[1]))

                    nodeCategoryPath = "{0}|{1}".format(
                        package_name, foo.__annotations__['meta']['Category'])
                    keywords = foo.__annotations__['meta']['Keywords']
                    checkString = name + nodeCategoryPath + ''.join(keywords)
                    if pattern.lower() in checkString.lower():
                        # create all nodes items if clicked on canvas
                        if dataType is None:
                            self.suggestionsEnabled = False
                            self.insertNode(nodeCategoryPath, name,
                                            foo.__doc__, libName)
                        else:
                            self.suggestionsEnabled = True
                            if pinDirection == PinDirection.Output:
                                if pinStructure != PinStructure.Multi:
                                    hasMultiPins = PinStructure.Multi in fooInpStructs
                                    if dataType in fooInpTypes and (
                                            pinStructure in fooInpStructs
                                            or hasMultiPins):
                                        self.insertNode(
                                            nodeCategoryPath, name,
                                            foo.__doc__, libName)
                                elif dataType in fooInpTypes:
                                    self.insertNode(nodeCategoryPath, name,
                                                    foo.__doc__, libName)
                            else:
                                if pinStructure != PinStructure.Multi:
                                    hasMultiPins = PinStructure.Multi in fooOutStructs
                                    if dataType in fooOutTypes and (
                                            pinStructure in fooOutStructs
                                            or hasMultiPins):
                                        self.insertNode(
                                            nodeCategoryPath, name,
                                            foo.__doc__, libName)
                                elif dataType in fooOutTypes:
                                    self.insertNode(nodeCategoryPath, name,
                                                    foo.__doc__, libName)

            # class based nodes
            for node_class in package.GetNodeClasses().values():
                if node_class.__name__ in ('setVar', 'getVar'):
                    continue

                nodeCategoryPath = "{0}|{1}".format(package_name,
                                                    node_class.category())

                checkString = node_class.__name__ + nodeCategoryPath + ''.join(
                    node_class.keywords())
                if pattern.lower() not in checkString.lower():
                    continue
                if dataType is None:
                    self.insertNode(nodeCategoryPath, node_class.__name__,
                                    node_class.description())
                else:
                    # if pressed pin is output pin
                    # filter by nodes input types
                    hints = node_class.pinTypeHints()
                    if pinDirection == PinDirection.Output:
                        if pinStructure != PinStructure.Multi:
                            hasMultiPins = PinStructure.Multi in hints.inputStructs
                            if dataType in hints.inputTypes and (
                                    pinStructure in hints.inputStructs
                                    or hasMultiPins):
                                self.insertNode(nodeCategoryPath,
                                                node_class.__name__,
                                                node_class.description())
                        elif dataType in hints.inputTypes:
                            self.insertNode(nodeCategoryPath,
                                            node_class.__name__,
                                            node_class.description())
                    else:
                        # if pressed pin is input pin
                        # filter by nodes output types
                        if pinStructure != PinStructure.Multi:
                            hasMultiPins = PinStructure.Multi in hints.outputStructs
                            if dataType in hints.outputTypes and (
                                    pinStructure in hints.outputStructs
                                    or hasMultiPins):
                                self.insertNode(nodeCategoryPath,
                                                node_class.__name__,
                                                node_class.description())
                        elif dataType in hints.outputTypes:
                            self.insertNode(nodeCategoryPath,
                                            node_class.__name__,
                                            node_class.description())
            # expand all categories
            if dataType is not None:
                for categoryItem in self.categoryPaths.values():
                    categoryItem.setExpanded(True)
            self.sortItems(0, QtCore.Qt.AscendingOrder)
Esempio n. 11
0
    def refresh(self,
                pattern='',
                pinDirection=None,
                pinStructure=PinStructure.Single):
        self.clear()
        self.categoryPaths = {}

        dataType = None
        if self.canvas.pressedPin is not None:
            dataType = self.canvas.pressedPin.dataType

        for package_name, package in GET_PACKAGES().items():
            # annotated functions
            for libName, lib in package.GetFunctionLibraries().items():
                foos = lib.getFunctions()
                for name, foo in foos.items():
                    foo = foo
                    libName = foo.__annotations__["lib"]
                    fooArgNames = getargspec(foo).args
                    fooInpTypes = set()
                    fooOutTypes = set()
                    fooInpStructs = set()
                    fooOutStructs = set()
                    if foo.__annotations__['nodeType'] == NodeTypes.Callable:
                        fooInpTypes.add('ExecPin')
                        fooOutTypes.add('ExecPin')
                        fooInpStructs.add(PinStructure.Single)
                        fooOutStructs.add(PinStructure.Single)

                    # consider return type if not None
                    if foo.__annotations__['return'] is not None:
                        fooOutTypes.add(foo.__annotations__['return'][0])
                        fooOutStructs.add(
                            findStructFromValue(
                                foo.__annotations__['return'][1]))

                    for index in range(len(fooArgNames)):
                        dType = foo.__annotations__[fooArgNames[index]]
                        # if tuple - this means ref pin type (output) + default value
                        # eg: (3, True) - bool with True default val
                        fooInpTypes.add(dType[0])
                        fooInpStructs.add(findStructFromValue(dType[1]))

                    nodeCategoryPath = "{0}|{1}".format(
                        package_name, foo.__annotations__['meta']['Category'])
                    keywords = foo.__annotations__['meta']['Keywords']
                    checkString = name + nodeCategoryPath + ''.join(keywords)
                    if pattern.lower() in checkString.lower():
                        # create all nodes items if clicked on canvas
                        if dataType is None:
                            self.suggestionsEnabled = False
                            self.insertNode(nodeCategoryPath, name,
                                            foo.__doc__, libName)
                        else:
                            self.suggestionsEnabled = True
                            if pinDirection == PinDirection.Output:
                                if pinStructure != PinStructure.Multi:
                                    hasMultiPins = PinStructure.Multi in fooInpStructs
                                    if dataType in fooInpTypes and (
                                            pinStructure in fooInpStructs
                                            or hasMultiPins):
                                        self.insertNode(
                                            nodeCategoryPath, name,
                                            foo.__doc__, libName)
                                elif dataType in fooInpTypes:
                                    self.insertNode(nodeCategoryPath, name,
                                                    foo.__doc__, libName)
                            else:
                                if pinStructure != PinStructure.Multi:
                                    hasMultiPins = PinStructure.Multi in fooOutStructs
                                    if dataType in fooOutTypes and (
                                            pinStructure in fooOutStructs
                                            or hasMultiPins):
                                        self.insertNode(
                                            nodeCategoryPath, name,
                                            foo.__doc__, libName)
                                elif dataType in fooOutTypes:
                                    self.insertNode(nodeCategoryPath, name,
                                                    foo.__doc__, libName)

            # class based nodes
            for node_class in package.GetNodeClasses().values():
                if node_class.__name__ in ('setVar', 'getVar'):
                    continue

                nodeCategoryPath = "{0}|{1}".format(package_name,
                                                    node_class.category())

                checkString = node_class.__name__ + nodeCategoryPath + ''.join(
                    node_class.keywords())
                if pattern.lower() not in checkString.lower():
                    continue
                if dataType is None:
                    self.insertNode(nodeCategoryPath, node_class.__name__,
                                    node_class.description())
                else:
                    # if pressed pin is output pin
                    # filter by nodes input types
                    hints = node_class.pinTypeHints()
                    if pinDirection == PinDirection.Output:
                        if pinStructure != PinStructure.Multi:
                            hasMultiPins = PinStructure.Multi in hints.inputStructs
                            if dataType in hints.inputTypes and (
                                    pinStructure in hints.inputStructs
                                    or hasMultiPins):
                                self.insertNode(nodeCategoryPath,
                                                node_class.__name__,
                                                node_class.description())
                        elif dataType in hints.inputTypes:
                            self.insertNode(nodeCategoryPath,
                                            node_class.__name__,
                                            node_class.description())
                    else:
                        # if pressed pin is input pin
                        # filter by nodes output types
                        if pinStructure != PinStructure.Multi:
                            hasMultiPins = PinStructure.Multi in hints.outputStructs
                            if dataType in hints.outputTypes and (
                                    pinStructure in hints.outputStructs
                                    or hasMultiPins):
                                self.insertNode(nodeCategoryPath,
                                                node_class.__name__,
                                                node_class.description())
                        elif dataType in hints.outputTypes:
                            self.insertNode(nodeCategoryPath,
                                            node_class.__name__,
                                            node_class.description())

            # populate exported py nodes
            packagePath = GET_PACKAGE_PATH(package_name)
            pyNodesRoot = os.path.join(packagePath, "PyNodes")
            if os.path.exists(pyNodesRoot):
                for path, dirs, files in os.walk(pyNodesRoot):
                    for f in files:
                        pyNodeName, extension = os.path.splitext(f)
                        if extension == ".pynode":
                            p = os.path.normpath(path)
                            folders = p.split(os.sep)
                            index = folders.index("PyNodes")
                            categorySuffix = '|'.join(folders[index:])
                            category = "{0}|{1}".format(
                                package_name, categorySuffix)
                            self.insertNode(category, pyNodeName, bPyNode=True)

            # populate exported compounds
            compoundNodesRoot = os.path.join(packagePath, "Compounds")
            if os.path.exists(compoundNodesRoot):
                for path, dirs, files in os.walk(compoundNodesRoot):
                    for f in files:
                        _, extension = os.path.splitext(f)
                        if extension == ".compound":
                            compoundsRoot = os.path.normpath(path)
                            fullCompoundPath = os.path.join(compoundsRoot, f)
                            with open(fullCompoundPath, 'r') as compoundFile:
                                data = json.load(compoundFile)
                                compoundCategoryName = data["category"]
                                compoundNodeName = data["name"]
                                category = "{0}|{1}|{2}".format(
                                    package_name, "Compounds",
                                    compoundCategoryName)
                                self.insertNode(category,
                                                compoundNodeName,
                                                bCompoundNode=True)

            # expand all categories
            if dataType is not None:
                for categoryItem in self.categoryPaths.values():
                    categoryItem.setExpanded(True)
            self.sortItems(0, QtCore.Qt.AscendingOrder)
Esempio n. 12
0
def getNodesClasses():
    packages = GET_PACKAGES()
    return packages
Esempio n. 13
0
def createNode(packageName, nodeClass, nodeName, **kvargs):
    packages = GET_PACKAGES()
    classNodes = packages[packageName].GetNodeClasses()
    node = classNodes[nodeClass](nodeName, **kvargs)
    return node
Esempio n. 14
0
def createFunction(packageName, libName, functionName):
    packages = GET_PACKAGES()
    lib = packages[packageName].GetFunctionLibraries()[libName]
    defFoos = lib.getFunctions()
    fun = NodeBase.initializeFromFunction(defFoos[functionName])
    return fun