Draft: new get_param function with defaults

This PR introduces a new get_param function. For its default values it checks a dictionary largely filled by reading the preferences UI files. The goal is to have all defaults in one place to avoid inconsistencies. The dictionary is created once and then stored in a global variable.

Once merged this function will be implemented in Draft and Arch. The get_param function in utils.py will become obsolete.

Related issue: #10176
This commit is contained in:
Roy-043
2023-12-07 11:18:22 +01:00
committed by Yorik van Havre
parent ac7a409d1d
commit 4262da5fc1

View File

@@ -21,17 +21,23 @@
# * *
# ***************************************************************************
""" Contains a parameter observer class and several related functions."""
""" Contains a parameter observer class and parameter related functions."""
import PySide.QtCore as QtCore
import xml.etree.ElementTree as ET
import FreeCAD as App
import FreeCADGui as Gui
from PySide import QtGui
import Draft_rc
import Arch_rc
from draftutils import init_draft_statusbar
from draftutils import utils
from draftutils.translate import translate
from draftviewproviders import view_base
if App.GuiUp:
import FreeCADGui as Gui
from PySide import QtGui
class ParamObserverDraft:
@@ -193,8 +199,9 @@ of existing objects in all opened documents?""")
def _param_observer_start():
_param_observer_start_draft()
_param_observer_start_view()
if App.GuiUp:
_param_observer_start_draft()
_param_observer_start_view()
def _param_observer_start_draft(param_grp = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")):
@@ -203,3 +210,331 @@ def _param_observer_start_draft(param_grp = App.ParamGet("User parameter:BaseApp
def _param_observer_start_view(param_grp = App.ParamGet("User parameter:BaseApp/Preferences/View")):
param_grp.AttachManager(ParamObserverView())
def _param_from_PrefCheckBox(widget):
value = False
for elem in list(widget):
if "name" in elem.keys():
att_name = elem.attrib["name"]
if att_name == "checked": # Can be missing.
value = elem.find("bool").text == "true"
elif att_name == "prefEntry":
entry = elem.find("cstring").text
elif att_name == "prefPath":
path = elem.find("cstring").text
return path, entry, value
def _param_from_PrefRadioButton(widget):
return _param_from_PrefCheckBox(widget)
def _param_from_PrefComboBox(widget):
value = 0
for elem in list(widget):
if "name" in elem.keys():
att_name = elem.attrib["name"]
if att_name == "currentIndex": # Can be missing.
value = int(elem.find("number").text)
elif att_name == "prefEntry":
entry = elem.find("cstring").text
elif att_name == "prefPath":
path = elem.find("cstring").text
return path, entry, value
def _param_from_PrefSpinBox(widget):
value = 0
for elem in list(widget):
if "name" in elem.keys():
att_name = elem.attrib["name"]
if att_name == "value": # Can be missing.
value = int(elem.find("number").text)
elif att_name == "prefEntry":
entry = elem.find("cstring").text
elif att_name == "prefPath":
path = elem.find("cstring").text
return path, entry, value
def _param_from_PrefDoubleSpinBox(widget):
value = 0.0
for elem in list(widget):
if "name" in elem.keys():
att_name = elem.attrib["name"]
if att_name == "value": # Can be missing.
value = float(elem.find("double").text)
elif att_name == "prefEntry":
entry = elem.find("cstring").text
elif att_name == "prefPath":
path = elem.find("cstring").text
return path, entry, value
def _param_from_PrefUnitSpinBox(widget):
return _param_from_PrefDoubleSpinBox(widget)
def _param_from_PrefQuantitySpinBox(widget):
value = "0"
for elem in list(widget):
if "name" in elem.keys():
att_name = elem.attrib["name"]
if att_name == "rawValue": # Not sure if this can be missing.
value = elem.find("double").text.rstrip(".0")
elif att_name == "unit":
unit = elem.find("string").text
elif att_name == "prefEntry":
entry = elem.find("cstring").text
elif att_name == "prefPath":
path = elem.find("cstring").text
value = value + " " + unit
return path, entry, value
def _param_from_PrefColorButton(widget):
for elem in list(widget):
if "name" in elem.keys():
att_name = elem.attrib["name"]
if att_name == "color":
sub = list(elem)[0]
r = int(sub.find("red").text)
g = int(sub.find("green").text)
b = int(sub.find("blue").text)
elif att_name == "prefEntry":
entry = elem.find("cstring").text
elif att_name == "prefPath":
path = elem.find("cstring").text
value = (r << 24) + (g << 16) + (b << 8) + 255
return path, entry, value
def _param_from_PrefLineEdit(widget):
value = None
for elem in list(widget):
if "name" in elem.keys():
att_name = elem.attrib["name"]
if att_name == "text": # Can be missing.
value = elem.find("string").text # If text is missing value will be None here.
elif att_name == "prefEntry":
entry = elem.find("cstring").text
elif att_name == "prefPath":
path = elem.find("cstring").text
if value is None:
value = ""
return path, entry, value
def _param_from_PrefFileChooser(widget):
for elem in list(widget):
if "name" in elem.keys():
att_name = elem.attrib["name"]
if att_name == "prefEntry":
entry = elem.find("cstring").text
elif att_name == "prefPath":
path = elem.find("cstring").text
return path, entry, ""
def _get_param_dictionary():
# print("Creating preferences dictionary...")
param_dict = {}
# Draft parameters that are not in the preferences:
param_dict["Mod/Draft"] = {
"DefaultAnnoDisplayMode": ("int", 0),
"DefaultDisplayMode": ("int", 0),
"DefaultDrawStyle": ("int", 0),
"Draft_array_fuse": ("bool", False),
"Draft_array_Link": ("bool", True),
"fillmode": ("bool", True),
"HatchPatternResolution": ("int", 128),
"labeltype": ("string", "Custom"),
"snapModes": ("string", "100000000000000"),
"snapRange": ("int", 8),
}
# Arch parameters that are not in the preferences:
param_dict["Mod/Arch"] = {
}
# For the View parameters we do not check the preferences:
param_dict["View"] = {
"DefaultShapeColor": ("unsigned", 3435973887),
"DefaultShapeLineColor": ("unsigned", 255),
"DefaultShapeLineWidth": ("int", 2),
"DefaultShapePointSize": ("int", 2),
"DefaultShapeTransparency": ("int", 0),
"DefaultShapeVertexColor": ("unsigned", 255),
}
# Preferences ui files are stored in resource files.
# For the Draft Workbench: /Mod/Draft/Draft_rc.py
# For the Arch Workbench: /Mod/Arch/Arch_rc.py
for fnm in (":/ui/preferences-draft.ui",
":/ui/preferences-draftinterface.ui",
":/ui/preferences-draftsnap.ui",
":/ui/preferences-drafttexts.ui",
":/ui/preferences-draftvisual.ui",
":/ui/preferences-dwg.ui",
":/ui/preferences-dxf.ui",
":/ui/preferences-oca.ui",
":/ui/preferences-svg.ui",
":/ui/preferences-arch.ui",
":/ui/preferences-archdefaults.ui",
":/ui/preferences-dae.ui",
":/ui/preferences-ifc.ui",
":/ui/preferences-ifc-export.ui"):
# https://stackoverflow.com/questions/14750997/load-txt-file-from-resources-in-python
fd = QtCore.QFile(fnm)
if fd.open(QtCore.QIODevice.ReadOnly | QtCore.QFile.Text):
text = QtCore.QTextStream(fd).readAll()
fd.close()
else:
print("Preferences file " + fnm + " not found")
continue
# https://docs.python.org/3/library/xml.etree.elementtree.html
root = ET.fromstring(text)
# Get all preference widgets:
# pref_widgets = [wid for wid in root.iter("widget") if "Gui::Pref" in wid.attrib["class"]]
for widget in root.iter("widget"):
if "class" in widget.keys():
path = None
att_class = widget.attrib["class"]
if att_class == "Gui::PrefCheckBox":
path, entry, value = _param_from_PrefCheckBox(widget)
typ = "bool"
elif att_class == "Gui::PrefRadioButton":
path, entry, value = _param_from_PrefRadioButton(widget)
typ = "bool"
elif att_class == "Gui::PrefComboBox":
path, entry, value = _param_from_PrefComboBox(widget)
typ = "int"
elif att_class == "Gui::PrefSpinBox":
path, entry, value = _param_from_PrefSpinBox(widget)
typ = "int"
elif att_class == "Gui::PrefDoubleSpinBox":
path, entry, value = _param_from_PrefDoubleSpinBox(widget)
typ = "float"
elif att_class == "Gui::PrefUnitSpinBox":
path, entry, value = _param_from_PrefUnitSpinBox(widget)
typ = "float"
elif att_class == "Gui::PrefQuantitySpinBox":
path, entry, value = _param_from_PrefQuantitySpinBox(widget)
typ = "string"
elif att_class == "Gui::PrefColorButton":
path, entry, value = _param_from_PrefColorButton(widget)
typ = "unsigned"
elif att_class == "Gui::PrefLineEdit":
path, entry, value = _param_from_PrefLineEdit(widget)
typ = "string"
elif att_class == "Gui::PrefFileChooser":
path, entry, value = _param_from_PrefFileChooser(widget)
typ = "string"
if path is not None:
if path in param_dict:
param_dict[path][entry] = (typ, value)
else:
param_dict[path] = {entry: (typ, value)}
return param_dict
PARAM_DICT = _get_param_dictionary()
# get_param("gridSpacing")
def get_param(entry, path="Mod/Draft"):
"""Return a stored parameter value or its default.
Parameters
----------
entry: str
Name of the parameter.
path: str, optional
Defaults to "Mod/Draft".
The path where the parameter can be found.
This string is appended to "User parameter:BaseApp/Preferences/".
Returns
-------
bool, float, int or str (if successful) or `None`.
"""
if path not in PARAM_DICT:
return None
if entry not in PARAM_DICT[path]:
return None
param = App.ParamGet("User parameter:BaseApp/Preferences/" + path)
typ, default = PARAM_DICT[path][entry]
if typ == "bool":
return param.GetBool(entry, default)
if typ == "float":
return param.GetFloat(entry, default)
if typ == "int":
return param.GetInt(entry, default)
if typ == "string":
return param.GetString(entry, default)
if typ == "unsigned":
return param.GetUnsigned(entry, default)
return None
def get_param_arch(entry):
return get_param(entry, path="Mod/Arch")
def set_param(entry, value, path="Mod/Draft"):
"""Store a parameter value.
Parameters
----------
entry: str
Name of the parameter.
value: bool, float, int or str
New value of the correct type.
path: str, optional
Defaults to "Mod/Draft".
The path where the parameter can be found.
This string is appended to "User parameter:BaseApp/Preferences/".
Returns
-------
`True` (if successful) or `False`.
"""
if path not in PARAM_DICT:
return False
if entry not in PARAM_DICT[path]:
return False
param = App.ParamGet("User parameter:BaseApp/Preferences/" + path)
typ = PARAM_DICT[path][entry][0]
ret = True
if typ == "bool":
param.SetBool(entry, value)
elif typ == "float":
param.SetFloat(entry, value)
elif typ == "int":
param.SetInt(entry, value)
elif typ == "string":
param.SetString(entry, value)
elif typ == "unsigned":
param.SetUnsigned(entry, value)
else:
ret = False
return ret
def set_param_arch(entry, value):
return set_param(entry, value, path="Mod/Arch")