Merge branch 'main' into CURA-9514_collapsable_printers_list

This commit is contained in:
joeydelarago 2022-08-23 10:07:27 +02:00
commit d1ae3136aa
10 changed files with 126 additions and 13 deletions

View File

@ -135,6 +135,9 @@ jobs:
user = "_" user = "_"
channel = "_" channel = "_"
else: else:
if latest_branch_version.prerelease and not "." in latest_branch_version.prerelease:
# The prerealese did not contain a version number, default it to 1
latest_branch_version.prerelease += ".1"
if event_name == "pull_request": if event_name == "pull_request":
actual_version = f"{latest_branch_version.major}.{latest_branch_version.minor}.{latest_branch_version.patch}-{latest_branch_version.prerelease.lower()}+{buildmetadata}pr_{issue_number}_{no_commits}" actual_version = f"{latest_branch_version.major}.{latest_branch_version.minor}.{latest_branch_version.patch}-{latest_branch_version.prerelease.lower()}+{buildmetadata}pr_{issue_number}_{no_commits}"
else: else:

View File

@ -11,3 +11,4 @@ CuraCloudAPIVersion = "{{ cura_cloud_api_version }}"
CuraCloudAccountAPIRoot = "{{ cura_cloud_account_api_root }}" CuraCloudAccountAPIRoot = "{{ cura_cloud_account_api_root }}"
CuraMarketplaceRoot = "{{ cura_marketplace_root }}" CuraMarketplaceRoot = "{{ cura_marketplace_root }}"
CuraDigitalFactoryURL = "{{ cura_digital_factory_url }}" CuraDigitalFactoryURL = "{{ cura_digital_factory_url }}"
CuraLatestURL = "{{ cura_latest_url }}"

View File

@ -100,6 +100,10 @@ class CuraConan(ConanFile):
def _digital_factory_url(self): def _digital_factory_url(self):
return "https://digitalfactory-staging.ultimaker.com" if self._staging else "https://digitalfactory.ultimaker.com" return "https://digitalfactory-staging.ultimaker.com" if self._staging else "https://digitalfactory.ultimaker.com"
@property
def _cura_latest_url(self):
return "https://software.ultimaker.com/latest.json"
@property @property
def requirements_txts(self): def requirements_txts(self):
if self.options.devtools: if self.options.devtools:
@ -161,7 +165,8 @@ class CuraConan(ConanFile):
cura_cloud_api_version = self.options.cloud_api_version, cura_cloud_api_version = self.options.cloud_api_version,
cura_cloud_account_api_root = self._cloud_account_api_root, cura_cloud_account_api_root = self._cloud_account_api_root,
cura_marketplace_root = self._marketplace_root, cura_marketplace_root = self._marketplace_root,
cura_digital_factory_url = self._digital_factory_url)) cura_digital_factory_url = self._digital_factory_url,
cura_latest_url = self._cura_latest_url))
def _generate_pyinstaller_spec(self, location, entrypoint_location, icon_path, entitlements_file): def _generate_pyinstaller_spec(self, location, entrypoint_location, icon_path, entitlements_file):
pyinstaller_metadata = self._um_data()["pyinstaller"] pyinstaller_metadata = self._um_data()["pyinstaller"]

View File

@ -9,12 +9,20 @@ DEFAULT_CURA_DISPLAY_NAME = "Ultimaker Cura"
DEFAULT_CURA_VERSION = "dev" DEFAULT_CURA_VERSION = "dev"
DEFAULT_CURA_BUILD_TYPE = "" DEFAULT_CURA_BUILD_TYPE = ""
DEFAULT_CURA_DEBUG_MODE = False DEFAULT_CURA_DEBUG_MODE = False
DEFAULT_CURA_LATEST_URL = "https://software.ultimaker.com/latest.json"
# Each release has a fixed SDK version coupled with it. It doesn't make sense to make it configurable because, for # Each release has a fixed SDK version coupled with it. It doesn't make sense to make it configurable because, for
# example Cura 3.2 with SDK version 6.1 will not work. So the SDK version is hard-coded here and left out of the # example Cura 3.2 with SDK version 6.1 will not work. So the SDK version is hard-coded here and left out of the
# CuraVersion.py.in template. # CuraVersion.py.in template.
CuraSDKVersion = "8.1.0" CuraSDKVersion = "8.1.0"
try:
from cura.CuraVersion import CuraLatestURL
if CuraLatestURL == "":
CuraLatestURL = DEFAULT_CURA_LATEST_URL
except ImportError:
CuraLatestURL = DEFAULT_CURA_LATEST_URL
try: try:
from cura.CuraVersion import CuraAppName # type: ignore from cura.CuraVersion import CuraAppName # type: ignore
if CuraAppName == "": if CuraAppName == "":

View File

@ -145,6 +145,8 @@ class CuraApplication(QtApplication):
DefinitionChangesContainer = Resources.UserType + 10 DefinitionChangesContainer = Resources.UserType + 10
SettingVisibilityPreset = Resources.UserType + 11 SettingVisibilityPreset = Resources.UserType + 11
IntentInstanceContainer = Resources.UserType + 12 IntentInstanceContainer = Resources.UserType + 12
AbstractMachineStack = Resources.UserType + 13
pyqtEnum(ResourceTypes) pyqtEnum(ResourceTypes)
@ -152,6 +154,7 @@ class CuraApplication(QtApplication):
super().__init__(name = ApplicationMetadata.CuraAppName, super().__init__(name = ApplicationMetadata.CuraAppName,
app_display_name = ApplicationMetadata.CuraAppDisplayName, app_display_name = ApplicationMetadata.CuraAppDisplayName,
version = ApplicationMetadata.CuraVersion if not ApplicationMetadata.IsAlternateVersion else ApplicationMetadata.CuraBuildType, version = ApplicationMetadata.CuraVersion if not ApplicationMetadata.IsAlternateVersion else ApplicationMetadata.CuraBuildType,
latest_url = ApplicationMetadata.CuraLatestURL,
api_version = ApplicationMetadata.CuraSDKVersion, api_version = ApplicationMetadata.CuraSDKVersion,
build_type = ApplicationMetadata.CuraBuildType, build_type = ApplicationMetadata.CuraBuildType,
is_debug_mode = ApplicationMetadata.CuraDebugMode, is_debug_mode = ApplicationMetadata.CuraDebugMode,
@ -422,6 +425,7 @@ class CuraApplication(QtApplication):
Resources.addStorageType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes") Resources.addStorageType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
Resources.addStorageType(self.ResourceTypes.SettingVisibilityPreset, "setting_visibility") Resources.addStorageType(self.ResourceTypes.SettingVisibilityPreset, "setting_visibility")
Resources.addStorageType(self.ResourceTypes.IntentInstanceContainer, "intent") Resources.addStorageType(self.ResourceTypes.IntentInstanceContainer, "intent")
Resources.addStorageType(self.ResourceTypes.AbstractMachineStack, "abstract_machine_instances")
self._container_registry.addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality") self._container_registry.addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality")
self._container_registry.addResourceType(self.ResourceTypes.QualityChangesInstanceContainer, "quality_changes") self._container_registry.addResourceType(self.ResourceTypes.QualityChangesInstanceContainer, "quality_changes")
@ -432,6 +436,7 @@ class CuraApplication(QtApplication):
self._container_registry.addResourceType(self.ResourceTypes.MachineStack, "machine") self._container_registry.addResourceType(self.ResourceTypes.MachineStack, "machine")
self._container_registry.addResourceType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes") self._container_registry.addResourceType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
self._container_registry.addResourceType(self.ResourceTypes.IntentInstanceContainer, "intent") self._container_registry.addResourceType(self.ResourceTypes.IntentInstanceContainer, "intent")
self._container_registry.addResourceType(self.ResourceTypes.AbstractMachineStack, "abstract_machine")
Resources.addType(self.ResourceTypes.QmlFiles, "qml") Resources.addType(self.ResourceTypes.QmlFiles, "qml")
Resources.addType(self.ResourceTypes.Firmware, "firmware") Resources.addType(self.ResourceTypes.Firmware, "firmware")
@ -480,6 +485,7 @@ class CuraApplication(QtApplication):
("variant", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.VariantInstanceContainer, "application/x-uranium-instancecontainer"), ("variant", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.VariantInstanceContainer, "application/x-uranium-instancecontainer"),
("setting_visibility", SettingVisibilityPresetsModel.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.SettingVisibilityPreset, "application/x-uranium-preferences"), ("setting_visibility", SettingVisibilityPresetsModel.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.SettingVisibilityPreset, "application/x-uranium-preferences"),
("machine", 2): (Resources.DefinitionContainers, "application/x-uranium-definitioncontainer"), ("machine", 2): (Resources.DefinitionContainers, "application/x-uranium-definitioncontainer"),
("abstract_machine", 1): (Resources.DefinitionContainers, "application/x-uranium-definitioncontainer"),
("extruder", 2): (Resources.DefinitionContainers, "application/x-uranium-definitioncontainer") ("extruder", 2): (Resources.DefinitionContainers, "application/x-uranium-definitioncontainer")
} }
) )

View File

@ -0,0 +1,35 @@
from typing import List
from UM.Settings.ContainerStack import ContainerStack
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from cura.Settings.GlobalStack import GlobalStack
from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
from UM.Settings.ContainerRegistry import ContainerRegistry
class AbstractMachine(GlobalStack):
""" Represents a group of machines of the same type. This allows the user to select settings before selecting a printer. """
def __init__(self, container_id: str) -> None:
super().__init__(container_id)
self.setMetaDataEntry("type", "abstract_machine")
def getMachines(self) -> List[ContainerStack]:
from cura.CuraApplication import CuraApplication
application = CuraApplication.getInstance()
registry = application.getContainerRegistry()
printer_type = self.definition.getId()
return [machine for machine in registry.findContainerStacks(type="machine") if machine.definition.id == printer_type and ConnectionType.CloudConnection in machine.configuredConnectionTypes]
## private:
_abstract_machine_mime = MimeType(
name = "application/x-cura-abstract-machine",
comment = "Cura Abstract Machine",
suffixes = ["global.cfg"]
)
MimeTypeDatabase.addMimeType(_abstract_machine_mime)
ContainerRegistry.addContainerTypeByName(AbstractMachine, "abstract_machine", _abstract_machine_mime.name)

View File

@ -108,7 +108,7 @@ class CuraContainerRegistry(ContainerRegistry):
:param container_type: :type{string} Type of the container (machine, quality, ...) :param container_type: :type{string} Type of the container (machine, quality, ...)
:param container_name: :type{string} Name to check :param container_name: :type{string} Name to check
""" """
container_class = ContainerStack if container_type == "machine" else InstanceContainer container_class = ContainerStack if "machine" in container_type else InstanceContainer
return self.findContainersMetadata(container_type = container_class, id = container_name, type = container_type, ignore_case = True) or \ return self.findContainersMetadata(container_type = container_class, id = container_name, type = container_type, ignore_case = True) or \
self.findContainersMetadata(container_type = container_class, name = container_name, type = container_type) self.findContainersMetadata(container_type = container_class, name = container_name, type = container_type)

View File

@ -427,4 +427,4 @@ class _ContainerIndexes:
} }
# Reverse lookup: type -> index # Reverse lookup: type -> index
TypeIndexMap = dict([(v, k) for k, v in IndexTypeMap.items()]) TypeIndexMap = {v: k for k, v in IndexTypeMap.items()}

View File

@ -9,6 +9,7 @@ from UM.Settings.Interfaces import DefinitionContainerInterface
from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.InstanceContainer import InstanceContainer
from cura.Machines.ContainerTree import ContainerTree from cura.Machines.ContainerTree import ContainerTree
from .AbstractMachine import AbstractMachine
from .GlobalStack import GlobalStack from .GlobalStack import GlobalStack
from .ExtruderStack import ExtruderStack from .ExtruderStack import ExtruderStack
@ -27,7 +28,7 @@ class CuraStackBuilder:
:return: The new global stack or None if an error occurred. :return: The new global stack or None if an error occurred.
""" """
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication # inline import needed due to circular import
application = CuraApplication.getInstance() application = CuraApplication.getInstance()
registry = application.getContainerRegistry() registry = application.getContainerRegistry()
container_tree = ContainerTree.getInstance() container_tree = ContainerTree.getInstance()
@ -91,7 +92,7 @@ class CuraStackBuilder:
:param extruder_position: The position of the current extruder. :param extruder_position: The position of the current extruder.
""" """
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication # inline import needed due to circular import
application = CuraApplication.getInstance() application = CuraApplication.getInstance()
registry = application.getContainerRegistry() registry = application.getContainerRegistry()
@ -199,13 +200,21 @@ class CuraStackBuilder:
:return: A new Global stack instance with the specified parameters. :return: A new Global stack instance with the specified parameters.
""" """
from cura.CuraApplication import CuraApplication
application = CuraApplication.getInstance()
registry = application.getContainerRegistry()
stack = GlobalStack(new_stack_id) stack = GlobalStack(new_stack_id)
stack.setDefinition(definition) stack.setDefinition(definition)
cls.createUserContainer(new_stack_id, definition, stack, variant_container, material_container, quality_container)
return stack
@classmethod
def createUserContainer(cls, new_stack_id: str, definition: DefinitionContainerInterface,
stack: GlobalStack,
variant_container: "InstanceContainer",
material_container: "InstanceContainer",
quality_container: "InstanceContainer") -> None:
from cura.CuraApplication import CuraApplication
application = CuraApplication.getInstance()
registry = application.getContainerRegistry()
# Create user container # Create user container
user_container = cls.createUserChangesContainer(new_stack_id + "_user", definition.getId(), new_stack_id, user_container = cls.createUserChangesContainer(new_stack_id + "_user", definition.getId(), new_stack_id,
@ -221,8 +230,6 @@ class CuraStackBuilder:
registry.addContainer(user_container) registry.addContainer(user_container)
return stack
@classmethod @classmethod
def createUserChangesContainer(cls, container_name: str, definition_id: str, stack_id: str, def createUserChangesContainer(cls, container_name: str, definition_id: str, stack_id: str,
is_global_stack: bool) -> "InstanceContainer": is_global_stack: bool) -> "InstanceContainer":
@ -259,3 +266,49 @@ class CuraStackBuilder:
container_stack.definitionChanges = definition_changes_container container_stack.definitionChanges = definition_changes_container
return definition_changes_container return definition_changes_container
@classmethod
def createAbstractMachine(cls, definition_id: str) -> Optional[AbstractMachine]:
"""Create a new instance of an abstract machine.
:param definition_id: The ID of the machine definition to use.
:return: The new Abstract Machine or None if an error occurred.
"""
abstract_machine_id = definition_id + "_abstract_machine"
from cura.CuraApplication import CuraApplication
application = CuraApplication.getInstance()
registry = application.getContainerRegistry()
container_tree = ContainerTree.getInstance()
if registry.findContainerStacks(type = "abstract_machine", id = abstract_machine_id):
# This abstract machine already exists
return None
match registry.findDefinitionContainers(type = "machine", id = definition_id):
case []:
# It should not be possible for the definition to be missing since an abstract machine will only
# be created as a result of a machine with definition_id being created.
Logger.error(f"Definition {definition_id} was not found!")
return None
case [machine_definition, *_definitions]:
machine_node = container_tree.machines[machine_definition.getId()]
name = machine_definition.getName()
stack = AbstractMachine(abstract_machine_id)
stack.setDefinition(machine_definition)
cls.createUserContainer(
name,
machine_definition,
stack,
application.empty_variant_container,
application.empty_material_container,
machine_node.preferredGlobalQuality().container,
)
stack.setName(name)
registry.addContainer(stack)
return stack

View File

@ -400,11 +400,13 @@ class CloudOutputDeviceManager:
# We do not use use MachineManager.addMachine here because we need to set the cluster ID before activating it. # We do not use use MachineManager.addMachine here because we need to set the cluster ID before activating it.
new_machine = CuraStackBuilder.createMachine(device.name, device.printerType, show_warning_message=False) new_machine = CuraStackBuilder.createMachine(device.name, device.printerType, show_warning_message=False)
if not new_machine: if not new_machine:
Logger.log("e", "Failed creating a new machine") Logger.error(f"Failed creating a new machine for {device.name}")
return False return False
self._setOutputDeviceMetadata(device, new_machine) self._setOutputDeviceMetadata(device, new_machine)
_abstract_machine = CuraStackBuilder.createAbstractMachine(device.printerType)
if activate: if activate:
CuraApplication.getInstance().getMachineManager().setActiveMachine(new_machine.getId()) CuraApplication.getInstance().getMachineManager().setActiveMachine(new_machine.getId())