Skip to content

Commit 1d77bca

Browse files
committed
added edit mode with task panel UI
1 parent eba13b4 commit 1d77bca

7 files changed

+126
-19
lines changed

Feature1.py Feature1/Feature1.py

+57-8
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@
55
__license__ = "LGPL 2.1"
66
__doc__ = "An example for a workbench feature"
77

8-
import PythonWorkbenchTemplate
98
import os
109
import FreeCADGui
1110
import FreeCAD
12-
from FreeCAD import Vector
13-
import Part
1411

12+
__dir__ = os.path.dirname(__file__)
13+
__iconpath__ = os.path.join(__dir__, 'feature1.svg')
1514

1615
class Feature1Worker:
1716
def __init__(self,
@@ -44,7 +43,7 @@ def __init__(self, vobj):
4443

4544
def getIcon(self):
4645
'''Return the icon which will appear in the tree view. This method is optional and if not defined a default icon is shown.'''
47-
return (os.path.join(PythonWorkbenchTemplate.get_module_path(), "Resources", "icons", "feature1.svg"))
46+
return __iconpath__
4847

4948
def attach(self, vobj):
5049
'''Setup the scene sub-graph of the view provider, this method is mandatory'''
@@ -67,29 +66,79 @@ def onChanged(self, fp, prop):
6766
'''Here we can do something when a single property got changed'''
6867
pass
6968

69+
def setEdit(self, vobj=None, mode=0):
70+
'''Enter edit mode when double clicking onto the feature. Optional.'''
71+
# Create a task panel UI
72+
self.panel = Feature1TaskPanel(self.Object)
73+
FreeCADGui.Control.showDialog(self.panel)
74+
return True
75+
7076
def __getstate__(self):
7177
'''When saving the document this object gets stored using Python's json module.\
7278
Since we have some un-serializable parts here -- the Coin stuff -- we must define this method\
7379
to return a tuple of all serializable objects or None.'''
7480
return None
7581

76-
def __setstate__(self,state):
82+
def __setstate__(self, state):
7783
'''When restoring the serialized object from document we have the chance to set some internals here.\
7884
Since no data were serialized nothing needs to be done here.'''
7985
return None
86+
8087

88+
class Feature1TaskPanel:
89+
def __init__(self, fp):
90+
self.fp = fp
91+
# this will create a Qt widget from our ui file
92+
self.form = FreeCADGui.PySideUic.loadUi(os.path.join(__dir__, 'feature1.ui'))
93+
# connect controls from the .ui file to class methods
94+
self.form.pushButtonSelect.pressed.connect(self._selectPart)
95+
self.form.radioButtonRed.released.connect(self._changeColor)
96+
self.form.radioButtonGreen.released.connect(self._changeColor)
97+
if self.fp.Base:
98+
self.form.labelSelected.setText(self.fp.Base.Name)
8199

100+
def accept(self):
101+
'''called when the OK button in the task panel is pressed'''
102+
self.fp.Base = FreeCAD.ActiveDocument.getObject(self.form.labelSelected.text())
103+
self.fp.Green = self.form.radioButtonGreen.isChecked()
104+
105+
redrawFeature1(self.fp)
106+
FreeCADGui.ActiveDocument.resetEdit()
107+
return True
108+
109+
def reject(self):
110+
'''called when the Cancel button in the task panel is pressed'''
111+
FreeCADGui.ActiveDocument.resetEdit()
112+
return True
113+
114+
def _selectPart(self):
115+
'''called when the Select Part button defined in the .ui file is pressed'''
116+
selection = FreeCADGui.Selection.getSelectionEx()
117+
if len(selection) > 0:
118+
self.fp.Base = FreeCAD.ActiveDocument.getObject(selection[0].ObjectName)
119+
self.form.labelSelected.setText(selection[0].ObjectName)
120+
121+
def _changeColor(self):
122+
'''called when a radio button defined in the .ui file is pressed'''
123+
self.fp.Green = self.form.radioButtonGreen.isChecked()
124+
changeFeature1Color(self.fp)
125+
126+
82127
def redrawFeature1(fp):
83128
# check plausibility of all parameters
84129
if not fp.Base:
85130
return
86131

87132
# fp.Shape contains the newly created object
88133
fp.Shape = fp.Base.Shape.copy()
134+
fp.Placement = fp.Base.Placement
135+
# place the new object on top of the selected one
136+
fp.Placement.Base.z += fp.Base.Shape.BoundBox.ZLength
137+
89138
changeFeature1Color(fp)
90139

91140

92-
def changeFeature1Color(fp):
141+
def changeFeature1Color(fp):
93142
if fp.Green:
94143
fp.ViewObject.ShapeColor = (0.00, 1.00, 0.00)
95144
else:
@@ -122,9 +171,9 @@ def IsActive(self):
122171

123172
def GetResources(self):
124173
'''Return the icon which will appear in the tree view. This method is optional and if not defined a default icon is shown.'''
125-
return {'Pixmap' : os.path.join(PythonWorkbenchTemplate.get_module_path(), "Resources", "icons", "feature1.svg"),
174+
return {'Pixmap' : __iconpath__,
126175
'Accel' : "", # a default shortcut (optional)
127176
'MenuText': "Feature1",
128-
'ToolTip' : "A template for a workbench feature" }
177+
'ToolTip' : __doc__ }
129178

130179
FreeCADGui.addCommand('Feature1', Feature1())
File renamed without changes.

Feature1/feature1.ui

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>Form</class>
4+
<widget class="QWidget" name="Form">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>287</width>
10+
<height>90</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Form</string>
15+
</property>
16+
<layout class="QVBoxLayout" name="verticalLayout">
17+
<item>
18+
<widget class="QPushButton" name="pushButtonSelect">
19+
<property name="text">
20+
<string>Select Part</string>
21+
</property>
22+
</widget>
23+
</item>
24+
<item>
25+
<widget class="QLabel" name="labelSelected">
26+
<property name="text">
27+
<string>&lt;nothing selected&gt;</string>
28+
</property>
29+
</widget>
30+
</item>
31+
<item>
32+
<widget class="QRadioButton" name="radioButtonRed">
33+
<property name="text">
34+
<string>red</string>
35+
</property>
36+
<property name="checked">
37+
<bool>true</bool>
38+
</property>
39+
</widget>
40+
</item>
41+
<item>
42+
<widget class="QRadioButton" name="radioButtonGreen">
43+
<property name="text">
44+
<string>green</string>
45+
</property>
46+
</widget>
47+
</item>
48+
</layout>
49+
</widget>
50+
<resources/>
51+
<connections/>
52+
</ui>

InitGui.py

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# -*- coding: utf-8 -*-
22

3-
__title__ = "FreeCAD Default Workbench - Init file"
3+
__title__ = "FreeCAD Python Workbench Template - Init file"
44
__author__ = "Christian Bergmann"
55
__url__ = ["http://www.freecadweb.org"]
6+
__doc__ = "A template for a new workbench"
67
__version__ = "0.0.1"
78

89

@@ -12,16 +13,16 @@ def __init__(self):
1213
import PythonWorkbenchTemplate
1314
self.__class__.MenuText = "PythonWorkbenchTemplate"
1415
self.__class__.ToolTip = "A template for a new workbench"
15-
self.__class__.Icon = os.path.join(PythonWorkbenchTemplate.get_module_path(), "Resources", "icons", "freecad.svg")
16+
self.__class__.Icon = os.path.join(PythonWorkbenchTemplate.get_module_path(), "freecad.svg")
1617

1718
def Initialize(self):
1819
"This function is executed when FreeCAD starts"
1920
# import here all the needed files that create your FreeCAD commands
20-
import Feature1
21+
from Feature1 import Feature1
2122

2223
self.list = ["Feature1"] # A list of command names created in the line above
23-
self.appendToolbar("Curved Shapes", self.list) # creates a new toolbar with your commands
24-
self.appendMenu("Curved Shapes", self.list) # creates a new menu
24+
self.appendToolbar("PythonWorkbenchTemplate", self.list) # creates a new toolbar with your commands
25+
self.appendMenu("PythonWorkbenchTemplate", self.list) # creates a new menu
2526

2627
def Activated(self):
2728
"This function is executed when the workbench is activated"
@@ -34,10 +35,11 @@ def Deactivated(self):
3435
def ContextMenu(self, recipient):
3536
"This is executed whenever the user right-clicks on screen"
3637
# "recipient" will be either "view" or "tree"
37-
self.appendContextMenu("Curved Shapes", self.list) # add commands to the context menu
38+
self.appendContextMenu(self.__class__.MenuText, self.list) # add commands to the context menu
3839

3940
def GetClassName(self):
4041
# this function is mandatory if this is a full python workbench
4142
return "Gui::PythonWorkbench"
43+
4244

43-
Gui.addWorkbench(PythonWorkbenchTemplate())
45+
Gui.addWorkbench(PythonWorkbenchTemplate())

PythonWorkbenchTemplate.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# -*- coding: utf-8 -*-
2+
13
import os
24
import FreeCAD
35
from importlib import reload
@@ -12,12 +14,13 @@ def get_module_path():
1214

1315

1416
def makeFeature1(base = None, green = False):
15-
'''Python command to create a Feature1'''
16-
import Feature1
17-
reload(Feature1) # causes FreeCAD to reload Feature1.py every time a new Feature1 is created.
17+
'''Python command to create a Feature1.'''
18+
from Feature1 import Feature1
19+
reload(Feature1) # causes FreeCAD to reload Feature1.py every time a new Feature1 is created. Useful while developping the feature.
1820
fp = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Feature1")
1921
Feature1.Feature1Worker(fp, base, green)
20-
Feature1.Feature1ViewProvider(fp.ViewObject)
22+
vp = Feature1.Feature1ViewProvider(fp.ViewObject)
2123
FreeCAD.ActiveDocument.recompute()
24+
vp.setEdit(fp)
2225
return fp
2326

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ When you restart FreeCAD, "Python Workbench Template" workbench should now show
2525
- Edit InitGui.py. Delete Feature1 and add your new feature instead. Edit the \__title\__, \__author\__, \__url\__ and \__version\__ tags.
2626
- Write your new feature and test it well.
2727
- Write a documentation in README.md. Explain the purpose of your workbench. Explain your features. Screenshots are great.
28+
- Draw a .svg icon for the workbench and for each feature. You can export FreeCAD designs to .svg.
2829
- Announce your workbench in the [FreeCAD forum](https://forum.freecadweb.org/index.php). Add the link of your new thread in README.md
2930
- Add your workbench to the [Addon manager](https://github.com/FreeCAD/FreeCAD-addons)
3031

File renamed without changes.

0 commit comments

Comments
 (0)