Merge branch 'master' into python_type_hinting

This commit is contained in:
Simon Edwards 2017-01-17 08:42:55 +01:00
commit fb70eb6813
124 changed files with 65675 additions and 49200 deletions

View file

@ -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)

View file

@ -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()

View file

@ -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()

View file

@ -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
}
}
}

View file

@ -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")
}
]