~freecad-community/freecad-extras/fasteners

« back to all changes in this revision

Viewing changes to FastenersCmd.py

  • Committer: GitHub
  • Author(s): Shai Seger
  • Date: 2022-02-09 15:56:43 UTC
  • mfrom: (152.1.1)
  • Revision ID: git-v1:dfeb76eec3cec9c7a264eed2c399672cb6a0e1da
Merge pull request #125 from shaise/revert-123-fix_indent

Revert "Fix indentations"

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#  
24
24
###################################################################################
25
25
 
26
 
import FreeCAD
27
 
import os
28
26
from FreeCAD import Gui
29
 
 
 
27
import FreeCAD, FreeCADGui, Part, os
30
28
__dir__ = os.path.dirname(__file__)
31
 
iconPath = os.path.join(__dir__, 'Icons')
 
29
iconPath = os.path.join( __dir__, 'Icons' )
 
30
import screw_maker
32
31
 
33
32
import FastenerBase
34
33
from FastenerBase import FSBaseObject
35
 
import ScrewMaker
36
 
 
 
34
import ScrewMaker  
37
35
screwMaker = ScrewMaker.Instance()
38
36
 
39
 
 
40
37
class FSScrewObject(FSBaseObject):
41
 
    def __init__(self, obj, type, attachTo):
42
 
        '''"Add screw type fastener" '''
43
 
        super().__init__(self, obj, attachTo)
44
 
        self.itemText = screwMaker.GetTypeName(type)
45
 
        diameters = screwMaker.GetAllDiams(type)
46
 
        diameters.insert(0, 'Auto')
47
 
        self.type = ''
48
 
        self.diameter = ''
49
 
        self.matchOuter = ''
50
 
        self.length = ''
51
 
        self.customlen = -1
52
 
        # self.Proxy = obj.Name
53
 
        obj.addProperty("App::PropertyEnumeration", "type", "Parameters", "Screw type").type = screwMaker.GetAllTypes(
54
 
            self.itemText)
55
 
        obj.type = type
56
 
        obj.addProperty("App::PropertyEnumeration", "diameter", "Parameters",
57
 
                        "Screw diameter standard").diameter = diameters
58
 
        self.VerifyMissingAttrs(obj, diameters[1])
59
 
        if self.itemText != "Washer":
60
 
            obj.addProperty("App::PropertyBool", "thread", "Parameters", "Generate real thread").thread = False
61
 
        obj.Proxy = self
62
 
 
63
 
    def inswap(self, inpstr):
64
 
        if '″' in inpstr:
65
 
            return inpstr.replace('″', 'in')
66
 
        else:
67
 
            return inpstr
68
 
 
69
 
    def VerifyMissingAttrs(self, obj, diameter):
70
 
        self.updateProps(obj)
71
 
        if not hasattr(obj, 'matchOuter'):
72
 
            obj.addProperty("App::PropertyBool", "matchOuter", "Parameters", "Match outer thread diameter").matchOuter = FastenerBase.FSMatchOuter
73
 
        if self.itemText == "Screw" and not hasattr(obj, 'lengthCustom'):
74
 
            slens = screwMaker.GetAllLengths(obj.type, diameter)
75
 
            if hasattr(obj, 'length'):
76
 
                origLen = obj.length
77
 
                obj.length = slens
78
 
                obj.length = origLen
79
 
            else:
80
 
                obj.addProperty("App::PropertyEnumeration", "length", "Parameters", "Screw length").length = slens
81
 
            obj.addProperty("App::PropertyLength", "lengthCustom", "Parameters",
82
 
                            "Custom length").lengthCustom = self.inswap(slens[0])
83
 
 
84
 
    def ActiveLength(self, obj):
85
 
        if not hasattr(obj, 'length'):
86
 
            return '0'
87
 
        if obj.length == 'Custom':
88
 
            return str(float(obj.lengthCustom)).rstrip("0").rstrip('.')
89
 
        return obj.length
90
 
 
91
 
    def execute(self, fp):
92
 
        '''"Print a short message when doing a recomputation, this method is mandatory" '''
93
 
 
94
 
        try:
95
 
            baseobj = fp.baseObject[0]
96
 
            shape = baseobj.Shape.getElement(fp.baseObject[1][0])
97
 
        except:
98
 
            baseobj = None
99
 
            shape = None
100
 
 
101
 
        # for backward compatibility: add missing attribute if needed
102
 
        self.VerifyMissingAttrs(fp, fp.diameter)
103
 
 
104
 
        # FreeCAD.Console.PrintLog("MatchOuter:" + str(fp.matchOuter) + "\n")
105
 
 
106
 
        typechange = False
107
 
        if fp.type == "ISO7380":
108
 
            fp.type = "ISO7380-1"  # backward compatibility
109
 
        if not (hasattr(self, 'type')) or fp.type != self.type:
110
 
            typechange = True
111
 
            curdiam = fp.diameter
112
 
            diameters = screwMaker.GetAllDiams(fp.type)
113
 
            diameters.insert(0, 'Auto')
114
 
            if not (curdiam in diameters):
115
 
                curdiam = 'Auto'
116
 
            fp.diameter = diameters
117
 
            fp.diameter = curdiam
118
 
 
119
 
        diameterchange = False
120
 
        if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
121
 
            diameterchange = True
122
 
 
123
 
        matchouterchange = not (hasattr(self, 'matchOuter')) or self.matchOuter != fp.matchOuter
124
 
 
125
 
        if fp.diameter == 'Auto' or matchouterchange:
126
 
            d = screwMaker.AutoDiameter(fp.type, shape, baseobj, fp.matchOuter)
127
 
            fp.diameter = d
128
 
            diameterchange = True
129
 
        else:
130
 
            d = fp.diameter
131
 
 
132
 
        if hasattr(fp, 'length'):
133
 
            if fp.length != self.length:
134
 
                if fp.length != 'Custom':
135
 
                    fp.lengthCustom = FastenerBase.LenStr2Num(fp.length)  # ***
136
 
            elif hasattr(self, 'customlen') and float(fp.lengthCustom) != self.customlen:
137
 
                fp.length = 'Custom'
138
 
            origLen = self.ActiveLength(fp)
139
 
            origIsCustom = fp.length == 'Custom'
140
 
            d, l = screwMaker.FindClosest(fp.type, d, origLen)
141
 
            if d != fp.diameter:
142
 
                diameterchange = True
143
 
                fp.diameter = d
144
 
 
145
 
            if origIsCustom:
146
 
                l = origLen
147
 
 
148
 
            if l != origLen or diameterchange or typechange:
149
 
                if diameterchange or typechange:
150
 
                    fp.length = screwMaker.GetAllLengths(fp.type, fp.diameter)
151
 
                if origIsCustom:
152
 
                    fp.length = 'Custom'
153
 
                else:
154
 
                    fp.length = l
155
 
                    fp.lengthCustom = l
156
 
        else:
157
 
            l = 1
158
 
 
159
 
        screwMaker.updateFastenerParameters()
160
 
 
161
 
        threadType = 'simple'
162
 
        if hasattr(fp, 'thread') and fp.thread:
163
 
            threadType = 'real'
164
 
 
165
 
        (key, s) = FastenerBase.FSGetKey(self.itemText, fp.type, d, l, threadType)
166
 
        if s is None:
167
 
            s = screwMaker.createFastener(fp.type, d, l, threadType, True)
168
 
            FastenerBase.FSCache[key] = s
169
 
        else:
170
 
            FreeCAD.Console.PrintLog("Using cached object\n")
171
 
 
172
 
        self.type = fp.type
173
 
        self.diameter = fp.diameter
174
 
        self.matchOuter = fp.matchOuter
175
 
        if hasattr(fp, 'length'):
176
 
            self.length = l
177
 
            self.customlen = float(fp.lengthCustom)
178
 
            fp.Label = fp.diameter + 'x' + l + '-' + self.itemText
179
 
        else:
180
 
            fp.Label = fp.diameter + '-' + self.itemText
181
 
 
182
 
        if hasattr(fp, 'thread'):
183
 
            self.realThread = fp.thread
184
 
        # self.itemText = s[1]
185
 
        fp.Shape = s
186
 
 
187
 
        if shape is not None:
188
 
            # feature = FreeCAD.ActiveDocument.getObject(self.Proxy)
189
 
            # fp.Placement = FreeCAD.Placement() # reset placement
190
 
            FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
191
 
 
192
 
    # def getItemText():
193
 
    #  return self.itemText
 
38
  def __init__(self, obj, type, attachTo):
 
39
    '''"Add screw type fastener" '''
 
40
    FSBaseObject.__init__(self, obj, attachTo)
 
41
    self.itemText = screwMaker.GetTypeName(type)
 
42
    diameters = screwMaker.GetAllDiams(type)
 
43
    diameters.insert(0, 'Auto')
 
44
    self.type = ''
 
45
    self.diameter = ''
 
46
    self.matchOuter = ''
 
47
    self.length = ''
 
48
    self.customlen = -1
 
49
    #self.Proxy = obj.Name
 
50
    obj.addProperty("App::PropertyEnumeration","type","Parameters","Screw type").type = screwMaker.GetAllTypes(self.itemText)
 
51
    obj.type = type
 
52
    obj.addProperty("App::PropertyEnumeration","diameter","Parameters","Screw diameter standard").diameter = diameters
 
53
    self.VerifyMissingAttrs(obj, diameters[1])
 
54
    if self.itemText != "Washer":
 
55
      obj.addProperty("App::PropertyBool", "thread", "Parameters", "Generate real thread").thread = False
 
56
    obj.Proxy = self
 
57
    
 
58
  def inswap(self, inpstr):
 
59
    if '″' in inpstr:
 
60
      return inpstr.replace('″', 'in')
 
61
    else:
 
62
      return inpstr
 
63
 
 
64
  def VerifyMissingAttrs(self, obj, diameter):
 
65
    self.updateProps(obj)
 
66
    if not (hasattr(obj, 'matchOuter')):
 
67
      obj.addProperty("App::PropertyBool", "matchOuter", "Parameters", "Match outer thread diameter").matchOuter = FastenerBase.FSMatchOuter
 
68
    if self.itemText == "Screw" and  not hasattr(obj, 'lengthCustom'):
 
69
      slens = screwMaker.GetAllLengths(obj.type, diameter)
 
70
      if hasattr(obj, 'length'):
 
71
        origLen = obj.length
 
72
        obj.length = slens
 
73
        obj.length = origLen
 
74
      else:
 
75
        obj.addProperty("App::PropertyEnumeration","length","Parameters","Screw length").length = slens
 
76
      obj.addProperty("App::PropertyLength","lengthCustom","Parameters","Custom length").lengthCustom = self.inswap(slens[0])
 
77
 
 
78
  def ActiveLength(self, obj):
 
79
    if not hasattr(obj,'length'):
 
80
      return '0'
 
81
    if obj.length == 'Custom':
 
82
      return str(float(obj.lengthCustom)).rstrip("0").rstrip('.')
 
83
    return obj.length
 
84
 
 
85
  def execute(self, fp):
 
86
    '''"Print a short message when doing a recomputation, this method is mandatory" '''
 
87
    
 
88
    try:
 
89
      baseobj = fp.baseObject[0]
 
90
      shape = baseobj.Shape.getElement(fp.baseObject[1][0])
 
91
    except:
 
92
      baseobj = None
 
93
      shape = None
 
94
    
 
95
    # for backward compatibility: add missing attribute if needed
 
96
    self.VerifyMissingAttrs(fp, fp.diameter)
 
97
    
 
98
    #FreeCAD.Console.PrintLog("MatchOuter:" + str(fp.matchOuter) + "\n")
 
99
    
 
100
    typechange = False
 
101
    if fp.type == "ISO7380":
 
102
      fp.type = "ISO7380-1"   # backward compatibility
 
103
    if not (hasattr(self, 'type')) or fp.type != self.type:
 
104
      typechange = True
 
105
      curdiam = fp.diameter
 
106
      diameters = screwMaker.GetAllDiams(fp.type)
 
107
      diameters.insert(0, 'Auto')
 
108
      if not(curdiam in diameters):
 
109
        curdiam='Auto'
 
110
      fp.diameter = diameters
 
111
      fp.diameter = curdiam
 
112
      
 
113
    diameterchange = False      
 
114
    if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
 
115
      diameterchange = True      
 
116
 
 
117
    matchouterchange = not (hasattr(self, 'matchOuter')) or self.matchOuter != fp.matchOuter
 
118
 
 
119
    if fp.diameter == 'Auto' or matchouterchange:
 
120
      d = screwMaker.AutoDiameter(fp.type, shape, baseobj, fp.matchOuter)
 
121
      fp.diameter = d
 
122
      diameterchange = True      
 
123
    else:
 
124
      d = fp.diameter
 
125
    
 
126
    if hasattr(fp,'length'):
 
127
      if fp.length !=  self.length:
 
128
        if fp.length != 'Custom':
 
129
          fp.lengthCustom = FastenerBase.LenStr2Num(fp.length) #***
 
130
      elif hasattr(self,'customlen') and float(fp.lengthCustom) != self.customlen:
 
131
        fp.length = 'Custom'
 
132
      origLen = self.ActiveLength(fp)
 
133
      origIsCustom = fp.length == 'Custom'
 
134
      d , l = screwMaker.FindClosest(fp.type, d, origLen)
 
135
      if d != fp.diameter:
 
136
        diameterchange = True      
 
137
        fp.diameter = d
 
138
 
 
139
      if origIsCustom:
 
140
        l = origLen
 
141
        
 
142
      if l != origLen or diameterchange or typechange:
 
143
        if diameterchange or typechange:
 
144
          fp.length = screwMaker.GetAllLengths(fp.type, fp.diameter)
 
145
        if origIsCustom:
 
146
          fp.length = 'Custom'
 
147
        else:
 
148
          fp.length = l
 
149
          fp.lengthCustom = l
 
150
    else:
 
151
      l = 1
 
152
      
 
153
    screwMaker.updateFastenerParameters()  
 
154
      
 
155
    threadType = 'simple'
 
156
    if hasattr(fp,'thread') and fp.thread:
 
157
      threadType = 'real'
 
158
      
 
159
    (key, s) = FastenerBase.FSGetKey(self.itemText, fp.type, d, l, threadType)
 
160
    if s is None:
 
161
      s = screwMaker.createFastener(fp.type, d, l, threadType, True)
 
162
      FastenerBase.FSCache[key] = s
 
163
    else:
 
164
      FreeCAD.Console.PrintLog("Using cached object\n")
 
165
 
 
166
    self.type = fp.type
 
167
    self.diameter = fp.diameter
 
168
    self.matchOuter = fp.matchOuter
 
169
    if hasattr(fp,'length'):
 
170
      self.length = l
 
171
      self.customlen = float(fp.lengthCustom)
 
172
      fp.Label = fp.diameter + 'x' + l + '-' + self.itemText
 
173
    else:
 
174
      fp.Label = fp.diameter + '-' + self.itemText
 
175
    
 
176
    if hasattr(fp,'thread'):
 
177
      self.realThread = fp.thread
 
178
    #self.itemText = s[1]
 
179
    fp.Shape = s
 
180
 
 
181
    if shape is not None:
 
182
      #feature = FreeCAD.ActiveDocument.getObject(self.Proxy)
 
183
      #fp.Placement = FreeCAD.Placement() # reset placement
 
184
      FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
 
185
    
 
186
  #def getItemText():
 
187
  #  return self.itemText
 
188
    
194
189
 
195
190
 
196
191
class FSViewProviderTree:
197
 
    "A View provider for custom icon"
198
 
 
199
 
    def __init__(self, obj):
200
 
        obj.Proxy = self
201
 
        self.Object = obj.Object
202
 
 
203
 
    def attach(self, obj):
204
 
        self.Object = obj.Object
205
 
        return
206
 
 
207
 
    def updateData(self, fp, prop):
208
 
        return
209
 
 
210
 
    def getDisplayModes(self, obj):
211
 
        modes = []
212
 
        return modes
213
 
 
214
 
    def setDisplayMode(self, mode):
215
 
        return mode
216
 
 
217
 
    def onChanged(self, vp, prop):
218
 
        return
219
 
 
220
 
    def __getstate__(self):
221
 
        #        return {'ObjectName' : self.Object.Name}
222
 
        return None
223
 
 
224
 
    def __setstate__(self, state):
225
 
        if state is not None:
226
 
            import FreeCAD
227
 
            doc = FreeCAD.ActiveDocument  # crap
228
 
            self.Object = doc.getObject(state['ObjectName'])
229
 
 
230
 
    def getIcon(self):
231
 
        if hasattr(self.Object, "type"):
232
 
            return os.path.join(iconPath, self.Object.type + '.svg')
233
 
        elif hasattr(self.Object.Proxy, "type"):
234
 
            return os.path.join(iconPath, self.Object.Proxy.type + '.svg')
235
 
        # default to ISO4017.svg
236
 
        return os.path.join(iconPath, 'ISO4017.svg')
 
192
  "A View provider for custom icon"
 
193
      
 
194
  def __init__(self, obj):
 
195
    obj.Proxy = self
 
196
    self.Object = obj.Object
 
197
      
 
198
  def attach(self, obj):
 
199
    self.Object = obj.Object
 
200
    return
 
201
 
 
202
  def updateData(self, fp, prop):
 
203
    return
 
204
 
 
205
  def getDisplayModes(self,obj):
 
206
    modes=[]
 
207
    return modes
 
208
 
 
209
  def setDisplayMode(self,mode):
 
210
    return mode
 
211
 
 
212
  def onChanged(self, vp, prop):
 
213
    return
 
214
 
 
215
  def __getstate__(self):
 
216
    #        return {'ObjectName' : self.Object.Name}
 
217
    return None
 
218
 
 
219
  def __setstate__(self,state):
 
220
    if state is not None:
 
221
      import FreeCAD
 
222
      doc = FreeCAD.ActiveDocument #crap
 
223
      self.Object = doc.getObject(state['ObjectName'])
 
224
 
 
225
  def getIcon(self):
 
226
    if hasattr(self.Object, "type"):
 
227
      return os.path.join( iconPath , self.Object.type + '.svg')
 
228
    elif hasattr(self.Object.Proxy, "type"):
 
229
      return os.path.join( iconPath, self.Object.Proxy.type + '.svg')
 
230
    # default to ISO4017.svg
 
231
    return os.path.join( iconPath , 'ISO4017.svg')
 
232
 
237
233
 
238
234
 
239
235
class FSScrewCommand:
240
 
    """Add Screw command"""
241
 
 
242
 
    def __init__(self, type, help):
243
 
        self.Type = type
244
 
        self.Help = help
245
 
        self.TypeName = screwMaker.GetTypeName(type)
246
 
 
247
 
    def GetResources(self):
248
 
        icon = os.path.join(iconPath, self.Type + '.svg')
249
 
        return {
250
 
            'Pixmap': icon,  # the name of a svg file available in the resources
251
 
            'MenuText': "Add " + self.Help,
252
 
            'ToolTip': self.Help
253
 
        }
254
 
 
255
 
    def Activated(self):
256
 
        for selObj in FastenerBase.FSGetAttachableSelections():
257
 
            a = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", self.TypeName)
258
 
            FSScrewObject(a, self.Type, selObj)
259
 
            a.Label = a.Proxy.itemText
260
 
            FSViewProviderTree(a.ViewObject)
261
 
        FreeCAD.ActiveDocument.recompute()
262
 
        return
263
 
 
264
 
    def IsActive(self):
265
 
        return Gui.ActiveDocument is not None
266
 
 
267
 
 
268
 
def FSAddScrewCommand(type, help, dropGroup=None):
269
 
    cmd = 'FS' + type
270
 
    Gui.addCommand(cmd, FSScrewCommand(type, help))
271
 
    FastenerBase.FSCommands.append(cmd, "screws", dropGroup)
272
 
 
273
 
 
 
236
  """Add Screw command"""
 
237
 
 
238
  def __init__(self, type, help):
 
239
    self.Type = type
 
240
    self.Help = help
 
241
    self.TypeName = screwMaker.GetTypeName(type)
 
242
 
 
243
  def GetResources(self):
 
244
    icon = os.path.join( iconPath , self.Type + '.svg')
 
245
    return {'Pixmap'  : icon , # the name of a svg file available in the resources
 
246
            'MenuText': "Add " + self.Help ,
 
247
            'ToolTip' : self.Help}
 
248
 
 
249
  def Activated(self):
 
250
    for selObj in FastenerBase.FSGetAttachableSelections():
 
251
      a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython",self.TypeName)
 
252
      FSScrewObject(a, self.Type, selObj)
 
253
      a.Label = a.Proxy.itemText
 
254
      FSViewProviderTree(a.ViewObject)
 
255
    FreeCAD.ActiveDocument.recompute()
 
256
    return
 
257
   
 
258
  def IsActive(self):
 
259
    return Gui.ActiveDocument is not None
 
260
 
 
261
def FSAddScrewCommand(type, help, dropGroup = None):
 
262
  cmd = 'FS' + type
 
263
  Gui.addCommand(cmd,FSScrewCommand(type, help))
 
264
  FastenerBase.FSCommands.append(cmd, "screws", dropGroup)
 
265
  
274
266
FSAddScrewCommand("ISO4017", "ISO 4017 Hex head screw", "Hex head")
275
267
FSAddScrewCommand("ISO4014", "ISO 4014 Hex head bolt", "Hex head")
276
268
FSAddScrewCommand("EN1662", "EN 1662 Hexagon bolt with flange, small series", "Hex head")
292
284
FSAddScrewCommand("ISO7048", "ISO 7048 Cheese head screws with type H cross r.", "H cross")
293
285
FSAddScrewCommand("ISO14579", "ISO 14579 Hexalobular socket head cap screws", "Hexalobular socket")
294
286
FSAddScrewCommand("ISO14580", "ISO 14580 Hexalobular socket cheese head screws", "Hexalobular socket")
295
 
# FSAddScrewCommand("ISO14581", "ISO 14581 Hexalobular socket countersunk flat head screws", "Hexalobular socket")
 
287
#FSAddScrewCommand("ISO14581", "ISO 14581 Hexalobular socket countersunk flat head screws", "Hexalobular socket")
296
288
FSAddScrewCommand("ISO14582", "ISO 14582 Hexalobular socket countersunk head screws, high head", "Hexalobular socket")
297
289
FSAddScrewCommand("ISO14583", "ISO 14583 Hexalobular socket pan head screws", "Hexalobular socket")
298
290
FSAddScrewCommand("ISO14584", "ISO 14584 Hexalobular socket raised countersunk head screws", "Hexalobular socket")
299
291
FSAddScrewCommand("ISO7379", "ISO 7379 Hexagon socket head shoulder screw", "Hexagon socket")
300
292
FSAddScrewCommand("ISO7089", "ISO 7089 Washer", "Washer")
301
293
FSAddScrewCommand("ISO7090", "ISO 7090 Plain Washers, chamfered - Normal series", "Washer")
302
 
# FSAddScrewCommand("ISO7091", "ISO 7091 Plain washer - Normal series Product Grade C", "Washer")  # same as 7089??
 
294
#FSAddScrewCommand("ISO7091", "ISO 7091 Plain washer - Normal series Product Grade C", "Washer")  # same as 7089??
303
295
FSAddScrewCommand("ISO7092", "ISO 7092 Plain washers - Small series", "Washer")
304
296
FSAddScrewCommand("ISO7093-1", "ISO 7093-1 Plain washers - Large series", "Washer")
305
297
FSAddScrewCommand("ISO7094", "ISO 7094 Plain washers - Extra large series", "Washer")
310
302
FSAddScrewCommand("ISO4032", "ISO 4032 Hexagon nuts, Style 1", "Nut")
311
303
FSAddScrewCommand("ISO4033", "ISO 4033 Hexagon nuts, Style 2", "Nut")
312
304
FSAddScrewCommand("ISO4035", "ISO 4035 Hexagon thin nuts, chamfered", "Nut")
313
 
# FSAddScrewCommand("ISO4036", "ISO 4035 Hexagon thin nuts, unchamfered", "Nut")
 
305
#FSAddScrewCommand("ISO4036", "ISO 4035 Hexagon thin nuts, unchamfered", "Nut")
314
306
FSAddScrewCommand("EN1661", "EN 1661 Hexagon nuts with flange", "Nut")
315
307
FSAddScrewCommand("DIN557", "DIN 557 Square nuts", "Nut")
316
308
FSAddScrewCommand("DIN562", "DIN 562 Square nuts", "Nut")
336
328
FSAddScrewCommand("ASMEB18.21.1.12C", "ASME B18.21.1 UN washers, wide series", "Washer")
337
329
 
338
330
 
339
 
# deprecated
 
331
 
 
332
 
 
333
#deprecated    
340
334
class FSWasherObject(FSBaseObject):
341
 
    def __init__(self, obj, type, attachTo):
342
 
        '''"Add washer / nut type fastener" '''
343
 
        FSBaseObject.__init__(self, obj, attachTo)
344
 
        self.itemText = screwMaker.GetTypeName(type)
345
 
        diameters = screwMaker.GetAllDiams(type)
346
 
        diameters.insert(0, 'Auto')
347
 
        # self.Proxy = obj.Name
348
 
 
349
 
        obj.addProperty("App::PropertyEnumeration", "type", "Parameters", "Screw type").type = screwMaker.GetAllTypes(
350
 
            self.itemText)
351
 
        obj.addProperty("App::PropertyEnumeration", "diameter", "Parameters",
352
 
                        "Screw diameter standard").diameter = diameters
353
 
        obj.type = type
354
 
        obj.Proxy = self
355
 
 
356
 
    def execute(self, fp):
357
 
        '''"Print a short message when doing a recomputation, this method is mandatory" '''
358
 
 
359
 
        try:
360
 
            baseobj = fp.baseObject[0]
361
 
            shape = baseobj.Shape.getElement(fp.baseObject[1][0])
362
 
        except:
363
 
            baseobj = None
364
 
            shape = None
365
 
 
366
 
        if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
367
 
            if fp.diameter == 'Auto':
368
 
                d = screwMaker.AutoDiameter(fp.type, shape)
369
 
                diameterchange = True
370
 
            else:
371
 
                d = fp.diameter
372
 
 
373
 
            d, l = screwMaker.FindClosest(fp.type, d, '0')
374
 
            if d != fp.diameter:
375
 
                fp.diameter = d
376
 
            s = screwMaker.createScrew(fp.type, d, l, 'simple', True)
377
 
            self.diameter = fp.diameter
378
 
            fp.Label = fp.diameter + '-' + self.itemText
379
 
            # self.itemText = s[1]
380
 
            fp.Shape = s
381
 
        else:
382
 
            FreeCAD.Console.PrintLog("Using cached object\n")
383
 
        if shape is not None:
384
 
            # feature = FreeCAD.ActiveDocument.getObject(self.Proxy)
385
 
            # fp.Placement = FreeCAD.Placement() # reset placement
386
 
            FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
387
 
 
388
 
    def getItemText(self):
389
 
        return self.itemText
390
 
 
391
 
 
392
 
# deprecated
 
335
  def __init__(self, obj, type, attachTo):
 
336
    '''"Add washer / nut type fastener" '''
 
337
    FSBaseObject.__init__(self, obj, attachTo)
 
338
    self.itemText = screwMaker.GetTypeName(type)
 
339
    diameters = screwMaker.GetAllDiams(type)
 
340
    diameters.insert(0, 'Auto')
 
341
    #self.Proxy = obj.Name
 
342
    
 
343
    obj.addProperty("App::PropertyEnumeration","type","Parameters","Screw type").type = screwMaker.GetAllTypes(self.itemText)
 
344
    obj.addProperty("App::PropertyEnumeration","diameter","Parameters","Screw diameter standard").diameter = diameters
 
345
    obj.type = type
 
346
    obj.Proxy = self
 
347
 
 
348
  def execute(self, fp):
 
349
    '''"Print a short message when doing a recomputation, this method is mandatory" '''
 
350
    
 
351
    try:
 
352
      baseobj = fp.baseObject[0]
 
353
      shape = baseobj.Shape.getElement(fp.baseObject[1][0])
 
354
    except:
 
355
      baseobj = None
 
356
      shape = None
 
357
   
 
358
    if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
 
359
      if fp.diameter == 'Auto':
 
360
        d = screwMaker.AutoDiameter(fp.type, shape)
 
361
        diameterchange = True      
 
362
      else:
 
363
        d = fp.diameter
 
364
        
 
365
      d , l = screwMaker.FindClosest(fp.type, d, '0')
 
366
      if d != fp.diameter: 
 
367
        fp.diameter = d
 
368
      s = screwMaker.createScrew(fp.type, d, l, 'simple', True)
 
369
      self.diameter = fp.diameter
 
370
      fp.Label = fp.diameter + '-' + self.itemText
 
371
      #self.itemText = s[1]
 
372
      fp.Shape = s
 
373
    else:
 
374
      FreeCAD.Console.PrintLog("Using cached object\n")
 
375
    if shape is not None:
 
376
      #feature = FreeCAD.ActiveDocument.getObject(self.Proxy)
 
377
      #fp.Placement = FreeCAD.Placement() # reset placement
 
378
      FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
 
379
    
 
380
  def getItemText():
 
381
    return self.itemText
 
382
 
 
383
#deprecated    
393
384
class FSWasherCommand:
394
 
    """Add Screw command"""
395
 
 
396
 
    def __init__(self, type, help):
397
 
        self.Type = type
398
 
        self.Help = help
399
 
 
400
 
    def GetResources(self):
401
 
        icon = os.path.join(iconPath, self.Type + '.svg')
402
 
        return {
403
 
            'Pixmap': icon,  # the name of a svg file available in the resources
404
 
            'MenuText': "Add " + self.Help,
405
 
            'ToolTip': self.Help
406
 
        }
407
 
 
408
 
    def Activated(self):
409
 
        for selObj in FastenerBase.FSGetAttachableSelections():
410
 
            a = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Washer")
411
 
            FSWasherObject(a, self.Type, selObj)
412
 
            a.Label = a.Proxy.itemText
413
 
            FSViewProviderTree(a.ViewObject)
414
 
        FreeCAD.ActiveDocument.recompute()
415
 
        return
416
 
 
417
 
    def IsActive(self):
418
 
        return Gui.ActiveDocument is not None
419
 
 
420
 
 
421
 
# Gui.addCommand("FSISO7089",FSWasherCommand("ISO7089", "Washer"))
422
 
# FastenerBase.FSCommands.append("FSISO7089")
 
385
  """Add Screw command"""
 
386
 
 
387
  def __init__(self, type, help):
 
388
    self.Type = type
 
389
    self.Help = help
 
390
 
 
391
  def GetResources(self):
 
392
    icon = os.path.join( iconPath , self.Type + '.svg')
 
393
    return {'Pixmap'  : icon , # the name of a svg file available in the resources
 
394
            'MenuText': "Add " + self.Help ,
 
395
            'ToolTip' : self.Help}
 
396
 
 
397
  def Activated(self):
 
398
    for selObj in FastenerBase.FSGetAttachableSelections():
 
399
      a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Washer")
 
400
      FSWasherObject(a, self.Type, selObj)
 
401
      a.Label = a.Proxy.itemText
 
402
      FSViewProviderTree(a.ViewObject)
 
403
    FreeCAD.ActiveDocument.recompute()
 
404
    return
 
405
   
 
406
  def IsActive(self):
 
407
    return Gui.ActiveDocument is not None
 
408
 
 
409
#Gui.addCommand("FSISO7089",FSWasherCommand("ISO7089", "Washer"))
 
410
#FastenerBase.FSCommands.append("FSISO7089")
423
411
 
424
412
class FSScrewRodObject(FSBaseObject):
425
 
    def __init__(self, obj, attachTo, typeStr):
426
 
        '''"Add screw rod" '''
427
 
        FSBaseObject.__init__(self, obj, attachTo)
428
 
        self.itemText = "ScrewTap"
429
 
        self.type = typeStr
430
 
        diameters = screwMaker.GetAllDiams(self.type) + ["Custom"]
431
 
        diameters.insert(0, 'Auto')
432
 
        obj.addProperty("App::PropertyEnumeration", "diameter", "Parameters", "Screw diameter standard").diameter = diameters
433
 
        obj.addProperty("App::PropertyLength", "diameterCustom", "Parameters", "Screw major diameter custom").diameterCustom = 6
434
 
        obj.addProperty("App::PropertyLength", "pitchCustom", "Parameters", "Screw pitch custom").pitchCustom = 1.0
435
 
        obj.addProperty("App::PropertyLength", "length", "Parameters", "Screw length").length = 20.0
436
 
        self.VerifyMissingAttrs(obj)
437
 
        obj.addProperty("App::PropertyBool", "thread", "Parameters", "Generate real thread").thread = False
438
 
        obj.Proxy = self
439
 
 
440
 
    def VerifyMissingAttrs(self, obj):
441
 
        self.updateProps(obj)
442
 
        if not (hasattr(obj, 'matchOuter')):
443
 
            obj.addProperty("App::PropertyBool", "matchOuter", "Parameters", "Match outer thread diameter").matchOuter = FastenerBase.FSMatchOuter
444
 
        # for old objects from before custom diameter and pitch were implemented
445
 
        if not hasattr(obj, "pitchCustom"):
446
 
            obj.addProperty("App::PropertyLength", "pitchCustom", "Parameters", "Screw pitch custom").pitchCustom = 1.0
447
 
            obj.addProperty("App::PropertyLength", "diameterCustom", "Parameters", "Screw major diameter custom").diameterCustom = 6
448
 
            dia_tmp = obj.diameter
449
 
            self.type = "ScrewTap"
450
 
            obj.diameter = screwMaker.GetAllDiams(self.type) + ["Custom"]
451
 
            obj.diameter = dia_tmp
452
 
 
453
 
    def execute(self, fp):
454
 
        '''"Print a short message when doing a recomputation, this method is mandatory" '''
455
 
 
456
 
        try:
457
 
            baseobj = fp.baseObject[0]
458
 
            shape = baseobj.Shape.getElement(fp.baseObject[1][0])
459
 
        except:
460
 
            baseobj = None
461
 
            shape = None
462
 
        self.VerifyMissingAttrs(fp)
463
 
        diameterchange = False
464
 
        if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
465
 
            diameterchange = True
466
 
 
467
 
        matchouterchange = not (hasattr(self, 'matchOuter')) or self.matchOuter != fp.matchOuter
468
 
 
469
 
        if fp.diameter == 'Auto' or matchouterchange:
470
 
            d = screwMaker.AutoDiameter(self.type, shape, baseobj, fp.matchOuter)
471
 
            fp.diameter = d
472
 
            diameterchange = True
473
 
            d_custom = None
474
 
        elif fp.diameter == 'Custom':
475
 
            d = fp.diameter
476
 
            d_custom = fp.diameterCustom.Value
477
 
        else:
478
 
            d = fp.diameter
479
 
            d_custom = None
480
 
 
481
 
        l = fp.length.Value
482
 
        if l < 2.0:
483
 
            l = 2.0
484
 
            fp.length = 2.0
485
 
 
486
 
        if fp.diameter == 'Custom':
487
 
            p = fp.pitchCustom.Value
488
 
        else:
489
 
            p = None
490
 
        screwMaker.updateFastenerParameters()
491
 
        threadType = 'simple'
492
 
        if hasattr(fp, 'thread') and fp.thread:
493
 
            threadType = 'real'
494
 
        # since we are bypassing the createScrew() method, we must set
495
 
        # the rThread parameter manually
496
 
        screwMaker.rThread = (threadType == 'real')
497
 
        s = screwMaker.makeScrewTap(self.type, d, l, p, d_custom)
498
 
 
499
 
        self.diameter = fp.diameter
500
 
        self.length = l
501
 
        self.matchOuter = fp.matchOuter
502
 
        diastr = fp.diameter if fp.diameter != 'Custom' else str(fp.diameterCustom)
503
 
        fp.Label = diastr + 'x' + str(l) + '-' + self.itemText
504
 
        self.realThread = fp.thread
505
 
        fp.Shape = s
506
 
 
507
 
        if shape is not None:
508
 
            FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
509
 
 
 
413
  def __init__(self, obj, attachTo, typeStr):
 
414
    '''"Add screw rod" '''
 
415
    FSBaseObject.__init__(self, obj, attachTo)
 
416
    self.itemText = "ScrewTap"
 
417
    self.type = typeStr
 
418
    diameters = screwMaker.GetAllDiams(self.type) + ["Custom"]
 
419
    diameters.insert(0, 'Auto')
 
420
    obj.addProperty("App::PropertyEnumeration","diameter","Parameters","Screw diameter standard").diameter = diameters
 
421
    obj.addProperty("App::PropertyLength","diameterCustom","Parameters","Screw major diameter custom").diameterCustom = 6
 
422
    obj.addProperty("App::PropertyLength","pitchCustom","Parameters","Screw pitch custom").pitchCustom = 1.0
 
423
    obj.addProperty("App::PropertyLength","length","Parameters","Screw length").length = 20.0
 
424
    self.VerifyMissingAttrs(obj)
 
425
    obj.addProperty("App::PropertyBool", "thread", "Parameters", "Generate real thread").thread = False
 
426
    obj.Proxy = self
 
427
 
 
428
  def VerifyMissingAttrs(self, obj):
 
429
    self.updateProps(obj)
 
430
    if not (hasattr(obj, 'matchOuter')):
 
431
      obj.addProperty("App::PropertyBool", "matchOuter", "Parameters", "Match outer thread diameter").matchOuter = FastenerBase.FSMatchOuter
 
432
    # for old objects from before custom diameter and pitch were implemented
 
433
    if not hasattr(obj,"pitchCustom"):
 
434
      obj.addProperty("App::PropertyLength","pitchCustom","Parameters","Screw pitch custom").pitchCustom = 1.0
 
435
      obj.addProperty("App::PropertyLength","diameterCustom","Parameters","Screw major diameter custom").diameterCustom = 6
 
436
      dia_tmp = obj.diameter
 
437
      self.type = "ScrewTap"
 
438
      obj.diameter = screwMaker.GetAllDiams(self.type) + ["Custom"]
 
439
      obj.diameter = dia_tmp
 
440
 
 
441
 
 
442
  def execute(self, fp):
 
443
    '''"Print a short message when doing a recomputation, this method is mandatory" '''
 
444
    
 
445
    try:
 
446
      baseobj = fp.baseObject[0]
 
447
      shape = baseobj.Shape.getElement(fp.baseObject[1][0])
 
448
    except:
 
449
      baseobj = None
 
450
      shape = None
 
451
    self.VerifyMissingAttrs(fp)
 
452
    diameterchange = False      
 
453
    if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
 
454
      diameterchange = True    
 
455
      
 
456
    matchouterchange = not (hasattr(self, 'matchOuter')) or self.matchOuter != fp.matchOuter
 
457
 
 
458
    if fp.diameter == 'Auto' or matchouterchange:
 
459
      d = screwMaker.AutoDiameter(self.type, shape, baseobj, fp.matchOuter)
 
460
      fp.diameter = d
 
461
      diameterchange = True      
 
462
      d_custom = None
 
463
    elif fp.diameter == 'Custom':
 
464
      d = fp.diameter
 
465
      d_custom = fp.diameterCustom.Value
 
466
    else:
 
467
      d = fp.diameter
 
468
      d_custom = None
 
469
    
 
470
    l = fp.length.Value
 
471
    if l < 2.0:
 
472
      l = 2.0
 
473
      fp.length = 2.0
 
474
 
 
475
    if fp.diameter == 'Custom':
 
476
      p = fp.pitchCustom.Value
 
477
    else:
 
478
      p = None
 
479
    screwMaker.updateFastenerParameters()  
 
480
    threadType = 'simple'
 
481
    if hasattr(fp,'thread') and fp.thread:
 
482
      threadType = 'real'
 
483
    # since we are bypassing the createScrew() method, we must set
 
484
    # the rThread parameter manually
 
485
    screwMaker.rThread = (threadType == 'real')
 
486
    s = screwMaker.makeScrewTap(self.type,d,l,p,d_custom)
 
487
 
 
488
    self.diameter = fp.diameter
 
489
    self.length = l
 
490
    self.matchOuter = fp.matchOuter
 
491
    diastr = fp.diameter if fp.diameter != 'Custom' else str(fp.diameterCustom)
 
492
    fp.Label = diastr + 'x' + str(l) + '-' + self.itemText
 
493
    self.realThread = fp.thread
 
494
    fp.Shape = s
 
495
 
 
496
    if shape is not None:
 
497
      FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
510
498
 
511
499
class FSScrewRodCommand:
512
 
    """Add Screw Rod command"""
513
 
 
514
 
    def GetResources(self):
515
 
        icon = os.path.join(iconPath, 'ScrewTap.svg')
516
 
        return {
517
 
            'Pixmap': icon,  # the name of a svg file available in the resources
518
 
            'MenuText': "Add threaded rod for tapping holes",
519
 
            'ToolTip': "Add arbitrary length threaded rod for tapping holes"
520
 
        }
521
 
 
522
 
    def Activated(self):
523
 
        for selObj in FastenerBase.FSGetAttachableSelections():
524
 
            a = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "ScrewTap")
525
 
            FSScrewRodObject(a, selObj, "ScrewTap")
526
 
            a.Label = a.Proxy.itemText
527
 
            FSViewProviderTree(a.ViewObject)
528
 
        FreeCAD.ActiveDocument.recompute()
529
 
        return
530
 
 
531
 
    def IsActive(self):
532
 
        return Gui.ActiveDocument is not None
533
 
 
534
 
 
535
 
Gui.addCommand("FSScrewTap", FSScrewRodCommand())
 
500
  """Add Screw Rod command"""
 
501
 
 
502
  def GetResources(self):
 
503
    icon = os.path.join( iconPath , 'ScrewTap.svg')
 
504
    return {'Pixmap'  : icon , # the name of a svg file available in the resources
 
505
            'MenuText': "Add threaded rod for tapping holes" ,
 
506
            'ToolTip' : "Add arbitrary length threaded rod for tapping holes"}
 
507
 
 
508
  def Activated(self):
 
509
    for selObj in FastenerBase.FSGetAttachableSelections():
 
510
      a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","ScrewTap")
 
511
      FSScrewRodObject(a, selObj, "ScrewTap")
 
512
      a.Label = a.Proxy.itemText
 
513
      FSViewProviderTree(a.ViewObject)
 
514
    FreeCAD.ActiveDocument.recompute()
 
515
    return
 
516
   
 
517
  def IsActive(self):
 
518
    return Gui.ActiveDocument is not None
 
519
 
 
520
Gui.addCommand("FSScrewTap",FSScrewRodCommand())
536
521
FastenerBase.FSCommands.append("FSScrewTap", "screws", "misc")
537
522
 
538
 
 
539
523
class FSScrewRodCommandInch:
540
 
    """Add Screw Rod command"""
541
 
 
542
 
    def GetResources(self):
543
 
        icon = os.path.join(iconPath, 'ScrewTapInch.svg')
544
 
        return {
545
 
            'Pixmap': icon,  # the name of a svg file available in the resources
546
 
            'MenuText': "Add inch threaded rod for tapping holes",
547
 
            'ToolTip': "Add arbitrary length threaded rod for tapping holes (inch sizes)"
548
 
        }
549
 
 
550
 
    def Activated(self):
551
 
        for selObj in FastenerBase.FSGetAttachableSelections():
552
 
            a = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "ScrewTap")
553
 
            FSScrewRodObject(a, selObj, "ScrewTapInch")
554
 
            a.Label = a.Proxy.itemText
555
 
            FSViewProviderTree(a.ViewObject)
556
 
        FreeCAD.ActiveDocument.recompute()
557
 
        return
558
 
 
559
 
    def IsActive(self):
560
 
        return Gui.ActiveDocument is not None
561
 
 
562
 
 
563
 
Gui.addCommand("FSScrewTapInch", FSScrewRodCommandInch())
 
524
  """Add Screw Rod command"""
 
525
 
 
526
  def GetResources(self):
 
527
    icon = os.path.join( iconPath , 'ScrewTapInch.svg')
 
528
    return {'Pixmap'  : icon , # the name of a svg file available in the resources
 
529
            'MenuText': "Add inch threaded rod for tapping holes" ,
 
530
            'ToolTip' : "Add arbitrary length threaded rod for tapping holes (inch sizes)"}
 
531
 
 
532
  def Activated(self):
 
533
    for selObj in FastenerBase.FSGetAttachableSelections():
 
534
      a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","ScrewTap")
 
535
      FSScrewRodObject(a, selObj, "ScrewTapInch")
 
536
      a.Label = a.Proxy.itemText
 
537
      FSViewProviderTree(a.ViewObject)
 
538
    FreeCAD.ActiveDocument.recompute()
 
539
    return
 
540
   
 
541
  def IsActive(self):
 
542
    return Gui.ActiveDocument is not None
 
543
 
 
544
Gui.addCommand("FSScrewTapInch",FSScrewRodCommandInch())
564
545
FastenerBase.FSCommands.append("FSScrewTapInch", "screws", "misc")
565
546
 
566
547
 
 
548
 
567
549
class FSScrewDieObject(FSBaseObject):
568
 
    def __init__(self, obj, attachTo, typeStr):
569
 
        '''"Add screw die" '''
570
 
        FSBaseObject.__init__(self, obj, attachTo)
571
 
        self.itemText = "ScrewDie"
572
 
        self.type = typeStr
573
 
        diameters = screwMaker.GetAllDiams(self.type) + ["Custom"]
574
 
        diameters.insert(0, 'Auto')
575
 
        # self.Proxy = obj.Name
576
 
 
577
 
        obj.addProperty("App::PropertyEnumeration", "diameter", "Parameters", "Screw diameter standard").diameter = diameters
578
 
        obj.addProperty("App::PropertyLength", "length", "Parameters", "Screw length").length = 20.0
579
 
        obj.addProperty("App::PropertyLength", "diameterCustom", "Parameters", "Screw major diameter custom").diameterCustom = 6
580
 
        obj.addProperty("App::PropertyLength", "pitchCustom", "Parameters", "Screw pitch custom").pitchCustom = 1.0
581
 
        self.VerifyMissingAttrs(obj)
582
 
        obj.addProperty("App::PropertyBool", "thread", "Parameters", "Generate real thread").thread = False
583
 
        obj.Proxy = self
584
 
 
585
 
    def VerifyMissingAttrs(self, obj):
586
 
        self.updateProps(obj)
587
 
        if not hasattr(obj, 'matchOuter'):
588
 
            obj.addProperty("App::PropertyBool", "matchOuter", "Parameters", "Match outer thread diameter").matchOuter = FastenerBase.FSMatchOuter
589
 
        # for old objects from before custom diameter and pitch were implemented
590
 
        if not hasattr(obj, "pitchCustom"):
591
 
            obj.addProperty("App::PropertyLength", "pitchCustom", "Parameters", "Screw pitch custom").pitchCustom = 1.0
592
 
            obj.addProperty("App::PropertyLength", "diameterCustom", "Parameters", "Screw major diameter custom").diameterCustom = 6
593
 
            dia_tmp = obj.diameter
594
 
            self.type = "ScrewDie"
595
 
            obj.diameter = screwMaker.GetAllDiams(self.type) + ["Custom"]
596
 
            obj.diameter = dia_tmp
597
 
 
598
 
    def execute(self, fp):
599
 
        '''"Print a short message when doing a recomputation, this method is mandatory" '''
600
 
 
601
 
        try:
602
 
            baseobj = fp.baseObject[0]
603
 
            shape = baseobj.Shape.getElement(fp.baseObject[1][0])
604
 
        except:
605
 
            baseobj = None
606
 
            shape = None
607
 
 
608
 
        self.VerifyMissingAttrs(fp)
609
 
        diameterchange = False
610
 
        if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
611
 
            diameterchange = True
612
 
 
613
 
        matchouterchange = not (hasattr(self, 'matchOuter')) or self.matchOuter != fp.matchOuter
614
 
 
615
 
        if fp.diameter == 'Auto' or matchouterchange:
616
 
            d = screwMaker.AutoDiameter(self.type, shape, baseobj, fp.matchOuter)
617
 
            fp.diameter = d
618
 
            diameterchange = True
619
 
            d_custom = None
620
 
        elif fp.diameter == 'Custom':
621
 
            d = fp.diameter
622
 
            d_custom = fp.diameterCustom.Value
623
 
        else:
624
 
            d = fp.diameter
625
 
            d_custom = None
626
 
 
627
 
        l = fp.length.Value
628
 
        if l < 2.0:
629
 
            l = 2.0
630
 
            fp.length = 2.0
631
 
 
632
 
        if fp.diameter == 'Custom':
633
 
            p = fp.pitchCustom.Value
634
 
        else:
635
 
            p = None
636
 
 
637
 
        screwMaker.updateFastenerParameters()
638
 
 
639
 
        threadType = 'simple'
640
 
        if hasattr(fp, 'thread') and fp.thread:
641
 
            threadType = 'real'
642
 
        # since we are bypassing the createScrew() method, we must set
643
 
        # the rThread parameter manually
644
 
        screwMaker.rThread = (threadType == 'real')
645
 
        s = screwMaker.makeScrewDie(self.type, d, l, p, d_custom)
646
 
        self.diameter = fp.diameter
647
 
        self.length = l
648
 
        self.matchOuter = fp.matchOuter
649
 
        diastr = fp.diameter if fp.diameter != 'Custom' else str(fp.diameterCustom)
650
 
        fp.Label = diastr + 'x' + str(l) + '-' + self.itemText
651
 
        self.realThread = fp.thread
652
 
        fp.Shape = s
653
 
 
654
 
        if shape is not None:
655
 
            FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
656
 
 
 
550
  def __init__(self, obj, attachTo, typeStr):
 
551
    '''"Add screw die" '''
 
552
    FSBaseObject.__init__(self, obj, attachTo)
 
553
    self.itemText = "ScrewDie"
 
554
    self.type = typeStr
 
555
    diameters = screwMaker.GetAllDiams(self.type) + ["Custom"]
 
556
    diameters.insert(0, 'Auto')
 
557
    #self.Proxy = obj.Name
 
558
    
 
559
    obj.addProperty("App::PropertyEnumeration","diameter","Parameters","Screw diameter standard").diameter = diameters
 
560
    obj.addProperty("App::PropertyLength","length","Parameters","Screw length").length = 20.0
 
561
    obj.addProperty("App::PropertyLength","diameterCustom","Parameters","Screw major diameter custom").diameterCustom = 6
 
562
    obj.addProperty("App::PropertyLength","pitchCustom","Parameters","Screw pitch custom").pitchCustom = 1.0
 
563
    self.VerifyMissingAttrs(obj)
 
564
    obj.addProperty("App::PropertyBool", "thread", "Parameters", "Generate real thread").thread = False
 
565
    obj.Proxy = self
 
566
 
 
567
  def VerifyMissingAttrs(self, obj):
 
568
    self.updateProps(obj)
 
569
    if not (hasattr(obj, 'matchOuter')):
 
570
      obj.addProperty("App::PropertyBool", "matchOuter", "Parameters", "Match outer thread diameter").matchOuter = FastenerBase.FSMatchOuter
 
571
    # for old objects from before custom diameter and pitch were implemented
 
572
    if not hasattr(obj,"pitchCustom"):
 
573
      obj.addProperty("App::PropertyLength","pitchCustom","Parameters","Screw pitch custom").pitchCustom = 1.0
 
574
      obj.addProperty("App::PropertyLength","diameterCustom","Parameters","Screw major diameter custom").diameterCustom = 6
 
575
      dia_tmp = obj.diameter
 
576
      self.type = "ScrewDie"
 
577
      obj.diameter = screwMaker.GetAllDiams(self.type) + ["Custom"]
 
578
      obj.diameter = dia_tmp
 
579
 
 
580
  def execute(self, fp):
 
581
    '''"Print a short message when doing a recomputation, this method is mandatory" '''
 
582
    
 
583
    try:
 
584
      baseobj = fp.baseObject[0]
 
585
      shape = baseobj.Shape.getElement(fp.baseObject[1][0])
 
586
    except:
 
587
      baseobj = None
 
588
      shape = None
 
589
          
 
590
    self.VerifyMissingAttrs(fp)
 
591
    diameterchange = False      
 
592
    if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
 
593
      diameterchange = True    
 
594
      
 
595
    matchouterchange = not (hasattr(self, 'matchOuter')) or self.matchOuter != fp.matchOuter
 
596
 
 
597
    if fp.diameter == 'Auto' or matchouterchange:
 
598
      d = screwMaker.AutoDiameter(self.type, shape, baseobj, fp.matchOuter)
 
599
      fp.diameter = d
 
600
      diameterchange = True      
 
601
      d_custom = None
 
602
    elif fp.diameter == 'Custom':
 
603
      d = fp.diameter
 
604
      d_custom = fp.diameterCustom.Value
 
605
    else:
 
606
      d = fp.diameter
 
607
      d_custom = None
 
608
    
 
609
    l = fp.length.Value
 
610
    if l < 2.0:
 
611
      l = 2.0
 
612
      fp.length = 2.0
 
613
 
 
614
    if fp.diameter == 'Custom':
 
615
      p = fp.pitchCustom.Value
 
616
    else:
 
617
      p = None
 
618
      
 
619
    screwMaker.updateFastenerParameters()  
 
620
 
 
621
    threadType = 'simple'
 
622
    if hasattr(fp,'thread') and fp.thread:
 
623
      threadType = 'real'
 
624
    # since we are bypassing the createScrew() method, we must set
 
625
    # the rThread parameter manually
 
626
    screwMaker.rThread = (threadType == 'real')
 
627
    s = screwMaker.makeScrewDie(self.type,d,l,p,d_custom)
 
628
    self.diameter = fp.diameter
 
629
    self.length = l
 
630
    self.matchOuter = fp.matchOuter
 
631
    diastr = fp.diameter if fp.diameter != 'Custom' else str(fp.diameterCustom)
 
632
    fp.Label = diastr + 'x' + str(l) + '-' + self.itemText
 
633
    self.realThread = fp.thread
 
634
    fp.Shape = s
 
635
 
 
636
    if shape is not None:
 
637
      FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
657
638
 
658
639
class FSScrewDieCommand:
659
 
    """Add Screw Die command"""
660
 
 
661
 
    def GetResources(self):
662
 
        icon = os.path.join(iconPath, 'ScrewDie.svg')
663
 
        return {
664
 
            'Pixmap': icon,  # the name of a svg file available in the resources
665
 
            'MenuText': "Add object to cut external threads",
666
 
            'ToolTip': "Add arbitrary length threaded tube for cutting external threads"
667
 
        }
668
 
 
669
 
    def Activated(self):
670
 
        for selObj in FastenerBase.FSGetAttachableSelections():
671
 
            a = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "ScrewDie")
672
 
            FSScrewDieObject(a, selObj, "ScrewDie")
673
 
            a.Label = a.Proxy.itemText
674
 
            FSViewProviderTree(a.ViewObject)
675
 
        FreeCAD.ActiveDocument.recompute()
676
 
        return
677
 
 
678
 
    def IsActive(self):
679
 
        return Gui.ActiveDocument is not None
680
 
 
681
 
 
682
 
Gui.addCommand("FSScrewDie", FSScrewDieCommand())
 
640
  """Add Screw Die command"""
 
641
 
 
642
  def GetResources(self):
 
643
    icon = os.path.join( iconPath , 'ScrewDie.svg')
 
644
    return {'Pixmap'  : icon , # the name of a svg file available in the resources
 
645
            'MenuText': "Add object to cut external threads" ,
 
646
            'ToolTip' : "Add arbitrary length threaded tube for cutting external threads"}
 
647
 
 
648
  def Activated(self):
 
649
    for selObj in FastenerBase.FSGetAttachableSelections():
 
650
      a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","ScrewDie")
 
651
      FSScrewDieObject(a, selObj, "ScrewDie")
 
652
      a.Label = a.Proxy.itemText
 
653
      FSViewProviderTree(a.ViewObject)
 
654
    FreeCAD.ActiveDocument.recompute()
 
655
    return
 
656
   
 
657
  def IsActive(self):
 
658
    return Gui.ActiveDocument is not None
 
659
 
 
660
Gui.addCommand("FSScrewDie",FSScrewDieCommand())
683
661
FastenerBase.FSCommands.append("FSScrewDie", "screws", "misc")
684
662
 
685
663
 
 
664
 
 
665
 
686
666
class FSScrewDieCommandInch:
687
 
    """Add Screw Die command"""
688
 
 
689
 
    def GetResources(self):
690
 
        icon = os.path.join(iconPath, 'ScrewDieInch.svg')
691
 
        return {
692
 
            'Pixmap': icon,  # the name of a svg file available in the resources
693
 
            'MenuText': 'Add object to cut external non-metric threads',
694
 
            'ToolTip': 'Add arbitrary length threaded tube for cutting inch standard external threads'
695
 
        }
696
 
 
697
 
    def Activated(self):
698
 
        for selObj in FastenerBase.FSGetAttachableSelections():
699
 
            a = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', 'ScrewDie')
700
 
            FSScrewDieObject(a, selObj, 'ScrewDieInch')
701
 
            a.Label = a.Proxy.itemText
702
 
            FSViewProviderTree(a.ViewObject)
703
 
        FreeCAD.ActiveDocument.recompute()
704
 
        return
705
 
 
706
 
    def IsActive(self):
707
 
        return Gui.ActiveDocument is not None
708
 
 
709
 
 
710
 
Gui.addCommand('FSScrewDieInch', FSScrewDieCommandInch())
711
 
FastenerBase.FSCommands.append('FSScrewDieInch', 'screws', 'misc')
 
667
  """Add Screw Die command"""
 
668
 
 
669
  def GetResources(self):
 
670
    icon = os.path.join( iconPath , 'ScrewDieInch.svg')
 
671
    return {'Pixmap'  : icon , # the name of a svg file available in the resources
 
672
            'MenuText': "Add object to cut external non-metric threads" ,
 
673
            'ToolTip' : "Add arbitrary length threaded tube for cutting inch standard external threads"}
 
674
 
 
675
  def Activated(self):
 
676
    for selObj in FastenerBase.FSGetAttachableSelections():
 
677
      a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","ScrewDie")
 
678
      FSScrewDieObject(a, selObj, "ScrewDieInch")
 
679
      a.Label = a.Proxy.itemText
 
680
      FSViewProviderTree(a.ViewObject)
 
681
    FreeCAD.ActiveDocument.recompute()
 
682
    return
 
683
   
 
684
  def IsActive(self):
 
685
    return Gui.ActiveDocument is not None
 
686
 
 
687
Gui.addCommand("FSScrewDieInch",FSScrewDieCommandInch())
 
688
FastenerBase.FSCommands.append("FSScrewDieInch", "screws", "misc")
 
689
 
 
690
 
712
691
 
713
692
 
714
693
class FSThreadedRodObject(FSBaseObject):
715
 
    def __init__(self, obj, attachTo, typeStr):
716
 
        '''"Add threaded rod" '''
717
 
        FSBaseObject.__init__(self, obj, attachTo)
718
 
        self.itemText = "ThreadedRod"
719
 
        self.type = typeStr
720
 
        diameters = screwMaker.GetAllDiams(self.type) + ["Custom"]
721
 
        diameters.insert(0, 'Auto')
722
 
        # self.Proxy = obj.Name
723
 
 
724
 
        obj.addProperty("App::PropertyEnumeration", "diameter", "Parameters", "Screw diameter standard").diameter = diameters
725
 
        obj.addProperty("App::PropertyLength", "length", "Parameters", "Screw length").length = 20.0
726
 
        obj.addProperty("App::PropertyLength", "diameterCustom", "Parameters", "Screw major diameter custom").diameterCustom = 6
727
 
        obj.addProperty("App::PropertyLength", "pitchCustom", "Parameters", "Screw pitch custom").pitchCustom = 1.0
728
 
        self.VerifyMissingAttrs(obj)
729
 
        obj.addProperty("App::PropertyBool", "thread", "Parameters", "Generate real thread").thread = False
730
 
        obj.Proxy = self
731
 
 
732
 
    def VerifyMissingAttrs(self, obj):
733
 
        self.updateProps(obj)
734
 
        if not (hasattr(obj, 'matchOuter')):
735
 
            obj.addProperty("App::PropertyBool", "matchOuter", "Parameters", "Match outer thread diameter").matchOuter = FastenerBase.FSMatchOuter
736
 
        # for old objects from before custom diameter and pitch were implemented
737
 
        if not hasattr(obj, "pitchCustom"):
738
 
            obj.addProperty("App::PropertyLength", "pitchCustom", "Parameters", "Screw pitch custom").pitchCustom = 1.0
739
 
            obj.addProperty("App::PropertyLength", "diameterCustom", "Parameters", "Screw major diameter custom").diameterCustom = 6
740
 
            dia_tmp = obj.diameter
741
 
            self.type = "ThreadedRod"
742
 
            obj.diameter = screwMaker.GetAllDiams(self.type) + ["Custom"]
743
 
            obj.diameter = dia_tmp
744
 
 
745
 
    def execute(self, fp):
746
 
        '''"Print a short message when doing a recomputation, this method is mandatory" '''
747
 
 
748
 
        try:
749
 
            baseobj = fp.baseObject[0]
750
 
            shape = baseobj.Shape.getElement(fp.baseObject[1][0])
751
 
        except:
752
 
            baseobj = None
753
 
            shape = None
754
 
 
755
 
        self.VerifyMissingAttrs(fp)
756
 
        diameterchange = False
757
 
        if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
758
 
            diameterchange = True
759
 
 
760
 
        matchouterchange = not (hasattr(self, 'matchOuter')) or self.matchOuter != fp.matchOuter
761
 
 
762
 
        if fp.diameter == 'Auto' or matchouterchange:
763
 
            d = screwMaker.AutoDiameter(self.type, shape, baseobj, fp.matchOuter)
764
 
            fp.diameter = d
765
 
            diameterchange = True
766
 
            d_custom = None
767
 
        elif fp.diameter == 'Custom':
768
 
            d = fp.diameter
769
 
            d_custom = fp.diameterCustom.Value
770
 
        else:
771
 
            d = fp.diameter
772
 
            d_custom = None
773
 
 
774
 
        l = fp.length.Value
775
 
        if l < 2.0:
776
 
            l = 2.0
777
 
            fp.length = 2.0
778
 
 
779
 
        if fp.diameter == 'Custom':
780
 
            p = fp.pitchCustom.Value
781
 
        else:
782
 
            p = None
783
 
 
784
 
        screwMaker.updateFastenerParameters()
785
 
 
786
 
        threadType = 'simple'
787
 
        if hasattr(fp, 'thread') and fp.thread:
788
 
            threadType = 'real'
789
 
        # since we are bypassing the createScrew() method, we must set
790
 
        # the rThread parameter manually
791
 
        screwMaker.rThread = (threadType == 'real')
792
 
        s = screwMaker.makeThreadedRod(self.type, d, l, p, d_custom)
793
 
 
794
 
        self.diameter = fp.diameter
795
 
        self.length = l
796
 
        self.matchOuter = fp.matchOuter
797
 
        diastr = fp.diameter if fp.diameter != 'Custom' else str(fp.diameterCustom)
798
 
        fp.Label = diastr + 'x' + str(l) + '-' + self.itemText
799
 
        self.realThread = fp.thread
800
 
        fp.Shape = s
801
 
 
802
 
        if shape is not None:
803
 
            FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
804
 
 
 
694
  def __init__(self, obj, attachTo, typeStr):
 
695
    '''"Add threaded rod" '''
 
696
    FSBaseObject.__init__(self, obj, attachTo)
 
697
    self.itemText = "ThreadedRod"
 
698
    self.type = typeStr
 
699
    diameters = screwMaker.GetAllDiams(self.type) + ["Custom"]
 
700
    diameters.insert(0, 'Auto')
 
701
    #self.Proxy = obj.Name
 
702
    
 
703
    obj.addProperty("App::PropertyEnumeration","diameter","Parameters","Screw diameter standard").diameter = diameters
 
704
    obj.addProperty("App::PropertyLength","length","Parameters","Screw length").length = 20.0
 
705
    obj.addProperty("App::PropertyLength","diameterCustom","Parameters","Screw major diameter custom").diameterCustom = 6
 
706
    obj.addProperty("App::PropertyLength","pitchCustom","Parameters","Screw pitch custom").pitchCustom = 1.0
 
707
    self.VerifyMissingAttrs(obj)
 
708
    obj.addProperty("App::PropertyBool", "thread", "Parameters", "Generate real thread").thread = False
 
709
    obj.Proxy = self
 
710
 
 
711
  def VerifyMissingAttrs(self, obj):
 
712
    self.updateProps(obj)
 
713
    if not (hasattr(obj, 'matchOuter')):
 
714
      obj.addProperty("App::PropertyBool", "matchOuter", "Parameters", "Match outer thread diameter").matchOuter = FastenerBase.FSMatchOuter
 
715
    # for old objects from before custom diameter and pitch were implemented
 
716
    if not hasattr(obj,"pitchCustom"):
 
717
      obj.addProperty("App::PropertyLength","pitchCustom","Parameters","Screw pitch custom").pitchCustom = 1.0
 
718
      obj.addProperty("App::PropertyLength","diameterCustom","Parameters","Screw major diameter custom").diameterCustom = 6
 
719
      dia_tmp = obj.diameter
 
720
      self.type = "ThreadedRod"
 
721
      obj.diameter = screwMaker.GetAllDiams(self.type) + ["Custom"]
 
722
      obj.diameter = dia_tmp
 
723
 
 
724
  def execute(self, fp):
 
725
    '''"Print a short message when doing a recomputation, this method is mandatory" '''
 
726
    
 
727
    try:
 
728
      baseobj = fp.baseObject[0]
 
729
      shape = baseobj.Shape.getElement(fp.baseObject[1][0])
 
730
    except:
 
731
      baseobj = None
 
732
      shape = None
 
733
          
 
734
    self.VerifyMissingAttrs(fp)
 
735
    diameterchange = False      
 
736
    if not (hasattr(self, 'diameter')) or self.diameter != fp.diameter:
 
737
      diameterchange = True    
 
738
      
 
739
    matchouterchange = not (hasattr(self, 'matchOuter')) or self.matchOuter != fp.matchOuter
 
740
 
 
741
    if fp.diameter == 'Auto' or matchouterchange:
 
742
      d = screwMaker.AutoDiameter(self.type, shape, baseobj, fp.matchOuter)
 
743
      fp.diameter = d
 
744
      diameterchange = True      
 
745
      d_custom = None
 
746
    elif fp.diameter == 'Custom':
 
747
      d = fp.diameter
 
748
      d_custom = fp.diameterCustom.Value
 
749
    else:
 
750
      d = fp.diameter
 
751
      d_custom = None
 
752
    
 
753
    l = fp.length.Value
 
754
    if l < 2.0:
 
755
      l = 2.0
 
756
      fp.length = 2.0
 
757
 
 
758
    if fp.diameter == 'Custom':
 
759
      p = fp.pitchCustom.Value
 
760
    else:
 
761
      p = None
 
762
      
 
763
    screwMaker.updateFastenerParameters()  
 
764
 
 
765
    threadType = 'simple'
 
766
    if hasattr(fp,'thread') and fp.thread:
 
767
      threadType = 'real'
 
768
    # since we are bypassing the createScrew() method, we must set
 
769
    # the rThread parameter manually
 
770
    screwMaker.rThread = (threadType == 'real')
 
771
    s = screwMaker.makeThreadedRod(self.type,d,l,p,d_custom)
 
772
 
 
773
    self.diameter = fp.diameter
 
774
    self.length = l
 
775
    self.matchOuter = fp.matchOuter
 
776
    diastr = fp.diameter if fp.diameter != 'Custom' else str(fp.diameterCustom)
 
777
    fp.Label = diastr + 'x' + str(l) + '-' + self.itemText
 
778
    self.realThread = fp.thread
 
779
    fp.Shape = s
 
780
 
 
781
    if shape is not None:
 
782
      FastenerBase.FSMoveToObject(fp, shape, fp.invert, fp.offset.Value)
805
783
 
806
784
class FSThreadedRodCommand:
807
 
    """Add Threaded Rod command"""
808
 
 
809
 
    def GetResources(self):
810
 
        icon = os.path.join(iconPath, 'ThreadedRod.svg')
811
 
        return {
812
 
            'Pixmap': icon,  # the name of a svg file available in the resources
813
 
            'MenuText': "Add DIN 975 threaded rod",
814
 
            'ToolTip': "Add arbitrary length threaded rod object"
815
 
        }
816
 
 
817
 
    def Activated(self):
818
 
        for selObj in FastenerBase.FSGetAttachableSelections():
819
 
            a = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "ThreadedRod")
820
 
            FSThreadedRodObject(a, selObj, "ThreadedRod")
821
 
            a.Label = a.Proxy.itemText
822
 
            FSViewProviderTree(a.ViewObject)
823
 
        FreeCAD.ActiveDocument.recompute()
824
 
        return
825
 
 
826
 
    def IsActive(self):
827
 
        return Gui.ActiveDocument is not None
828
 
 
829
 
 
830
 
Gui.addCommand("FSThreadedRod", FSThreadedRodCommand())
 
785
  """Add Threaded Rod command"""
 
786
 
 
787
  def GetResources(self):
 
788
    icon = os.path.join( iconPath , 'ThreadedRod.svg')
 
789
    return {'Pixmap'  : icon , # the name of a svg file available in the resources
 
790
            'MenuText': "Add DIN 975 threaded rod" ,
 
791
            'ToolTip' : "Add arbitrary length threaded rod object"}
 
792
 
 
793
  def Activated(self):
 
794
    for selObj in FastenerBase.FSGetAttachableSelections():
 
795
      a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","ThreadedRod")
 
796
      FSThreadedRodObject(a, selObj, "ThreadedRod")
 
797
      a.Label = a.Proxy.itemText
 
798
      FSViewProviderTree(a.ViewObject)
 
799
    FreeCAD.ActiveDocument.recompute()
 
800
    return
 
801
   
 
802
  def IsActive(self):
 
803
    return Gui.ActiveDocument is not None
 
804
 
 
805
Gui.addCommand("FSThreadedRod",FSThreadedRodCommand())
831
806
FastenerBase.FSCommands.append("FSThreadedRod", "screws", "misc")
832
807
 
833
808
 
834
809
class FSThreadedRodCommandInch:
835
 
    """Add Threaded Rod command"""
836
 
 
837
 
    def GetResources(self):
838
 
        icon = os.path.join(iconPath, 'ThreadedRodInch.svg')
839
 
        return {
840
 
            'Pixmap': icon,  # the name of a svg file available in the resources
841
 
            'MenuText': "Add UNC threaded rod",
842
 
            'ToolTip': "Add arbitrary length threaded rod object, inch standard coarse threads"
843
 
        }
844
 
 
845
 
    def Activated(self):
846
 
        for selObj in FastenerBase.FSGetAttachableSelections():
847
 
            a = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "ThreadedRod")
848
 
            FSThreadedRodObject(a, selObj, "ThreadedRodInch")
849
 
            a.Label = a.Proxy.itemText
850
 
            FSViewProviderTree(a.ViewObject)
851
 
        FreeCAD.ActiveDocument.recompute()
852
 
        return
853
 
 
854
 
    def IsActive(self):
855
 
        return Gui.ActiveDocument is not None
856
 
 
857
 
 
858
 
Gui.addCommand("FSThreadedRodInch", FSThreadedRodCommandInch())
 
810
  """Add Threaded Rod command"""
 
811
 
 
812
  def GetResources(self):
 
813
    icon = os.path.join( iconPath , 'ThreadedRodInch.svg')
 
814
    return {'Pixmap'  : icon , # the name of a svg file available in the resources
 
815
            'MenuText': "Add UNC threaded rod" ,
 
816
            'ToolTip' : "Add arbitrary length threaded rod object, inch standard coarse threads"}
 
817
 
 
818
  def Activated(self):
 
819
    for selObj in FastenerBase.FSGetAttachableSelections():
 
820
      a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","ThreadedRod")
 
821
      FSThreadedRodObject(a, selObj, "ThreadedRodInch")
 
822
      a.Label = a.Proxy.itemText
 
823
      FSViewProviderTree(a.ViewObject)
 
824
    FreeCAD.ActiveDocument.recompute()
 
825
    return
 
826
   
 
827
  def IsActive(self):
 
828
    return Gui.ActiveDocument is not None
 
829
 
 
830
Gui.addCommand("FSThreadedRodInch",FSThreadedRodCommandInch())
859
831
FastenerBase.FSCommands.append("FSThreadedRodInch", "screws", "misc")
860
832
 
 
833
 
861
834
## add fastener types
862
835
FastenerBase.FSAddFastenerType("Screw")
863
836
FastenerBase.FSAddFastenerType("Washer", False)
866
839
FastenerBase.FSAddFastenerType("ScrewDie", True, False)
867
840
FastenerBase.FSAddFastenerType("ThreadedRod", True, False)
868
841
for item in ScrewMaker.screwTables:
869
 
    FastenerBase.FSAddItemsToType(ScrewMaker.screwTables[item][0], item)
 
842
  FastenerBase.FSAddItemsToType(ScrewMaker.screwTables[item][0], item)