Merge branch 'refactoring_machine_manager' of github.com:Ultimaker/Cura into refactoring_machine_manager

This commit is contained in:
Jack Ha 2018-02-22 14:28:09 +01:00
commit b29d091b1d
10 changed files with 68 additions and 161 deletions

View File

@ -2,6 +2,8 @@
# Cura is released under the terms of the LGPLv3 or higher.
#Type hinting.
from typing import Dict
from PyQt5.QtCore import QObject
from PyQt5.QtNetwork import QLocalServer
from PyQt5.QtNetwork import QLocalSocket
@ -540,8 +542,6 @@ class CuraApplication(QtApplication):
has_user_interaction = True
return has_user_interaction
onDiscardOrKeepProfileChangesClosed = pyqtSignal() # Used to notify other managers that the dialog was closed
@pyqtSlot(str)
def discardOrKeepProfileChangesClosed(self, option):
if option == "discard":
@ -564,7 +564,6 @@ class CuraApplication(QtApplication):
user_global_container.update()
# notify listeners that quality has changed (after user selected discard or keep)
self.onDiscardOrKeepProfileChangesClosed.emit()
self.getMachineManager().activeQualityChanged.emit()
@pyqtSlot(int)
@ -862,11 +861,13 @@ class CuraApplication(QtApplication):
self._object_manager = ObjectsModel.createObjectsModel()
return self._object_manager
@pyqtSlot(result = QObject)
def getMultiBuildPlateModel(self, *args):
if self._multi_build_plate_model is None:
self._multi_build_plate_model = MultiBuildPlateModel(self)
return self._multi_build_plate_model
@pyqtSlot(result = QObject)
def getBuildPlateModel(self, *args):
if self._build_plate_model is None:
self._build_plate_model = BuildPlateModel(self)
@ -939,8 +940,8 @@ class CuraApplication(QtApplication):
qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager)
qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 0, "ObjectsModel", self.getObjectsModel)
qmlRegisterSingletonType(BuildPlateModel, "Cura", 1, 0, "BuildPlateModel", self.getBuildPlateModel)
qmlRegisterSingletonType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel", self.getMultiBuildPlateModel)
qmlRegisterType(BuildPlateModel, "Cura", 1, 0, "BuildPlateModel")
qmlRegisterType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel")
qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer")
qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")

View File

@ -54,12 +54,6 @@ class MachineManager(QObject):
self.machine_extruder_material_update_dict = collections.defaultdict(list)
# Used to store the new containers until after confirming the dialog
self._new_variant_container = None # type: Optional[InstanceContainer]
self._new_buildplate_container = None # type: Optional[InstanceContainer]
self._new_material_container = None # type: Optional[InstanceContainer]
self._new_quality_containers = [] # type: List[Dict]
self._error_check_timer = QTimer()
self._error_check_timer.setInterval(250)
self._error_check_timer.setSingleShot(True)
@ -79,6 +73,9 @@ class MachineManager(QObject):
self.globalContainerChanged.connect(self.activeVariantChanged)
self.globalContainerChanged.connect(self.activeQualityChanged)
self.globalContainerChanged.connect(self.activeQualityChangesGroupChanged)
self.globalContainerChanged.connect(self.activeQualityGroupChanged)
self._stacks_have_errors = None # type:Optional[bool]
self._empty_definition_changes_container = ContainerRegistry.getInstance().findContainers(id = "empty_definition_changes")[0]
@ -101,9 +98,6 @@ class MachineManager(QObject):
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeStackChanged)
self.activeStackChanged.connect(self.activeStackValueChanged)
# when a user closed dialog check if any delayed material or variant changes need to be applied
Application.getInstance().onDiscardOrKeepProfileChangesClosed.connect(self._executeDelayedActiveContainerStackChanges)
Preferences.getInstance().addPreference("cura/active_machine", "")
self._global_event_keys = set()
@ -169,18 +163,6 @@ class MachineManager(QObject):
self.outputDevicesChanged.emit()
@property
def newVariant(self):
return self._new_variant_container
@property
def newBuildplate(self):
return self._new_buildplate_container
@property
def newMaterial(self):
return self._new_material_container
@pyqtProperty("QVariantList", notify = outputDevicesChanged)
def printerOutputDevices(self):
return self._printer_output_devices
@ -242,6 +224,7 @@ class MachineManager(QObject):
Application.getInstance().callLater(func)
del self.machine_extruder_material_update_dict[self._global_container_stack.getId()]
self.activeQualityGroupChanged.emit()
self._error_check_timer.start()
## Update self._stacks_valid according to _checkStacksForErrors and emit if change.
@ -290,26 +273,26 @@ class MachineManager(QObject):
material_dict[position] = extruder.material.getMetaDataEntry("base_file")
self._current_root_material_id = material_dict
global_quality = global_stack.quality
global_quality_changes = global_stack.qualityChanges
quality_groups = self._application._quality_manager.getQualityGroups(global_stack)
quality_type = global_quality.getMetaDataEntry("quality_type")
if not quality_type in quality_groups:
Logger.log("w", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values()))
return
new_quality_group = quality_groups[quality_type]
self._setQualityGroup(new_quality_group)
global_quality_changes = global_stack.qualityChanges
global_quality_changes_name = global_quality_changes.getName()
if global_quality_changes.getId() != "empty_quality_changes":
quality_changes_groups = self._application._quality_manager.getQualityChangesGroups(global_stack)
if quality_type in quality_changes_groups:
new_quality_changes_group = quality_changes_groups[quality_type]
if global_quality_changes_name in quality_changes_groups:
new_quality_changes_group = quality_changes_groups[global_quality_changes_name]
self._setQualityChangesGroup(new_quality_changes_group)
else:
quality_groups = self._application._quality_manager.getQualityGroups(global_stack)
if quality_type not in quality_groups:
Logger.log("w", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values()))
return
new_quality_group = quality_groups[quality_type]
self._setQualityGroup(new_quality_group)
@pyqtSlot(str)
def setActiveMachine(self, stack_id: str) -> None:
self.blurSettings.emit() # Ensure no-one has focus.
self._cancelDelayedActiveContainerStackChanges()
container_registry = ContainerRegistry.getInstance()
@ -491,7 +474,7 @@ class MachineManager(QObject):
#
# \return The layer height of the currently active quality profile. If
# there is no quality profile, this returns 0.
@pyqtProperty(float, notify=activeQualityChanged)
@pyqtProperty(float, notify = activeQualityGroupChanged)
def activeQualityLayerHeight(self) -> float:
if not self._global_container_stack:
return 0
@ -511,34 +494,7 @@ class MachineManager(QObject):
return 0 # No quality profile.
@pyqtProperty(str, notify=activeQualityChanged)
def activeQualityId(self) -> str:
if self._active_container_stack:
quality = self._active_container_stack.quality
if isinstance(quality, type(self._empty_quality_container)):
return ""
quality_changes = self._active_container_stack.qualityChanges
if quality and quality_changes:
if isinstance(quality_changes, type(self._empty_quality_changes_container)):
# It's a built-in profile
return quality.getId()
else:
# Custom profile
return quality_changes.getId()
return ""
@pyqtProperty(str, notify=activeQualityChanged)
def globalQualityId(self) -> str:
if self._global_container_stack:
quality = self._global_container_stack.qualityChanges
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
return quality.getId()
quality = self._global_container_stack.quality
if quality:
return quality.getId()
return ""
@pyqtProperty(str, notify=activeVariantChanged)
@pyqtProperty(str, notify = activeVariantChanged)
def globalVariantName(self) -> str:
if self._global_container_stack:
variant = self._global_container_stack.variant
@ -546,21 +502,21 @@ class MachineManager(QObject):
return variant.getName()
return ""
@pyqtProperty(str, notify = activeQualityChanged)
@pyqtProperty(str, notify = activeQualityGroupChanged)
def activeQualityType(self) -> str:
quality_type = ""
if self._active_container_stack:
quality = self._active_container_stack.quality
if quality:
return quality.getMetaDataEntry("quality_type")
return ""
if self._current_quality_group:
quality_type = self._current_quality_group.quality_type
return quality_type
@pyqtProperty(bool, notify = activeQualityChanged)
@pyqtProperty(bool, notify = activeQualityGroupChanged)
def isActiveQualitySupported(self) -> bool:
if self._active_container_stack:
quality = self._active_container_stack.quality
if quality:
return Util.parseBool(quality.getMetaDataEntry("supported", True))
return False
is_supported = False
if self._global_container_stack:
if self._current_quality_group:
is_supported = self._current_quality_group.is_available
return is_supported
## Returns whether there is anything unsupported in the current set-up.
#
@ -595,61 +551,6 @@ class MachineManager(QObject):
if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value:
extruder_stack.userChanges.setProperty(key, "value", new_value) # TODO: nested property access, should be improved
## Used to update material and variant in the active container stack with a delay.
# This delay prevents the stack from triggering a lot of signals (eventually resulting in slicing)
# before the user decided to keep or discard any of their changes using the dialog.
# The Application.onDiscardOrKeepProfileChangesClosed signal triggers this method.
def _executeDelayedActiveContainerStackChanges(self):
Logger.log("d", "Applying configuration changes...")
if self._new_variant_container is not None:
self._active_container_stack.variant = self._new_variant_container
self._new_variant_container = None
if self._new_buildplate_container is not None:
self._global_container_stack.variant = self._new_buildplate_container
self._new_buildplate_container = None
if self._new_material_container is not None:
self._active_container_stack.material = self._new_material_container
self._new_material_container = None
# apply the new quality to all stacks
if self._new_quality_containers:
for new_quality in self._new_quality_containers:
self._replaceQualityOrQualityChangesInStack(new_quality["stack"], new_quality["quality"], postpone_emit = True)
self._replaceQualityOrQualityChangesInStack(new_quality["stack"], new_quality["quality_changes"], postpone_emit = True)
for new_quality in self._new_quality_containers:
new_quality["stack"].nameChanged.connect(self._onQualityNameChanged)
new_quality["stack"].sendPostponedEmits() # Send the signals that were postponed in _replaceQualityOrQualityChangesInStack
self._new_quality_containers.clear()
Logger.log("d", "New configuration applied")
## Cancel set changes for material and variant in the active container stack.
# Used for ignoring any changes when switching between printers (setActiveMachine)
def _cancelDelayedActiveContainerStackChanges(self):
self._new_material_container = None
self._new_buildplate_container = None
self._new_variant_container = None
def _replaceQualityOrQualityChangesInStack(self, stack: "CuraContainerStack", container: "InstanceContainer", postpone_emit = False):
# Disconnect the signal handling from the old container.
container_type = container.getMetaDataEntry("type")
if container_type == "quality":
stack.quality.nameChanged.disconnect(self._onQualityNameChanged)
stack.setQuality(container, postpone_emit = postpone_emit)
stack.quality.nameChanged.connect(self._onQualityNameChanged)
elif container_type == "quality_changes" or container_type is None:
# If the container is an empty container, we need to change the quality_changes.
# Quality can never be set to empty.
stack.qualityChanges.nameChanged.disconnect(self._onQualityNameChanged)
stack.setQualityChanges(container, postpone_emit = postpone_emit)
stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged)
self._onQualityNameChanged()
@pyqtProperty(str, notify = activeVariantChanged)
def activeVariantName(self) -> str:
if self._active_container_stack:
@ -945,6 +846,7 @@ class MachineManager(QObject):
extruder.qualityChanges = self._empty_quality_changes_container
self.activeQualityGroupChanged.emit()
self.activeQualityChangesGroupChanged.emit()
def _setQualityGroup(self, quality_group, empty_quality_changes = True):
self._current_quality_group = quality_group

View File

@ -173,7 +173,7 @@ Item
Action
{
id: updateProfileAction;
enabled: !Cura.MachineManager.stacksHaveErrors && Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId)
enabled: !Cura.MachineManager.stacksHaveErrors && Cura.MachineManager.hasUserSettings && Cura.MachineManager.activeQualityChangesGroup != null
text: catalog.i18nc("@action:inmenu menubar:profile","&Update profile with current settings/overrides");
onTriggered: Cura.ContainerManager.updateQualityChanges();
}

View File

@ -12,17 +12,19 @@ Menu
id: menu
title: "Build plate"
property Cura.BuildPlateModel buildPlateModel: CuraApplication.getBuildPlateModel()
Instantiator
{
model: Cura.BuildPlateModel
model: menu.buildPlateModel
MenuItem {
text: model.name
checkable: true
checked: model.name == Cura.MachineManager.globalVariantName // TODO
checked: model.name == Cura.MachineManager.globalVariantName
exclusiveGroup: group
onTriggered: {
Cura.MachineManager.setGlobalVariant(model.container_node); // TODO
Cura.MachineManager.setGlobalVariant(model.container_node);
}
}

View File

@ -15,6 +15,8 @@ Menu
property bool shouldShowExtruders: machineExtruderCount.properties.value > 1;
property Cura.MultiBuildPlateModel multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel()
// Selection-related actions.
MenuItem { action: Cura.Actions.centerSelection; }
MenuItem { action: Cura.Actions.deleteSelection; }
@ -45,13 +47,13 @@ Menu
Instantiator
{
model: Cura.MultiBuildPlateModel
model: base.multiBuildPlateModel
MenuItem {
enabled: UM.Selection.hasSelection
text: Cura.MultiBuildPlateModel.getItem(index).name;
onTriggered: CuraActions.setBuildPlateForSelection(Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber);
text: base.multiBuildPlateModel.getItem(index).name;
onTriggered: CuraActions.setBuildPlateForSelection(base.multiBuildPlateModel.getItem(index).buildPlateNumber);
checkable: true
checked: Cura.MultiBuildPlateModel.selectionBuildPlates.indexOf(Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber) != -1;
checked: base.multiBuildPlateModel.selectionBuildPlates.indexOf(base.multiBuildPlateModel.getItem(index).buildPlateNumber) != -1;
visible: UM.Preferences.getValue("cura/use_multi_build_plate")
}
onObjectAdded: base.insertItem(index, object);
@ -62,7 +64,7 @@ Menu
enabled: UM.Selection.hasSelection
text: "New build plate";
onTriggered: {
CuraActions.setBuildPlateForSelection(Cura.MultiBuildPlateModel.maxBuildPlate + 1);
CuraActions.setBuildPlateForSelection(base.multiBuildPlateModel.maxBuildPlate + 1);
checked = false;
}
checkable: true

View File

@ -13,6 +13,8 @@ Menu
id: base
enabled: !PrintInformation.preSliced
property Cura.MultiBuildPlateModel multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel()
// main views
Instantiator
{
@ -53,12 +55,12 @@ Menu
visible: UM.Preferences.getValue("cura/use_multi_build_plate")
Instantiator
{
model: Cura.MultiBuildPlateModel
model: base.multiBuildPlateModel
MenuItem {
text: Cura.MultiBuildPlateModel.getItem(index).name;
onTriggered: Cura.SceneController.setActiveBuildPlate(Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber);
text: base.multiBuildPlateModel.getItem(index).name;
onTriggered: Cura.SceneController.setActiveBuildPlate(base.multiBuildPlateModel.getItem(index).buildPlateNumber);
checkable: true;
checked: Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber == Cura.MultiBuildPlateModel.activeBuildPlate;
checked: base.multiBuildPlateModel.getItem(index).buildPlateNumber == base.multiBuildPlateModel.activeBuildPlate;
exclusiveGroup: buildPlateGroup;
visible: UM.Preferences.getValue("cura/use_multi_build_plate")
}

View File

@ -33,6 +33,8 @@ Rectangle
property bool collapsed: true;
property Cura.MultiBuildPlateModel multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel()
SystemPalette { id: palette }
Button {
@ -67,7 +69,7 @@ Rectangle
Rectangle
{
height: childrenRect.height
color: Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber == Cura.MultiBuildPlateModel.activeBuildPlate ? palette.highlight : index % 2 ? palette.base : palette.alternateBase
color: multiBuildPlateModel.getItem(index).buildPlateNumber == multiBuildPlateModel.activeBuildPlate ? palette.highlight : index % 2 ? palette.base : palette.alternateBase
width: parent.width
Label
{
@ -75,8 +77,8 @@ Rectangle
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width
width: parent.width - 2 * UM.Theme.getSize("default_margin").width - 30
text: Cura.MultiBuildPlateModel.getItem(index) ? Cura.MultiBuildPlateModel.getItem(index).name : "";
color: Cura.MultiBuildPlateModel.activeBuildPlate == index ? palette.highlightedText : palette.text
text: multiBuildPlateModel.getItem(index) ? multiBuildPlateModel.getItem(index).name : "";
color: multiBuildPlateModel.activeBuildPlate == index ? palette.highlightedText : palette.text
elide: Text.ElideRight
}
@ -118,13 +120,12 @@ Rectangle
ListView
{
id: buildPlateListView
model: Cura.MultiBuildPlateModel
model: multiBuildPlateModel
width: parent.width
delegate: buildPlateDelegate
}
}
Component {
id: objectDelegate
Rectangle
@ -200,7 +201,6 @@ Rectangle
}
}
CheckBox
{
id: filterBuildPlateCheckbox
@ -260,6 +260,4 @@ Rectangle
}
action: Cura.Actions.arrangeAll;
}
}

View File

@ -36,8 +36,8 @@ Tab
anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.right: parent.right
text: (styleData.value.substr(0,1) == "=") ? catalog.i18nc("@info:status", "Calculated") : styleData.value
font.strikeout: styleData.column == 1 && setting.user_value != "" // TODO && quality == Cura.MachineManager.globalQualityId
font.italic: setting.profile_value_source == "quality_changes" || (setting.user_value != "") // TODO: (setting.user_value != "" && quality == Cura.MachineManager.globalQualityId)
font.strikeout: styleData.column == 1 && setting.user_value != "" && qualityItem.name == Cura.MachineManager.activeQualityOrQualityChangesName
font.italic: setting.profile_value_source == "quality_changes" || (setting.user_value != "" && qualityItem.name == Cura.MachineManager.activeQualityOrQualityChangesName)
opacity: font.strikeout ? 0.5 : 1
color: styleData.textColor
elide: Text.ElideRight
@ -63,7 +63,7 @@ Tab
{
role: "user_value"
title: catalog.i18nc("@title:column", "Current");
visible: true // TODO quality == Cura.MachineManager.globalQualityId
visible: qualityItem.name == Cura.MachineManager.activeQualityOrQualityChangesName
width: (parent.width * 0.18) | 0
delegate: itemDelegate
}

View File

@ -408,14 +408,14 @@ Item
height: childrenRect.height
Label {
text: base.currentItem.name // TODO
text: base.currentItem.name
font: UM.Theme.getFont("large")
}
}
Flow {
id: currentSettingsActions
visible: true // TODO //currentItem && currentItem.id == Cura.MachineManager.activeQualityId
visible: base.hasCurrentItem && base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName
anchors.left: parent.left
anchors.right: parent.right
anchors.top: profileName.bottom
@ -424,7 +424,7 @@ Item
Button
{
text: catalog.i18nc("@action:button", "Update profile with current settings/overrides")
enabled: Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId)
enabled: Cura.MachineManager.hasUserSettings && !base.currentItem.is_read_only
onClicked: Cura.ContainerManager.updateQualityChanges()
}
@ -453,7 +453,7 @@ Item
}
Label {
id: noCurrentSettingsMessage
visible: currentItem && currentItem.id == Cura.MachineManager.activeQualityId && !Cura.MachineManager.hasUserSettings
visible: base.isCurrentItemActivated && !Cura.MachineManager.hasUserSettings
text: catalog.i18nc("@action:label", "Your current settings match the selected profile.")
wrapMode: Text.WordWrap
width: parent.width

View File

@ -1,7 +1,7 @@
// Copyright (c) 2015 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.8
import QtQuick.Controls 2.0
import "Settings"