diff --git a/README.md b/README.md index f8d809df16..ba6a986093 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ For crashes and similar issues, please attach the following information: If the Cura user interface still starts, you can also reach this directory from the application menu in Help -> Show settings folder +For additional support, you could also ask in the #cura channel on FreeNode IRC. For help with development, there is also the #cura-dev channel. + Dependencies ------------ diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index c6f94f0a80..7a386ee903 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -108,11 +108,11 @@ class CrashHandler: except: self.cura_version = catalog.i18nc("@label unknown version of Cura", "Unknown") - crash_info = catalog.i18nc("@label Cura version", "Cura version: {version}
").format(version = self.cura_version) - crash_info += catalog.i18nc("@label Platform", "Platform: {platform}
").format(platform = platform.platform()) - crash_info += catalog.i18nc("@label Qt version", "Qt version: {qt}
").format(qt = QT_VERSION_STR) - crash_info += catalog.i18nc("@label PyQt version", "PyQt version: {pyqt}
").format(pyqt = PYQT_VERSION_STR) - crash_info += catalog.i18nc("@label OpenGL", "OpenGL: {opengl}
").format(opengl = self._getOpenGLInfo()) + crash_info = "" + catalog.i18nc("@label Cura version number", "Cura version") + ": " + str(self.cura_version) + "
" + crash_info += "" + catalog.i18nc("@label Type of platform", "Platform") + ": " + str(platform.platform()) + "
" + crash_info += "" + catalog.i18nc("@label", "Qt version") + ": " + str(QT_VERSION_STR) + "
" + crash_info += "" + catalog.i18nc("@label", "PyQt version") + ": " + str(PYQT_VERSION_STR) + "
" + crash_info += "" + catalog.i18nc("@label OpenGL version", "OpenGL") + ": " + str(self._getOpenGLInfo()) + "
" label.setText(crash_info) layout.addWidget(label) @@ -280,5 +280,7 @@ class CrashHandler: Application.getInstance().callLater(self._show) def _show(self): - self.dialog.exec_() - os._exit(1) + # When the exception is not in the fatal_exception_types list, the dialog is not created, so we don't need to show it + if self.dialog: + self.dialog.exec_() + os._exit(1) diff --git a/cura/MachineAction.py b/cura/MachineAction.py index bc7b17af85..37f09b4efa 100644 --- a/cura/MachineAction.py +++ b/cura/MachineAction.py @@ -73,14 +73,8 @@ class MachineAction(QObject, PluginObject): ## Protected helper to create a view object based on provided QML. def _createViewFromQML(self): - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), self._qml_url)) - self._component = QQmlComponent(Application.getInstance()._engine, path) - self._context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._context.setContextProperty("manager", self) - self._view = self._component.create(self._context) - if self._view is None: - Logger.log("c", "QQmlComponent status %s", self._component.status()) - Logger.log("c", "QQmlComponent error string %s", self._component.errorString()) + path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), self._qml_url) + self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) @pyqtProperty(QObject, constant = True) def displayItem(self): diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 543678ee22..3590d70602 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -454,16 +454,14 @@ class CuraContainerRegistry(ContainerRegistry): material_id = "default" if machine.material.getId() not in ("empty", "empty_material"): - # TODO: find the ID that's suitable for this extruder - pass + material_id = machine.material.getId() else: material_id = "empty_material" extruder_stack.setMaterialById(material_id) quality_id = "default" if machine.quality.getId() not in ("empty", "empty_quality"): - # TODO: find the ID that's suitable for this extruder - pass + quality_id = machine.quality.getId() else: quality_id = "empty_quality" extruder_stack.setQualityById(quality_id) diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index 156883ade3..f0cec3c450 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -121,7 +121,7 @@ class CuraContainerStack(ContainerStack): # # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. def setQualityById(self, new_quality_id: str) -> None: - quality = self._empty_instance_container + quality = self._empty_quality if new_quality_id == "default": new_quality = self.findDefaultQuality() if new_quality: @@ -159,7 +159,7 @@ class CuraContainerStack(ContainerStack): # # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. def setMaterialById(self, new_material_id: str) -> None: - material = self._empty_instance_container + material = self._empty_material if new_material_id == "default": new_material = self.findDefaultMaterial() if new_material: @@ -197,7 +197,7 @@ class CuraContainerStack(ContainerStack): # # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. def setVariantById(self, new_variant_id: str) -> None: - variant = self._empty_instance_container + variant = self._empty_variant if new_variant_id == "default": new_variant = self.findDefaultVariant() if new_variant: diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7be654e4f4..2dc3851c83 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -769,9 +769,10 @@ class MachineManager(QObject): candidate_quality = None if quality_type: candidate_quality = quality_manager.findQualityByQualityType(quality_type, - quality_manager.getWholeMachineDefinition(machine_definition), + quality_manager.getWholeMachineDefinition(material_container.getDefinition()), [material_container]) + if not candidate_quality or isinstance(candidate_quality, type(self._empty_quality_changes_container)): Logger.log("d", "Attempting to find fallback quality") # Fall back to a quality (which must be compatible with all other extruders) diff --git a/cura/Settings/MaterialsModel.py b/cura/Settings/MaterialsModel.py index bee9307b53..bab8929765 100644 --- a/cura/Settings/MaterialsModel.py +++ b/cura/Settings/MaterialsModel.py @@ -18,4 +18,8 @@ class MaterialsModel(InstanceContainersModel): # \param container The container whose metadata was changed. def _onContainerMetaDataChanged(self, container): if container.getMetaDataEntry("type") == "material": #Only need to update if a material was changed. - self._update() \ No newline at end of file + self._update() + + def _onContainerChanged(self, container): + if container.getMetaDataEntry("type", "") == "material": + super()._onContainerChanged(container) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 8e087611ef..dfb16b91e1 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -751,12 +751,15 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer(): stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings")) - extruder_stacks.append(stack) + if stack.getMetaDataEntry("type") == "extruder_train": + extruder_stacks.append(stack) # If not extruder stacks were saved in the project file (pre 3.1) create one manually # We re-use the container registry's addExtruderStackForSingleExtrusionMachine method for this if not extruder_stacks: - extruder_stacks.append(self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder")) + stack = self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder") + if stack: + extruder_stacks.append(stack) except: Logger.logException("w", "We failed to serialize the stack. Trying to clean up.") @@ -790,6 +793,46 @@ class ThreeMFWorkspaceReader(WorkspaceReader): for stack in [global_stack] + extruder_stacks: stack.replaceContainer(_ContainerIndexes.Quality, empty_quality_container) + # Fix quality: + # The quality specified in an old project file can be wrong, for example, for UM2, it should be "um2_normal" + # but instead it was "normal". This should be fixed by setting it to the correct quality. + # Note that this only seems to happen on single-extrusion machines on the global stack, so we only apply the + # fix for that + quality = global_stack.quality + if quality.getId() not in ("empty", "empty_quality"): + quality_type = quality.getMetaDataEntry("quality_type") + quality_containers = self._container_registry.findInstanceContainers(definition = global_stack.definition.getId(), + type = "quality", + quality_type = quality_type) + quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] + if quality_containers: + global_stack.quality = quality_containers[0] + else: + # look for "fdmprinter" qualities if the machine-specific qualities cannot be found + quality_containers = self._container_registry.findInstanceContainers(definition = "fdmprinter", + type = "quality", + quality_type = quality_type) + quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] + if quality_containers: + global_stack.quality = quality_containers[0] + else: + # the quality_type of the quality profile cannot be found. + # this can happen if a quality_type has been removed in a newer version, for example: + # "extra_coarse" is removed from 2.7 to 3.0 + # in this case, the quality will be reset to "normal" + quality_containers = self._container_registry.findInstanceContainers( + definition = global_stack.definition.getId(), + type = "quality", + quality_type = "normal") + quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] + if quality_containers: + global_stack.quality = quality_containers[0] + else: + # This should not happen! + Logger.log("e", "Cannot find quality normal for global stack [%s] [%s]", + global_stack.getId(), global_stack.definition.getId()) + global_stack.quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0] + # Replacing the old containers if resolve is "new". # When resolve is "new", some containers will get renamed, so all the other containers that reference to those # MUST get updated too. diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 151771b25d..95fef78081 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -256,14 +256,8 @@ class WorkspaceDialog(QObject): return self._result def _createViewFromQML(self): - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url)) - self._component = QQmlComponent(Application.getInstance()._engine, path) - self._context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._context.setContextProperty("manager", self) - self._view = self._component.create(self._context) - if self._view is None: - Logger.log("c", "QQmlComponent status %s", self._component.status()) - Logger.log("c", "QQmlComponent error string %s", self._component.errorString()) + path = os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url) + self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) def show(self): # Emit signal so the right thread actually shows the view. diff --git a/plugins/ChangeLogPlugin/ChangeLog.py b/plugins/ChangeLogPlugin/ChangeLog.py index a80779da50..22218bfaeb 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.py +++ b/plugins/ChangeLogPlugin/ChangeLog.py @@ -106,9 +106,5 @@ class ChangeLog(Extension, QObject,): self._changelog_window.hide() def createChangelogWindow(self): - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml")) - - component = QQmlComponent(Application.getInstance()._engine, path) - self._changelog_context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._changelog_context.setContextProperty("manager", self) - self._changelog_window = component.create(self._changelog_context) + path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml") + self._changelog_window = Application.getInstance().createQmlComponent(path, {"manager": self}) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 51fcf3ec59..37ab451d16 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -95,22 +95,22 @@ class ProcessSlicedLayersJob(Job): # Find the minimum layer number # When using a raft, the raft layers are sent as layers < 0. Instead of allowing layers < 0, we - # instead simply offset all other layers so the lowest layer is always 0. + # instead simply offset all other layers so the lowest layer is always 0. It could happens that + # the first raft layer has value -8 but there are just 4 raft (negative) layers. min_layer_number = 0 + negative_layers = 0 for layer in self._layers: if layer.id < min_layer_number: min_layer_number = layer.id + if layer.id < 0: + negative_layers += 1 current_layer = 0 for layer in self._layers: - abs_layer_number = layer.id + abs(min_layer_number) - - # Workaround when the last layer doesn't have paths, this layer is skipped because this was generating - # some glitches when rendering. - if layer.id == len(self._layers)-1 and layer.repeatedMessageCount("path_segment") == 0: - Logger.log("i", "No sliced data in the layer", layer.id) - continue + # Negative layers are offset by the minimum layer number, but the positive layers are just + # offset by the number of negative layers so there is no layer gap between raft and model + abs_layer_number = layer.id + abs(min_layer_number) if layer.id < 0 else layer.id + negative_layers layer_data.addLayer(abs_layer_number) this_layer = layer_data.getLayer(abs_layer_number) diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py index ba4c12abb2..14d3a2b741 100755 --- a/plugins/GCodeReader/GCodeReader.py +++ b/plugins/GCodeReader/GCodeReader.py @@ -144,6 +144,11 @@ class GCodeReader(MeshReader): this_layer.polygons.append(this_poly) return True + def _createEmptyLayer(self, layer_number): + self._layer_data_builder.addLayer(layer_number) + self._layer_data_builder.setLayerHeight(layer_number, 0) + self._layer_data_builder.setLayerThickness(layer_number, 0) + def _calculateLineWidth(self, current_point, previous_point, current_extrusion, previous_extrusion, layer_thickness): # Area of the filament Af = (self._filament_diameter / 2) ** 2 * numpy.pi @@ -206,7 +211,6 @@ class GCodeReader(MeshReader): return self._position( params.x if params.x is not None else position.x, params.y if params.y is not None else position.y, - 0, position.f, position.e) @@ -269,11 +273,11 @@ class GCodeReader(MeshReader): position.e.extend([0] * (self._extruder_number - len(position.e) + 1)) return position - def _processMCode(self, m): - if m == 82: + def _processMCode(self, M): + if M == 82: # Set absolute extrusion mode self._is_absolute_extrusion = True - elif m == 83: + elif M == 83: # Set relative extrusion mode self._is_absolute_extrusion = False @@ -333,6 +337,9 @@ class GCodeReader(MeshReader): current_position = self._position(0, 0, 0, 0, [0]) current_path = [] + min_layer_number = 0 + negative_layers = 0 + previous_layer = 0 for line in file: if self._cancelled: @@ -370,7 +377,23 @@ class GCodeReader(MeshReader): layer_number = int(line[len(self._layer_keyword):]) self._createPolygon(self._current_layer_thickness, current_path, self._extruder_offsets.get(self._extruder_number, [0, 0])) current_path.clear() + + # When using a raft, the raft layers are stored as layers < 0, it mimics the same behavior + # as in ProcessSlicedLayersJob + if layer_number < min_layer_number: + min_layer_number = layer_number + if layer_number < 0: + layer_number += abs(min_layer_number) + negative_layers += 1 + else: + layer_number += negative_layers + + # In case there is a gap in the layer count, empty layers are created + for empty_layer in range(previous_layer + 1, layer_number): + self._createEmptyLayer(empty_layer) + self._layer_number = layer_number + previous_layer = layer_number except: pass diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 2751ea4f60..b7bff91f9b 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -376,7 +376,7 @@ class SimulationView(View): if layer is None: return new_max_paths = layer.lineMeshElementCount() - if new_max_paths > 0 and new_max_paths != self._max_paths: + if new_max_paths >= 0 and new_max_paths != self._max_paths: self._max_paths = new_max_paths self.maxPathsChanged.emit() diff --git a/plugins/SimulationView/SimulationView.qml b/plugins/SimulationView/SimulationView.qml index bc224f19e2..42cd23cd5f 100644 --- a/plugins/SimulationView/SimulationView.qml +++ b/plugins/SimulationView/SimulationView.qml @@ -138,11 +138,10 @@ Item text: catalog.i18nc("@label:listbox", "Feedrate"), type_id: 2 }) - // TODO DON'T DELETE!!!! This part must be enabled when adaptive layer height feature is available -// layerViewTypes.append({ -// text: catalog.i18nc("@label:listbox", "Layer thickness"), -// type_id: 3 // these ids match the switching in the shader -// }) + layerViewTypes.append({ + text: catalog.i18nc("@label:listbox", "Layer thickness"), + type_id: 3 // these ids match the switching in the shader + }) } ComboBox diff --git a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py index b6e94121f8..09518575c9 100644 --- a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py @@ -486,7 +486,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte printer_name = self.__getPrinterNameFromUuid(print_job["printer_uuid"]) if printer_name is None: - printer_name = i18n_catalog.i18nc("@label", "Unknown") + printer_name = i18n_catalog.i18nc("@label Printer name", "Unknown") message_text = (i18n_catalog.i18nc("@info:status", "Printer '{printer_name}' has finished printing '{job_name}'.") diff --git a/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml b/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml index 7ae8520d19..c253ebae89 100644 --- a/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml +++ b/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml @@ -44,7 +44,7 @@ Rectangle case "maintenance": // TODO: new string case "unknown": default: - return catalog.i18nc("@label", "Unknown"); + return catalog.i18nc("@label Printer status", "Unknown"); } } diff --git a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py index fe9095a08b..6167356c4b 100644 --- a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py +++ b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py @@ -91,12 +91,8 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension): # This will create the view if its not already created. def spawnFirmwareInterface(self, serial_port): if self._firmware_view is None: - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml")) - component = QQmlComponent(Application.getInstance()._engine, path) - - self._firmware_context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._firmware_context.setContextProperty("manager", self) - self._firmware_view = component.create(self._firmware_context) + path = os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml") + self._firmware_view = Application.getInstance().createQmlComponent(path, {"manager": self}) self._firmware_view.show() diff --git a/plugins/UserAgreementPlugin/UserAgreement.py b/plugins/UserAgreementPlugin/UserAgreement.py index f472b6fb13..da225a63b4 100644 --- a/plugins/UserAgreementPlugin/UserAgreement.py +++ b/plugins/UserAgreementPlugin/UserAgreement.py @@ -45,9 +45,5 @@ class UserAgreement(QObject, Extension): CuraApplication.getInstance().setNeedToShowUserAgreement(False) def createUserAgreementWindow(self): - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "UserAgreement.qml")) - - component = QQmlComponent(Application.getInstance()._engine, path) - self._user_agreement_context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._user_agreement_context.setContextProperty("manager", self) - self._user_agreement_window = component.create(self._user_agreement_context) + path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "UserAgreement.qml") + self._user_agreement_window = Application.getInstance().createQmlComponent(path, {"manager": self}) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 88ec34274e..8db02b67f8 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1568,7 +1568,7 @@ "infill_offset_x": { "label": "Infill X Offset", - "description": "The infill pattern is offset this distance along the X axis.", + "description": "The infill pattern is moved this distance along the X axis.", "unit": "mm", "type": "float", "default_value": 0, @@ -1579,7 +1579,7 @@ "infill_offset_y": { "label": "Infill Y Offset", - "description": "The infill pattern is offset this distance along the Y axis.", + "description": "The infill pattern is moved this distance along the Y axis.", "unit": "mm", "type": "float", "default_value": 0, @@ -1966,7 +1966,7 @@ "material_bed_temperature": { "label": "Build Plate Temperature", - "description": "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print.", + "description": "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted.", "unit": "°C", "type": "float", "resolve": "max(extruderValues('material_bed_temperature'))", diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 5e014faf24..cd04b79b20 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -322,7 +322,6 @@ UM.ManagementPage { messageDialog.icon = StandardIcon.Information messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully imported material %1").arg(fileUrl) - currentItem = base.model.getItem(base.objectList.currentIndex) } else if(result.status == "duplicate") { diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 3237dd9ade..b258ecad43 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -157,7 +157,7 @@ Item { Button { id: prepareButton - tooltip: catalog.i18nc("@info:tooltip","Slice"); + tooltip: [1, 5].indexOf(UM.Backend.state) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process") // 1 = not started, 2 = Processing enabled: (base.backendState == 1 || base.backendState == 2) && base.activity == true visible: { diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index cdc0588940..8a51f2baff 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -1,5 +1,5 @@ -// Copyright (c) 2015 Ultimaker B.V. -// Uranium is released under the terms of the LGPLv3 or higher. +// Copyright (c) 2017 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 import QtQuick.Controls 1.2 @@ -108,6 +108,7 @@ SettingItem left: parent.left leftMargin: UM.Theme.getSize("setting_unit_margin").width right: parent.right + rightMargin: UM.Theme.getSize("setting_unit_margin").width verticalCenter: parent.verticalCenter } renderType: Text.NativeRendering @@ -154,7 +155,8 @@ SettingItem selectByMouse: true; - maximumLength: (definition.type == "[int]") ? 20 : (definition.type == "str") ? -1 : 10; + maximumLength: (definition.type == "str" || definition.type == "[int]") ? -1 : 10; + clip: true; //Hide any text that exceeds the width of the text box. validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[?(\s*-?[0-9]{0,9}\s*,)*(\s*-?[0-9]{0,9})\s*\]?$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : (definition.type == "float") ? /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ : /^.*$/ } // definition.type property from parent loader used to disallow fractional number entry