diff --git a/src/Mod/Draft/draftutils/params.py b/src/Mod/Draft/draftutils/params.py index a8427953ed..4e87e24caa 100644 --- a/src/Mod/Draft/draftutils/params.py +++ b/src/Mod/Draft/draftutils/params.py @@ -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")