from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
import UM.Settings
from UM.Signal import signalemitter
from UM.Application import Application
import cura.Settings

class SettingInheritanceManager(QObject):
    def __init__(self, parent = None):
        super().__init__(parent)
        Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
        self._global_container_stack = None
        self._onGlobalContainerChanged()

        self._active_container_stack = None
        cura.Settings.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
        self._onActiveExtruderChanged()

        self._settings_with_inheritance_warning = []

    settingsWithIntheritanceChanged = pyqtSignal()

    @pyqtSlot()
    def test(self):
        pass

    def _onActiveExtruderChanged(self):
        if self._active_container_stack:
            self._active_container_stack.propertyChanged.disconnect(self._onPropertyChanged)

        new_active_stack = cura.Settings.ExtruderManager.getInstance().getActiveExtruderStack()
        if not new_active_stack:
            new_active_stack = self._global_container_stack

        if new_active_stack != self._active_container_stack:
            # Check if changed
            self._active_container_stack = new_active_stack
            self._update()  # Ensure that the settings_with_inheritance_warning list is populated.
            self._active_container_stack.propertyChanged.connect(self._onPropertyChanged)

    def _onPropertyChanged(self, key, property_name):
        if property_name == "value" and self._global_container_stack:

            definitions = self._global_container_stack.getBottom().findDefinitions(key = key)
            if not definitions:
                return

            has_overwritten_inheritance = self._settingIsOverwritingInheritance(key)

            settings_with_inheritance_warning_changed = False

            # Check if the setting needs to be in the list.
            if key not in self._settings_with_inheritance_warning and has_overwritten_inheritance:
                self._settings_with_inheritance_warning.append(key)
                settings_with_inheritance_warning_changed = True
            elif key in self._settings_with_inheritance_warning and not has_overwritten_inheritance:
                self._settings_with_inheritance_warning.remove(key)
                settings_with_inheritance_warning_changed = True

            # Find the topmost parent & add that to the list as well
            parent = definitions[0].parent
            while parent.parent is not None:
                parent = parent.parent

            if parent.key not in self._settings_with_inheritance_warning and has_overwritten_inheritance:
                self._settings_with_inheritance_warning.append(parent.key)
                settings_with_inheritance_warning_changed = True

            elif parent.key in self._settings_with_inheritance_warning and not has_overwritten_inheritance:
                if not self._recursiveCheck(parent):
                    self._settings_with_inheritance_warning.remove(parent.key)
                    settings_with_inheritance_warning_changed = True

            # Emit the signal if there was any change to the list.
            if settings_with_inheritance_warning_changed:
                self.settingsWithIntheritanceChanged.emit()

    def _recursiveCheck(self, definition):
        for child in definition.children:
            if child.key in self._settings_with_inheritance_warning:
                return True
            if child.children:
                if self._recursiveCheck(child):
                    return True
        return False


    @pyqtProperty("QVariantList", notify = settingsWithIntheritanceChanged)
    def settingsWithInheritanceWarning(self):
        return self._settings_with_inheritance_warning

    # Check if a setting is being overwritten.
    def _settingIsOverwritingInheritance(self, key):
        has_setting_function = False
        stack = self._active_container_stack
        containers = []

        has_user_state = self._active_container_stack.getProperty(key, "state") == UM.Settings.InstanceState.User
        if not has_user_state:
            return False
        while stack:
            containers.extend(stack.getContainers())
            stack = stack.getNextStack()

        for container in containers:
            try:
                has_setting_function = isinstance(container.getProperty(key, "value"), UM.Settings.SettingFunction)
            except AttributeError:
                continue
            if has_setting_function:
                break
        return has_setting_function and not isinstance(self._active_container_stack.getTop().getProperty(key, "value"), UM.Settings.SettingFunction)

    def _update(self):
        self._settings_with_inheritance_warning = []
        for setting_key in self._global_container_stack.getAllKeys():
            override = self._settingIsOverwritingInheritance(setting_key)
            if override:
                self._settings_with_inheritance_warning.append(setting_key)
            definitions = self._global_container_stack.getBottom().findDefinitions(key=setting_key)
            parent = definitions[0].parent
            if parent is not None and override:
                while parent.parent is not None:
                    parent = parent.parent
                # Add the topmost container as well (if this wasn't already the case)
                if parent.key not in self._settings_with_inheritance_warning:
                    self._settings_with_inheritance_warning.append(parent.key)
        self.settingsWithIntheritanceChanged.emit()

    def _onGlobalContainerChanged(self):
        self._global_container_stack = Application.getInstance().getGlobalContainerStack()

    @staticmethod
    def createSettingInheritanceManager(engine=None, script_engine=None):
        return SettingInheritanceManager()
@@ -471,32 +471,84 @@
 tainerChanged()%0A
+        self._settings_with_inheritance_warning = %5B%5D
 %0A        self._a
@@ -734,60 +734,8 @@
 ()%0A%0A
-        self._settings_with_inheritance_warning = %5B%5D
 %0A%0A  
@@ -1537,24 +1537,25 @@
 tyChanged)%0A%0A
+%0A
     def _onP

Change order of initialisation, so we don't overwrite list with empty data