mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-13 01:37:51 -06:00
Merge branch 'master' into fix_tests_cura_engine_backend
This commit is contained in:
commit
75d5828f5f
13 changed files with 119 additions and 54 deletions
|
@ -1,12 +1,13 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
|
||||
import shutil
|
||||
|
||||
from typing import Optional
|
||||
from typing import Dict, Optional
|
||||
from zipfile import ZipFile, ZIP_DEFLATED, BadZipfile
|
||||
|
||||
from UM import i18nCatalog
|
||||
|
@ -28,9 +29,9 @@ class Backup:
|
|||
# Re-use translation catalog.
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
def __init__(self, zip_file: bytes = None, meta_data: dict = None) -> None:
|
||||
def __init__(self, zip_file: bytes = None, meta_data: Dict[str, str] = None) -> None:
|
||||
self.zip_file = zip_file # type: Optional[bytes]
|
||||
self.meta_data = meta_data # type: Optional[dict]
|
||||
self.meta_data = meta_data # type: Optional[Dict[str, str]]
|
||||
|
||||
## Create a back-up from the current user config folder.
|
||||
def makeFromCurrent(self) -> None:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from UM.Logger import Logger
|
||||
from cura.Backups.Backup import Backup
|
||||
|
@ -18,7 +19,7 @@ class BackupsManager:
|
|||
## Get a back-up of the current configuration.
|
||||
# \return A tuple containing a ZipFile (the actual back-up) and a dict
|
||||
# containing some metadata (like version).
|
||||
def createBackup(self) -> Tuple[Optional[bytes], Optional[dict]]:
|
||||
def createBackup(self) -> Tuple[Optional[bytes], Optional[Dict[str, str]]]:
|
||||
self._disableAutoSave()
|
||||
backup = Backup()
|
||||
backup.makeFromCurrent()
|
||||
|
@ -30,7 +31,7 @@ class BackupsManager:
|
|||
# \param zip_file A bytes object containing the actual back-up.
|
||||
# \param meta_data A dict containing some metadata that is needed to
|
||||
# restore the back-up correctly.
|
||||
def restoreBackup(self, zip_file: bytes, meta_data: dict) -> None:
|
||||
def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, str]) -> None:
|
||||
if not meta_data.get("cura_release", None):
|
||||
# If there is no "cura_release" specified in the meta data, we don't execute a backup restore.
|
||||
Logger.log("w", "Tried to restore a backup without specifying a Cura version number.")
|
||||
|
@ -43,13 +44,13 @@ class BackupsManager:
|
|||
if restored:
|
||||
# At this point, Cura will need to restart for the changes to take effect.
|
||||
# We don't want to store the data at this point as that would override the just-restored backup.
|
||||
self._application.windowClosed(save_data=False)
|
||||
self._application.windowClosed(save_data = False)
|
||||
|
||||
## Here we try to disable the auto-save plug-in as it might interfere with
|
||||
# restoring a back-up.
|
||||
def _disableAutoSave(self):
|
||||
def _disableAutoSave(self) -> None:
|
||||
self._application.setSaveDataEnabled(False)
|
||||
|
||||
## Re-enable auto-save after we're done.
|
||||
def _enableAutoSave(self):
|
||||
def _enableAutoSave(self) -> None:
|
||||
self._application.setSaveDataEnabled(True)
|
||||
|
|
|
@ -47,10 +47,10 @@ class BuildVolume(SceneNode):
|
|||
self._disallowed_area_color = None
|
||||
self._error_area_color = None
|
||||
|
||||
self._width = 0
|
||||
self._height = 0
|
||||
self._depth = 0
|
||||
self._shape = ""
|
||||
self._width = 0 #type: float
|
||||
self._height = 0 #type: float
|
||||
self._depth = 0 #type: float
|
||||
self._shape = "" #type: str
|
||||
|
||||
self._shader = None
|
||||
|
||||
|
@ -154,19 +154,19 @@ class BuildVolume(SceneNode):
|
|||
if active_extruder_changed is not None:
|
||||
active_extruder_changed.connect(self._updateDisallowedAreasAndRebuild)
|
||||
|
||||
def setWidth(self, width):
|
||||
def setWidth(self, width: float) -> None:
|
||||
if width is not None:
|
||||
self._width = width
|
||||
|
||||
def setHeight(self, height):
|
||||
def setHeight(self, height: float) -> None:
|
||||
if height is not None:
|
||||
self._height = height
|
||||
|
||||
def setDepth(self, depth):
|
||||
def setDepth(self, depth: float) -> None:
|
||||
if depth is not None:
|
||||
self._depth = depth
|
||||
|
||||
def setShape(self, shape: str):
|
||||
def setShape(self, shape: str) -> None:
|
||||
if shape:
|
||||
self._shape = shape
|
||||
|
||||
|
@ -294,7 +294,7 @@ class BuildVolume(SceneNode):
|
|||
if not self._width or not self._height or not self._depth:
|
||||
return
|
||||
|
||||
if not self._application._qml_engine:
|
||||
if not self._engine_ready:
|
||||
return
|
||||
|
||||
if not self._volume_outline_color:
|
||||
|
|
10
cura_app.py
10
cura_app.py
|
@ -12,14 +12,14 @@ from UM.Platform import Platform
|
|||
|
||||
parser = argparse.ArgumentParser(prog = "cura",
|
||||
add_help = False)
|
||||
parser.add_argument('--debug',
|
||||
action='store_true',
|
||||
parser.add_argument("--debug",
|
||||
action="store_true",
|
||||
default = False,
|
||||
help = "Turn on the debug mode by setting this option."
|
||||
)
|
||||
parser.add_argument('--trigger-early-crash',
|
||||
dest = 'trigger_early_crash',
|
||||
action = 'store_true',
|
||||
parser.add_argument("--trigger-early-crash",
|
||||
dest = "trigger_early_crash",
|
||||
action = "store_true",
|
||||
default = False,
|
||||
help = "FOR TESTING ONLY. Trigger an early crash to show the crash dialog."
|
||||
)
|
||||
|
|
|
@ -287,7 +287,9 @@ class FlavorParser:
|
|||
# We obtain the filament diameter from the selected extruder to calculate line widths
|
||||
global_stack = CuraApplication.getInstance().getGlobalContainerStack()
|
||||
|
||||
if global_stack:
|
||||
if not global_stack:
|
||||
return None
|
||||
|
||||
self._filament_diameter = global_stack.extruders[str(self._extruder_number)].getProperty("material_diameter", "value")
|
||||
|
||||
scene_node = CuraSceneNode()
|
||||
|
|
|
@ -247,57 +247,57 @@ class PauseAtHeight(Script):
|
|||
prepend_gcode += ";added code by post processing\n"
|
||||
prepend_gcode += ";script: PauseAtHeight.py\n"
|
||||
if pause_at == "height":
|
||||
prepend_gcode += ";current z: {z}\n".format(z=current_z)
|
||||
prepend_gcode += ";current height: {height}\n".format(height=current_height)
|
||||
prepend_gcode += ";current z: {z}\n".format(z = current_z)
|
||||
prepend_gcode += ";current height: {height}\n".format(height = current_height)
|
||||
else:
|
||||
prepend_gcode += ";current layer: {layer}\n".format(layer=current_layer)
|
||||
prepend_gcode += ";current layer: {layer}\n".format(layer = current_layer)
|
||||
|
||||
# Retraction
|
||||
prepend_gcode += self.putValue(M=83) + "\n"
|
||||
prepend_gcode += self.putValue(M = 83) + "\n"
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G=1, E=-retraction_amount, F=retraction_speed * 60) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n"
|
||||
|
||||
# Move the head away
|
||||
prepend_gcode += self.putValue(G=1, Z=current_z + 1, F=300) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n"
|
||||
|
||||
# This line should be ok
|
||||
prepend_gcode += self.putValue(G=1, X=park_x, Y=park_y, F=9000) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, X = park_x, Y = park_y, F = 9000) + "\n"
|
||||
|
||||
if current_z < 15:
|
||||
prepend_gcode += self.putValue(G=1, Z=15, F=300) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, Z = 15, F = 300) + "\n"
|
||||
|
||||
# Set extruder standby temperature
|
||||
prepend_gcode += self.putValue(M=104, S=standby_temperature) + "; standby temperature\n"
|
||||
prepend_gcode += self.putValue(M = 104, S = standby_temperature) + "; standby temperature\n"
|
||||
|
||||
# Wait till the user continues printing
|
||||
prepend_gcode += self.putValue(M=0) + ";Do the actual pause\n"
|
||||
prepend_gcode += self.putValue(M = 0) + ";Do the actual pause\n"
|
||||
|
||||
# Set extruder resume temperature
|
||||
prepend_gcode += self.putValue(M = 109, S = int(target_temperature.get(current_t, 0))) + "; resume temperature\n"
|
||||
|
||||
# Push the filament back,
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G=1, E=retraction_amount, F=retraction_speed * 60) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n"
|
||||
|
||||
# Optionally extrude material
|
||||
if extrude_amount != 0:
|
||||
prepend_gcode += self.putValue(G=1, E=extrude_amount, F=extrude_speed * 60) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, E = extrude_amount, F = extrude_speed * 60) + "\n"
|
||||
|
||||
# and retract again, the properly primes the nozzle
|
||||
# when changing filament.
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G=1, E=-retraction_amount, F=retraction_speed * 60) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n"
|
||||
|
||||
# Move the head back
|
||||
prepend_gcode += self.putValue(G=1, Z=current_z + 1, F=300) + "\n"
|
||||
prepend_gcode += self.putValue(G=1, X=x, Y=y, F=9000) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, X = x, Y = y, F = 9000) + "\n"
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G=1, E=retraction_amount, F=retraction_speed * 60) + "\n"
|
||||
prepend_gcode += self.putValue(G=1, F=9000) + "\n"
|
||||
prepend_gcode += self.putValue(M=82) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, F = 9000) + "\n"
|
||||
prepend_gcode += self.putValue(M = 82) + "\n"
|
||||
|
||||
# reset extrude value to pre pause value
|
||||
prepend_gcode += self.putValue(G=92, E=current_e) + "\n"
|
||||
prepend_gcode += self.putValue(G = 92, E = current_e) + "\n"
|
||||
|
||||
layer = prepend_gcode + layer
|
||||
|
||||
|
|
|
@ -76,11 +76,26 @@ Item
|
|||
}
|
||||
}
|
||||
|
||||
Component
|
||||
{
|
||||
id: columnTextDelegate
|
||||
Label
|
||||
{
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: styleData.value || ""
|
||||
elide: Text.ElideRight
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
}
|
||||
|
||||
TableViewColumn
|
||||
{
|
||||
role: "machine"
|
||||
title: "Machine"
|
||||
width: Math.floor(table.width * 0.25)
|
||||
delegate: columnTextDelegate
|
||||
}
|
||||
TableViewColumn
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@ Item
|
|||
Label
|
||||
{
|
||||
text: catalog.i18nc("@info", "You will need to restart Cura before changes in packages have effect.")
|
||||
color: UM.Theme.getColor("text")
|
||||
height: Math.floor(UM.Theme.getSize("toolbox_footer_button").height)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors
|
||||
|
@ -25,7 +26,7 @@ Item
|
|||
right: restartButton.right
|
||||
rightMargin: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
color: UM.Theme.getColor("text")
|
||||
|
||||
}
|
||||
Button
|
||||
{
|
||||
|
|
|
@ -224,6 +224,11 @@ class Toolbox(QObject, Extension):
|
|||
|
||||
if not self._dialog:
|
||||
self._dialog = self._createDialog("Toolbox.qml")
|
||||
|
||||
if not self._dialog:
|
||||
Logger.log("e", "Unexpected error trying to create the 'Toolbox' dialog.")
|
||||
return
|
||||
|
||||
self._dialog.show()
|
||||
|
||||
# Apply enabled/disabled state to installed plugins
|
||||
|
@ -231,9 +236,11 @@ class Toolbox(QObject, Extension):
|
|||
|
||||
def _createDialog(self, qml_name: str) -> QObject:
|
||||
Logger.log("d", "Toolbox: Creating dialog [%s].", qml_name)
|
||||
path = os.path.join(cast(str, PluginRegistry.getInstance().getPluginPath(self.getPluginId())), "resources", "qml", qml_name)
|
||||
if not path:
|
||||
raise Exception("Failed to create toolbox QML path")
|
||||
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
|
||||
if not plugin_path:
|
||||
return None
|
||||
path = os.path.join(plugin_path, "resources", "qml", qml_name)
|
||||
|
||||
dialog = self._application.createQmlComponent(path, {"toolbox": self})
|
||||
if not dialog:
|
||||
raise Exception("Failed to create toolbox dialog")
|
||||
|
|
|
@ -128,6 +128,10 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
|||
else:
|
||||
writer = CuraApplication.getInstance().getMeshFileHandler().getWriterByMimeType(cast(str, preferred_format["mime_type"]))
|
||||
|
||||
if not writer:
|
||||
Logger.log("e", "Unexpected error when trying to get the FileWriter")
|
||||
return
|
||||
|
||||
#This function pauses with the yield, waiting on instructions on which printer it needs to print with.
|
||||
if not writer:
|
||||
Logger.log("e", "Missing file or mesh writer!")
|
||||
|
|
|
@ -170,11 +170,10 @@ class DiscoverUM3Action(MachineAction):
|
|||
Logger.log("d", "Creating additional ui components for UM3.")
|
||||
|
||||
# Create networking dialog
|
||||
path = os.path.join(cast(str, PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting")), "UM3InfoComponents.qml")
|
||||
if not path:
|
||||
Logger.log("w", "Could not get QML path for UM3 network printing UI.")
|
||||
plugin_path = PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting")
|
||||
if not plugin_path:
|
||||
return
|
||||
|
||||
path = os.path.join(plugin_path, "UM3InfoComponents.qml")
|
||||
self.__additional_components_view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self})
|
||||
if not self.__additional_components_view:
|
||||
Logger.log("w", "Could not create ui components for UM3.")
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import configparser #To parse the resulting config files.
|
||||
import pytest #To register tests with.
|
||||
|
||||
import VersionUpgrade34to40 #The module we're testing.
|
||||
|
||||
## Creates an instance of the upgrader to test with.
|
||||
@pytest.fixture
|
||||
def upgrader():
|
||||
return VersionUpgrade34to40.VersionUpgrade34to40()
|
||||
|
||||
test_upgrade_version_nr_data = [
|
||||
("Empty config file",
|
||||
"""[general]
|
||||
version = 5
|
||||
[metadata]
|
||||
setting_version = 4
|
||||
"""
|
||||
)
|
||||
]
|
||||
|
||||
## Tests whether the version numbers are updated.
|
||||
@pytest.mark.parametrize("test_name, file_data", test_upgrade_version_nr_data)
|
||||
def test_upgradeVersionNr(test_name, file_data, upgrader):
|
||||
#Perform the upgrade.
|
||||
_, upgraded_instances = upgrader.upgradePreferences(file_data, "<string>")
|
||||
upgraded_instance = upgraded_instances[0]
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(upgraded_instance)
|
||||
|
||||
#Check the new version.
|
||||
assert parser["general"]["version"] == "6"
|
||||
assert parser["metadata"]["setting_version"] == "5"
|
|
@ -2,6 +2,7 @@
|
|||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from math import pi, sin, cos, sqrt
|
||||
from typing import Dict
|
||||
|
||||
import numpy
|
||||
|
||||
|
@ -42,8 +43,7 @@ class X3DReader(MeshReader):
|
|||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._supported_extensions = [".x3d"]
|
||||
# TODO: Remove after testing because it appears to be unused
|
||||
# self._namespaces = {}
|
||||
self._namespaces = {} # type: Dict[str, str]
|
||||
|
||||
# Main entry point
|
||||
# Reads the file, returns a SceneNode (possibly with nested ones), or None
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue