Merge branch 'master' into CURA-6915_identify_objects_on_buildplate

This commit is contained in:
Nino van Hooff 2020-07-02 16:35:35 +02:00
commit b7ee65d5a5
13 changed files with 101 additions and 133 deletions

2
.gitignore vendored
View File

@ -78,3 +78,5 @@ CuraEngine
#Prevents import failures when plugin running tests
plugins/__init__.py
/venv

View File

@ -533,7 +533,7 @@ class CuraApplication(QtApplication):
preferences.addPreference("cura/active_mode", "simple")
preferences.addPreference("cura/categories_expanded", "")
preferences.addPreference("cura/jobname_prefix", True)
preferences.addPreference("cura/job_name_template", "{machine_name_short}_{project_name}")
preferences.addPreference("cura/select_models_on_load", False)
preferences.addPreference("view/center_on_select", False)
preferences.addPreference("mesh/scale_to_fit", False)

View File

@ -252,11 +252,11 @@ class PrintInformation(QObject):
self.materialNamesChanged.emit()
def _onPreferencesChanged(self, preference: str) -> None:
if preference != "cura/material_settings":
return
for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
self._calculateInformation(build_plate_number)
if preference == "cura/job_name_template":
self._updateJobName()
elif preference == "cura/material_settings":
for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
self._calculateInformation(build_plate_number)
def _onActiveBuildPlateChanged(self) -> None:
new_active_build_plate = self._multi_build_plate_model.activeBuildPlate
@ -305,12 +305,8 @@ class PrintInformation(QObject):
# Only update the job name when it's not user-specified.
if not self._is_user_specified_job_name:
if self._application.getInstance().getPreferences().getValue("cura/jobname_prefix") and not self._pre_sliced:
# Don't add abbreviation if it already has the exact same abbreviation.
if base_name.startswith(self._abbr_machine + "_"):
self._job_name = base_name
else:
self._job_name = self._abbr_machine + "_" + base_name
if not self._pre_sliced:
self._job_name = self.parseTemplate()
else:
self._job_name = base_name
@ -440,3 +436,28 @@ class PrintInformation(QObject):
"""Listen to scene changes to check if we need to reset the print information"""
self.setToZeroPrintInformation(self._active_build_plate)
def parseTemplate(self) -> str:
"""Generate a print job name from the job name template
The template is a user preference: "cura/job_name_template"
"""
template = self._application.getInstance().getPreferences().getValue("cura/job_name_template")
output = template
output = output.replace("{machine_name_short}", self._abbr_machine)
if "{machine_name}" in template:
global_container_stack = self._application.getGlobalContainerStack()
active_machine_type_name = global_container_stack.definition.getName() \
if global_container_stack \
else "no_machine"
active_machine_type_name = active_machine_type_name.replace(" ", "_")
output = output.replace("{machine_name}", active_machine_type_name)
if "{project_name}" in template:
base_name = self._stripAccents(self._base_name)
output = output.replace("{project_name}", base_name)
return output

View File

@ -151,8 +151,8 @@ class UFPWriter(MeshWriter):
To retrieve, use: `archive.getMetadata(METADATA_OBJECTS_PATH)`
"""
objectsModel = CuraApplication.getInstance().getObjectsModel()
objectMetas = [{"name": item["name"]} for item in objectsModel.items]
objects_model = CuraApplication.getInstance().getObjectsModel()
object_metas = [{"name": item["name"]} for item in objects_model.items]
data = {METADATA_OBJECTS_PATH: objectMetas}
data = {METADATA_OBJECTS_PATH: object_metas}
archive.setMetadata(data)

View File

@ -2,7 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher.
import configparser
from typing import Tuple, List, Dict
from typing import Tuple, List, Dict, Set
import io
from UM.VersionUpgrade import VersionUpgrade
@ -10,8 +10,17 @@ from UM.VersionUpgrade import VersionUpgrade
# Renamed definition files
_RENAMED_DEFINITION_DICT = {
"dagoma_discoeasy200": "dagoma_discoeasy200_bicolor",
} # type: Dict[str, str]
} # type: Dict[str, str]
_removed_settings = {
"spaghetti_infill_enabled",
"spaghetti_infill_stepped",
"spaghetti_max_infill_angle",
"spaghetti_max_height",
"spaghetti_inset",
"spaghetti_flow",
"spaghetti_infill_extra_volume"
} # type: Set[str]
class VersionUpgrade462to47(VersionUpgrade):
def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
@ -27,6 +36,11 @@ class VersionUpgrade462to47(VersionUpgrade):
# Update version number.
parser["metadata"]["setting_version"] = "15"
# Remove deleted settings from the visible settings list.
if "general" in parser and "visible_settings" in parser["general"]:
parser["general"]["visible_settings"] = ";".join(
set(parser["general"]["visible_settings"].split(";")).difference(_removed_settings))
result = io.StringIO()
parser.write(result)
@ -77,6 +91,9 @@ class VersionUpgrade462to47(VersionUpgrade):
correction = " + skin_line_width * (1.0 - ironing_flow / 100) / 2"
ironing_inset = "=(" + ironing_inset + ")" + correction
parser["values"]["ironing_inset"] = ironing_inset
for removed in set(parser["values"].keys()).intersection(_removed_settings):
del parser["values"][removed]
# Check renamed definitions
if "definition" in parser["general"] and parser["general"]["definition"] in _RENAMED_DEFINITION_DICT:

View File

@ -1510,11 +1510,12 @@
{
"label": "Extra Skin Wall Count",
"description": "Replaces the outermost part of the top/bottom pattern with a number of concentric lines. Using one or two lines improves roofs that start on infill material.",
"value": "0 if top_bottom_pattern == 'concentric' else 1",
"default_value": 1,
"minimum_value": "0",
"maximum_value_warning": "10",
"type": "int",
"enabled": "top_layers > 0 or bottom_layers > 0",
"enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern != 'concentric'",
"limit_to_extruder": "top_bottom_extruder_nr",
"settable_per_mesh": true
},
@ -1816,7 +1817,7 @@
"type": "int",
"minimum_value": "1",
"maximum_value_warning": "infill_line_distance / infill_line_width",
"enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled and infill_pattern != 'zigzag'",
"enabled": "infill_sparse_density > 0 and infill_pattern != 'zigzag'",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
@ -1827,7 +1828,7 @@
"default_value": 0,
"type": "int",
"minimum_value": "0",
"enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled",
"enabled": "infill_sparse_density > 0",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
@ -1898,9 +1899,9 @@
"default_value": 0.1,
"minimum_value": "resolveOrValue('layer_height') / 2 if infill_line_distance > 0 else -999999",
"maximum_value_warning": "0.75 * machine_nozzle_size",
"maximum_value": "resolveOrValue('layer_height') * (1.45 if spaghetti_infill_enabled else 8) if infill_line_distance > 0 else 999999",
"maximum_value": "resolveOrValue('layer_height') * 8 if infill_line_distance > 0 else 999999",
"value": "resolveOrValue('layer_height')",
"enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled",
"enabled": "infill_sparse_density > 0",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
@ -1912,8 +1913,8 @@
"type": "int",
"minimum_value": "0",
"maximum_value_warning": "1 if (infill_pattern == 'cross' or infill_pattern == 'cross_3d' or support_pattern == 'concentric') else 5",
"maximum_value": "0 if spaghetti_infill_enabled else (999999 if infill_line_distance == 0 else (20 - math.log(infill_line_distance) / math.log(2)))",
"enabled": "infill_sparse_density > 0 and infill_pattern != 'cubicsubdiv' and not spaghetti_infill_enabled",
"maximum_value": "999999 if infill_line_distance == 0 else (20 - math.log(infill_line_distance) / math.log(2))",
"enabled": "infill_sparse_density > 0 and infill_pattern != 'cubicsubdiv'",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
@ -6584,92 +6585,6 @@
"settable_per_mesh": false,
"settable_per_extruder": true
},
"spaghetti_infill_enabled":
{
"label": "Spaghetti Infill",
"description": "Print the infill every so often, so that the filament will curl up chaotically inside the object. This reduces print time, but the behaviour is rather unpredictable.",
"type": "bool",
"default_value": false,
"enabled": "infill_sparse_density > 0",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"spaghetti_infill_stepped":
{
"label": "Spaghetti Infill Stepping",
"description": "Whether to print spaghetti infill in steps or extrude all the infill filament at the end of the print.",
"type": "bool",
"default_value": true,
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"spaghetti_max_infill_angle":
{
"label": "Spaghetti Maximum Infill Angle",
"description": "The maximum angle w.r.t. the Z axis of the inside of the print for areas which are to be filled with spaghetti infill afterwards. Lowering this value causes more angled parts in your model to be filled on each layer.",
"unit": "°",
"type": "float",
"default_value": 10,
"minimum_value": "0",
"maximum_value": "90",
"maximum_value_warning": "45",
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled and spaghetti_infill_stepped",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"spaghetti_max_height":
{
"label": "Spaghetti Infill Maximum Height",
"description": "The maximum height of inside space which can be combined and filled from the top.",
"unit": "mm",
"type": "float",
"default_value": 2.0,
"minimum_value": "layer_height",
"maximum_value_warning": "10.0",
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled and spaghetti_infill_stepped",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"spaghetti_inset":
{
"label": "Spaghetti Inset",
"description": "The offset from the walls from where the spaghetti infill will be printed.",
"unit": "mm",
"type": "float",
"default_value": 0.2,
"minimum_value_warning": "0",
"maximum_value_warning": "5.0",
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"spaghetti_flow":
{
"label": "Spaghetti Flow",
"description": "Adjusts the density of the spaghetti infill. Note that the Infill Density only controls the line spacing of the filling pattern, not the amount of extrusion for spaghetti infill.",
"unit": "%",
"type": "float",
"default_value": 20,
"minimum_value": "0",
"maximum_value_warning": "100",
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"spaghetti_infill_extra_volume":
{
"label": "Spaghetti Infill Extra Volume",
"description": "A correction term to adjust the total volume being extruded each time when filling spaghetti.",
"unit": "mm³",
"type": "float",
"default_value": 0,
"minimum_value_warning": "0",
"maximum_value_warning": "100",
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"support_conical_enabled":
{
"label": "Enable Conical Support",

View File

@ -447,7 +447,7 @@
"value": "5"
},
"skin_outline_count": {
"default_value": 0
"value": 0
},
"skirt_brim_speed": {
"value": "10.0"

View File

@ -147,13 +147,15 @@ UM.Dialog
projectsModel.append({ name: "NumPy-STL", description: catalog.i18nc("@label", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" });
projectsModel.append({ name: "Shapely", description: catalog.i18nc("@label", "Support library for handling planar objects"), license: "BSD", url: "https://github.com/Toblerity/Shapely" });
projectsModel.append({ name: "Trimesh", description: catalog.i18nc("@label", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" });
projectsModel.append({ name: "NetworkX", description: catalog.i18nc("@label", "Support library for analysis of complex networks"), license: "3-clause BSD", url: "https://networkx.github.io/" });
projectsModel.append({ name: "libSavitar", description: catalog.i18nc("@label", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" });
projectsModel.append({ name: "libCharon", description: catalog.i18nc("@label", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" });
projectsModel.append({ name: "PySerial", description: catalog.i18nc("@label", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" });
projectsModel.append({ name: "python-zeroconf", description: catalog.i18nc("@label", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" });
projectsModel.append({ name: "Clipper", description: catalog.i18nc("@label", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" });
projectsModel.append({ name: "Requests", description: catalog.i18nc("@Label", "Python HTTP library"), license: "GPL", url: "http://docs.python-requests.org" });
projectsModel.append({ name: "mypy", description: catalog.i18nc("@Label", "Static type checker for Python"), license: "MIT", url: "http://mypy-lang.org/" });
projectsModel.append({ name: "certifi", description: catalog.i18nc("@Label", "Root Certificates for validating SSL trustworthiness"), license: "MPL", url: "https://github.com/certifi/python-certifi" });
projectsModel.append({ name: "cryptography", description: catalog.i18nc("@Label", "Root Certificates for validating SSL trustworthiness"), license: "APACHE and BSD", url: "https://cryptography.io/" });
projectsModel.append({ name: "Sentry", description: catalog.i18nc("@Label", "Python Error tracking library"), license: "BSD 2-Clause 'Simplified'", url: "https://sentry.io/for/python/" });
projectsModel.append({ name: "Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" });
projectsModel.append({ name: "Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" });

View File

@ -85,8 +85,8 @@ UM.PreferencesPage
scaleTinyCheckbox.checked = boolCheck(UM.Preferences.getValue("mesh/scale_tiny_meshes"))
UM.Preferences.resetPreference("cura/select_models_on_load")
selectModelsOnLoadCheckbox.checked = boolCheck(UM.Preferences.getValue("cura/select_models_on_load"))
UM.Preferences.resetPreference("cura/jobname_prefix")
prefixJobNameCheckbox.checked = boolCheck(UM.Preferences.getValue("cura/jobname_prefix"))
UM.Preferences.resetPreference("cura/job_name_template")
jobnameTemplateTextField.text = UM.Preferences.getValue("cura/job_name_template")
UM.Preferences.resetPreference("view/show_overhang");
showOverhangCheckbox.checked = boolCheck(UM.Preferences.getValue("view/show_overhang"))
UM.Preferences.resetPreference("view/show_xray_warning");
@ -627,14 +627,25 @@ UM.PreferencesPage
{
width: childrenRect.width
height: childrenRect.height
text: catalog.i18nc("@info:tooltip", "Should a prefix based on the printer name be added to the print job name automatically?")
text: catalog.i18nc("@info:tooltip. Note variable names themselves (ie. machine_name_short, project_name) should not be translated", "Variables: machine_name_short, machine_name, project_name")
CheckBox
Column
{
id: prefixJobNameCheckbox
text: catalog.i18nc("@option:check", "Add machine prefix to job name")
checked: boolCheck(UM.Preferences.getValue("cura/jobname_prefix"))
onCheckedChanged: UM.Preferences.setValue("cura/jobname_prefix", checked)
spacing: 4 * screenScaleFactor
Label
{
id: jobNameTemplateLabel
text: catalog.i18nc("@label","Print job template:")
}
TextField
{
id: jobNameTemplateTextField
width: 250 * screenScaleFactor
text: UM.Preferences.getValue("cura/job_name_template")
onTextChanged: UM.Preferences.setValue("cura/job_name_template", text)
}
}
}
@ -670,7 +681,7 @@ UM.PreferencesPage
ComboBox
{
id: choiceOnOpenProjectDropDownButton
width: 200 * screenScaleFactor
width: 250 * screenScaleFactor
model: ListModel
{
@ -736,7 +747,7 @@ UM.PreferencesPage
ComboBox
{
id: choiceOnProfileOverrideDropDownButton
width: 200 * screenScaleFactor
width: 250 * screenScaleFactor
model: ListModel
{

View File

@ -85,7 +85,7 @@ Item
onEditingFinished:
{
definitionsModel.filter = {"i18n_label": "*" + text}
definitionsModel.filter = {"i18n_label|i18n_description" : "*" + text}
findingSettings = (text.length > 0)
if (findingSettings != lastFindingSettings)
{

View File

@ -378,13 +378,6 @@ coasting_volume
coasting_min_volume
coasting_speed
cross_infill_pocket_size
spaghetti_infill_enabled
spaghetti_infill_stepped
spaghetti_max_infill_angle
spaghetti_max_height
spaghetti_inset
spaghetti_flow
spaghetti_infill_extra_volume
support_conical_enabled
support_conical_angle
support_conical_min_width

View File

@ -140,7 +140,7 @@ A new performance enhancement that limits re-rendering of the application interf
Previous versions used different ways of handling HTTP requests. This version uses a unified method, for better performance.
* Job names less sensitive to being touched.
A contribution from fieldOfview has fixed an issue where the jobname in the bottom-left of the scene is no longer made static by clicking on it. If you load a model and change to another printer, the prefix is now correctly updated.
A contribution from fieldOfview has fixed an issue where the job name in the bottom-left of the scene is no longer made static by clicking on it. If you load a model and change to another printer, the prefix is now correctly updated.
* Property checks on instance containers.
A new speed optimization for reading setting values from profiles.

View File

@ -8,6 +8,13 @@ from unittest.mock import MagicMock, patch
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
def preferencesGetValue(key: str):
if key == "cura/job_name_template":
return "{machine_name_short}_{project_name}"
return '{"omgzomg": {"spool_weight": 10, "spool_cost": 9}}'
def getPrintInformation(printer_name) -> PrintInformation:
mock_application = MagicMock(name = "mock_application")
@ -19,7 +26,7 @@ def getPrintInformation(printer_name) -> PrintInformation:
mocked_extruder_stack.material = mocked_material
mock_application.getInstance = MagicMock(return_value = mock_application)
mocked_preferences.getValue = MagicMock(return_value = '{"omgzomg": {"spool_weight": 10, "spool_cost": 9}}')
mocked_preferences.getValue = MagicMock(side_effect = preferencesGetValue)
global_container_stack = MagicMock()
global_container_stack.definition.getName = MagicMock(return_value = printer_name)