<commit_before>
import re

from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
from UM.Application import Application
from UM.Preferences import Preferences
from UM.Logger import Logger

import UM.Settings
from UM.Settings.Validator import ValidatorState
from UM.Settings.InstanceContainer import InstanceContainer


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

        self._global_container_stack = None
        Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
        self._onGlobalContainerChanged()

        ##  When the global container is changed, active material probably needs to be updated.
        self.globalContainerChanged.connect(self.activeMaterialChanged)
        self.globalContainerChanged.connect(self.activeVariantChanged)
        self.globalContainerChanged.connect(self.activeQualityChanged)

        self._empty_variant_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_variant")[0]
        self._empty_material_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_material")[0]
        self._empty_quality_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality")[0]

        Preferences.getInstance().addPreference("cura/active_machine", "")

        active_machine_id = Preferences.getInstance().getValue("cura/active_machine")

        if active_machine_id != "":
            # An active machine was saved, so restore it.
            self.setActiveMachine(active_machine_id)
            pass


    globalContainerChanged = pyqtSignal()
    activeMaterialChanged = pyqtSignal()
    activeVariantChanged = pyqtSignal()
    activeQualityChanged = pyqtSignal()

    globalValueChanged = pyqtSignal()  # Emitted whenever a property inside global container is changed.

    def _onGlobalPropertyChanged(self, key, property_name):
        if property_name == "value":
            self.globalValueChanged.emit()

    def _onGlobalContainerChanged(self):
        if self._global_container_stack:
            self._global_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged)
            self._global_container_stack.propertyChanged.disconnect(self._onGlobalPropertyChanged)

        self._global_container_stack = Application.getInstance().getGlobalContainerStack()
        self.globalContainerChanged.emit()

        if self._global_container_stack:
            Preferences.getInstance().setValue("cura/active_machine", self._global_container_stack.getId())
            self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged)
            self._global_container_stack.propertyChanged.connect(self._onGlobalPropertyChanged)

    def _onInstanceContainersChanged(self, container):
        container_type = container.getMetaDataEntry("type")
        if container_type == "material":
            self.activeMaterialChanged.emit()
        elif container_type == "variant":
            self.activeVariantChanged.emit()
        elif container_type == "quality":
            self.activeQualityChanged.emit()

    @pyqtSlot(str)
    def setActiveMachine(self, stack_id):
        containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = stack_id)
        if containers:
            Application.getInstance().setGlobalContainerStack(containers[0])

    @pyqtSlot(str, str)
    def addMachine(self,name, definition_id):
        definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id=definition_id)
        if definitions:
            definition = definitions[0]
            name = self._createUniqueStackName(name, definition.getName())

            new_global_stack = UM.Settings.ContainerStack(name)
            new_global_stack.addMetaDataEntry("type", "machine")
            UM.Settings.ContainerRegistry.getInstance().addContainer(new_global_stack)

            variant_instance_container = self._empty_variant_container
            if definition.getMetaDataEntry("has_variants"):
                variant_instance_container = self._getPreferredContainer(definition, "preferred_variant", self._empty_variant_container)

                if variant_instance_container == self._empty_variant_container:
                    variants = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id)
                    if variants:
                        variant_instance_container = variants[0]

                if variant_instance_container == self._empty_variant_container:
                    Logger.log("w", "Machine %s defines it has variants but no variants found", definition.id)

            material_instance_container = self._empty_material_container
            if definition.getMetaDataEntry("has_materials"):
                material_instance_container = self._getPreferredContainer(definition, "preferred_material", self._empty_material_container)

                if material_instance_container == self._empty_material_container:
                    materials = None
                    if definition.getMetaDataEntry("has_machine_materials"):
                        if variant_instance_container != self._empty_material_container:
                            materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = definition.id, variant = variant_instance_container.id)
                        else:
                            materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = definition.id)
                    else:
                        materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = "fdmprinter")

                    if materials:
                        material_instance_container = materials[0]

                if material_instance_container == self._empty_material_container:
                    Logger.log("w", "Machine %s defines it has materials but no matererials found", definition.id)

            quality_instance_container = self._getPreferredContainer(definition, "preferred_quality", self._empty_quality_container)
            if quality_instance_container == self._empty_quality_container:
                if definition.getMetaDataEntry("has_machine_quality"):
                    if material_instance_container:
                        qualities = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "quality", definition = definition.id, material = material_instance_container.id)
                    else:
                        qualities = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "quality", definition = definition.id)
                else:
                    qualities = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "quality", definition = "fdmprinter")

                if qualities:
                    quality_instance_container = qualities[0]

            current_settings_instance_container = UM.Settings.InstanceContainer(name + "_current_settings")
            current_settings_instance_container.addMetaDataEntry("machine", name)
            current_settings_instance_container.addMetaDataEntry("type", "user")
            current_settings_instance_container.setDefinition(definitions[0])
            UM.Settings.ContainerRegistry.getInstance().addContainer(current_settings_instance_container)

            # If a definition is found, its a list. Should only have one item.
            new_global_stack.addContainer(definitions[0])
            if variant_instance_container:
                new_global_stack.addContainer(variant_instance_container)
            if material_instance_container:
                new_global_stack.addContainer(material_instance_container)
            if quality_instance_container:
                new_global_stack.addContainer(quality_instance_container)
            new_global_stack.addContainer(current_settings_instance_container)

            Application.getInstance().setGlobalContainerStack(new_global_stack)

    # Create a name that is not empty and unique
    def _createUniqueStackName(self, name, fallback_name):
        name = name.strip()
        num_check = re.compile("(.*?)\s*#\d$").match(name)
        if(num_check):
            name = num_check.group(1)
        if name == "":
            name = fallback_name
        unique_name = name
        i = 1

        # Check both the id and the name, because they may not be the same and it is better if they are both unique
        while UM.Settings.ContainerRegistry.getInstance().findContainers(None, id = unique_name) or \
                UM.Settings.ContainerRegistry.getInstance().findContainers(None, name = unique_name):
            i += 1
            unique_name = "%s #%d" % (name, i)

        return unique_name

    ##  Convenience function to check if a stack has errors.
    def _checkStackForErrors(self, stack):
        if stack is None:
            return False

        for key in stack.getAllKeys():
            validation_state = stack.getProperty(key, "validationState")
            if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
                return True
        return False

    @pyqtSlot()
    def clearUserSettings(self):
        if not self._global_container_stack:
            return
        user_settings = self._global_container_stack.getTop()
        user_settings.clear()

    @pyqtProperty(bool, notify = globalValueChanged)
    def hasUserSettings(self):
        if not self._global_container_stack:
            return

        user_settings = self._global_container_stack.getTop().findInstances(**{})
        return len(user_settings) != 0

    @pyqtProperty(bool, notify = globalValueChanged)
    def isGlobalStackValid(self):
        return not self._checkStackForErrors(self._global_container_stack)

    @pyqtProperty(str, notify = globalContainerChanged)<commit_msg>Added signal for validation state<commit_after>
import re

from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
from UM.Application import Application
from UM.Preferences import Preferences
from UM.Logger import Logger

import UM.Settings
from UM.Settings.Validator import ValidatorState
from UM.Settings.InstanceContainer import InstanceContainer


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

        self._global_container_stack = None
        Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
        self._onGlobalContainerChanged()

        ##  When the global container is changed, active material probably needs to be updated.
        self.globalContainerChanged.connect(self.activeMaterialChanged)
        self.globalContainerChanged.connect(self.activeVariantChanged)
        self.globalContainerChanged.connect(self.activeQualityChanged)

        self._empty_variant_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_variant")[0]
        self._empty_material_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_material")[0]
        self._empty_quality_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality")[0]

        Preferences.getInstance().addPreference("cura/active_machine", "")

        active_machine_id = Preferences.getInstance().getValue("cura/active_machine")

        if active_machine_id != "":
            # An active machine was saved, so restore it.
            self.setActiveMachine(active_machine_id)
            pass


    globalContainerChanged = pyqtSignal()
    activeMaterialChanged = pyqtSignal()
    activeVariantChanged = pyqtSignal()
    activeQualityChanged = pyqtSignal()

    globalValueChanged = pyqtSignal()  # Emitted whenever a value inside global container is changed.
    globalValidationChanged = pyqtSignal()  # Emitted whenever a validation inside global container is changed.

    def _onGlobalPropertyChanged(self, key, property_name):
        if property_name == "value":
            self.globalValueChanged.emit()
        if property_name == "validationState":
            self.globalValidationChanged.emit()

    def _onGlobalContainerChanged(self):
        if self._global_container_stack:
            self._global_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged)
            self._global_container_stack.propertyChanged.disconnect(self._onGlobalPropertyChanged)

        self._global_container_stack = Application.getInstance().getGlobalContainerStack()
        self.globalContainerChanged.emit()

        if self._global_container_stack:
            Preferences.getInstance().setValue("cura/active_machine", self._global_container_stack.getId())
            self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged)
            self._global_container_stack.propertyChanged.connect(self._onGlobalPropertyChanged)

    def _onInstanceContainersChanged(self, container):
        container_type = container.getMetaDataEntry("type")
        if container_type == "material":
            self.activeMaterialChanged.emit()
        elif container_type == "variant":
            self.activeVariantChanged.emit()
        elif container_type == "quality":
            self.activeQualityChanged.emit()

    @pyqtSlot(str)
    def setActiveMachine(self, stack_id):
        containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = stack_id)
        if containers:
            Application.getInstance().setGlobalContainerStack(containers[0])

    @pyqtSlot(str, str)
    def addMachine(self,name, definition_id):
        definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id=definition_id)
        if definitions:
            definition = definitions[0]
            name = self._createUniqueStackName(name, definition.getName())

            new_global_stack = UM.Settings.ContainerStack(name)
            new_global_stack.addMetaDataEntry("type", "machine")
            UM.Settings.ContainerRegistry.getInstance().addContainer(new_global_stack)

            variant_instance_container = self._empty_variant_container
            if definition.getMetaDataEntry("has_variants"):
                variant_instance_container = self._getPreferredContainer(definition, "preferred_variant", self._empty_variant_container)

                if variant_instance_container == self._empty_variant_container:
                    variants = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id)
                    if variants:
                        variant_instance_container = variants[0]

                if variant_instance_container == self._empty_variant_container:
                    Logger.log("w", "Machine %s defines it has variants but no variants found", definition.id)

            material_instance_container = self._empty_material_container
            if definition.getMetaDataEntry("has_materials"):
                material_instance_container = self._getPreferredContainer(definition, "preferred_material", self._empty_material_container)

                if material_instance_container == self._empty_material_container:
                    materials = None
                    if definition.getMetaDataEntry("has_machine_materials"):
                        if variant_instance_container != self._empty_material_container:
                            materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = definition.id, variant = variant_instance_container.id)
                        else:
                            materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = definition.id)
                    else:
                        materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = "fdmprinter")

                    if materials:
                        material_instance_container = materials[0]

                if material_instance_container == self._empty_material_container:
                    Logger.log("w", "Machine %s defines it has materials but no matererials found", definition.id)

            quality_instance_container = self._getPreferredContainer(definition, "preferred_quality", self._empty_quality_container)
            if quality_instance_container == self._empty_quality_container:
                if definition.getMetaDataEntry("has_machine_quality"):
                    if material_instance_container:
                        qualities = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "quality", definition = definition.id, material = material_instance_container.id)
                    else:
                        qualities = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "quality", definition = definition.id)
                else:
                    qualities = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "quality", definition = "fdmprinter")

                if qualities:
                    quality_instance_container = qualities[0]

            current_settings_instance_container = UM.Settings.InstanceContainer(name + "_current_settings")
            current_settings_instance_container.addMetaDataEntry("machine", name)
            current_settings_instance_container.addMetaDataEntry("type", "user")
            current_settings_instance_container.setDefinition(definitions[0])
            UM.Settings.ContainerRegistry.getInstance().addContainer(current_settings_instance_container)

            # If a definition is found, its a list. Should only have one item.
            new_global_stack.addContainer(definitions[0])
            if variant_instance_container:
                new_global_stack.addContainer(variant_instance_container)
            if material_instance_container:
                new_global_stack.addContainer(material_instance_container)
            if quality_instance_container:
                new_global_stack.addContainer(quality_instance_container)
            new_global_stack.addContainer(current_settings_instance_container)

            Application.getInstance().setGlobalContainerStack(new_global_stack)

    # Create a name that is not empty and unique
    def _createUniqueStackName(self, name, fallback_name):
        name = name.strip()
        num_check = re.compile("(.*?)\s*#\d$").match(name)
        if(num_check):
            name = num_check.group(1)
        if name == "":
            name = fallback_name
        unique_name = name
        i = 1

        # Check both the id and the name, because they may not be the same and it is better if they are both unique
        while UM.Settings.ContainerRegistry.getInstance().findContainers(None, id = unique_name) or \
                UM.Settings.ContainerRegistry.getInstance().findContainers(None, name = unique_name):
            i += 1
            unique_name = "%s #%d" % (name, i)

        return unique_name

    ##  Convenience function to check if a stack has errors.
    def _checkStackForErrors(self, stack):
        if stack is None:
            return False

        for key in stack.getAllKeys():
            validation_state = stack.getProperty(key, "validationState")
            if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
                return True
        return False

    @pyqtSlot()
    def clearUserSettings(self):
        if not self._global_container_stack:
            return
        user_settings = self._global_container_stack.getTop()
        user_settings.clear()

    @pyqtProperty(bool, notify = globalValueChanged)
    def hasUserSettings(self):
        if not self._global_container_stack:
            return

        user_settings = self._global_container_stack.getTop().findInstances(**{})
        return len(user_settings) != 0

    @pyqtProperty(bool, notify = globalValidationChanged)
    def isGlobalStackValid(self):
        return not self._checkStackForErrors(self._global_container_stack)

    @pyqtProperty(str, notify = globalContainerChanged)
{'fraction_non_alphanumeric': 0.07858146407635289, 'fraction_numerical': 0.0014534179545564654, 'mean_word_length': 3.062586105097422, 'pattern_counts': {'":': 13, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4198077', 'n_tokens_mistral': 5025, 'n_tokens_neox': 4839, 'n_words': 954}