Enumerate Property
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
-
- Veteran
- Posts: 2764
- Joined: Mon Feb 27, 2012 5:31 pm
Enumerate Property
I have an enumerate property which can have about 50-60 different values, ideally I would like to split the list into sub lists.
i.e. When a user selects such a property, instead of being offered a list of 50-60 values they are offered say 5 and depending on which one
of the five is selected a list of around 10 values are offered.
Is this possible? or do I need to create a feature request?
i.e. When a user selects such a property, instead of being offered a list of 50-60 values they are offered say 5 and depending on which one
of the five is selected a list of around 10 values are offered.
Is this possible? or do I need to create a feature request?
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: Enumerate Property
Possibly you could populate it based on the selection with a "back" option at the top to get back to the previous level.
Or you could have 2 enumerate properties and populate the 2nd one based on the selection in the first.
Or you could have 2 enumerate properties and populate the 2nd one based on the selection in the first.
-
- Veteran
- Posts: 2764
- Joined: Mon Feb 27, 2012 5:31 pm
Re: Enumerate Property
But how do you code it?TheMarkster wrote: ↑Tue Jan 25, 2022 1:19 am Possibly you could populate it based on the selection with a "back" option at the top to get back to the previous level.
Or you could have 2 enumerate properties and populate the 2nd one based on the selection in the first.
You add Objects properties with calls like obj.addProperty("App::PropertyFloat", "Length")
and enumeration is one property type https://wiki.freecadweb.org/Property
But I don't know of any way to control how FreeCAD handles a Property, like there is no call back function that I am aware of.
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: Enumerate Property
I'm thinking you have the top level items in the enumeration to start with:
All of this is untested. It might cause some infinite loop or some other problem to change the enumeration during onChanged(). If that happens you might be able to set some flag such as bHandlingEnumeration and set it to True when changing the enumeration.
Code: Select all
obj.addProperty("App::PropertyEnumeration", "Enum").Enum = ["A", "B", "C"]
def onChanged(self, fp, prop):
if prop == "Enum":
if fp.Enum == "A":
fp.Enum = ["Back", "Apple", "Artichoke"]
elif fp.Enum == "B":
fp.Enum = ["Back", "Banana", "Belgium Waffle"]
elif fp.Enum == "C":
fp.Enum = ["Back", "Cranberries", "Custard", "Cucumbers"]
elif fp.Enum == "Back":
fp.Enum = ["A", "B", "C"]
else:
self.handleEnum(fp, prop) #in here you would test for the various menu options, all of which should be unique
#or you might deal with the Enum value in execute(self, fp) instead.
Code: Select all
if prop == "Enum" and not self.bHandlingEnumeration:
if fp.Enum == "A":
self.bHandlingEnumeration = True
fp.Enum = ["Back", "Apple", "Artichoke"]
self.bHandlingEnumeration = False
-
- Veteran
- Posts: 2764
- Joined: Mon Feb 27, 2012 5:31 pm
Re: Enumerate Property
No loop but when I select B it just displays the letter B and not 'Back' etc.TheMarkster wrote: ↑Tue Jan 25, 2022 6:52 pm I'm thinking you have the top level items in the enumeration to start with:
All of this is untested. It might cause some infinite loop or some other problem to change the enumeration during onChanged(). If that happens you might be able to set some flag such as bHandlingEnumeration and set it to True when changing the enumeration.Code: Select all
obj.addProperty("App::PropertyEnumeration", "Enum").Enum = ["A", "B", "C"] def onChanged(self, fp, prop): if prop == "Enum": if fp.Enum == "A": fp.Enum = ["Back", "Apple", "Artichoke"] elif fp.Enum == "B": fp.Enum = ["Back", "Banana", "Belgium Waffle"] elif fp.Enum == "C": fp.Enum = ["Back", "Cranberries", "Custard", "Cucumbers"] elif fp.Enum == "Back": fp.Enum = ["A", "B", "C"] else: self.handleEnum(fp, prop) #in here you would test for the various menu options, all of which should be unique #or you might deal with the Enum value in execute(self, fp) instead.
Code: Select all
if prop == "Enum" and not self.bHandlingEnumeration: if fp.Enum == "A": self.bHandlingEnumeration = True fp.Enum = ["Back", "Apple", "Artichoke"] self.bHandlingEnumeration = False
The value has changed as a subsequent change gives
20:51:17 <Exception> 'C' is not part of the enumeration
Needs some call to refresh the property window
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: Enumerate Property
This works somewhat, but you need to click away and click back to see the updated items.
Code: Select all
class Enums:
def __init__(self,obj):
obj.addProperty("App::PropertyEnumeration","Enum").Enum=["Select One","A","B","C"]
obj.Proxy = self
self.bIsHandlingEnumeration = False
def onChanged(self, fp, prop):
if prop == "Enum" and not self.bIsHandlingEnumeration:
self.bIsHandlingEnumeration = True
current = getattr(fp,"Enum")
if current == "A":
fp.Enum = ["Back", "Apple", "Apricot"]
fp.Enum = "Apple"
self.bIsHandlingEnumeration = False
elif current == "B":
fp.Enum = ["Back", "Banana", "Blackberry"]
fp.Enum = "Banana"
self.bIsHandlingEnumeration = False
elif current == "C":
fp.Enum = ["Back", "Carrots", "Cabbage", "Cinnamon Rolls"]
fp.Enum = "Carrots"
self.bIsHandlingEnumeration = False
elif current == "Back":
fp.Enum = ["Select One","A","B","C"]
self.bIsHandlingEnumeration = False
else:
self.bIsHandlingEnumeration = False
enum = FreeCAD.ActiveDocument.addObject("App::FeaturePython","FP")
Enums(enum)
FreeCAD.ActiveDocument.recompute()
-
- Veteran
- Posts: 2764
- Joined: Mon Feb 27, 2012 5:31 pm
Re: Enumerate Property
Mmmh Close but no cigarTheMarkster wrote: ↑Wed Jan 26, 2022 12:11 am This works somewhat, but you need to click away and click back to see the updated items.
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: Enumerate Property
It could be possible with Qt to set the focus away and then back to the tree widget to make the update happen, maybe with a singleShot a few milliseconds after finishing in onChanged(). I also didn't try Gui.updateGui(). There might be a way to force a property update before it loses focus, too, but I don't know it. Another option could be to have 2 separate Enums, one with the top level "A, B, C" options and the other with the lower level "Apple, Artichoke" options. Or just put all the options in a single enumeration, perhaps with some leading spaces to distinguish the sublevels.
-
- Veteran
- Posts: 2764
- Joined: Mon Feb 27, 2012 5:31 pm
Re: Enumerate Property
TheMarkster wrote: ↑Wed Jan 26, 2022 4:58 pm It could be possible with Qt to set the focus away and then back to the tree widget to make the update happen, maybe with a singleShot a few milliseconds after finishing in onChanged(). I also didn't try Gui.updateGui(). There might be a way to force a property update before it loses focus, too, but I don't know it. Another option could be to have 2 separate Enums, one with the top level "A, B, C" options and the other with the lower level "Apple, Artichoke" options. Or just put all the options in a single enumeration, perhaps with some leading spaces to distinguish the sublevels.
- Tried Gui.updateGui()
- did not work, change anything. - single enumeration, perhaps with some leading spaces to distinguish the sublevels.
- Does not address the problem that the list is too long to scroll through
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: Enumerate Property
This hack sets the focus to the report view and back to the tree view in a singleShot()
Code: Select all
from PySide import QtCore, QtGui
class Enums:
def __init__(self,obj):
obj.addProperty("App::PropertyEnumeration","Enum").Enum=["Select One","A","B","C"]
obj.Proxy = self
self.bIsHandlingEnumeration = False
def onChanged(self, fp, prop):
if prop == "Enum" and not self.bIsHandlingEnumeration:
self.bIsHandlingEnumeration = True
current = getattr(fp,"Enum")
if current == "A":
fp.Enum = ["Back", "Apple", "Apricot"]
fp.Enum = "Apple"
self.bIsHandlingEnumeration = False
elif current == "B":
fp.Enum = ["Back", "Banana", "Blackberry"]
fp.Enum = "Banana"
self.bIsHandlingEnumeration = False
elif current == "C":
fp.Enum = ["Back", "Carrots", "Cabbage", "Cinnamon Rolls"]
fp.Enum = "Carrots"
self.bIsHandlingEnumeration = False
elif current == "Back":
fp.Enum = ["Select One","A","B","C"]
self.bIsHandlingEnumeration = False
else:
self.bIsHandlingEnumeration = False
t = QtCore.QTimer()
t.singleShot(50, self.focusTree)
def focusTree(self):
rv = Gui.getMainWindow().findChild(QtGui.QTextEdit, "Report view")
trees = Gui.getMainWindow().findChildren(QtGui.QTreeWidget)
if trees:
tree = trees[0]
rv.setFocus()
tree.setFocus()
enum = FreeCAD.ActiveDocument.addObject("App::FeaturePython","FP")
Enums(enum)
FreeCAD.ActiveDocument.recompute()