mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-11-02 20:52:20 -07:00
Merge branch 'master' into python_type_hinting
This commit is contained in:
commit
fb70eb6813
124 changed files with 65675 additions and 49200 deletions
|
|
@ -1,21 +1,21 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from UM.Mesh.MeshReader import MeshReader
|
||||
from UM.Mesh.MeshBuilder import MeshBuilder
|
||||
import os.path
|
||||
import zipfile
|
||||
|
||||
from UM.Job import Job
|
||||
from UM.Logger import Logger
|
||||
from UM.Math.Matrix import Matrix
|
||||
from UM.Math.Vector import Vector
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Mesh.MeshBuilder import MeshBuilder
|
||||
from UM.Mesh.MeshReader import MeshReader
|
||||
from UM.Scene.GroupDecorator import GroupDecorator
|
||||
from UM.Job import Job
|
||||
from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
||||
from UM.Application import Application
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
from cura.QualityManager import QualityManager
|
||||
|
||||
import os.path
|
||||
import zipfile
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
|
||||
try:
|
||||
import xml.etree.cElementTree as ET
|
||||
|
|
@ -262,4 +262,4 @@ class ThreeMFReader(MeshReader):
|
|||
Logger.log("w", "Unrecognised unit %s used. Assuming mm instead", unit)
|
||||
scale = 1
|
||||
|
||||
return Vector(scale, scale, scale)
|
||||
return Vector(scale, scale, scale)
|
||||
|
|
|
|||
|
|
@ -54,7 +54,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
else:
|
||||
Logger.log("w", "Could not find reader that was able to read the scene data for 3MF workspace")
|
||||
return WorkspaceReader.PreReadResult.failed
|
||||
|
||||
machine_name = ""
|
||||
machine_type = ""
|
||||
variant_type_name = i18n_catalog.i18nc("@label", "Nozzle")
|
||||
|
||||
num_extruders = 0
|
||||
# Check if there are any conflicts, so we can ask the user.
|
||||
archive = zipfile.ZipFile(file_name, "r")
|
||||
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
||||
|
|
@ -76,6 +81,30 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
machine_conflict = True
|
||||
Job.yieldThread()
|
||||
|
||||
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
|
||||
for definition_container_file in definition_container_files:
|
||||
container_id = self._stripFileToId(definition_container_file)
|
||||
definitions = self._container_registry.findDefinitionContainers(id=container_id)
|
||||
|
||||
if not definitions:
|
||||
definition_container = DefinitionContainer(container_id)
|
||||
definition_container.deserialize(archive.open(definition_container_file).read().decode("utf-8"))
|
||||
|
||||
else:
|
||||
definition_container = definitions[0]
|
||||
|
||||
if definition_container.getMetaDataEntry("type") != "extruder":
|
||||
machine_type = definition_container.getName()
|
||||
variant_type_name = definition_container.getMetaDataEntry("variants_name", variant_type_name)
|
||||
else:
|
||||
num_extruders += 1
|
||||
Job.yieldThread()
|
||||
|
||||
if num_extruders == 0:
|
||||
num_extruders = 1 # No extruder stacks found, which means there is one extruder
|
||||
|
||||
extruders = num_extruders * [""]
|
||||
|
||||
material_labels = []
|
||||
material_conflict = False
|
||||
xml_material_profile = self._getXmlProfileClass()
|
||||
|
|
@ -95,6 +124,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
quality_name = ""
|
||||
quality_type = ""
|
||||
num_settings_overriden_by_quality_changes = 0 # How many settings are changed by the quality changes
|
||||
num_user_settings = 0
|
||||
for instance_container_file in instance_container_files:
|
||||
container_id = self._stripFileToId(instance_container_file)
|
||||
instance_container = InstanceContainer(container_id)
|
||||
|
|
@ -117,6 +147,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
if quality_name == "":
|
||||
quality_name = instance_container.getName()
|
||||
quality_type = instance_container.getName()
|
||||
elif container_type == "user":
|
||||
num_user_settings += len(instance_container._instances)
|
||||
|
||||
Job.yieldThread()
|
||||
num_visible_settings = 0
|
||||
try:
|
||||
|
|
@ -142,9 +175,13 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
self._dialog.setQualityName(quality_name)
|
||||
self._dialog.setQualityType(quality_type)
|
||||
self._dialog.setNumSettingsOverridenByQualityChanges(num_settings_overriden_by_quality_changes)
|
||||
self._dialog.setNumUserSettings(num_user_settings)
|
||||
self._dialog.setActiveMode(active_mode)
|
||||
self._dialog.setMachineName(machine_name)
|
||||
self._dialog.setMaterialLabels(material_labels)
|
||||
self._dialog.setMachineType(machine_type)
|
||||
self._dialog.setExtruders(extruders)
|
||||
self._dialog.setVariantType(variant_type_name)
|
||||
self._dialog.setHasObjectsOnPlate(Application.getInstance().getPlatformActivity)
|
||||
self._dialog.show()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
# Copyright (c) 2016 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from PyQt5.QtCore import Qt, QUrl, pyqtSignal, pyqtSlot, QObject, pyqtProperty, QCoreApplication
|
||||
from PyQt5.QtCore import Qt, QUrl, pyqtSignal, QObject, pyqtProperty, QCoreApplication
|
||||
from UM.FlameProfiler import pyqtSlot
|
||||
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Application import Application
|
||||
|
|
@ -36,12 +37,16 @@ class WorkspaceDialog(QObject):
|
|||
self._has_machine_conflict = False
|
||||
self._has_material_conflict = False
|
||||
self._num_visible_settings = 0
|
||||
self._num_user_settings = 0
|
||||
self._active_mode = ""
|
||||
self._quality_name = ""
|
||||
self._num_settings_overriden_by_quality_changes = 0
|
||||
self._quality_type = ""
|
||||
self._machine_name = ""
|
||||
self._machine_type = ""
|
||||
self._variant_type = ""
|
||||
self._material_labels = []
|
||||
self._extruders = []
|
||||
self._objects_on_plate = False
|
||||
|
||||
machineConflictChanged = pyqtSignal()
|
||||
|
|
@ -55,6 +60,34 @@ class WorkspaceDialog(QObject):
|
|||
machineNameChanged = pyqtSignal()
|
||||
materialLabelsChanged = pyqtSignal()
|
||||
objectsOnPlateChanged = pyqtSignal()
|
||||
numUserSettingsChanged = pyqtSignal()
|
||||
machineTypeChanged = pyqtSignal()
|
||||
variantTypeChanged = pyqtSignal()
|
||||
extrudersChanged = pyqtSignal()
|
||||
|
||||
@pyqtProperty(str, notify=variantTypeChanged)
|
||||
def variantType(self):
|
||||
return self._variant_type
|
||||
|
||||
def setVariantType(self, variant_type):
|
||||
self._variant_type = variant_type
|
||||
self.variantTypeChanged.emit()
|
||||
|
||||
@pyqtProperty(str, notify=machineTypeChanged)
|
||||
def machineType(self):
|
||||
return self._machine_type
|
||||
|
||||
def setMachineType(self, machine_type):
|
||||
self._machine_type = machine_type
|
||||
self.machineTypeChanged.emit()
|
||||
|
||||
def setNumUserSettings(self, num_user_settings):
|
||||
self._num_user_settings = num_user_settings
|
||||
self.numVisibleSettingsChanged.emit()
|
||||
|
||||
@pyqtProperty(int, notify=numUserSettingsChanged)
|
||||
def numUserSettings(self):
|
||||
return self._num_user_settings
|
||||
|
||||
@pyqtProperty(bool, notify=objectsOnPlateChanged)
|
||||
def hasObjectsOnPlate(self):
|
||||
|
|
@ -72,6 +105,14 @@ class WorkspaceDialog(QObject):
|
|||
self._material_labels = material_labels
|
||||
self.materialLabelsChanged.emit()
|
||||
|
||||
@pyqtProperty("QVariantList", notify=extrudersChanged)
|
||||
def extruders(self):
|
||||
return self._extruders
|
||||
|
||||
def setExtruders(self, extruders):
|
||||
self._extruders = extruders
|
||||
self.extrudersChanged.emit()
|
||||
|
||||
@pyqtProperty(str, notify = machineNameChanged)
|
||||
def machineName(self):
|
||||
return self._machine_name
|
||||
|
|
@ -144,6 +185,11 @@ class WorkspaceDialog(QObject):
|
|||
if key in self._result:
|
||||
self._result[key] = strategy
|
||||
|
||||
## Close the backend: otherwise one could end up with "Slicing..."
|
||||
@pyqtSlot()
|
||||
def closeBackend(self):
|
||||
Application.getInstance().getBackend().close()
|
||||
|
||||
def setMaterialConflict(self, material_conflict):
|
||||
self._has_material_conflict = material_conflict
|
||||
self.materialConflictChanged.emit()
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ UM.Dialog
|
|||
minimumWidth: 550
|
||||
maximumWidth: 550
|
||||
|
||||
height: 350
|
||||
minimumHeight: 350
|
||||
maximumHeight: 350
|
||||
height: 400
|
||||
minimumHeight: 400
|
||||
maximumHeight: 400
|
||||
property int comboboxHeight: 15
|
||||
property int spacerHeight: 10
|
||||
onClosing: manager.notifyClosed()
|
||||
|
|
@ -28,12 +28,20 @@ UM.Dialog
|
|||
{
|
||||
machineResolveComboBox.currentIndex = 0
|
||||
qualityChangesResolveComboBox.currentIndex = 0
|
||||
materialConflictComboBox.currentIndex = 0
|
||||
materialResolveComboBox.currentIndex = 0
|
||||
}
|
||||
}
|
||||
Item
|
||||
{
|
||||
anchors.fill: parent
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
anchors.topMargin: 20
|
||||
anchors.bottomMargin: 20
|
||||
anchors.leftMargin:20
|
||||
anchors.rightMargin: 20
|
||||
|
||||
UM.I18nCatalog
|
||||
{
|
||||
|
|
@ -77,27 +85,22 @@ UM.Dialog
|
|||
width: height
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Printer settings")
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Row
|
||||
{
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
width: parent.width
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Name")
|
||||
width: parent.width / 3
|
||||
text: catalog.i18nc("@action:label", "Printer settings")
|
||||
font.bold: true
|
||||
width: parent.width /3
|
||||
}
|
||||
Label
|
||||
Item
|
||||
{
|
||||
text: manager.machineName
|
||||
// spacer
|
||||
height: spacerHeight
|
||||
width: parent.width / 3
|
||||
}
|
||||
|
||||
UM.TooltipArea
|
||||
{
|
||||
id: machineResolveTooltip
|
||||
|
|
@ -118,16 +121,20 @@ UM.Dialog
|
|||
}
|
||||
}
|
||||
}
|
||||
Item // Spacer
|
||||
Row
|
||||
{
|
||||
height: spacerHeight
|
||||
width: height
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Profile settings")
|
||||
font.bold: true
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Type")
|
||||
width: parent.width / 3
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: manager.machineType
|
||||
width: parent.width / 3
|
||||
}
|
||||
}
|
||||
|
||||
Row
|
||||
|
|
@ -141,10 +148,32 @@ UM.Dialog
|
|||
}
|
||||
Label
|
||||
{
|
||||
text: manager.qualityName
|
||||
text: manager.machineName
|
||||
width: parent.width / 3
|
||||
}
|
||||
}
|
||||
|
||||
Item // Spacer
|
||||
{
|
||||
height: spacerHeight
|
||||
width: height
|
||||
}
|
||||
Row
|
||||
{
|
||||
height: childrenRect.height
|
||||
width: parent.width
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Profile settings")
|
||||
font.bold: true
|
||||
width: parent.width / 3
|
||||
}
|
||||
Item
|
||||
{
|
||||
// spacer
|
||||
height: spacerHeight
|
||||
width: parent.width / 3
|
||||
}
|
||||
UM.TooltipArea
|
||||
{
|
||||
id: qualityChangesResolveTooltip
|
||||
|
|
@ -170,13 +199,44 @@ UM.Dialog
|
|||
width: parent.width
|
||||
height: childrenRect.height
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Name")
|
||||
width: parent.width / 3
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: manager.qualityName
|
||||
width: parent.width / 3
|
||||
}
|
||||
}
|
||||
Row
|
||||
{
|
||||
width: parent.width
|
||||
height: manager.numUserSettings != 0 ? childrenRect.height : 0
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Not in profile")
|
||||
width: parent.width / 3
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: catalog.i18ncp("@action:label", "%1 override", "%1 overrides", manager.numUserSettings).arg(manager.numUserSettings)
|
||||
width: parent.width / 3
|
||||
}
|
||||
visible: manager.numUserSettings != 0
|
||||
}
|
||||
Row
|
||||
{
|
||||
width: parent.width
|
||||
height: manager.numSettingsOverridenByQualityChanges != 0 ? childrenRect.height : 0
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Derivative from")
|
||||
width: parent.width / 3
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "%1, %2 override(s)" ).arg(manager.qualityType).arg(manager.numSettingsOverridenByQualityChanges)
|
||||
text: catalog.i18ncp("@action:label", "%1, %2 override", "%1, %2 overrides", manager.numSettingsOverridenByQualityChanges).arg(manager.qualityType).arg(manager.numSettingsOverridenByQualityChanges)
|
||||
width: parent.width / 3
|
||||
}
|
||||
visible: manager.numSettingsOverridenByQualityChanges != 0
|
||||
|
|
@ -186,11 +246,41 @@ UM.Dialog
|
|||
height: spacerHeight
|
||||
width: height
|
||||
}
|
||||
|
||||
Label
|
||||
Row
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Material settings")
|
||||
font.bold: true
|
||||
height: childrenRect.height
|
||||
width: parent.width
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@action:label", "Material settings")
|
||||
font.bold: true
|
||||
width: parent.width / 3
|
||||
}
|
||||
Item
|
||||
{
|
||||
// spacer
|
||||
height: spacerHeight
|
||||
width: parent.width / 3
|
||||
}
|
||||
UM.TooltipArea
|
||||
{
|
||||
id: materialResolveTooltip
|
||||
width: parent.width / 3
|
||||
height: visible ? comboboxHeight : 0
|
||||
visible: manager.materialConflict
|
||||
text: catalog.i18nc("@info:tooltip", "How should the conflict in the material be resolved?")
|
||||
ComboBox
|
||||
{
|
||||
model: resolveStrategiesModel
|
||||
textRole: "label"
|
||||
id: materialResolveComboBox
|
||||
width: parent.width
|
||||
onActivated:
|
||||
{
|
||||
manager.setResolveStrategy("material", resolveStrategiesModel.get(index).key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater
|
||||
|
|
@ -213,37 +303,6 @@ UM.Dialog
|
|||
}
|
||||
}
|
||||
|
||||
Row
|
||||
{
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
visible: manager.materialConflict
|
||||
Item
|
||||
{
|
||||
width: parent.width / 3 * 2
|
||||
height: comboboxHeight
|
||||
}
|
||||
|
||||
UM.TooltipArea
|
||||
{
|
||||
id: materialResolveTooltip
|
||||
width: parent.width / 3
|
||||
height: visible ? comboboxHeight : 0
|
||||
|
||||
text: catalog.i18nc("@info:tooltip", "How should the conflict in the material be resolved?")
|
||||
ComboBox
|
||||
{
|
||||
model: resolveStrategiesModel
|
||||
textRole: "label"
|
||||
id: materialResolveComboBox
|
||||
width: parent.width
|
||||
onActivated:
|
||||
{
|
||||
manager.setResolveStrategy("material", resolveStrategiesModel.get(index).key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item // Spacer
|
||||
{
|
||||
height: spacerHeight
|
||||
|
|
@ -290,30 +349,47 @@ UM.Dialog
|
|||
height: spacerHeight
|
||||
width: height
|
||||
}
|
||||
Label
|
||||
Row
|
||||
{
|
||||
text: catalog.i18nc("@action:warning", "Loading a project will clear all models on the buildplate")
|
||||
visible: manager.hasObjectsOnPlate
|
||||
color: "red"
|
||||
width: parent.width
|
||||
wrapMode: Text.Wrap
|
||||
height: childrenRect.height
|
||||
visible: manager.hasObjectsOnPlate
|
||||
UM.RecolorImage
|
||||
{
|
||||
width: warningLabel.height
|
||||
height: width
|
||||
|
||||
source: UM.Theme.getIcon("notice")
|
||||
color: "black"
|
||||
|
||||
}
|
||||
Label
|
||||
{
|
||||
id: warningLabel
|
||||
text: catalog.i18nc("@action:warning", "Loading a project will clear all models on the buildplate")
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rightButtons: [
|
||||
Button
|
||||
{
|
||||
id: ok_button
|
||||
text: catalog.i18nc("@action:button","OK");
|
||||
onClicked: { manager.onOkButtonClicked() }
|
||||
enabled: true
|
||||
},
|
||||
Button
|
||||
{
|
||||
id: cancel_button
|
||||
text: catalog.i18nc("@action:button","Cancel");
|
||||
onClicked: { manager.onCancelButtonClicked() }
|
||||
enabled: true
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: ok_button.left
|
||||
anchors.bottomMargin: - 0.5 * height
|
||||
anchors.rightMargin:2
|
||||
}
|
||||
]
|
||||
Button
|
||||
{
|
||||
id: ok_button
|
||||
text: catalog.i18nc("@action:button","Open");
|
||||
onClicked: { manager.closeBackend(); manager.onOkButtonClicked() }
|
||||
anchors.bottomMargin: - 0.5 * height
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,16 @@
|
|||
from . import ThreeMFReader
|
||||
from . import ThreeMFWorkspaceReader
|
||||
from UM.i18n import i18nCatalog
|
||||
import UM.Platform
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
def getMetaData():
|
||||
# Workarround for osx not supporting double file extensions correclty.
|
||||
if UM.Platform.isOSX():
|
||||
workspace_extension = "3mf"
|
||||
else:
|
||||
workspace_extension = "curaproject.3mf"
|
||||
return {
|
||||
"plugin": {
|
||||
"name": catalog.i18nc("@label", "3MF Reader"),
|
||||
|
|
@ -25,7 +31,7 @@ def getMetaData():
|
|||
"workspace_reader":
|
||||
[
|
||||
{
|
||||
"extension": "curaproject.3mf",
|
||||
"extension": workspace_extension,
|
||||
"description": catalog.i18nc("@item:inlistbox", "3MF File")
|
||||
}
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue