File: ContainerPropertyProvider.py

package info (click to toggle)
uranium 5.0.0-9
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,328 kB
  • sloc: python: 31,765; sh: 132; makefile: 12
file content (169 lines) | stat: -rw-r--r-- 5,734 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# Copyright (c) 2022 Ultimaker B.V.
# Uranium is released under the terms of the LGPLv3 or higher.

from PyQt6.QtCore import QObject, pyqtProperty, pyqtSignal
from UM.FlameProfiler import pyqtSlot
from UM.Logger import Logger

from UM.Settings.SettingFunction import SettingFunction
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.SettingDefinition import SettingDefinition
from UM.Settings.DefinitionContainer import DefinitionContainer


class ContainerPropertyProvider(QObject):
    """This class provides the value and change notifications for the properties of a single setting

    This class provides the property values through QObject dynamic properties so that they
    are available from QML.
    """

    def __init__(self, parent = None):
        super().__init__(parent = parent)

        self._container_id = ""
        self._container = None
        self._key = ""
        self._watched_properties = []
        self._property_values = {}

    def setContainerId(self, container_id):
        """Set the containerId property."""

        if container_id == self._container_id:
            return # No change.

        self._container_id = container_id

        if self._container:
            self._container.propertyChanged.disconnect(self._onPropertyChanged)

        if self._container_id:
            containers = ContainerRegistry.getInstance().findContainers(id = self._container_id)
            if containers:
                self._container = containers[0]

            if self._container:
                self._container.propertyChanged.connect(self._onPropertyChanged)
        else:
            self._container = None

        self._update()
        self.containerIdChanged.emit()

    containerIdChanged = pyqtSignal()
    """Emitted when the containerId property changes."""
    @pyqtProperty(str, fset = setContainerId, notify = containerIdChanged)
    def containerId(self):
        """The ID of the container we should query for property values."""

        return self._container_id

    def setWatchedProperties(self, properties):
        """Set the watchedProperties property."""

        if properties != self._watched_properties:
            self._watched_properties = properties
            self._update()
            self.watchedPropertiesChanged.emit()

    watchedPropertiesChanged = pyqtSignal()
    """Emitted when the watchedProperties property changes."""

    @pyqtProperty("QVariantList", fset = setWatchedProperties, notify = watchedPropertiesChanged)
    def watchedProperties(self):
        """A list of property names that should be watched for changes."""

        return self._watched_properties

    def setKey(self, key):
        """Set the key property."""

        if key != self._key:
            self._key = key
            self._update()
            self.keyChanged.emit()

    keyChanged = pyqtSignal()
    """Emitted when the key property changes."""

    @pyqtProperty(str, fset = setKey, notify = keyChanged)
    def key(self):
        """The key of the setting that we should provide property values for."""

        return self._key

    propertiesChanged = pyqtSignal()

    @pyqtProperty("QVariantMap", notify = propertiesChanged)
    def properties(self):
        return self._property_values

    @pyqtSlot(str, "QVariant")
    def setPropertyValue(self, property_name, property_value):
        """Set the value of a property.

        :param property_name: The name of the property to set.
        :param property_value: The value of the property to set.
        """

        if not self._container or not self._key:
            return

        if ContainerRegistry.getInstance().isReadOnly(self._container_id):
            return

        if property_name not in self._watched_properties:
            Logger.log("w", "Tried to set a property that is not being watched")
            return

        if self._property_values[property_name] == property_value:
            return

        if isinstance(self._container, DefinitionContainer):
            return

        self._container.setProperty(self._key, property_name, property_value)

    # protected:

    def _onPropertyChanged(self, key, property_name):
        if key != self._key:
            return

        if property_name not in self._watched_properties:
            return
        value = self._getPropertyValue(property_name)

        if self._property_values.get(property_name, None) != value:
            self._property_values[property_name] = value
            self.propertiesChanged.emit()

    def _update(self, container = None):
        if not self._container or not self._watched_properties or not self._key:
            return

        new_properties = {}
        for property_name in self._watched_properties:
            new_properties[property_name] = self._getPropertyValue(property_name)

        if new_properties != self._property_values:
            self._property_values = new_properties
            self.propertiesChanged.emit()

    def _getPropertyValue(self, property_name: str) -> str:
        property_value = self._container.getProperty(self._key, property_name)
        if isinstance(property_value, SettingFunction):
            property_value = property_value(self._container)

        if property_name == "value":
            setting_type = self._container.getProperty(self._key, "type")
            if not setting_type:
                instance = self._container.getInstance(self._key)
                if instance:
                    setting_type = instance.definition.type

            if setting_type:
                property_value = SettingDefinition.settingValueToString(setting_type, property_value)

        return str(property_value)