Merge branch 'master' of github.com:FreeCAD/FreeCAD into TD-DetailWork

This commit is contained in:
donovaly
2020-04-21 00:36:42 +02:00
31 changed files with 3190 additions and 1592 deletions

2
.github/FUNDING.yml vendored
View File

@@ -6,7 +6,7 @@ open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
liberapay: FreeCAD
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ['https://www.patreon.com/yorikvanhavre', 'https://www.patreon.com/kkremitzki', 'https://www.patreon.com/thundereal']

View File

@@ -72,14 +72,23 @@ def getIndices(obj,shape,offsetv,offsetvn):
try:
if not isinstance(e.Curve,Part.LineSegment):
if not curves:
myshape = obj.Shape.copy(False)
myshape.Placement=obj.getGlobalPlacement()
if obj.isDerivedFrom("App::Link"):
myshape = obj.LinkedObject.Shape.copy(False)
myshape.Placement=obj.LinkPlacement
else:
myshape = obj.Shape.copy(False)
myshape.Placement=obj.getGlobalPlacement()
mesh=MeshPart.meshFromShape(Shape=myshape, LinearDeflection=0.1, AngularDeflection=0.7, Relative=True)
FreeCAD.Console.PrintWarning(translate("Arch","Found a shape containing curves, triangulating")+"\n")
break
except: # unimplemented curve type
myshape = obj.Shape.copy(False)
myshape.Placement=obj.getGlobalPlacement()
if obj.isDerivedFrom("App::Link"):
if obj.Shape:
myshape = obj.Shape.copy(False)
myshape.Placement=obj.LinkPlacement
else:
myshape = obj.Shape.copy(False)
myshape.Placement=obj.getGlobalPlacement()
mesh=MeshPart.meshFromShape(Shape=myshape, LinearDeflection=0.1, AngularDeflection=0.7, Relative=True)
FreeCAD.Console.PrintWarning(translate("Arch","Found a shape containing curves, triangulating")+"\n")
break
@@ -157,7 +166,7 @@ def export(exportList,filename,colors=None):
materials = []
outfile.write("mtllib " + os.path.basename(filenamemtl) + "\n")
for obj in objectslist:
if obj.isDerivedFrom("Part::Feature") or obj.isDerivedFrom("Mesh::Feature"):
if obj.isDerivedFrom("Part::Feature") or obj.isDerivedFrom("Mesh::Feature") or obj.isDerivedFrom("App::Link"):
hires = None
if FreeCAD.GuiUp:
visible = obj.ViewObject.isVisible()

View File

@@ -1893,8 +1893,7 @@ class DraftToolBar:
return str(a)
def togglesnap(self):
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.toggle()
FreeCADGui.doCommand('FreeCADGui.runCommand("Draft_Snap_Lock")')
def togglenearsnap(self):
if hasattr(FreeCADGui,"Snapper"):

View File

@@ -116,6 +116,7 @@ class DraftWorkbench(FreeCADGui.Workbench):
if hasattr(FreeCADGui, "draftToolBar"):
if not hasattr(FreeCADGui.draftToolBar, "loadedPreferences"):
FreeCADGui.addPreferencePage(":/ui/preferences-draft.ui", QT_TRANSLATE_NOOP("Draft", "Draft"))
FreeCADGui.addPreferencePage(":/ui/preferences-draftinterface.ui", QT_TRANSLATE_NOOP("Draft", "Draft"))
FreeCADGui.addPreferencePage(":/ui/preferences-draftsnap.ui", QT_TRANSLATE_NOOP("Draft", "Draft"))
FreeCADGui.addPreferencePage(":/ui/preferences-draftvisual.ui", QT_TRANSLATE_NOOP("Draft", "Draft"))
FreeCADGui.addPreferencePage(":/ui/preferences-drafttexts.ui", QT_TRANSLATE_NOOP("Draft", "Draft"))
@@ -140,7 +141,7 @@ class DraftWorkbench(FreeCADGui.Workbench):
if hasattr(FreeCADGui, "Snapper"):
FreeCADGui.Snapper.hide()
import draftutils.init_draft_statusbar as dsb
dsb.hide_draft_statusbar()
dsb.hide_draft_statusbar()
FreeCAD.Console.PrintLog("Draft workbench deactivated.\n")
def ContextMenu(self, recipient):

View File

@@ -153,6 +153,7 @@
<file>translations/Draft_zh-CN.qm</file>
<file>translations/Draft_zh-TW.qm</file>
<file>ui/preferences-draft.ui</file>
<file>ui/preferences-draftinterface.ui</file>
<file>ui/preferences-draftsnap.ui</file>
<file>ui/preferences-drafttexts.ui</file>
<file>ui/preferences-draftvisual.ui</file>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,975 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Gui::Dialog::DlgSettingsDraft</class>
<widget class="QWidget" name="Gui::Dialog::DlgSettingsDraft">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>456</width>
<height>338</height>
</rect>
</property>
<property name="windowTitle">
<string>User interface settings</string>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>In-Command Shortcuts</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0">
<item>
<layout class="QGridLayout" name="gridLayout_3">
<property name="topMargin">
<number>0</number>
</property>
<item row="4" column="1">
<widget class="Gui::PrefLineEdit" name="lineEdit_8">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>`</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutCycleSnap</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="Gui::PrefLineEdit" name="lineEdit_9">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>S</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutSnap</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Relative</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::PrefLineEdit" name="lineEdit_2">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>R</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutRelative</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="Gui::PrefLineEdit" name="lineEdit_4">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>O</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutClose</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="Gui::PrefLineEdit" name="lineEdit_3">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>T</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutContinue</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Continue</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Copy</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Increase Radius</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Cycle Snap</string>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="Gui::PrefLineEdit" name="lineEdit_19">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>[</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutIncreaseRadius</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="5" column="5">
<widget class="Gui::PrefLineEdit" name="lineEdit_17">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>]</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutDecreaseRadius</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Snap</string>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Decrease Radius</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Length</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Wipe</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="Gui::PrefLineEdit" name="lineEdit_11">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>D</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutSubelementMode</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLabel" name="label_18">
<property name="text">
<string>Add Hold</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="Gui::PrefLineEdit" name="lineEdit_12">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>L</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutFill</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Exit</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::PrefLineEdit" name="lineEdit_5">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>P</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutCopy</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Fill</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Subelement Mode</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="Gui::PrefLineEdit" name="lineEdit_13">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>E</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutSelectEdge</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="Gui::PrefLineEdit" name="lineEdit_7">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>H</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutLength</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Select Edge</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="Gui::PrefLineEdit" name="lineEdit_14">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>W</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutWipe</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::PrefLineEdit" name="lineEdit_6">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>A</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutExit</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="Gui::PrefLineEdit" name="lineEdit_15">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Q</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutAddHold</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Set WP</string>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="Gui::PrefLineEdit" name="lineEdit_16">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>U</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutSetWP</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
<string>Restrict X</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="Gui::PrefLineEdit" name="lineEdit_10">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>X</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutRestrictX</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Restrict Y</string>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="Gui::PrefLineEdit" name="lineEdit_20">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Y</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>inCommandShortcutRestrictY</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Restrict Z</string>
</property>
</widget>
</item>
<item row="6" column="5">
<widget class="Gui::PrefLineEdit" name="lineEdit_18">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Z</string>
</property>
<property name="maxLength">
<number>1</number>
</property>
<property name="placeholderText">
<string/>
</property>
<property name="clearButtonEnabled" stdset="0">
<bool>false</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>RestrictZ</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Enable draft statusbar customization</string>
</property>
<property name="title">
<string>Draft Statusbar</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<string notr="true">DisplayStatusbar</string>
</property>
<property name="prefPath" stdset="0">
<string notr="true">Mod/Draft</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QGridLayout" name="gridLayout_4">
<property name="topMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_3">
<property name="toolTip">
<string>Enable snap statusbar widget</string>
</property>
<property name="text">
<string>Draft snap widget</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>DisplayStatusbarSnapWidget</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_13">
<property name="toolTip">
<string>Enable draft statusbar annotation scale widget</string>
</property>
<property name="text">
<string>Annotation scale widget</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>DisplayStatusbarScaleWidget</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
<customwidgets>
<customwidget>
<class>Gui::PrefCheckBox</class>
<extends>QCheckBox</extends>
<header>Gui/PrefWidgets.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefLineEdit</class>
<extends>QLineEdit</extends>
<header>Gui/PrefWidgets.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -139,7 +139,7 @@ class Arc_3Points(gui_base.GuiCommandSimplest):
Parameters
----------
point: Base::Vector
The dynamic point pased by the callback
The dynamic point passed by the callback
as we move the pointer in the 3D view.
info: str

View File

@@ -33,7 +33,7 @@ import draftutils.todo as todo
from draftutils.messages import _msg, _log
class GuiCommandSimplest:
class GuiCommandSimplest(object):
"""Simplest base class for GuiCommands.
This class only sets up the command name and the document object
@@ -126,100 +126,7 @@ class GuiCommandNeedsSelection(GuiCommandSimplest):
return False
class GuiCommandSimplest:
"""Simplest base class for GuiCommands.
This class only sets up the command name and the document object
to use for the command.
When it is executed, it logs the command name to the log file,
and prints the command name to the console.
It implements the `IsActive` method, which must return `True`
when the command should be available.
It should return `True` when there is an active document,
otherwise the command (button or menu) should be disabled.
This class is meant to be inherited by other GuiCommand classes
to quickly log the command name, and set the correct document object.
Parameter
---------
name: str, optional
It defaults to `'None'`.
The name of the action that is being run,
for example, `'Heal'`, `'Flip dimensions'`,
`'Line'`, `'Circle'`, etc.
doc: App::Document, optional
It defaults to the value of `App.activeDocument()`.
The document object itself, which indicates where the actions
of the command will be executed.
Attributes
----------
command_name: str
This is the command name, which is assigned by `name`.
doc: App::Document
This is the document object itself, which is assigned by `doc`.
This attribute should be used by functions to make sure
that the operations are performed in the correct document
and not in other documents.
To set the active document we can use
>>> App.setActiveDocument(self.doc.Name)
"""
def __init__(self, name="None", doc=App.activeDocument()):
self.command_name = name
self.doc = doc
def IsActive(self):
"""Return True when this command should be available.
It is `True` when there is a document.
"""
if App.activeDocument():
return True
else:
return False
def Activated(self):
"""Execute when the command is called.
Log the command name to the log file and console.
Also update the `doc` attribute.
"""
self.doc = App.activeDocument()
_log("Document: {}".format(self.doc.Label))
_log("GuiCommand: {}".format(self.command_name))
_msg("{}".format(16*"-"))
_msg("GuiCommand: {}".format(self.command_name))
class GuiCommandNeedsSelection(GuiCommandSimplest):
"""Base class for GuiCommands that need a selection to be available.
It re-implements the `IsActive` method to return `True`
when there is both an active document and an active selection.
It inherits `GuiCommandSimplest` to set up the document
and other behavior. See this class for more information.
"""
def IsActive(self):
"""Return True when this command should be available.
It is `True` when there is a selection.
"""
if App.activeDocument() and Gui.Selection.getSelection():
return True
else:
return False
class GuiCommandBase:
class GuiCommandBase(object):
"""Generic class that is the basis of all Gui commands.
This class should eventually replace `DraftTools.DraftTool`,

View File

@@ -51,7 +51,7 @@ class AddToGroup(gui_base.GuiCommandNeedsSelection):
It adds selected objects to a group, or removes them from any group.
It inherits `GuiCommandNeedsSelection` to only be availbale
It inherits `GuiCommandNeedsSelection` to only be available
when there is a document and a selection.
See this class for more information.
"""
@@ -151,7 +151,7 @@ class SelectGroup(gui_base.GuiCommandNeedsSelection):
in this case it works in an intuitive manner, selecting
only the objects under the group.
It inherits `GuiCommandNeedsSelection` to only be availbale
It inherits `GuiCommandNeedsSelection` to only be available
when there is a document and a selection.
See this class for more information.
"""

File diff suppressed because it is too large Load Diff

View File

@@ -28,13 +28,74 @@
# \brief Provide the Draft_Snap commands used by the snapping mechanism
# in Draft.
from PySide import QtGui
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCADGui as Gui
import draftguitools.gui_base as gui_base
from draftutils.translate import _tr
# UTILITIES -----------------------------------------------------------------
def get_snap_statusbar_widget():
"""Return snap statusbar button."""
mw = Gui.getMainWindow()
if mw:
sb = mw.statusBar()
if sb:
return sb.findChild(QtGui.QToolBar,"draft_snap_widget")
return None
def sync_snap_toolbar_button(button, status):
"""Set snap toolbar button to given state."""
snap_toolbar = Gui.Snapper.get_snap_toolbar()
if not snap_toolbar:
return
for a in snap_toolbar.actions():
if a.objectName() == button:
if button == "Draft_Snap_Lock_Button":
# for lock button
snap_toolbar.actions()[0].setChecked(status)
for a in snap_toolbar.actions()[1:]:
a.setEnabled(status)
else:
# for every other button
a.setChecked(status)
if a.isChecked():
a.setToolTip(a.toolTip().replace("OFF","ON"))
else:
a.setToolTip(a.toolTip().replace("ON","OFF"))
def sync_snap_statusbar_button(button, status):
"""Set snap statusbar button to given state."""
ssw = get_snap_statusbar_widget()
if not ssw:
return
for child in ssw.children():
if child.objectName() == "Snap_Statusbutton":
ssb = child
actions = []
for a in ssb.menu().actions() + ssw.children()[-6:]:
actions.append(a)
if button == "Draft_Snap_Lock_Statusbutton":
ssb.setChecked(status)
for a in actions[1:]:
a.setEnabled(status)
else:
for a in actions:
if a.objectName() == button:
a.setChecked(status)
# SNAP GUI TOOLS ------------------------------------------------------------
class Draft_Snap_Lock(gui_base.GuiCommandSimplest):
"""GuiCommand for the Draft_Snap_Lock tool.
@@ -42,7 +103,7 @@ class Draft_Snap_Lock(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Main toggle snap"))
super(Draft_Snap_Lock, self).__init__(name=_tr("Main toggle snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -57,11 +118,13 @@ class Draft_Snap_Lock(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Lock, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "masterbutton"):
Gui.Snapper.masterbutton.toggle()
status = Gui.Snapper.toggle_snap('Lock')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Lock"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Lock"+"_Statusbutton", status)
Gui.addCommand('Draft_Snap_Lock', Draft_Snap_Lock())
@@ -74,7 +137,7 @@ class Draft_Snap_Midpoint(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Midpoint snap"))
super(Draft_Snap_Midpoint, self).__init__(name=_tr("Midpoint snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -87,13 +150,13 @@ class Draft_Snap_Midpoint(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Midpoint, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonmidpoint":
b.toggle()
status = Gui.Snapper.toggle_snap('Midpoint')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Midpoint"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Midpoint_Statusbutton", status)
Gui.addCommand('Draft_Snap_Midpoint', Draft_Snap_Midpoint())
@@ -106,7 +169,7 @@ class Draft_Snap_Perpendicular(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Perpendicular snap"))
super(Draft_Snap_Perpendicular, self).__init__(name=_tr("Perpendicular snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -121,13 +184,13 @@ class Draft_Snap_Perpendicular(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Perpendicular, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonperpendicular":
b.toggle()
status = Gui.Snapper.toggle_snap('Perpendicular')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Perpendicular"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Perpendicular_Statusbutton", status)
Gui.addCommand('Draft_Snap_Perpendicular', Draft_Snap_Perpendicular())
@@ -140,7 +203,7 @@ class Draft_Snap_Grid(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Grid snap"))
super(Draft_Snap_Grid, self).__init__(name=_tr("Grid snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -152,13 +215,13 @@ class Draft_Snap_Grid(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Grid, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtongrid":
b.toggle()
status = Gui.Snapper.toggle_snap('Grid')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Grid"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Grid_Statusbutton", status)
Gui.addCommand('Draft_Snap_Grid', Draft_Snap_Grid())
@@ -171,7 +234,7 @@ class Draft_Snap_Intersection(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Intersection snap"))
super(Draft_Snap_Intersection, self).__init__(name=_tr("Intersection snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -186,13 +249,13 @@ class Draft_Snap_Intersection(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Intersection, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonintersection":
b.toggle()
status = Gui.Snapper.toggle_snap('Intersection')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Intersection"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Intersection_Statusbutton", status)
Gui.addCommand('Draft_Snap_Intersection', Draft_Snap_Intersection())
@@ -205,7 +268,7 @@ class Draft_Snap_Parallel(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Parallel snap"))
super(Draft_Snap_Parallel, self).__init__(name=_tr("Parallel snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -218,13 +281,13 @@ class Draft_Snap_Parallel(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Parallel, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonparallel":
b.toggle()
status = Gui.Snapper.toggle_snap('Parallel')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Parallel"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Parallel_Statusbutton", status)
Gui.addCommand('Draft_Snap_Parallel', Draft_Snap_Parallel())
@@ -237,7 +300,7 @@ class Draft_Snap_Endpoint(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Endpoint snap"))
super(Draft_Snap_Endpoint, self).__init__(name=_tr("Endpoint snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -250,13 +313,13 @@ class Draft_Snap_Endpoint(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Endpoint, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonendpoint":
b.toggle()
status = Gui.Snapper.toggle_snap('Endpoint')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Endpoint"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Endpoint_Statusbutton", status)
Gui.addCommand('Draft_Snap_Endpoint', Draft_Snap_Endpoint())
@@ -270,7 +333,7 @@ class Draft_Snap_Angle(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Angle snap (30 and 45 degrees)"))
super(Draft_Snap_Angle, self).__init__(name=_tr("Angle snap (30 and 45 degrees)"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -284,13 +347,13 @@ class Draft_Snap_Angle(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Angle, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonangle":
b.toggle()
status = Gui.Snapper.toggle_snap('Angle')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Angle"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Angle_Statusbutton", status)
Gui.addCommand('Draft_Snap_Angle', Draft_Snap_Angle())
@@ -303,7 +366,7 @@ class Draft_Snap_Center(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Arc center snap"))
super(Draft_Snap_Center, self).__init__(name=_tr("Arc center snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -315,13 +378,13 @@ class Draft_Snap_Center(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Center, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtoncenter":
b.toggle()
status = Gui.Snapper.toggle_snap('Center')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Center"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Center_Statusbutton", status)
Gui.addCommand('Draft_Snap_Center', Draft_Snap_Center())
@@ -334,7 +397,7 @@ class Draft_Snap_Extension(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Edge extension snap"))
super(Draft_Snap_Extension, self).__init__(name=_tr("Edge extension snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -347,13 +410,13 @@ class Draft_Snap_Extension(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Extension, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonextension":
b.toggle()
status = Gui.Snapper.toggle_snap('Extension')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Extension"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Extension_Statusbutton", status)
Gui.addCommand('Draft_Snap_Extension', Draft_Snap_Extension())
@@ -366,7 +429,7 @@ class Draft_Snap_Near(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Near snap"))
super(Draft_Snap_Near, self).__init__(name=_tr("Near snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -378,13 +441,13 @@ class Draft_Snap_Near(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Near, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonpassive":
b.toggle()
status = Gui.Snapper.toggle_snap('Near')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Near"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Near_Statusbutton", status)
Gui.addCommand('Draft_Snap_Near', Draft_Snap_Near())
@@ -398,7 +461,7 @@ class Draft_Snap_Ortho(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Orthogonal snap"))
super(Draft_Snap_Ortho, self).__init__(name=_tr("Orthogonal snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -412,13 +475,13 @@ class Draft_Snap_Ortho(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Ortho, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonortho":
b.toggle()
status = Gui.Snapper.toggle_snap('Ortho')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Ortho"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Ortho"+"_Statusbutton", status)
Gui.addCommand('Draft_Snap_Ortho', Draft_Snap_Ortho())
@@ -431,7 +494,7 @@ class Draft_Snap_Special(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Special point snap"))
super(Draft_Snap_Special, self).__init__(name=_tr("Special point snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -444,13 +507,13 @@ class Draft_Snap_Special(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Special, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonspecial":
b.toggle()
status = Gui.Snapper.toggle_snap('Special')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Special"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Special_Statusbutton", status)
Gui.addCommand('Draft_Snap_Special', Draft_Snap_Special())
@@ -464,7 +527,7 @@ class Draft_Snap_Dimensions(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Dimension display"))
super(Draft_Snap_Dimensions, self).__init__(name=_tr("Dimension display"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -478,13 +541,13 @@ class Draft_Snap_Dimensions(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_Dimensions, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonDimensions":
b.toggle()
status = Gui.Snapper.toggle_snap('Dimensions')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_Dimensions"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_Dimensions"+"_Statusbutton", status)
Gui.addCommand('Draft_Snap_Dimensions', Draft_Snap_Dimensions())
@@ -500,7 +563,7 @@ class Draft_Snap_WorkingPlane(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Working plane snap"))
super(Draft_Snap_WorkingPlane, self).__init__(name=_tr("Working plane snap"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -520,13 +583,13 @@ class Draft_Snap_WorkingPlane(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(Draft_Snap_WorkingPlane, self).Activated()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonWorkingPlane":
b.toggle()
status = Gui.Snapper.toggle_snap('WorkingPlane')
# change interface consistently
sync_snap_toolbar_button("Draft_Snap_WorkingPlane"+"_Button", status)
sync_snap_statusbar_button("Draft_Snap_WorkingPlane_Statusbutton", status)
Gui.addCommand('Draft_Snap_WorkingPlane', Draft_Snap_WorkingPlane())
@@ -539,7 +602,7 @@ class ShowSnapBar(gui_base.GuiCommandSimplest):
"""
def __init__(self):
super().__init__(name=_tr("Show snap toolbar"))
super(ShowSnapBar, self).__init__(name=_tr("Show snap toolbar"))
def GetResources(self):
"""Set icon, menu and tooltip."""
@@ -553,7 +616,7 @@ class ShowSnapBar(gui_base.GuiCommandSimplest):
def Activated(self):
"""Execute when the command is called."""
super().Activated()
super(ShowSnapBar, self).Activated()
if hasattr(Gui, "Snapper"):
Gui.Snapper.show()

View File

@@ -160,7 +160,7 @@ class ToggleDisplayMode(gui_base.GuiCommandNeedsSelection):
Switches the display mode of selected objects from flatlines
to wireframe and back.
It inherits `GuiCommandNeedsSelection` to only be availbale
It inherits `GuiCommandNeedsSelection` to only be available
when there is a document and a selection.
See this class for more information.
"""

View File

@@ -62,7 +62,7 @@ def make_label(targetpoint=None, target=None, direction=None,
["Horizontal","Vertical","Custom"]
distance : Quantity
Lenght of the straight segment of label leader line
Length of the straight segment of label leader line
labeltype : String
Label type in

View File

@@ -1,11 +1,3 @@
"""Draft Statusbar commands.
This module provide the code for the Draft Statusbar, activated by initGui
"""
## @package init_draft_statusbar
# \ingroup DRAFT
# \brief This module provides the code for the Draft Statusbar.
# ***************************************************************************
# * *
# * Copyright (c) 2020 Carlo Pavan <carlopav@gmail.com> *
@@ -29,12 +21,22 @@ This module provide the code for the Draft Statusbar, activated by initGui
# * USA *
# * *
# ***************************************************************************
"""Draft Statusbar commands.
import FreeCAD as App
import FreeCADGui as Gui
This module provide the code for the Draft Statusbar, activated by initGui
"""
## @package init_draft_statusbar
# \ingroup DRAFT
# \brief This module provides the code for the Draft Statusbar.
from PySide import QtCore
from PySide import QtGui
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import FreeCADGui as Gui
from draftutils.init_tools import get_draft_snap_commands
#----------------------------------------------------------------------------
# SCALE WIDGET FUNCTIONS
@@ -124,7 +126,8 @@ def label_to_scale(label):
return scale
except:
err = QT_TRANSLATE_NOOP("draft",
"Unable to convert input into a scale factor")
"Unable to convert input into a "
"scale factor")
App.Console.PrintWarning(err)
return None
@@ -137,22 +140,25 @@ def _set_scale(action):
mw = Gui.getMainWindow()
sb = mw.statusBar()
statuswidget = sb.findChild(QtGui.QToolBar,"draft_status_widget")
scale_widget = sb.findChild(QtGui.QToolBar,"draft_status_scale_widget")
if action.text() == QT_TRANSLATE_NOOP("draft","custom"):
dialog_text = QT_TRANSLATE_NOOP("draft",
"Set custom annotation scale in format x:x, x=x"
"Set custom annotation scale in "
"format x:x, x=x"
)
custom_scale = QtGui.QInputDialog.getText(None, "Set custom scale", dialog_text)
custom_scale = QtGui.QInputDialog.getText(None, "Set custom scale",
dialog_text)
if custom_scale[1]:
print(custom_scale[0])
scale = label_to_scale(custom_scale[0])
if scale is None: return
if scale is None:
return
param.SetFloat("DraftAnnotationScale", scale)
cs = scale_to_label(scale)
statuswidget.scaleLabel.setText(cs)
scale_widget.scaleLabel.setText(cs)
else:
text_scale = action.text()
statuswidget.scaleLabel.setText(text_scale)
scale_widget.scaleLabel.setText(text_scale)
scale = label_to_scale(text_scale)
param.SetFloat("DraftAnnotationScale", scale)
@@ -164,21 +170,131 @@ def init_draft_statusbar(sb):
"""
this function initializes draft statusbar
"""
param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
# SNAP WIDGET - init ----------------------------------------------------
statuswidget = QtGui.QToolBar()
statuswidget.setObjectName("draft_status_widget")
snap_widget = QtGui.QToolBar()
snap_widget.setObjectName("draft_snap_widget")
snap_widget.setIconSize(QtCore.QSize(16,16))
# GRID BUTTON - init
gridbutton = QtGui.QPushButton(snap_widget)
gridbutton.setIcon(QtGui.QIcon.fromTheme("Draft",
QtGui.QIcon(":/icons/"
"Draft_Grid.svg")))
gridbutton.setToolTip(QT_TRANSLATE_NOOP("Draft",
"Toggles Grid On/Off"))
gridbutton.setObjectName("Grid_Statusbutton")
gridbutton.setWhatsThis("Draft_ToggleGrid")
gridbutton.setFlat(True)
QtCore.QObject.connect(gridbutton,QtCore.SIGNAL("clicked()"),
lambda f=Gui.doCommand,
arg='Gui.runCommand("Draft_ToggleGrid")':f(arg))
snap_widget.addWidget(gridbutton)
# SNAP BUTTON - init
snappref = param.GetString("snapModes","111111111101111")[0]
snapbutton = QtGui.QPushButton(snap_widget)
snapbutton.setIcon(QtGui.QIcon.fromTheme("Draft",
QtGui.QIcon(":/icons/"
"Snap_Lock.svg")))
snapbutton.setObjectName("Snap_Statusbutton")
snapbutton.setWhatsThis("Draft_ToggleLockSnap")
snapbutton.setToolTip(QT_TRANSLATE_NOOP("Draft",
"Object snapping"))
snapbutton.setCheckable(True)
snapbutton.setChecked(bool(int(snappref)))
snapbutton.setFlat(True)
snaps_menu = QtGui.QMenu(snapbutton)
snaps_menu.setObjectName("draft_statusbar_snap_toolbar")
snap_gui_commands = get_draft_snap_commands()
if 'Draft_Snap_Ortho' in snap_gui_commands:
snap_gui_commands.remove('Draft_Snap_Ortho')
if 'Draft_Snap_WorkingPlane' in snap_gui_commands:
snap_gui_commands.remove('Draft_Snap_WorkingPlane')
if 'Draft_Snap_Dimensions' in snap_gui_commands:
snap_gui_commands.remove('Draft_Snap_Dimensions')
Gui.Snapper.init_draft_snap_buttons(snap_gui_commands,snaps_menu, "_Statusbutton")
Gui.Snapper.restore_snap_buttons_state(snaps_menu, "_Statusbutton")
snapbutton.setMenu(snaps_menu)
snap_widget.addWidget(snapbutton)
# DIMENSION BUTTON - init
dimpref = param.GetString("snapModes","111111111101111")[13]
dimbutton = QtGui.QPushButton(snap_widget)
dimbutton.setIcon(QtGui.QIcon.fromTheme("Draft",
QtGui.QIcon(":/icons/"
"Snap_Dimensions.svg")))
dimbutton.setToolTip(QT_TRANSLATE_NOOP("Draft",
"Toggles Visual Aid Dimensions On/Off"))
dimbutton.setObjectName("Draft_Snap_Dimensions_Statusbutton")
dimbutton.setWhatsThis("Draft_ToggleDimensions")
dimbutton.setFlat(True)
dimbutton.setCheckable(True)
dimbutton.setChecked(bool(int(dimpref)))
QtCore.QObject.connect(dimbutton,QtCore.SIGNAL("clicked()"),
lambda f=Gui.doCommand,
arg='Gui.runCommand("Draft_Snap_Dimensions")':f(arg))
snap_widget.addWidget(dimbutton)
# ORTHO BUTTON - init
ortopref = param.GetString("snapModes","111111111101111")[10]
orthobutton = QtGui.QPushButton(snap_widget)
orthobutton.setIcon(QtGui.QIcon.fromTheme("Draft",
QtGui.QIcon(":/icons/"
"Snap_Ortho.svg")))
orthobutton.setObjectName("Draft_Snap_Ortho"+"_Statusbutton")
orthobutton.setWhatsThis("Draft_ToggleOrtho")
orthobutton.setToolTip(QT_TRANSLATE_NOOP("Draft",
"Toggles Ortho On/Off"))
orthobutton.setFlat(True)
orthobutton.setCheckable(True)
orthobutton.setChecked(bool(int(ortopref)))
QtCore.QObject.connect(orthobutton,QtCore.SIGNAL("clicked()"),
lambda f=Gui.doCommand,
arg='Gui.runCommand("Draft_Snap_Ortho")':f(arg))
snap_widget.addWidget(orthobutton)
# WORKINGPLANE BUTTON - init
wppref = param.GetString("snapModes","111111111101111")[14]
wpbutton = QtGui.QPushButton(snap_widget)
wpbutton.setIcon(QtGui.QIcon.fromTheme("Draft",
QtGui.QIcon(":/icons/"
"Snap_WorkingPlane.svg")))
wpbutton.setObjectName("Draft_Snap_WorkingPlane_Statusbutton")
wpbutton.setWhatsThis("Draft_ToggleWorkingPlaneSnap")
wpbutton.setToolTip(QT_TRANSLATE_NOOP("Draft",
"Toggles Constrain to Working Plane On/Off"))
wpbutton.setFlat(True)
wpbutton.setCheckable(True)
wpbutton.setChecked(bool(int(wppref)))
QtCore.QObject.connect(wpbutton,QtCore.SIGNAL("clicked()"),
lambda f=Gui.doCommand,
arg='Gui.runCommand("Draft_Snap_WorkingPlane")':f(arg))
snap_widget.addWidget(wpbutton)
# add snap widget to the statusbar
sb.insertPermanentWidget(2, snap_widget)
snap_widget.show()
# SCALE TOOL -------------------------------------------------------------
# SCALE WIDGET ----------------------------------------------------------
scale_widget = QtGui.QToolBar()
scale_widget.setObjectName("draft_status_scale_widget")
# get scales list according to system units
draft_scales = get_scales()
# get draft annotation scale
param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
draft_annotation_scale = param.GetFloat("DraftAnnotationScale", 1.0)
# initializes scale widget
statuswidget.draft_scales = draft_scales
scale_widget.draft_scales = draft_scales
scaleLabel = QtGui.QPushButton("Scale")
scaleLabel.setObjectName("ScaleLabel")
scaleLabel.setFlat(True)
@@ -194,39 +310,70 @@ def init_draft_statusbar(sb):
scaleLabel.setText(scale_label)
tooltip = "Set the scale used by draft annotation tools"
scaleLabel.setToolTip(QT_TRANSLATE_NOOP("draft",tooltip))
statuswidget.addWidget(scaleLabel)
statuswidget.scaleLabel = scaleLabel
scale_widget.addWidget(scaleLabel)
scale_widget.scaleLabel = scaleLabel
# ADD TOOLS TO STATUS BAR ------------------------------------------------
sb.addPermanentWidget(statuswidget)
statuswidget.show()
# add scale widget to the statusbar
sb.insertPermanentWidget(3, scale_widget)
scale_widget.show()
def show_draft_statusbar():
"""
shows draft statusbar if present or initializes it
"""
params = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
display_statusbar = params.GetBool("DisplayStatusbar", True)
if not display_statusbar:
return
mw = Gui.getMainWindow()
if mw:
sb = mw.statusBar()
statuswidget = sb.findChild(QtGui.QToolBar,"draft_status_widget")
if statuswidget:
statuswidget.show()
else:
scale_widget = sb.findChild(QtGui.QToolBar,
"draft_status_scale_widget")
if scale_widget:
scale_widget.show()
elif params.GetBool("DisplayStatusbarScaleWidget", True):
init_draft_statusbar(sb)
snap_widget = sb.findChild(QtGui.QToolBar,"draft_snap_widget")
if snap_widget:
snap_widget.show()
elif params.GetBool("DisplayStatusbarSnapWidget", True):
init_draft_statusbar(sb)
def hide_draft_statusbar():
"""
hides draft statusbar if present
"""
mw = Gui.getMainWindow()
if mw:
sb = mw.statusBar()
statuswidget = sb.findChild(QtGui.QToolBar,"draft_status_widget")
if statuswidget:
statuswidget.hide()
else:
# when switching workbenches, the toolbar sometimes "jumps"
# out of the status bar to any other dock area...
statuswidget = mw.findChild(QtGui.QToolBar,"draft_status_widget")
if statuswidget:
statuswidget.hide()
if not mw:
return
sb = mw.statusBar()
# hide scale widget
scale_widget = sb.findChild(QtGui.QToolBar,
"draft_status_scale_widget")
if scale_widget:
scale_widget.hide()
else:
# when switching workbenches, the toolbar sometimes "jumps"
# out of the status bar to any other dock area...
scale_widget = mw.findChild(QtGui.QToolBar,
"draft_status_scale_widget")
if scale_widget:
scale_widget.hide()
# hide snap widget
snap_widget = sb.findChild(QtGui.QToolBar,"draft_snap_widget")
if snap_widget:
snap_widget.hide()
else:
# when switching workbenches, the toolbar sometimes "jumps"
# out of the status bar to any other dock area...
snap_widget = mw.findChild(QtGui.QToolBar,"draft_snap_widget")
if snap_widget:
snap_widget.hide()

View File

@@ -115,15 +115,15 @@ def get_draft_utility_commands():
def get_draft_snap_commands():
"""Return the snapping commands list."""
return ['Draft_Snap_Lock', 'Draft_Snap_Midpoint',
'Draft_Snap_Perpendicular',
'Draft_Snap_Grid', 'Draft_Snap_Intersection',
'Draft_Snap_Parallel',
'Draft_Snap_Endpoint', 'Draft_Snap_Angle',
'Draft_Snap_Center',
'Draft_Snap_Extension', 'Draft_Snap_Near',
'Draft_Snap_Ortho', 'Draft_Snap_Special',
'Draft_Snap_Dimensions', 'Draft_Snap_WorkingPlane']
return ['Draft_Snap_Lock',
'Draft_Snap_Endpoint', 'Draft_Snap_Midpoint',
'Draft_Snap_Center', 'Draft_Snap_Angle',
'Draft_Snap_Intersection', 'Draft_Snap_Perpendicular',
'Draft_Snap_Extension', 'Draft_Snap_Parallel',
'Draft_Snap_Special', 'Draft_Snap_Near',
'Draft_Snap_Ortho', 'Draft_Snap_Grid',
'Draft_Snap_WorkingPlane', 'Draft_Snap_Dimensions',
]
def init_draft_toolbars(workbench):

View File

@@ -469,7 +469,7 @@ an empty dictionary if there is no intersection.
<UserDocu>getPlanarSegments(dev,[min faces=0]) -> list
Get all planes of the mesh as segment.
In the worst case each triangle can be regarded as single
plane if none of its neighours is coplanar.</UserDocu>
plane if none of its neighbors are coplanar.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getSegmentsOfType" Const="true">

View File

@@ -750,7 +750,7 @@ private:
p1.Transform(loc.Transformation());
p2.Transform(loc.Transformation());
p3.Transform(loc.Transformation());
// TODO: verify if tolerence should be hard coded
// TODO: verify if tolerance should be hard coded
if (!p1.IsEqual(p2, 0.01) && !p2.IsEqual(p3, 0.01) && !p3.IsEqual(p1, 0.01)) {
PyObject *t1 = PyTuple_Pack(3, PyFloat_FromDouble(p1.X()), PyFloat_FromDouble(p1.Y()), PyFloat_FromDouble(p1.Z()));
PyObject *t2 = PyTuple_Pack(3, PyFloat_FromDouble(p2.X()), PyFloat_FromDouble(p2.Y()), PyFloat_FromDouble(p2.Z()));

View File

@@ -40,7 +40,7 @@
<property name="toolTip">
<string>The default color for new shapes</string>
</property>
<property name="color" stdset="0">
<property name="color">
<color>
<red>204</red>
<green>204</green>
@@ -89,7 +89,7 @@
<property name="toolTip">
<string>The default line color for new shapes</string>
</property>
<property name="color" stdset="0">
<property name="color">
<color>
<red>25</red>
<green>25</green>
@@ -157,7 +157,7 @@
<property name="toolTip">
<string>The default color for new vertices</string>
</property>
<property name="color" stdset="0">
<property name="color">
<color>
<red>25</red>
<green>25</green>
@@ -225,7 +225,7 @@
<property name="toolTip">
<string>The color of bounding boxes in the 3D view</string>
</property>
<property name="color" stdset="0">
<property name="color">
<color>
<red>255</red>
<green>255</green>
@@ -248,6 +248,12 @@
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Bottom side of surface will be rendered the same way than top.
If not checked, it depends on the option &quot;Backlight color&quot;
(preferences section Display -&gt; 3D View); either the backlight color
will be used or black.</string>
</property>
<property name="text">
<string>Two-side rendering</string>
</property>
@@ -303,6 +309,9 @@
</item>
<item row="0" column="1">
<widget class="Gui::PrefColorButton" name="AnnotationTextColor">
<property name="toolTip">
<string>Text color for document annotations</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>AnnotationTextColor</cstring>
</property>

View File

@@ -16,6 +16,8 @@ if(BUILD_GUI)
TestPartDesignGui.py
InvoluteGearFeature.py
InvoluteGearFeature.ui
SprocketFeature.py
SprocketFeature.ui
)
endif(BUILD_GUI)
@@ -60,6 +62,13 @@ set(PartDesign_GearScripts
fcgear/svggear.py
)
set(PartDesign_SprocketScripts
fcsprocket/__init__.py
fcsprocket/fcsprocket.py
fcsprocket/fcsprocketdialog.py
fcsprocket/sprocket.py
)
set(PartDesign_WizardShaft
WizardShaft/__init__.py
WizardShaft/WizardShaft.svg
@@ -76,6 +85,7 @@ add_custom_target(PartDesignScripts ALL SOURCES
${PartDesign_OtherScripts}
${PartDesign_TestScripts}
${PartDesign_GearScripts}
${PartDesign_SprocketScripts}
)
fc_target_copy_resource(PartDesignScripts
@@ -85,6 +95,7 @@ fc_target_copy_resource(PartDesignScripts
${PartDesign_OtherScripts}
${PartDesign_TestScripts}
${PartDesign_GearScripts}
${PartDesign_SprocketScripts}
)
INSTALL(
@@ -113,7 +124,13 @@ INSTALL(
${PartDesign_GearScripts}
DESTINATION
Mod/PartDesign/fcgear
)
INSTALL(
FILES
${PartDesign_SprocketScripts}
DESTINATION
Mod/PartDesign/fcsprocket
)
if(BUILD_FEM)

View File

@@ -37,6 +37,7 @@
<file>icons/PartDesign_Revolution.svg</file>
<file>icons/PartDesign_Scaled.svg</file>
<file>icons/PartDesign_ShapeBinder.svg</file>
<file>icons/PartDesign_Sprocket.svg</file>
<file>icons/PartDesign_SubShapeBinder.svg</file>
<file>icons/PartDesign_Subtractive_Box.svg</file>
<file>icons/PartDesign_Subtractive_Cone.svg</file>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 89 KiB

View File

@@ -509,9 +509,10 @@ Gui::MenuItem* Workbench::setupMenuBar() const
<< "PartDesign_Boolean"
<< "Separator"
//<< "PartDesign_Hole"
<< "PartDesign_InvoluteGear"
<< "Separator"
<< "PartDesign_Migrate";
<< "PartDesign_Migrate"
<< "PartDesign_Sprocket"
<< "PartDesign_InvoluteGear";
// For 0.13 a couple of python packages like numpy, matplotlib and others
// are not deployed with the installer on Windows. Thus, the WizardShaft is

View File

@@ -51,6 +51,7 @@ class PartDesignWorkbench ( Workbench ):
import PartDesign
try:
from PartDesign import InvoluteGearFeature
from PartDesign import SprocketFeature
except ImportError:
print("Involute gear module cannot be loaded")
#try:

View File

@@ -0,0 +1,248 @@
#***************************************************************************
#* Copyright (c) 2020 Adam Spontarelli <adam@vector-space.org> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import FreeCAD, Part
from fcsprocket import fcsprocket
from fcsprocket import sprocket
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtCore, QtGui
from FreeCADGui import PySideUic as uic
__title__="PartDesign SprocketObject management"
__author__ = "Adam Spontarelli"
__url__ = "http://www.freecadweb.org"
def makeSprocket(name):
"""
makeSprocket(name): makes a Sprocket
"""
obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",name)
Sprocket(obj)
if FreeCAD.GuiUp:
ViewProviderSprocket(obj.ViewObject)
#FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
body=FreeCADGui.ActiveDocument.ActiveView.getActiveObject("pdbody")
part=FreeCADGui.ActiveDocument.ActiveView.getActiveObject("part")
if body:
body.Group=body.Group+[obj]
elif part:
part.Group=part.Group+[obj]
return obj
class CommandSprocket:
"""
the Fem Sprocket command definition
"""
def GetResources(self):
return {'Pixmap' : 'PartDesign_Sprocket',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PartDesign_Sprocket","Sprocket..."),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PartDesign_Sprocket","Creates or edit the sprocket definition.")}
def Activated(self):
FreeCAD.ActiveDocument.openTransaction("Create Sprocket")
FreeCADGui.addModule("SprocketFeature")
FreeCADGui.doCommand("SprocketFeature.makeSprocket('Sprocket')")
FreeCADGui.doCommand("Gui.activeDocument().setEdit(App.ActiveDocument.ActiveObject.Name,0)")
def IsActive(self):
if FreeCAD.ActiveDocument:
return True
else:
return False
class Sprocket:
"""
The Sprocket object
"""
def __init__(self,obj):
self.Type = "Sprocket"
obj.addProperty("App::PropertyInteger","NumberOfTeeth","Sprocket","Number of gear teeth")
obj.addProperty("App::PropertyLength","Pitch","Sprocket","Chain Pitch")
obj.addProperty("App::PropertyLength","RollerDiameter","Sprocket","Roller Diameter")
obj.addProperty("App::PropertyString","ANSISize","Sprocket","ANSI Size")
obj.NumberOfTeeth = 50
obj.Pitch = "0.375 in"
obj.RollerDiameter = "0.20 in"
obj.ANSISize = "35"
obj.Proxy = self
def execute(self,obj):
w = fcsprocket.FCWireBuilder()
sprocket.CreateSprocket(w, obj.Pitch.Value, obj.NumberOfTeeth, obj.RollerDiameter.Value)
sprocketw = Part.Wire([o.toShape() for o in w.wire])
obj.Shape = sprocketw
obj.positionBySupport();
return
class ViewProviderSprocket:
"""
A View Provider for the Sprocket object
"""
def __init__(self,vobj):
vobj.Proxy = self
def getIcon(self):
return ":/icons/PartDesign_Sprocket.svg"
def attach(self, vobj):
self.ViewObject = vobj
self.Object = vobj.Object
def setEdit(self,vobj,mode):
taskd = SprocketTaskPanel(self.Object,mode)
taskd.obj = vobj.Object
taskd.update()
FreeCADGui.Control.showDialog(taskd)
return True
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return
def __getstate__(self):
return None
def __setstate__(self,state):
return None
class SprocketTaskPanel:
"""
The editmode TaskPanel for Sprocket objects
"""
def __init__(self,obj,mode):
self.obj = obj
self.form=FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/PartDesign/SprocketFeature.ui")
self.form.setWindowIcon(QtGui.QIcon(":/icons/PartDesign_Sprocket.svg"))
QtCore.QObject.connect(self.form.Quantity_Pitch, QtCore.SIGNAL("valueChanged(double)"), self.pitchChanged)
QtCore.QObject.connect(self.form.Quantity_RollerDiameter, QtCore.SIGNAL("valueChanged(double)"), self.rollerDiameterChanged)
QtCore.QObject.connect(self.form.spinBox_NumberOfTeeth, QtCore.SIGNAL("valueChanged(int)"), self.numTeethChanged)
QtCore.QObject.connect(self.form.comboBox_ANSISize, QtCore.SIGNAL("currentTextChanged(const QString)"), self.ANSISizeChanged)
self.update()
if mode == 0: # fresh created
self.obj.Proxy.execute(self.obj) # calculate once
FreeCAD.Gui.SendMsgToActiveView("ViewFit")
def transferTo(self):
"""
Transfer from the dialog to the object
"""
self.obj.NumberOfTeeth = self.form.spinBox_NumberOfTeeth.value()
self.obj.Pitch = self.form.Quantity_Pitch.text()
self.obj.RollerDiameter = self.form.Quantity_RollerDiameter.text()
self.obj.ANSISize = self.form.comboBox_ANSISize.currentText()
def transferFrom(self):
"""
Transfer from the object to the dialog
"""
self.form.spinBox_NumberOfTeeth.setValue(self.obj.NumberOfTeeth)
self.form.Quantity_Pitch.setText(self.obj.Pitch.UserString)
self.form.Quantity_RollerDiameter.setText(self.obj.RollerDiameter.UserString)
self.form.comboBox_ANSISize.setCurrentText(self.obj.ANSISize)
def pitchChanged(self, value):
self.obj.Pitch = value
self.obj.Proxy.execute(self.obj)
FreeCAD.Gui.SendMsgToActiveView("ViewFit")
def ANSISizeChanged(self, size):
"""
ANSI B29.1-2011 standard roller chain sizes in USCS units (inches)
{size: [Pitch, Roller Diameter]}
"""
ANSIRollerTable = {"25": [0.250, 0.130],
"35": [0.375, 0.200],
"41": [0.500, 0.306],
"40": [0.500, 0.312],
"50": [0.625, 0.400],
"60": [0.750, 0.469],
"80": [1.000, 0.625],
"100":[1.250, 0.750],
"120":[1.500, 0.875],
"140":[1.750, 1.000],
"160":[2.000, 1.125],
"180":[2.250, 1.460],
"200":[2.500, 1.562],
"240":[3.000, 1.875]}
self.obj.Pitch = str(ANSIRollerTable[size][0]) + " in"
self.obj.RollerDiameter = str(ANSIRollerTable[size][1]) + " in"
self.form.Quantity_Pitch.setText(self.obj.Pitch.UserString)
self.form.Quantity_RollerDiameter.setText(self.obj.RollerDiameter.UserString)
self.obj.Proxy.execute(self.obj)
FreeCAD.Gui.SendMsgToActiveView("ViewFit")
def rollerDiameterChanged(self, value):
self.obj.RollerDiameter = value
self.obj.Proxy.execute(self.obj)
def numTeethChanged(self, value):
self.obj.NumberOfTeeth = value
self.obj.Proxy.execute(self.obj)
FreeCAD.Gui.SendMsgToActiveView("ViewFit")
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok) | int(QtGui.QDialogButtonBox.Cancel)| int(QtGui.QDialogButtonBox.Apply)
def clicked(self,button):
if button == QtGui.QDialogButtonBox.Apply:
self.transferTo()
self.obj.Proxy.execute(self.obj)
def update(self):
self.transferFrom()
def accept(self):
self.transferTo()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.ActiveDocument.resetEdit()
def reject(self):
FreeCADGui.ActiveDocument.resetEdit()
FreeCAD.ActiveDocument.abortTransaction()
if FreeCAD.GuiUp:
FreeCADGui.addCommand('PartDesign_Sprocket', CommandSprocket())

View File

@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SprocketParameter</class>
<widget class="QWidget" name="SprocketParameter">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>195</width>
<height>142</height>
</rect>
</property>
<property name="windowTitle">
<string>Sprocket parameter</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Number of teeth:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBox_NumberOfTeeth">
<property name="minimum">
<number>3</number>
</property>
<property name="maximum">
<number>9999</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>ANSI Size:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBox_ANSISize">
<item>
<property name="text">
<string>25</string>
</property>
</item>
<item>
<property name="text">
<string>35</string>
</property>
</item>
<item>
<property name="text">
<string>41</string>
</property>
</item>
<item>
<property name="text">
<string>40</string>
</property>
</item>
<item>
<property name="text">
<string>50</string>
</property>
</item>
<item>
<property name="text">
<string>60</string>
</property>
</item>
<item>
<property name="text">
<string>80</string>
</property>
</item>
<item>
<property name="text">
<string>100</string>
</property>
</item>
<item>
<property name="text">
<string>120</string>
</property>
</item>
<item>
<property name="text">
<string>140</string>
</property>
</item>
<item>
<property name="text">
<string>160</string>
</property>
</item>
<item>
<property name="text">
<string>180</string>
</property>
</item>
<item>
<property name="text">
<string>200</string>
</property>
</item>
<item>
<property name="text">
<string>240</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Chain Pitch:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::InputField" name="Quantity_Pitch">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true">in</string>
</property>
<property name="decimals" stdset="0">
<number>3</number>
</property>
<property name="maximum" stdset="0">
<double>2000.000000000000000</double>
</property>
<property name="minimum" stdset="0">
<double>0.01</double>
</property>
<property name="singleStep" stdset="0">
<double>0.001</double>
</property>
<property name="value" stdset="0">
<double>0.375</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Roller Diameter:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="Gui::InputField" name="Quantity_RollerDiameter">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true">in</string>
</property>
<property name="decimals" stdset="0">
<number>3</number>
</property>
<property name="maximum" stdset="0">
<double>50.000000000000000</double>
</property>
<property name="minimum" stdset="0">
<double>0.01</double>
</property>
<property name="singleStep" stdset="0">
<double>0.01</double>
</property>
<property name="value" stdset="0">
<double>0.20</double>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::InputField</class>
<extends>QLineEdit</extends>
<header>Gui/InputField.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,24 @@
================================================
FCSprocket: a Sprocket Generator for FreeCAD
================================================
This is a simple sprocket generation tool. Sprockets are used in combination
with roller chain to transmit power. The tooth profiles are drawn according
to ANSI standards from the methods outlined in:
Standard handbook of chains : chains for power transmission and material
handling. Boca Raton: Taylor & Francis, 2006. Print.
AND
Oberg, Erik, et al. Machinery's handbook : a reference book for the
mechanical engineer, designer, manufacturing engineer, draftsman,
toolmaker, and machinist. New York: Industrial Press, 2016. Print.
This code is based on the work of David Douard and his implementation of the
gear generator (fcgear) found in FreeCAD.
Copyright 2020 Adam Spontarelli <adam@vector-space.org>.
Distributed under the LGPL licence.

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,105 @@
# (c) 2014 David Douard <david.douard@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (LGPL)
# as published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
# for detail see the LICENCE text file.
#
# FCGear is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with FCGear; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
from math import cos, sin, pi, acos, asin, atan, sqrt
import FreeCAD, Part
from FreeCAD import Base, Console
from . import sprocket
rotate = sprocket.rotate
def makeSprocket(P, N, Dr):
if FreeCAD.ActiveDocument is None:
FreeCAD.newDocument("Sprocket")
doc = FreeCAD.ActiveDocument
w = FCWireBuilder()
sprocket.CreateSprocket(w, P, N, Dr)
sprocketw = Part.Wire([o.toShape() for o in w.wire])
sprocket = doc.addObject("Part::Feature", "Sprocket")
sprocket.Shape = sprocketw
return sprocket
class FCWireBuilder(object):
"""A helper class to prepare a Part.Wire object"""
def __init__(self):
self.pos = None
self.theta = 0.0
self.wire = []
def move(self, p):
"""set current position"""
self.pos = Base.Vector(*p)
def line(self, p):
"""Add a segment between self.pos and p"""
p = rotate(p, self.theta)
end = Base.Vector(*p)
self.wire.append(Part.LineSegment(self.pos, end))
self.pos = end
def arc(self, p, r, sweep):
""""Add an arc from self.pos to p which radius is r
sweep (0 or 1) determine the orientation of the arc
"""
p = rotate(p, self.theta)
end = Base.Vector(*p)
mid = Base.Vector(*(midpoints(p, self.pos, r)[sweep]))
self.wire.append(Part.Arc(self.pos, mid, end))
self.pos = end
def curve(self, *points):
"""Add a Bezier curve from self.pos to points[-1]
every other points are the control points of the Bezier curve (which
will thus be of degree len(points) )
"""
points = [Base.Vector(*rotate(p, self.theta)) for p in points]
bz = Part.BezierCurve()
bz.setPoles([self.pos] + points)
self.wire.append(bz)
self.pos = points[-1]
def close(self):
pass
def midpoints(p1, p2, r):
"""A very ugly function that returns the midpoint of a p1 and p2
on the circle which radius is r and which pass through p1 and
p2
Return the 2 possible solutions
"""
vx, vy = p2[0]-p1[0], p2[1]-p1[1]
b = (vx**2 + vy**2)**.5
v = (vx/b, vy/b)
cosA = b**2 / (2*b*r)
A = acos(cosA)
vx, vy = rotate(v, A)
c1 = (p1[0]+r*vx, p1[1]+r*vy)
m1x, m1y = ((p1[0]+p2[0])/2 - c1[0], (p1[1]+p2[1])/2 - c1[1])
dm1 = (m1x**2+m1y**2)**.5
m1x, m1y = (c1[0] + r*m1x/dm1, c1[1] + r*m1y/dm1)
m1 = (m1x, m1y)
vx, vy = rotate(v, -A)
c2 = (p1[0]+r*vx, p1[1]+r*vy)
m2x, m2y = ((p1[0]+p2[0])/2 - c2[0], (p1[1]+p2[1])/2 - c2[1])
dm2 = (m2x**2+m2y**2)**.5
m2x, m2y = (c2[0] + r*m2x/dm2, c2[1] + r*m2y/dm2)
m2 = (m2x, m2y)
return m1, m2

View File

@@ -0,0 +1,66 @@
# (c) 2020 Adam Spontarelli <adam@vector-space.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (LGPL)
# as published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
# for detail see the LICENCE text file.
#
# FCGear is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with FCGear; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
from PySide import QtGui as qt
import fcsprocket
import FreeCAD, FreeCADGui
class SprocketCreationFrame(qt.QFrame):
def __init__(self, parent=None):
super(SprocketCreationFrame, self).__init__(parent)
self.P = qt.QSpinBox(value=0.375)
self.N = qt.QDoubleSpinBox(value=45)
self.Dr = qt.QDoubleSpinBox(value=0.20)
l = qt.QFormLayout(self)
l.setFieldGrowthPolicy(l.ExpandingFieldsGrow)
l.addRow('Number of teeth:', self.N)
l.addRow('Chain Pitch (in):', self.P)
l.addRow('Roller Diameter (in):', self.Dr)
class SprocketDialog(qt.QDialog):
def __init__(self, parent=None):
super(SprocketDialog, self).__init__(parent)
self.gc = SprocketCreationFrame()
btns = qt.QDialogButtonBox.Ok | qt.QDialogButtonBox.Cancel
buttonBox = qt.QDialogButtonBox(btns,
accepted=self.accept,
rejected=self.reject)
l = qt.QVBoxLayout(self)
l.addWidget(self.gc)
l.addWidget(buttonBox)
self.setWindowTitle('Sprocket creation dialog')
def accept(self):
if FreeCAD.ActiveDocument is None:
FreeCAD.newDocument("Sprocket")
gear = fcgear.makeSprocket(self.gc.m.value(),
self.gc.Z.value(),
self.gc.angle.value(),
not self.gc.split.currentIndex())
FreeCADGui.SendMsgToActiveView("ViewFit")
return super(SprocketDialog, self).accept()
if __name__ == '__main__':
a = qt.QApplication([])
w = SprocketDialog()
w.show()
a.exec_()

View File

@@ -0,0 +1,139 @@
# (c) 2020 Adam Spontarelli <adam@vector-space.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (LGPL)
# as published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
# for detail see the LICENCE text file.
#
# FCGear is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with FCGear; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
from math import cos, sin, tan, sqrt, radians, acos, atan, asin, degrees
def CreateSprocket(w, P, N, Dr):
"""
Create a sprocket
w is the wirebuilder object (in which the sprocket will be constructed)
P is the chain pitch
N is the number of teeth
Dr is the roller diameter
Remaining variables can be found in Standard Handbook of Chains
"""
Ds = 1.005 * Dr + (0.003 * 25.4)
R = Ds / 2
alpha = 35 + 60/N
beta = 18 - 56 / N
M = 0.8 * Dr * cos(radians(35) + radians(60/N))
T = 0.8 * Dr * sin(radians(35) + radians(60/N))
E = 1.3025 * Dr + (0.0015 * 25.4)
W = 1.4 * Dr * cos(radians(180/N))
V = 1.4 * Dr * sin(radians(180/N))
F = Dr * (0.8 * cos(radians(18) - radians(56)/N) + 1.4 *
cos(radians(17) - radians(64) / N) - 1.3025) - (0.0015 * 25.4)
PD = P / (sin(radians(180)/N))
H = sqrt(F**2 - (1.4 * Dr - P/2)**2)
OD = P * (0.6 + 1/tan(radians(180/N)))
# The sprocket tooth gullet consists of four segments
x0 = 0
y0 = PD/2 - R
# ---- Segment 1 -----
alpha = 35 + 60/N
x1 = -R * cos(radians(alpha))
y1 = PD/2 - R * sin(radians(alpha))
arc_end = [x1, y1]
# ---- Segment 2 -----
alpha = 35 + 60/N
beta = 18 - 56 / N
x2 = M - E * cos(radians(alpha-beta))
y2 = T - E * sin(radians(alpha-beta)) + PD/2
# # ---- Segment 3 -----
y2o = y2 - PD/2
hyp = sqrt((-W-x2)**2 + (-V-y2o)**2)
AP = sqrt(hyp**2 - F**2)
gamma = atan((y2o + V)/(x2 + W))
alpha = asin(AP / hyp)
beta = 180 - (90 - degrees(alpha)) - (90 - degrees(gamma))
x3o = AP * sin(radians(beta))
y3o = AP * cos(radians(beta))
x3 = x2 - x3o
y3 = y2 + y3o
# ---- Segment 4 -----
alpha = 180/N
m = -1/tan(radians(alpha))
yf = PD/2 - V
A = 1 + m**2
B = 2*m*yf - 2*W
C = W**2 + yf**2 - F**2
# x4a = (-B - sqrt(B**2 - 4 * A * C)) / (2*A)
x4b = (-B + sqrt(B**2 - 4 * A * C)) / (2*A)
x4 = -x4b
y4 = m * x4
p0 = [x0,y0]
p1 = [x1,y1]
p2 = [x2,y2]
p3 = [x3,y3]
p4 = [x4,y4]
p5 = [-x1,y1]
p6 = [-x2,y2]
p7 = [-x3,y3]
p8 = [-x4,y4]
w.move(p4) # vectors are lists [x,y]
w.arc(p3, F, 0)
w.line(p2)
w.arc(p1, E, 1)
w.arc(p0, R, 1)
# ---- Mirror -----
w.arc(p5, R, 1)
w.arc(p6, E, 1)
w.line(p7)
w.arc(p8, F, 0)
# ---- Polar Array ----
alpha = -radians(360/N)
for n in range(1,N):
# falling gullet slope
w.arc(rotate(p3, alpha*n), F, 0)
w.line(rotate(p2, alpha*n))
w.arc(rotate(p1, alpha*n), E, 1)
w.arc(rotate(p0, alpha*n), R, 1)
# rising gullet slope
w.arc(rotate(p5, alpha*n), R, 1)
w.line(rotate(p6, alpha*n))
w.arc(rotate(p7, alpha*n), E, 0)
w.arc(rotate(p8, alpha*n), F, 0)
w.close()
return w
def rotate(pt, rads):
"""
rotate pt by rads radians about origin
"""
sinA = sin(rads)
cosA = cos(rads)
return (pt[0] * cosA - pt[1] * sinA,
pt[0] * sinA + pt[1] * cosA)