示例#1
0
 def saveStockSettings(self):
     if self.form.stockGroup.isChecked():
         attrs = {}
         attrs['version'] = 1
         typ = [PathStock.StockType.CreateBox, PathStock.StockType.CreateCylinder, PathStock.StockType.FromBase][self.form.stock.currentIndex()]
         attrs['create'] = typ
         if typ == PathStock.StockType.CreateBox:
             attrs['length'] = FreeCAD.Units.Quantity(self.form.stockBoxLength.text()).UserString
             attrs['width'] = FreeCAD.Units.Quantity(self.form.stockBoxWidth.text()).UserString
             attrs['height'] = FreeCAD.Units.Quantity(self.form.stockBoxHeight.text()).UserString
         if typ == PathStock.StockType.CreateCylinder:
             attrs['radius'] = FreeCAD.Units.Quantity(self.form.stockCylinderRadius.text()).UserString
             attrs['height'] = FreeCAD.Units.Quantity(self.form.stockCylinderHeight.text()).UserString
         if typ == PathStock.StockType.FromBase:
             attrs['xneg'] = FreeCAD.Units.Quantity(self.form.stockExtXneg.text()).UserString
             attrs['xpos'] = FreeCAD.Units.Quantity(self.form.stockExtXpos.text()).UserString
             attrs['yneg'] = FreeCAD.Units.Quantity(self.form.stockExtYneg.text()).UserString
             attrs['ypos'] = FreeCAD.Units.Quantity(self.form.stockExtYpos.text()).UserString
             attrs['zneg'] = FreeCAD.Units.Quantity(self.form.stockExtZneg.text()).UserString
             attrs['zpos'] = FreeCAD.Units.Quantity(self.form.stockExtZpos.text()).UserString
         if self.form.stockPlacementGroup.isChecked():
             angle = FreeCAD.Units.Quantity(self.form.stockAngle.text()).Value
             axis = FreeCAD.Vector(self.form.stockAxisX.value(), self.form.stockAxisY.value(), self.form.stockAxisZ.value())
             rot = FreeCAD.Rotation(axis, angle)
             attrs['rotX'] = rot.Q[0]
             attrs['rotY'] = rot.Q[1]
             attrs['rotZ'] = rot.Q[2]
             attrs['rotW'] = rot.Q[3]
             attrs['posX'] = FreeCAD.Units.Quantity(self.form.stockPositionX.text()).Value
             attrs['posY'] = FreeCAD.Units.Quantity(self.form.stockPositionY.text()).Value
             attrs['posZ'] = FreeCAD.Units.Quantity(self.form.stockPositionZ.text()).Value
         PathPreferences.setDefaultStockTemplate(json.dumps(attrs))
     else:
         PathPreferences.setDefaultStockTemplate('')
示例#2
0
    def setupTemplate(self):
        templateFiles = []
        for path in PathPreferences.searchPaths():
            templateFiles.extend(self.templateFilesIn(path))

        template = {}
        for tFile in templateFiles:
            name = os.path.split(os.path.splitext(tFile)[0])[1][4:]
            if name in template:
                basename = name
                i = 0
                while name in template:
                    i = i + 1
                    name = basename + " (%s)" % i
            PathLog.track(name, tFile)
            template[name] = tFile
        selectTemplate = PathPreferences.defaultJobTemplate()
        index = 0
        self.dialog.jobTemplate.addItem('<none>', '')
        for name in sorted(template.keys()):
            if template[name] == selectTemplate:
                index = self.dialog.jobTemplate.count()
            self.dialog.jobTemplate.addItem(name, template[name])
        self.dialog.jobTemplate.setCurrentIndex(index)
        self.dialog.templateGroup.show()
示例#3
0
    def loadSettings(self):
        self.form.leDefaultFilePath.setText(PathPreferences.defaultFilePath())
        self.form.leDefaultJobTemplate.setText(PathPreferences.defaultJobTemplate())

        blacklist = PathPreferences.postProcessorBlacklist()
        for processor in PathPreferences.allAvailablePostProcessors():
            item = QtGui.QListWidgetItem(processor)
            if processor in blacklist:
                item.setCheckState(QtCore.Qt.CheckState.Unchecked)
            else:
                item.setCheckState(QtCore.Qt.CheckState.Checked)
            item.setFlags( QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsUserCheckable)
            self.form.postProcessorList.addItem(item)
        self.verifyAndUpdateDefaultPostProcessorWith(PathPreferences.defaultPostProcessor())

        self.form.defaultPostProcessorArgs.setText(PathPreferences.defaultPostProcessorArgs())

        geomTol = Units.Quantity(PathPreferences.defaultGeometryTolerance(), Units.Length)
        self.form.geometryTolerance.setText(geomTol.UserString)
        self.form.curveAccuracy.setText(Units.Quantity(PathPreferences.defaultLibAreaCurveAccuracy(), Units.Length).UserString)

        self.form.leOutputFile.setText(PathPreferences.defaultOutputFile())
        self.selectComboEntry(self.form.cboOutputPolicy, PathPreferences.defaultOutputPolicy())

        self.form.tbDefaultFilePath.clicked.connect(self.browseDefaultFilePath)
        self.form.tbDefaultJobTemplate.clicked.connect(self.browseDefaultJobTemplate)
        self.form.postProcessorList.itemEntered.connect(self.setProcessorListTooltip)
        self.form.postProcessorList.itemChanged.connect(self.verifyAndUpdateDefaultPostProcessor)
        self.form.defaultPostProcessor.currentIndexChanged.connect(self.updateDefaultPostProcessorToolTip)
        self.form.tbOutputFile.clicked.connect(self.browseOutputFile)

        self.loadStockSettings()
示例#4
0
    def resolveFileName(self, job):
        path = PathPreferences.defaultOutputFile()
        if job.PostProcessorOutputFile:
            path = job.PostProcessorOutputFile
        filename = path
        if '%D' in filename:
            D = FreeCAD.ActiveDocument.FileName
            if D:
                D = os.path.dirname(D)
                # in case the document is in the current working directory
                if not D:
                    D = '.'
            else:
                FreeCAD.Console.PrintError("Please save document in order to resolve output path!\n")
                return None
            filename = filename.replace('%D', D)

        if '%d' in filename:
            d = FreeCAD.ActiveDocument.Label
            filename = filename.replace('%d', d)

        if '%j' in filename:
            j = job.Label
            filename = filename.replace('%j', j)

        if '%M' in filename:
            pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")
            M = pref.GetString("MacroPath", FreeCAD.getUserAppDataDir())
            filename = filename.replace('%M', M)

        policy = PathPreferences.defaultOutputPolicy()

        openDialog = policy == 'Open File Dialog'
        if os.path.isdir(filename) or not os.path.isdir(os.path.dirname(filename)):
            # Either the entire filename resolves into a directory or the parent directory doesn't exist.
            # Either way I don't know what to do - ask for help
            openDialog = True

        if os.path.isfile(filename) and not openDialog:
            if policy == 'Open File Dialog on conflict':
                openDialog = True
            elif policy == 'Append Unique ID on conflict':
                fn, ext = os.path.splitext(filename)
                nr = fn[-3:]
                n = 1
                if nr.isdigit():
                    n = int(nr)
                while os.path.isfile("%s%03d%s" % (fn, n, ext)):
                    n = n + 1
                filename = "%s%03d%s" % (fn, n, ext)

        if openDialog:
            foo = QtGui.QFileDialog.getSaveFileName(QtGui.QApplication.activeWindow(), "Output File", filename)
            if foo:
                filename = foo[0]
            else:
                filename = None

        return filename
示例#5
0
 def renameLibrary(self):
     name = self.form.TableList.itemWidget(self.form.TableList.currentItem()).getTableName()
     newName, ok = QtGui.QInputDialog.getText(None, translate(
         "TooltableEditor", "Rename Tooltable"), translate(
             "TooltableEditor", "Enter Name:"), QtGui.QLineEdit.Normal, name)
     if ok and newName:
         os.rename(PathPreferences.lastPathToolLibrary() + '/' + name, PathPreferences.lastPathToolLibrary() + '/' + newName)
         self.libraryOpen(filedialog=False)
示例#6
0
 def curLib(self):
     libfile = PathPreferences.lastFileToolLibrary()
     if libfile is None or libfile == "":
         return ""
     else:
         libfile = os.path.split(PathPreferences.lastFileToolLibrary())[1]
         libfile = os.path.splitext(libfile)[0]
     return libfile
示例#7
0
 def saveSettings(self):
     PathPreferences.setPreferencesAdvanced(
         self.form.EnableAdvancedOCLFeatures.isChecked(),
         self.form.WarningSuppressAllSpeeds.isChecked(),
         self.form.WarningSuppressRapidSpeeds.isChecked(),
         self.form.WarningSuppressSelectionMode.isChecked(),
         self.form.WarningSuppressOpenCamLib.isChecked(),
     )
示例#8
0
def GetToolFiles(parent = None):
    if parent is None:
        parent = QtGui.QApplication.activeWindow()
    foo = QtGui.QFileDialog.getOpenFileNames(parent, 'Tool', PathPreferences.lastPathToolBit(), '*.fctb')
    if foo and foo[0]:
        PathPreferences.setLastPathToolBit(os.path.dirname(foo[0][0]))
        return foo[0]
    return []
    def libraryPath(self):
        PathLog.track()
        path = PySide.QtGui.QFileDialog.getExistingDirectory(self.form, 'Tool Library Path', PathPreferences.lastPathToolLibrary())
        if len(path) == 0:
            return

        PathPreferences.setLastPathToolLibrary(path)
        self.loadData()
 def libraryOpen(self):
     PathLog.track()
     foo = PySide.QtGui.QFileDialog.getOpenFileName(
         self.form, 'Tool Library', PathPreferences.lastPathToolLibrary(),
         '*.fctl')
     if foo and foo[0]:
         path = foo[0]
         PathPreferences.setLastPathToolLibrary(os.path.dirname(path))
         self.libraryLoad(path)
示例#11
0
    def checkWorkingDir(self):
        # users shouldn't use the example toolbits and libraries.
        # working directory should be writable
        PathLog.track()

        workingdir = os.path.dirname(PathPreferences.lastPathToolLibrary())
        defaultdir = os.path.dirname(PathPreferences.pathDefaultToolsPath())

        dirOK = lambda: workingdir != defaultdir and (os.access(
            workingdir, os.W_OK))

        if dirOK():
            return True

        qm = PySide.QtGui.QMessageBox
        ret = qm.question(
            None, '', "Toolbit working directory not set up. Do that now?",
            qm.Yes | qm.No)

        if ret == qm.No:
            return False

        msg = translate("Path", "Choose a writable location for your toolbits",
                        None)
        while not dirOK():
            workingdir = PySide.QtGui.QFileDialog.getExistingDirectory(
                None, msg, PathPreferences.filePath())

        PathPreferences.setLastPathToolLibrary("{}/Library".format(workingdir))

        subdirlist = ['Bit', 'Library', 'Shape']
        mode = 0o777
        for dir in subdirlist:
            subdir = "{}/{}".format(workingdir, dir)
            if not os.path.exists(subdir):
                qm = PySide.QtGui.QMessageBox
                ret = qm.question(
                    None, '',
                    "Toolbit Working directory {} should contain a '{}' subdirectory. Create it?"
                    .format(workingdir, dir), qm.Yes | qm.No)

                if ret == qm.Yes:
                    os.mkdir(subdir, mode)
                    qm = PySide.QtGui.QMessageBox
                    ret = qm.question(
                        None, '',
                        "Copy example files to new {} directory?".format(dir),
                        qm.Yes | qm.No)
                    if ret == qm.Yes:
                        src = "{}/{}".format(defaultdir, dir)
                        src_files = os.listdir(src)
                        for file_name in src_files:
                            full_file_name = os.path.join(src, file_name)
                            if os.path.isfile(full_file_name):
                                shutil.copy(full_file_name, subdir)

        return True
示例#12
0
 def test030(self):
     teststring = "%M/outfile.nc"
     self.job.PostProcessorOutputFile = teststring
     PathPreferences.setOutputFileDefaults(
         teststring, "Append Unique ID on conflict"
     )
     outlist = PathPost.buildPostList(self.job)
     subpart, objs = outlist[0]
     filename = PathPost.resolveFileName(self.job, subpart, 0)
     self.assertEqual(filename, f"{self.macro}outfile.nc")
示例#13
0
 def selectShape(self):
     path = self.tool.BitShape
     if not path:
         path = PathPreferences.lastPathToolShape()
     foo = QtGui.QFileDialog.getOpenFileName(self.form, "Path - Tool Shape",
                                             path, "*.fcstd")
     if foo and foo[0]:
         PathPreferences.setLastPathToolShape(os.path.dirname(foo[0]))
         self.form.shapePath.setText(foo[0])
         self.updateShape()
    def Activated(self):
        import PathScripts.PathToolBitLibraryGui as PathToolBitLibraryGui
        dock = PathToolBitLibraryGui.ToolBitSelector()

        lastlib = PathPreferences.lastPathToolLibrary()

        if PathPreferences.toolsOpenLastLibrary():
            dock.open(lastlib)
        else:
            dock.open()
示例#15
0
 def libraryDelete(self):
     PathLog.track()
     reply = QtGui.QMessageBox.question(
         self.form, 'Warning',
         "Delete " + os.path.basename(self.path) + "?",
         QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
     if reply == QtGui.QMessageBox.Yes and len(self.path) > 0:
         os.remove(self.path)
         PathPreferences.setLastPathToolTable("")
         self.libraryOpen(filedialog=False)
 def librarySaveAs(self):
     foo = PySide.QtGui.QFileDialog.getSaveFileName(
         self.form, 'Tool Library', PathPreferences.lastPathToolLibrary(),
         '*.fctl')
     if foo and foo[0]:
         path = foo[0] if foo[0].endswith('.fctl') else "{}.fctl".format(
             foo[0])
         PathPreferences.setLastPathToolLibrary(os.path.dirname(path))
         self.path = path
         self.librarySave()
         self.updateToolbar()
示例#17
0
 def test050(self):
     # explicitly using the sequence number should include it where indicated.
     teststring = "%S-%d.nc"
     self.job.PostProcessorOutputFile = teststring
     PathPreferences.setOutputFileDefaults(
         teststring, "Append Unique ID on conflict"
     )
     outlist = PathPost.buildPostList(self.job)
     subpart, objs = outlist[0]
     filename = PathPost.resolveFileName(self.job, subpart, 0)
     self.assertEqual(filename, "0-test_filenaming.nc")
示例#18
0
 def loadSettings(self):
     self.form.WarningSuppressAllSpeeds.setChecked(
         PathPreferences.suppressAllSpeedsWarning())
     self.form.WarningSuppressRapidSpeeds.setChecked(
         PathPreferences.suppressRapidSpeedsWarning(False))
     self.form.WarningSuppressSelectionMode.setChecked(
         PathPreferences.suppressSelectionModeWarning())
     self.form.EnableAdvancedOCLFeatures.setChecked(
         PathPreferences.advancedOCLFeaturesEnabled())
     self.form.WarningSuppressOpenCamLib.setChecked(
         PathPreferences.suppressOpenCamLibWarning())
     self.updateSelection()
示例#19
0
 def test040(self):
     # unused substitution strings should be ignored
     teststring = "%d%T%t%W%O/testdoc.nc"
     self.job.PostProcessorOutputFile = teststring
     PathPreferences.setOutputFileDefaults(
         teststring, "Append Unique ID on conflict"
     )
     outlist = PathPost.buildPostList(self.job)
     subpart, objs = outlist[0]
     filename = PathPost.resolveFileName(self.job, subpart, 0)
     self.assertEqual(
         os.path.normpath(filename),
         os.path.normpath(f"{self.testfilename}/testdoc.nc"),
     )
示例#20
0
 def test010(self):
     # Substitute current file path
     teststring = "%D/testfile.nc"
     self.job.PostProcessorOutputFile = teststring
     PathPreferences.setOutputFileDefaults(
         teststring, "Append Unique ID on conflict"
     )
     outlist = PathPost.buildPostList(self.job)
     subpart, objs = outlist[0]
     filename = PathPost.resolveFileName(self.job, subpart, 0)
     self.assertEqual(
         os.path.normpath(filename),
         os.path.normpath(f"{self.testfilepath}/testfile.nc"),
     )
示例#21
0
    def test10(self):
        '''Default paths for tools are resolved correctly'''

        self.assertTrue(
            PathPreferences.pathDefaultToolsPath().endswith('/Path/Tools/'))
        self.assertTrue(
            PathPreferences.pathDefaultToolsPath('Bit').endswith(
                '/Path/Tools/Bit'))
        self.assertTrue(
            PathPreferences.pathDefaultToolsPath('Library').endswith(
                '/Path/Tools/Library'))
        self.assertTrue(
            PathPreferences.pathDefaultToolsPath('Template').endswith(
                '/Path/Tools/Template'))
    def loadData(self, path=None):
        PathLog.track(path)
        self.toolTableView.setUpdatesEnabled(False)
        self.form.TableList.setUpdatesEnabled(False)

        if path is None:
            path, loc = self.libPaths()

            self.toolModel.clear()
            self.listModel.clear()
            self.factory.libraryOpen(self.toolModel, lib=path)
            self.factory.findLibraries(self.listModel)

        else:
            self.toolModel.clear()
            self.factory.libraryOpen(self.toolModel, lib=path)

        self.path = path
        self.form.setWindowTitle("{}".format(PathPreferences.lastPathToolLibrary()))
        self.toolModel.setHorizontalHeaderLabels(self.columnNames())
        self.listModel.setHorizontalHeaderLabels(['Library'])

        # Select the current library in the list of tables
        curIndex = None
        for i in range(self.listModel.rowCount()):
            item = self.listModel.item(i)
            if item.data(_PathRole) == path:
                curIndex = self.listModel.indexFromItem(item)

        if curIndex:
            sm = self.form.TableList.selectionModel()
            sm.select(curIndex, PySide.QtCore.QItemSelectionModel.Select)

        self.toolTableView.setUpdatesEnabled(True)
        self.form.TableList.setUpdatesEnabled(True)
示例#23
0
    def opExecute(self, obj):
        '''opExecute(obj) ... process engraving operation'''
        PathLog.track()

        output = ""
        if obj.Comment != "":
            output += '(' + str(obj.Comment) + ')\n'

        output += "(" + obj.Label + ")"
        output += "(Compensated Tool Path. Diameter: " + str(
            obj.ToolController.Tool.Diameter) + ")"

        parentJob = PathUtils.findParentJob(obj)
        if parentJob is None:
            return

        print("base object: " + self.baseobject.Name)

        if obj.Algorithm in ['OCL Dropcutter', 'OCL Waterline']:
            try:
                import ocl
            except:
                FreeCAD.Console.PrintError(
                    translate(
                        "Path_Surface",
                        "This operation requires OpenCamLib to be installed.")
                    + "\n")
                return

        if self.baseobject.TypeId.startswith('Mesh'):
            mesh = self.baseobject.Mesh
        else:
            # try/except is for Path Jobs created before GeometryTolerance
            try:
                deflection = parentJob.GeometryTolerance
            except AttributeError:
                import PathScripts.PathPreferences as PathPreferences
                deflection = PathPreferences.defaultGeometryTolerance()
            self.baseobject.Shape.tessellate(0.5)
            mesh = MeshPart.meshFromShape(self.baseobject.Shape,
                                          Deflection=deflection)

        bb = mesh.BoundBox

        s = ocl.STLSurf()
        for f in mesh.Facets:
            p = f.Points[0]
            q = f.Points[1]
            r = f.Points[2]
            t = ocl.Triangle(ocl.Point(p[0], p[1], p[2]),
                             ocl.Point(q[0], q[1], q[2]),
                             ocl.Point(r[0], r[1], r[2]))
            s.addTriangle(t)

        if obj.Algorithm == 'OCL Dropcutter':
            output = self._dropcutter(obj, s, bb)
        elif obj.Algorithm == 'OCL Waterline':
            output = self._waterline(obj, s, bb)

        self.commandlist.extend(output)
示例#24
0
def Create(name='TC: Default Tool',
           tool=None,
           toolNumber=1,
           assignViewProvider=True,
           assignTool=True):
    legacyTool = PathPreferences.toolsUseLegacyTools(
    ) if tool is None else isinstance(tool, Path.Tool)

    PathLog.track(tool, toolNumber, legacyTool)

    obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
    obj.Label = name
    obj.Proxy = ToolController(obj, legacyTool, assignTool)

    if FreeCAD.GuiUp and assignViewProvider:
        ViewProvider(obj.ViewObject)

    if assignTool:
        if not tool:
            if legacyTool:
                tool = Path.Tool()
                tool.Diameter = 5.0
                tool.Name = "Default Tool"
                tool.CuttingEdgeHeight = 15.0
                tool.ToolType = "EndMill"
                tool.Material = "HighSpeedSteel"
            else:
                tool = PathToolBit.Factory.Create()
                if tool.ViewObject:
                    tool.ViewObject.Visibility = False
        obj.Tool = tool
    obj.ToolNumber = toolNumber
    return obj
示例#25
0
 def SaveDialog(cls, job, dialog):
     foo = QtGui.QFileDialog.getSaveFileName(QtGui.QApplication.activeWindow(),
             "Path - Job Template",
             PathPreferences.filePath(),
             "job_*.json")[0]
     if foo: 
         cls.Execute(job, foo, dialog)
示例#26
0
def surfaceselect():
    gate = False
    if MESHGate() or FACEGate():
        gate = True
    FreeCADGui.Selection.addSelectionGate(gate)
    if not PathPreferences.suppressSelectionModeWarning():
        FreeCAD.Console.PrintWarning("Surfacing Select Mode\n")
示例#27
0
 def tableSelected(self, index):
     ''' loads the tools for the selected tool table '''
     name = self.form.TableList.itemWidget(
         self.form.TableList.itemFromIndex(index)).getTableName()
     self.libraryLoad(PathPreferences.lastPathToolLibrary() + '/' + name)
     self.form.ButtonRemoveToolTable.setEnabled(True)
     self.form.ButtonRenameToolTable.setEnabled(True)
示例#28
0
 def initOperation(self, obj):
     """initOperation(obj) ... create vcarve specific properties."""
     obj.addProperty(
         "App::PropertyFloat",
         "Discretize",
         "Path",
         QT_TRANSLATE_NOOP("App::Property",
                           "The deflection value for discretizing arcs"),
     )
     obj.addProperty(
         "App::PropertyFloat",
         "Colinear",
         "Path",
         QT_TRANSLATE_NOOP(
             "App::Property",
             "Cutoff for removing colinear segments (degrees). \
                     default=10.0.",
         ),
     )
     obj.addProperty(
         "App::PropertyFloat",
         "Tolerance",
         "Path",
         QT_TRANSLATE_NOOP("App::Property", "Vcarve Tolerance"),
     )
     obj.Colinear = 10.0
     obj.Discretize = 0.01
     obj.Tolerance = PathPreferences.defaultGeometryTolerance()
     self.setupAdditionalProperties(obj)
    def load(cls, processor):
        PathLog.track(processor)
        syspath = sys.path
        paths = PathPreferences.searchPaths()
        paths.extend(sys.path)
        sys.path = paths

        postname = processor + "_post"
        namespace = {}
        
        #can't modify function local scope with exec in python3
        exec("import %s as current_post" % postname, namespace)
        current_post = namespace['current_post']
        
        # make sure the script is reloaded if it was previously loaded
        # should the script have been imported for the first time above
        # then the initialization code of the script gets executed twice
        # resulting in 2 load messages if the script outputs one of those.
        try:
            # Python 2.7
            exec("reload(%s)" % 'current_post')
        except NameError:
            # Python 3.4+
            from importlib import reload
            exec("reload(%s)" % 'current_post')

        sys.path = syspath

        instance = PostProcessor(current_post)
        instance.units = None
        if hasattr(current_post, "UNITS"):
            if current_post.UNITS == "G21":
                instance.units = "Metric"
            else:
                instance.units = "Inch"

        instance.machineName = None
        if hasattr(current_post, "MACHINE_NAME"):
            instance.machineName = current_post.MACHINE_NAME

        instance.cornerMax = None
        if hasattr(current_post, "CORNER_MAX"):
            instance.cornerMax = {'x': current_post.CORNER_MAX['x'],
                    'y': current_post.CORNER_MAX['y'],
                    'z': current_post.CORNER_MAX['z']}

        instance.cornerMin = None
        if hasattr(current_post, "CORNER_MIN"):
            instance.cornerMin = {'x': current_post.CORNER_MIN['x'],
                    'y': current_post.CORNER_MIN['y'],
                    'z': current_post.CORNER_MIN['z']}

        instance.tooltip = None
        instance.tooltipArgs = None
        if hasattr(current_post, "TOOLTIP"):
            instance.tooltip = current_post.TOOLTIP
            if hasattr(current_post, "TOOLTIP_ARGS"):
                instance.tooltipArgs = current_post.TOOLTIP_ARGS
        return instance
示例#30
0
 def resolvePostProcessor(self, job):
     if hasattr(job, "PostProcessor"):
         post = PathPreferences.defaultPostProcessor()
         if job.PostProcessor:
             post = job.PostProcessor
         if post and PostProcessor.exists(post):
             return post
     dlg = DlgSelectPostProcessor()
     return dlg.exec_()
示例#31
0
    def setupColors(self):
        def colorForColorValue(val):
            v = [((val >> n) & 0xff) / 255. for n in [24, 16, 8, 0]]
            return coin.SbColor(v[0], v[1], v[2])

        pref = PathPreferences.preferences()
        #                                                      R         G          B          A
        npc = pref.GetUnsigned('DefaultPathMarkerColor', ((85*256 + 255)*256 + 0) * 256 + 255)
        hpc = pref.GetUnsigned('DefaultHighlightPathColor', ((255*256 + 125)*256 + 0)*256 + 255)
        dpc = pref.GetUnsigned('DefaultDisabledPathColor', ((205*256 + 205)*256 + 205)*256 + 154)
        self.colors = [colorForColorValue(npc), colorForColorValue(dpc), colorForColorValue(hpc)]
示例#32
0
    def __init__(self, parent=None):
        self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobCreate.ui")
        sel = FreeCADGui.Selection.getSelection()
        if sel:
            selected = sel[0].Label
        else:
            selected = None
        index = 0
        for base in PathJob.ObjectJob.baseCandidates():
            if base.Label == selected:
                index = self.dialog.cbModel.count()
            self.dialog.cbModel.addItem(base.Label)
        self.dialog.cbModel.setCurrentIndex(index)

        templateFiles = []
        for path in PathPreferences.searchPaths():
            templateFiles.extend(self.templateFilesIn(path))

        template = {}
        for tFile in templateFiles:
            name = os.path.split(os.path.splitext(tFile)[0])[1][4:]
            if name in template:
                basename = name
                i = 0
                while name in template:
                    i = i + 1
                    name = basename + " (%s)" % i
            PathLog.track(name, tFile)
            template[name] = tFile
        selectTemplate = PathPreferences.defaultJobTemplate()
        index = 0
        self.dialog.cbTemplate.addItem('<none>', '')
        for name in sorted(template.keys()):
            if template[name] == selectTemplate:
                index = self.dialog.cbTemplate.count()
            self.dialog.cbTemplate.addItem(name, template[name])
        self.dialog.cbTemplate.setCurrentIndex(index)
示例#33
0
    def __init__(self, obj, models, templateFile = None):
        self.obj = obj
        obj.addProperty("App::PropertyFile", "PostProcessorOutputFile", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob","The NC output file for this project"))
        obj.addProperty("App::PropertyEnumeration", "PostProcessor", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob","Select the Post Processor"))
        obj.addProperty("App::PropertyString", "PostProcessorArgs", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Arguments for the Post Processor (specific to the script)"))

        obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("PathJob","An optional description for this job"))
        obj.addProperty("App::PropertyDistance", "GeometryTolerance", "Geometry", QtCore.QT_TRANSLATE_NOOP("PathJob", "For computing Paths; smaller increases accuracy, but slows down computation"))

        obj.addProperty("App::PropertyLink", "Stock", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Solid object to be used as stock."))
        obj.addProperty("App::PropertyLink", "Operations", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Compound path of all operations in the order they are processed."))
        obj.addProperty("App::PropertyLinkList", "ToolController", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Collection of tool controllers available for this job."))

        obj.addProperty("App::PropertyBool", "SplitOutput", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob","Split output into multiple gcode files"))
        obj.addProperty("App::PropertyEnumeration", "OrderOutputBy", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "If multiple WCS, order the output this way"))
        obj.addProperty("App::PropertyStringList", "Fixtures", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "The Work Coordinate Systems for the Job"))
        obj.OrderOutputBy = ['Fixture', 'Tool', 'Operation']
        obj.Fixtures = ['G54']

        obj.PostProcessorOutputFile = PathPreferences.defaultOutputFile()
        #obj.setEditorMode("PostProcessorOutputFile", 0)  # set to default mode
        obj.PostProcessor = postProcessors = PathPreferences.allEnabledPostProcessors()
        defaultPostProcessor = PathPreferences.defaultPostProcessor()
        # Check to see if default post processor hasn't been 'lost' (This can happen when Macro dir has changed)
        if defaultPostProcessor in postProcessors:
            obj.PostProcessor = defaultPostProcessor
        else:
            obj.PostProcessor = postProcessors[0]
        obj.PostProcessorArgs = PathPreferences.defaultPostProcessorArgs()
        obj.GeometryTolerance = PathPreferences.defaultGeometryTolerance()

        ops = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Operations")
        if ops.ViewObject:
            ops.ViewObject.Proxy = 0
            ops.ViewObject.Visibility = False

        obj.Operations = ops
        obj.setEditorMode('Operations', 2) # hide
        obj.setEditorMode('Placement', 2)

        self.setupSetupSheet(obj)
        self.setupBaseModel(obj, models)

        obj.Proxy = self

        self.setFromTemplateFile(obj, templateFile)
        if not obj.Stock:
            stockTemplate = PathPreferences.defaultStockTemplate()
            if stockTemplate:
                obj.Stock = PathStock.CreateFromTemplate(obj, json.loads(stockTemplate))
            if not obj.Stock:
                obj.Stock = PathStock.CreateFromBase(obj)
        if obj.Stock.ViewObject:
            obj.Stock.ViewObject.Visibility = False
示例#34
0
 def __init__(self, parent=None):
     self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgSelectPostProcessor.ui")
     firstItem = None
     for post in PathPreferences.allEnabledPostProcessors():
         item = QtGui.QListWidgetItem(post)
         item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled)
         self.dialog.lwPostProcessor.addItem(item)
         if not firstItem:
             firstItem = item
     if firstItem:
         self.dialog.lwPostProcessor.setCurrentItem(firstItem)
     else:
         self.dialog.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(False)
     self.tooltips = {}
     self.dialog.lwPostProcessor.itemDoubleClicked.connect(self.dialog.accept)
     self.dialog.lwPostProcessor.setMouseTracking(True)
     self.dialog.lwPostProcessor.itemEntered.connect(self.updateTooltip)
示例#35
0
    def __init__(self, vobj, deleteOnReject):
        FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Edit Job"))
        self.vobj = vobj
        self.vproxy = vobj.Proxy
        self.obj = vobj.Object
        self.deleteOnReject = deleteOnReject
        self.form = FreeCADGui.PySideUic.loadUi(":/panels/PathEdit.ui")
        self.template = PathJobCmd.DlgJobTemplateExport(self.obj, self.form.jobBox.widget(1))

        vUnit = FreeCAD.Units.Quantity(1, FreeCAD.Units.Velocity).getUserPreferred()[2]
        self.form.toolControllerList.horizontalHeaderItem(1).setText('#')
        self.form.toolControllerList.horizontalHeaderItem(2).setText(vUnit)
        self.form.toolControllerList.horizontalHeaderItem(3).setText(vUnit)
        self.form.toolControllerList.horizontalHeader().setResizeMode(0, QtGui.QHeaderView.Stretch)
        self.form.toolControllerList.resizeColumnsToContents()

        currentPostProcessor = self.obj.PostProcessor
        postProcessors = PathPreferences.allEnabledPostProcessors(['', currentPostProcessor])
        for post in postProcessors:
            self.form.postProcessor.addItem(post)
        # update the enumeration values, just to make sure all selections are valid
        self.obj.PostProcessor = postProcessors
        self.obj.PostProcessor = currentPostProcessor

        base = self.obj.Base if PathJob.isResourceClone(self.obj, 'Base') else None
        stock = self.obj.Stock
        for o in PathJob.ObjectJob.baseCandidates():
            if o != base and o != stock:
                self.form.jobModel.addItem(o.Label, o)
        self.selectComboBoxText(self.form.jobModel, self.obj.Proxy.baseObject(self.obj).Label)

        self.postProcessorDefaultTooltip = self.form.postProcessor.toolTip()
        self.postProcessorArgsDefaultTooltip = self.form.postProcessorArguments.toolTip()

        self.vproxy.setupEditVisibility(self.obj)

        self.stockFromBase = None
        self.stockFromExisting = None
        self.stockCreateBox = None
        self.stockCreateCylinder = None
        self.stockEdit = None

        self.setupGlobal = PathSetupSheetGui.GlobalEditor(self.obj.SetupSheet, self.form)
        self.setupOps = PathSetupSheetGui.OpsDefaultEditor(self.obj.SetupSheet, self.form)
示例#36
0
    def exportObjectsWith(self, objs, job, needFilename = True):
        PathLog.track()
        # check if the user has a project and has set the default post and
        # output filename
        postArgs = PathPreferences.defaultPostProcessorArgs()
        if hasattr(job, "PostProcessorArgs") and job.PostProcessorArgs:
            postArgs = job.PostProcessorArgs
        elif hasattr(job, "PostProcessor") and job.PostProcessor:
            postArgs = ''

        postname = self.resolvePostProcessor(job)
        filename = '-'
        if postname and needFilename:
            filename = self.resolveFileName(job)

        if postname and filename:
            print("post: %s(%s, %s)" % (postname, filename, postArgs))
            processor = PostProcessor.load(postname)
            gcode = processor.export(objs, filename, postArgs)
            return (False, gcode)
        else:
            return (True, '')
    def saveSettings(self):
        filePath = self.form.leDefaultFilePath.text()
        jobTemplate = self.form.leDefaultJobTemplate.text()
        geometryTolerance = Units.Quantity(self.form.geometryTolerance.text())
        curveAccuracy = Units.Quantity(self.form.curveAccuracy.text())
        PathPreferences.setJobDefaults(filePath, jobTemplate, geometryTolerance, curveAccuracy)

        if curveAccuracy:
            Path.Area.setDefaultParams(Accuracy = curveAccuracy)

        processor = str(self.form.defaultPostProcessor.currentText())
        args = str(self.form.defaultPostProcessorArgs.text())
        blacklist = []
        for i in range(0, self.form.postProcessorList.count()):
            item = self.form.postProcessorList.item(i)
            if item.checkState() == QtCore.Qt.CheckState.Unchecked:
                blacklist.append(item.text())
        PathPreferences.setPostProcessorDefaults(processor, args, blacklist)

        path = str(self.form.leOutputFile.text())
        policy = str(self.form.cboOutputPolicy.currentText())
        PathPreferences.setOutputFileDefaults(path, policy)
        self.saveStockSettings()
    def loadStockSettings(self):
        stock = PathPreferences.defaultStockTemplate()
        index = -1
        if stock:
            attrs = json.loads(stock)
            if attrs.get('version') and 1 == int(attrs['version']):
                stockType = attrs.get('create')
                if stockType == PathStock.StockType.FromBase:
                    index = 2
                elif stockType == PathStock.StockType.CreateBox:
                    index = 0
                elif stockType == PathStock.StockType.CreateCylinder:
                    index = 1
                else:
                    index = -1
        if -1 == index:
            attrs = {}
            self.form.stockGroup.setChecked(False)
        else:
            self.form.stockGroup.setChecked(True)
            self.form.stock.setCurrentIndex(index)

        # this either sets the default value or the value from the template for each field
        self.form.stockExtXneg.setText(attrs.get('xneg', '1 mm'))
        self.form.stockExtXpos.setText(attrs.get('xpos', '1 mm'))
        self.form.stockExtYneg.setText(attrs.get('yneg', '1 mm'))
        self.form.stockExtYpos.setText(attrs.get('ypos', '1 mm'))
        self.form.stockExtZneg.setText(attrs.get('zneg', '1 mm'))
        self.form.stockExtZpos.setText(attrs.get('zpos', '1 mm'))
        self.form.stockBoxLength.setText(attrs.get('length', '10 mm'))
        self.form.stockBoxWidth.setText(attrs.get('width', '10 mm'))
        self.form.stockBoxHeight.setText(attrs.get('height', '10 mm'))
        self.form.stockCylinderRadius.setText(attrs.get('radius', '5 mm'))
        self.form.stockCylinderHeight.setText(attrs.get('height', '10 mm'))

        posX = attrs.get('posX')
        posY = attrs.get('posY')
        posZ = attrs.get('posZ')
        rotX = attrs.get('rotX')
        rotY = attrs.get('rotY')
        rotZ = attrs.get('rotZ')
        rotW = attrs.get('rotW')
        if posX is not None and posY is not None and posZ is not None and rotX is not None and rotY is not None and rotZ is not None and rotW is not None:
            pos = FreeCAD.Vector(float(posX), float(posY), float(posZ)) 
            rot = FreeCAD.Rotation(float(rotX), float(rotY), float(rotZ), float(rotW))
            placement = FreeCAD.Placement(pos, rot)
            self.form.stockPlacementGroup.setChecked(True)
        else:
            placement = FreeCAD.Placement()
            self.form.stockPlacementGroup.setChecked(False)

        self.form.stockAngle.setText(FreeCAD.Units.Quantity("%f rad" % placement.Rotation.Angle).UserString)
        self.form.stockAxisX.setValue(placement.Rotation.Axis.x)
        self.form.stockAxisY.setValue(placement.Rotation.Axis.y)
        self.form.stockAxisZ.setValue(placement.Rotation.Axis.z)
        self.form.stockPositionX.setText(FreeCAD.Units.Quantity(placement.Base.x, FreeCAD.Units.Length).UserString)
        self.form.stockPositionY.setText(FreeCAD.Units.Quantity(placement.Base.y, FreeCAD.Units.Length).UserString)
        self.form.stockPositionZ.setText(FreeCAD.Units.Quantity(placement.Base.z, FreeCAD.Units.Length).UserString)

        self.setupStock(index)
        self.form.stock.currentIndexChanged.connect(self.setupStock)
 def bestGuessForFilePath(self):
     path = self.form.leDefaultFilePath.text()
     if not path:
         path = PathPreferences.filePath()
     return path
示例#40
0
    def Initialize(self):
        global PathCommandGroup

        # Add preferences pages - before loading PathGui to properly order pages of Path group
        from PathScripts import PathPreferencesPathJob, PathPreferencesPathDressup
        FreeCADGui.addPreferencePage(PathPreferencesPathJob.JobPreferencesPage, "Path")
        FreeCADGui.addPreferencePage(PathPreferencesPathDressup.DressupPreferencesPage, "Path")

        # Check enablement of experimental features
        from PathScripts import PathPreferences

        # load the builtin modules
        import Path
        import PathScripts
        import PathGui
        from PySide import QtCore, QtGui
        FreeCADGui.addLanguagePath(":/translations")
        FreeCADGui.addIconPath(":/icons")
        from PathScripts import PathGuiInit
        from PathScripts import PathJobCmd
        import PathCommands
        PathGuiInit.Startup()

        # build commands list
        projcmdlist = ["Path_Job", "Path_Post"]
        toolcmdlist = ["Path_Inspect", "Path_Simulator", "Path_ToolLibraryEdit", "Path_SelectLoop", "Path_OpActiveToggle"]
        prepcmdlist = ["Path_Fixture", "Path_Comment", "Path_Stop", "Path_Custom"]
        twodopcmdlist = ["Path_Contour", "Path_Profile_Faces", "Path_Profile_Edges", "Path_Pocket_Shape", "Path_Drilling", "Path_MillFace", "Path_Helix", "Path_Adaptive" ]
        threedopcmdlist = ["Path_Pocket_3D"]
        engravecmdlist = ["Path_Engrave", "Path_Deburr"]
        modcmdlist = ["Path_OperationCopy", "Path_Array", "Path_SimpleCopy" ]
        dressupcmdlist = ["Path_DressupAxisMap", "Path_DressupDogbone", "Path_DressupDragKnife", "Path_DressupLeadInOut", "Path_DressupRampEntry", "Path_DressupTag"]
        extracmdlist = []
        #modcmdmore = ["Path_Hop",]
        #remotecmdlist = ["Path_Remote"]

        engravecmdgroup = ['Path_EngraveTools']
        FreeCADGui.addCommand('Path_EngraveTools', PathCommandGroup(engravecmdlist, QtCore.QT_TRANSLATE_NOOP("Path", 'Engraving Operations')))

        if PathPreferences.experimentalFeaturesEnabled():
            projcmdlist.append("Path_Sanity")
            prepcmdlist.append("Path_Shape")
            extracmdlist.extend(["Path_Area", "Path_Area_Workplane"])

            threedopcmdlist.append("Path_Surface")
            threedcmdgroup = ['Path_3dTools']
            FreeCADGui.addCommand('Path_3dTools', PathCommandGroup(threedopcmdlist, QtCore.QT_TRANSLATE_NOOP("Path",'3D Operations')))

        else:
            threedcmdgroup = threedopcmdlist

        self.appendToolbar(QtCore.QT_TRANSLATE_NOOP("Path", "Project Setup"), projcmdlist)
        self.appendToolbar(QtCore.QT_TRANSLATE_NOOP("Path", "Tool Commands"), toolcmdlist)
        self.appendToolbar(QtCore.QT_TRANSLATE_NOOP("Path", "New Operations"), twodopcmdlist+engravecmdgroup+threedcmdgroup)
        self.appendToolbar(QtCore.QT_TRANSLATE_NOOP("Path", "Path Modification"), modcmdlist)
        if extracmdlist:
            self.appendToolbar(QtCore.QT_TRANSLATE_NOOP("Path", "Helpful Tools"), extracmdlist)

        self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path")], projcmdlist +["Path_ExportTemplate", "Separator"] + toolcmdlist +["Separator"] + twodopcmdlist + engravecmdlist +["Separator"] +threedopcmdlist +["Separator"])
        self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path"), QtCore.QT_TRANSLATE_NOOP(
            "Path", "Path Dressup")], dressupcmdlist)
        self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path"), QtCore.QT_TRANSLATE_NOOP(
            "Path", "Supplemental Commands")], prepcmdlist)
        self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path"), QtCore.QT_TRANSLATE_NOOP(
            "Path", "Path Modification")], modcmdlist)
        if extracmdlist:
            self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path")], extracmdlist)

        self.dressupcmds = dressupcmdlist

        curveAccuracy = PathPreferences.defaultLibAreaCurveAccuracy()
        if curveAccuracy:
            Path.Area.setDefaultParams(Accuracy = curveAccuracy)

        Log('Loading Path workbench... done\n')
示例#41
0
    def opExecute(self, obj):
        '''opExecute(obj) ... process surface operation'''
        PathLog.track()

        # OCL must be installed
        try:
            import ocl
        except:
            FreeCAD.Console.PrintError(
                translate("Path_Surface", "This operation requires OpenCamLib to be installed.") + "\n")
            return

        print("StepOver is  " + str(obj.StepOver))
        if obj.StepOver > 100:
            obj.StepOver = 100
        if obj.StepOver < 1:
            obj.StepOver = 1
        output = ""
        if obj.Comment != "":
            output += '(' + str(obj.Comment) + ')\n'

        output += "(" + obj.Label + ")"
        output += "(Compensated Tool Path. Diameter: " + str(obj.ToolController.Tool.Diameter) + ")"

        parentJob = PathUtils.findParentJob(obj)
        if parentJob is None:
            return

        print("base object: " + self.baseobject.Name)

        if self.baseobject.TypeId.startswith('Mesh'):
            mesh = self.baseobject.Mesh
        else:
            # try/except is for Path Jobs created before GeometryTolerance
            try:
                deflection = parentJob.GeometryTolerance
            except AttributeError:
                import PathScripts.PathPreferences as PathPreferences
                deflection = PathPreferences.defaultGeometryTolerance()
            self.baseobject.Shape.tessellate(0.5)
            mesh = MeshPart.meshFromShape(self.baseobject.Shape, Deflection=deflection)
        if obj.BoundBox == "BaseBoundBox":
            bb = mesh.BoundBox
        else:
            bb = parentJob.Stock.Shape.BoundBox

        s = ocl.STLSurf()
        for f in mesh.Facets:
            p = f.Points[0]
            q = f.Points[1]
            r = f.Points[2]
            # offset the triangle in Z with DepthOffset
            t = ocl.Triangle(ocl.Point(p[0], p[1], p[2] + obj.DepthOffset.Value),
                             ocl.Point(q[0], q[1], q[2] + obj.DepthOffset.Value),
                             ocl.Point(r[0], r[1], r[2] + obj.DepthOffset.Value))
            s.addTriangle(t)

        if obj.Algorithm == 'OCL Dropcutter':
            output = self._dropcutter(obj, s, bb)
        elif obj.Algorithm == 'OCL Waterline':
            output = self._waterline(obj, s, bb)

        self.commandlist.extend(output)
示例#42
0
    def __init__(self, obj, deleteOnReject, opPage, selectionFactory):
        PathLog.track(obj.Label, deleteOnReject, opPage, selectionFactory)
        FreeCAD.ActiveDocument.openTransaction(translate("Path", "AreaOp Operation"))
        self.deleteOnReject = deleteOnReject
        self.featurePages = []

        features = obj.Proxy.opFeatures(obj)
        opPage.features = features

        if PathOp.FeatureBaseGeometry & features:
            if hasattr(opPage, 'taskPanelBaseGeometryPage'):
                self.featurePages.append(opPage.taskPanelBaseGeometryPage(obj, features))
            else:
                self.featurePages.append(TaskPanelBaseGeometryPage(obj, features))

        if PathOp.FeatureLocations & features:
            if hasattr(opPage, 'taskPanelBaseLocationPage'):
                self.featurePages.append(opPage.taskPanelBaseLocationPage(obj, features))
            else:
                self.featurePages.append(TaskPanelBaseLocationPage(obj, features))

        if PathOp.FeatureDepths & features or PathOp.FeatureStepDown:
            if hasattr(opPage, 'taskPanelDepthsPage'):
                self.featurePages.append(opPage.taskPanelDepthsPage(obj, features))
            else:
                self.featurePages.append(TaskPanelDepthsPage(obj, features))

        if PathOp.FeatureHeights & features:
            if hasattr(opPage, 'taskPanelHeightsPage'):
                self.featurePages.append(opPage.taskPanelHeightsPage(obj, features))
            else:
                self.featurePages.append(TaskPanelHeightsPage(obj, features))

        self.featurePages.append(opPage)

        for page in self.featurePages:
            page.initPage(obj)
            page.onDirtyChanged(self.pageDirtyChanged)

        taskPanelLayout = PathPreferences.defaultTaskPanelLayout()

        if taskPanelLayout < 2:
            opTitle = opPage.getTitle(obj)
            opPage.setTitle(translate('PathOp', 'Operation'))
            toolbox = QtGui.QToolBox()
            if taskPanelLayout == 0:
                for page in self.featurePages:
                    toolbox.addItem(page.form, page.getTitle(obj))
                toolbox.setCurrentIndex(len(self.featurePages)-1)
            else:
                for page in reversed(self.featurePages):
                    toolbox.addItem(page.form, page.getTitle(obj))
            PathLog.info("Title: '%s'" % opTitle)
            toolbox.setWindowTitle(opTitle)
            if opPage.getIcon(obj):
                toolbox.setWindowIcon(QtGui.QIcon(opPage.getIcon(obj)))

            self.form = toolbox
        elif taskPanelLayout == 2:
            forms = []
            for page in self.featurePages:
                page.form.setWindowTitle(page.getTitle(obj))
                forms.append(page.form)
            self.form = forms
        elif taskPanelLayout == 3:
            forms = []
            for page in reversed(self.featurePages):
                page.form.setWindowTitle(page.getTitle(obj))
                forms.append(page.form)
            self.form = forms

        self.selectionFactory = selectionFactory
        self.obj = obj
        self.isdirty = deleteOnReject
 def exists(cls, processor):
     return processor in PathPreferences.allAvailablePostProcessors()