Exemple #1
0
def createUpdateFileList(
        importPath,
        parentAssemblyDir,
        filesToUpdate,
        recursive=False,
        selectedFiles=[]  #only update parts with these sourceFiles
):

    # do not update converted parts
    print("createUpdateFileList importPath = {}".format(importPath))
    if a2plib.to_bytes(importPath) == b'converted':
        return False, filesToUpdate

    fileNameInProject = a2plib.findSourceFileInProject(importPath,
                                                       parentAssemblyDir)
    workingDir, basicFileName = os.path.split(fileNameInProject)
    docReader1 = FCdocumentReader()

    docReader1.openDocument(fileNameInProject)
    needToUpdate = False
    subAsmNeedsUpdate = False
    for ob in docReader1.getA2pObjects():

        if a2plib.to_bytes(ob.getA2pSource()) == b'converted':
            print("Did not update converted part '{}'".format(ob.name))
            continue

        #Only update parts which are selected by the user...
        fDir, fName = os.path.split(ob.getA2pSource())
        if len(selectedFiles) > 0 and fName not in selectedFiles:
            continue

        if ob.isSubassembly() and recursive:
            subAsmNeedsUpdate, filesToUpdate = createUpdateFileList(
                ob.getA2pSource(), workingDir, filesToUpdate, recursive)
        if subAsmNeedsUpdate:
            needToUpdate = True

        objFileNameInProject = a2plib.findSourceFileInProject(
            ob.getA2pSource(), workingDir)
        mtime = os.path.getmtime(objFileNameInProject)
        if ob.getTimeLastImport() < mtime:
            needToUpdate = True

    if needToUpdate:
        if fileNameInProject not in filesToUpdate:
            filesToUpdate.append(fileNameInProject)

    return needToUpdate, filesToUpdate
Exemple #2
0
    def Activated(self):
        selection = [s for s in FreeCADGui.Selection.getSelection() if s.Document == FreeCAD.ActiveDocument ]
        obj = selection[0]
        FreeCADGui.Selection.clearSelection() # very imporant! Avoid Editing the assembly the part was called from!
        fileNameWithinProjectFile = a2plib.findSourceFileInProject(obj.sourceFile)
        if fileNameWithinProjectFile == None:
            msg = \
'''
You want to edit a file which
is not found below your project-folder.
This is not allowed when using preference
"Use project Folder"
'''
            QtGui.QMessageBox.critical(
                QtGui.QApplication.activeWindow(),
                "File error ! ",
                msg
                )
            return
        docs = FreeCAD.listDocuments().values()
        docFilenames = [ d.FileName for d in docs ]
        if not fileNameWithinProjectFile in docFilenames :
            FreeCAD.open(fileNameWithinProjectFile)
        else:
            name = docs[docFilenames.index(fileNameWithinProjectFile)].Name
            FreeCAD.setActiveDocument( name )
            FreeCAD.ActiveDocument=FreeCAD.getDocument( name )
            FreeCADGui.ActiveDocument=FreeCADGui.getDocument( name )
Exemple #3
0
def updateImportedParts(doc):
    objectCache.cleanUp(doc)
    for obj in doc.Objects:
        if hasattr(obj, 'sourceFile'):
            if not hasattr( obj, 'timeLastImport'):
                obj.addProperty("App::PropertyFloat", "timeLastImport","importPart") #should default to zero which will force update.
                obj.setEditorMode("timeLastImport",1)
            if not hasattr( obj, 'a2p_Version'):
                obj.addProperty("App::PropertyString", "a2p_Version","importPart").a2p_Version = 'V0.0'
                obj.setEditorMode("a2p_Version",1)
            if not hasattr( obj, 'muxInfo'):
                obj.addProperty("App::PropertyStringList","muxInfo","importPart").muxInfo = []

            if a2plib.USE_PROJECTFILE:
                replacement = a2plib.findSourceFileInProject(obj.sourceFile) # work in any case with files within projectFolder!
            else:
                replacement = obj.sourceFile

            if replacement == None:
                QtGui.QMessageBox.critical(  QtGui.QApplication.activeWindow(),
                                            "Source file not found",
                                            "update of %s aborted!\nUnable to find %s" % (
                                                obj.Name,
                                                obj.sourceFile
                                                )
                                        )
            else:
                obj.sourceFile = replacement # update Filepath, perhaps location changed !

            if os.path.exists( obj.sourceFile ):
                newPartCreationTime = os.path.getmtime( obj.sourceFile )
                if ( newPartCreationTime > obj.timeLastImport or
                    obj.a2p_Version != A2P_VERSION
                    ):
                    if not objectCache.isCached(obj.sourceFile): # Load every changed object one time to cache
                        importPartFromFile(doc, obj.sourceFile, importToCache=True) # the version is now in the cache
                    newObject = objectCache.get(obj.sourceFile)
                    obj.timeLastImport = newPartCreationTime
                    if hasattr(newObject, 'a2p_Version'):
                        obj.a2p_Version = newObject.a2p_Version
                    importUpdateConstraintSubobjects( doc, obj, newObject )# do this before changing shape and mux
                    if hasattr(newObject, 'muxInfo'):
                        obj.muxInfo = newObject.muxInfo
                    # save Placement becaause following newObject.Shape.copy() ist resetting it to zeroes...
                    savedPlacement  = obj.Placement
                    obj.Shape = newObject.Shape.copy()
                    obj.ViewObject.DiffuseColor = copy.copy(newObject.ViewObject.DiffuseColor)
                    obj.Placement = savedPlacement # restore the old placement

    mw = FreeCADGui.getMainWindow()
    mdi = mw.findChild(QtGui.QMdiArea)
    sub = mdi.activeSubWindow()
    sub.showMaximized()

    objectCache.cleanUp(doc)
    a2p_solversystem.autoSolveConstraints(doc)
    doc.recompute()
Exemple #4
0
    def Activated(self):
        doc = FreeCAD.activeDocument()
        if doc == None:
            QtGui.QMessageBox.information(
                QtGui.QApplication.activeWindow(), "No active document found!",
                "Before editing a part, you have to open an assembly file.")
            return
        selection = [
            s for s in FreeCADGui.Selection.getSelection()
            if s.Document == FreeCAD.ActiveDocument
        ]
        if not selection:
            msg = \
'''
You must select a part to edit first.
'''
            QtGui.QMessageBox.information(QtGui.QApplication.activeWindow(),
                                          "Selection Error", msg)
            return
        obj = selection[0]
        FreeCADGui.Selection.clearSelection(
        )  # very important! Avoid Editing the assembly the part was called from!
        assemblyPath = os.path.normpath(os.path.split(doc.FileName)[0])
        fileNameWithinProjectFile = a2plib.findSourceFileInProject(
            obj.sourceFile, assemblyPath)
        if fileNameWithinProjectFile == None:
            msg = \
'''
You want to edit a file which
is not found below your project-folder.
This is not allowed when using preference
"Use project Folder"
'''
            QtGui.QMessageBox.critical(QtGui.QApplication.activeWindow(),
                                       "File error ! ", msg)
            return
        #TODO: WF fails if "use folder" = false here
        docs = []
        for d in FreeCAD.listDocuments().values(
        ):  #dict_values not indexable, docs now is...
            docs.append(d)
        #docs = FreeCAD.listDocuments().values()
        docFilenames = [d.FileName for d in docs]

        if not fileNameWithinProjectFile in docFilenames:
            FreeCAD.open(fileNameWithinProjectFile)
        else:
            idx = docFilenames.index(fileNameWithinProjectFile)
            name = docs[idx].Name
            # Search and activate the corresponding document window..
            mw = FreeCADGui.getMainWindow()
            mdi = mw.findChild(QtGui.QMdiArea)
            sub = mdi.subWindowList()
            for s in sub:
                mdi.setActiveSubWindow(s)
                if FreeCAD.activeDocument().Name == name: break
Exemple #5
0
def createPartList(
        importPath,
        parentAssemblyDir,
        partListEntries,
        recursive=False
        ):
    '''
    Extract quantities and descriptions of assembled parts from
    document.xml
    Is able to analyse subassemblies by recursion
    
    It works with a dict. Structure of an entry is:
    filename: [Quantity,[information,information,....] ]
    '''
    fileNameInProject = a2plib.findSourceFileInProject(
        importPath,
        parentAssemblyDir
        )
    workingDir,basicFileName = os.path.split(fileNameInProject)
    
    docReader1 = FCdocumentReader()
    docReader1.openDocument(fileNameInProject)
    
    for ob in docReader1.getA2pObjects():
        # skip converted parts...
        if a2plib.to_str(ob.getA2pSource()) == a2plib.to_str('converted'): continue
        
        if ob.isSubassembly() and recursive:
            partListEntries = createPartList(
                                        ob.getA2pSource(),
                                        workingDir,
                                        partListEntries,
                                        recursive
                                        )
            
        # Process information of this a2p object
        if not ob.isSubassembly() or not recursive:
            # Try to get spreadsheetdata _PARTINFO_ from linked source
            linkedSource1 = ob.getA2pSource()
            linkedSource = a2plib.findSourceFileInProject( #this returns unicode on py2 systems!
                            linkedSource1,
                            workingDir
                            )
            if linkedSource == None:
                print(u"BOM ERROR: Could not open sourcefile {}".format(linkedSource1))
                continue
            # Is it already processed minimum one time ?
            entry = partListEntries.get(linkedSource,None)
            if entry != None:
                partListEntries.get(linkedSource)[0]+=1 #count sourcefile usage
                continue # only needed to count imports of this file, information exists yet

            # There is no entry in dict, need to read out information from importFile...
            docReader2 = FCdocumentReader()
            docReader2.openDocument(linkedSource)

            # Initialize a default parts information...
            partInformation = []
            for i in range(0,len(PARTLIST_COLUMN_NAMES)):
                partInformation.append("*")
                
            # if there is a proper spreadsheet, then read it...
            for ob in docReader2.getSpreadsheetObjects():
                
                sheetName = PARTINFORMATION_SHEET_NAME
                if a2plib.PYVERSION > 2:
                    sheetName = a2plib.to_bytes(PARTINFORMATION_SHEET_NAME)
                    
                if ob.name == sheetName:
                    cells = ob.getCells()
                    for addr in cells.keys():
                        if addr[:1] == b'B': #column B contains the data, A only the titles
                            idx = int(addr[1:])-1
                            if idx < len(PARTLIST_COLUMN_NAMES): # don't read further!
                                partInformation[idx] = cells[addr]
            # last entry of partinformations is reserved for filename
            partInformation[-1] = os.path.split(linkedSource)[1] #without complete path...

            # put information to dict and count usage of sourcefiles..
            entry = partListEntries.get(linkedSource,None)
            if entry == None:
                partListEntries[linkedSource] = [
                    1,
                    partInformation
                    ]
            else:
                partListEntries.get(linkedSource)[0]+=1 #count sourcefile usage
                
    return partListEntries
Exemple #6
0
def updateImportedParts(doc):
    if doc == None:
        QtGui.QMessageBox.information(
            QtGui.QApplication.activeWindow(), "No active document found!",
            "Before updating parts, you have to open an assembly file.")
        return

    # modififying object's subelements causes solving of the assembly, disable autosolve here
    autoSolveState = a2plib.getAutoSolveState()
    a2plib.setAutoSolve(False)

    doc.openTransaction("updateImportParts")
    objectCache.cleanUp(doc)
    for obj in doc.Objects:
        if hasattr(obj, 'sourceFile'):
            if not hasattr(obj, 'timeLastImport'):
                obj.addProperty(
                    "App::PropertyFloat", "timeLastImport", "importPart"
                )  #should default to zero which will force update.
                obj.setEditorMode("timeLastImport", 1)
            if not hasattr(obj, 'a2p_Version'):
                obj.addProperty("App::PropertyString", "a2p_Version",
                                "importPart").a2p_Version = 'V0.0'
                obj.setEditorMode("a2p_Version", 1)
            if not hasattr(obj, 'muxInfo'):
                obj.addProperty("App::PropertyStringList", "muxInfo",
                                "importPart").muxInfo = []

            assemblyPath = os.path.normpath(os.path.split(doc.FileName)[0])
            absPath = a2plib.findSourceFileInProject(obj.sourceFile,
                                                     assemblyPath)

            if absPath == None:
                QtGui.QMessageBox.critical(
                    QtGui.QApplication.activeWindow(),
                    u"Source file not found",
                    u"Unable to find {}".format(obj.sourceFile))
            if absPath != None and os.path.exists(absPath):
                newPartCreationTime = os.path.getmtime(absPath)
                if (newPartCreationTime > obj.timeLastImport
                        or obj.a2p_Version != A2P_VERSION):
                    if not objectCache.isCached(
                            absPath
                    ):  # Load every changed object one time to cache
                        importPartFromFile(doc, absPath, importToCache=True
                                           )  # the version is now in the cache
                    newObject = objectCache.get(absPath)
                    obj.timeLastImport = newPartCreationTime
                    if hasattr(newObject, 'a2p_Version'):
                        obj.a2p_Version = A2P_VERSION
                    importUpdateConstraintSubobjects(
                        doc, obj,
                        newObject)  # do this before changing shape and mux
                    if hasattr(newObject, 'muxInfo'):
                        obj.muxInfo = newObject.muxInfo
                    # save Placement because following newObject.Shape.copy() isn't resetting it to zeroes...
                    savedPlacement = obj.Placement
                    obj.Shape = newObject.Shape.copy()
                    obj.ViewObject.DiffuseColor = copy.copy(
                        newObject.ViewObject.DiffuseColor)
                    obj.ViewObject.Transparency = newObject.ViewObject.Transparency
                    obj.Placement = savedPlacement  # restore the old placement

    mw = FreeCADGui.getMainWindow()
    mdi = mw.findChild(QtGui.QMdiArea)
    sub = mdi.activeSubWindow()
    if sub != None:
        sub.showMaximized()

    objectCache.cleanUp(doc)
    a2plib.setAutoSolve(autoSolveState)

    if not a2plib.getUseTopoNaming():
        # This is only needed when not using toponames.
        # Otherwise updating constraints.subelements triggers this.
        a2p_solversystem.autoSolveConstraints(
            doc, useTransaction=False, callingFuncName="updateImportedParts"
        )  #transaction is already open...

    doc.recompute()
    doc.commitTransaction()