Merge pull request #6240 from Ultimaker/CURA-6732_available_configurations

Cura 6732 available configurations
This commit is contained in:
Lipu Fei 2019-08-22 16:03:46 +02:00 committed by GitHub
commit 8d8f18d953
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 145 additions and 17 deletions

View File

@ -7,6 +7,7 @@ from UM.Math.Vector import Vector
from cura.PrinterOutput.Peripheral import Peripheral
from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
from cura.PrinterOutput.Models.ExtruderOutputModel import ExtruderOutputModel
from UM.Logger import Logger
if TYPE_CHECKING:
from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
@ -37,7 +38,7 @@ class PrinterOutputModel(QObject):
self._controller = output_controller
self._controller.canUpdateFirmwareChanged.connect(self._onControllerCanUpdateFirmwareChanged)
self._extruders = [ExtruderOutputModel(printer = self, position = i) for i in range(number_of_extruders)]
self._printer_configuration = PrinterConfigurationModel() # Indicates the current configuration setup in this printer
self._active_printer_configuration = PrinterConfigurationModel() # Indicates the current configuration setup in this printer
self._head_position = Vector(0, 0, 0)
self._active_print_job = None # type: Optional[PrintJobOutputModel]
self._firmware_version = firmware_version
@ -47,8 +48,10 @@ class PrinterOutputModel(QObject):
self._buildplate = ""
self._peripherals = [] # type: List[Peripheral]
self._printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in
self._extruders]
self._active_printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in
self._extruders]
self._available_printer_configurations = [] # type: List[PrinterConfigurationModel]
self._camera_url = QUrl() # type: QUrl
@ -81,7 +84,7 @@ class PrinterOutputModel(QObject):
def updateType(self, printer_type: str) -> None:
if self._printer_type != printer_type:
self._printer_type = printer_type
self._printer_configuration.printerType = self._printer_type
self._active_printer_configuration.printerType = self._printer_type
self.typeChanged.emit()
self.configurationChanged.emit()
@ -92,7 +95,7 @@ class PrinterOutputModel(QObject):
def updateBuildplate(self, buildplate: str) -> None:
if self._buildplate != buildplate:
self._buildplate = buildplate
self._printer_configuration.buildplateConfiguration = self._buildplate
self._active_printer_configuration.buildplateConfiguration = self._buildplate
self.buildplateChanged.emit()
self.configurationChanged.emit()
@ -290,18 +293,18 @@ class PrinterOutputModel(QObject):
def _onControllerCanUpdateFirmwareChanged(self) -> None:
self.canUpdateFirmwareChanged.emit()
# Returns the configuration (material, variant and buildplate) of the current printer
# Returns the active configuration (material, variant and buildplate) of the current printer
@pyqtProperty(QObject, notify = configurationChanged)
def printerConfiguration(self) -> Optional[PrinterConfigurationModel]:
if self._printer_configuration.isValid():
return self._printer_configuration
if self._active_printer_configuration.isValid():
return self._active_printer_configuration
return None
peripheralsChanged = pyqtSignal()
@pyqtProperty(str, notify = peripheralsChanged)
def peripherals(self) -> str:
return ", ".join(*[peripheral.name for peripheral in self._peripherals])
return ", ".join([peripheral.name for peripheral in self._peripherals])
def addPeripheral(self, peripheral: Peripheral) -> None:
self._peripherals.append(peripheral)
@ -309,4 +312,29 @@ class PrinterOutputModel(QObject):
def removePeripheral(self, peripheral: Peripheral) -> None:
self._peripherals.remove(peripheral)
self.peripheralsChanged.emit()
self.peripheralsChanged.emit()
availableConfigurationsChanged = pyqtSignal()
# The availableConfigurations are configuration options that a printer can switch to, but doesn't currently have
# active (eg; Automatic tool changes, material loaders, etc).
@pyqtProperty("QVariantList", notify = availableConfigurationsChanged)
def availableConfigurations(self) -> List[PrinterConfigurationModel]:
return self._available_printer_configurations
def addAvailableConfiguration(self, new_configuration: PrinterConfigurationModel) -> None:
if new_configuration not in self._available_printer_configurations:
self._available_printer_configurations.append(new_configuration)
self.availableConfigurationsChanged.emit()
def removeAvailableConfiguration(self, config_to_remove: PrinterConfigurationModel) -> None:
try:
self._available_printer_configurations.remove(config_to_remove)
except ValueError:
Logger.log("w", "Unable to remove configuration that isn't in the list of available configurations")
else:
self.availableConfigurationsChanged.emit()
def setAvailableConfigurations(self, new_configurations: List[PrinterConfigurationModel]) -> None:
self._available_printer_configurations = new_configurations
self.availableConfigurationsChanged.emit()

View File

@ -220,11 +220,15 @@ class PrinterOutputDevice(QObject, OutputDevice):
return self._unique_configurations
def _updateUniqueConfigurations(self) -> None:
self._unique_configurations = sorted(
{printer.printerConfiguration for printer in self._printers if printer.printerConfiguration is not None},
key=lambda config: config.printerType,
)
self.uniqueConfigurationsChanged.emit()
all_configurations = set()
for printer in self._printers:
if printer.printerConfiguration is not None:
all_configurations.add(printer.printerConfiguration)
all_configurations.update(printer.availableConfigurations)
new_configurations = sorted(all_configurations, key = lambda config: config.printerType)
if new_configurations != self._unique_configurations:
self._unique_configurations = new_configurations
self.uniqueConfigurationsChanged.emit()
# Returns the unique configurations of the printers within this output device
@pyqtProperty("QStringList", notify = uniqueConfigurationsChanged)
@ -234,6 +238,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
def _onPrintersChanged(self) -> None:
for printer in self._printers:
printer.configurationChanged.connect(self._updateUniqueConfigurations)
printer.availableConfigurationsChanged.connect(self._updateUniqueConfigurations)
# At this point there may be non-updated configurations
self._updateUniqueConfigurations()

View File

@ -5,11 +5,14 @@ from unittest.mock import MagicMock
import pytest
from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.Peripheral import Peripheral
test_validate_data_get_set = [
{"attribute": "name", "value": "YAY"},
{"attribute": "targetBedTemperature", "value": 192},
{"attribute": "cameraUrl", "value": "YAY!"}
]
test_validate_data_get_update = [
@ -22,6 +25,7 @@ test_validate_data_get_update = [
{"attribute": "targetBedTemperature", "value": 9001},
{"attribute": "activePrintJob", "value": PrintJobOutputModel(MagicMock())},
{"attribute": "state", "value": "BEEPBOOP"},
]
@ -79,3 +83,67 @@ def test_getAndUpdate(data):
getattr(model, "update" + attribute)(data["value"])
# The signal should not fire again
assert signal.emit.call_count == 1
def test_peripherals():
model = PrinterOutputModel(MagicMock())
model.peripheralsChanged = MagicMock()
peripheral = MagicMock(spec=Peripheral)
peripheral.name = "test"
peripheral2 = MagicMock(spec=Peripheral)
peripheral2.name = "test2"
model.addPeripheral(peripheral)
assert model.peripheralsChanged.emit.call_count == 1
model.addPeripheral(peripheral2)
assert model.peripheralsChanged.emit.call_count == 2
assert model.peripherals == "test, test2"
model.removePeripheral(peripheral)
assert model.peripheralsChanged.emit.call_count == 3
assert model.peripherals == "test2"
def test_availableConfigurations_addConfiguration():
model = PrinterOutputModel(MagicMock())
configuration = MagicMock(spec = PrinterConfigurationModel)
model.addAvailableConfiguration(configuration)
assert model.availableConfigurations == [configuration]
def test_availableConfigurations_addConfigTwice():
model = PrinterOutputModel(MagicMock())
configuration = MagicMock(spec=PrinterConfigurationModel)
model.setAvailableConfigurations([configuration])
assert model.availableConfigurations == [configuration]
# Adding it again should not have any effect
model.addAvailableConfiguration(configuration)
assert model.availableConfigurations == [configuration]
def test_availableConfigurations_removeConfig():
model = PrinterOutputModel(MagicMock())
configuration = MagicMock(spec=PrinterConfigurationModel)
model.addAvailableConfiguration(configuration)
model.removeAvailableConfiguration(configuration)
assert model.availableConfigurations == []
def test_removeAlreadyRemovedConfiguration():
model = PrinterOutputModel(MagicMock())
configuration = MagicMock(spec=PrinterConfigurationModel)
model.availableConfigurationsChanged = MagicMock()
model.removeAvailableConfiguration(configuration)
assert model.availableConfigurationsChanged.emit.call_count == 0
assert model.availableConfigurations == []

View File

@ -1,6 +1,10 @@
from unittest.mock import MagicMock
import pytest
from unittest.mock import patch
from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
test_validate_data_get_set = [
@ -8,10 +12,15 @@ test_validate_data_get_set = [
{"attribute": "connectionState", "value": 1},
]
@pytest.fixture()
def printer_output_device():
with patch("UM.Application.Application.getInstance"):
return PrinterOutputDevice("whatever")
@pytest.mark.parametrize("data", test_validate_data_get_set)
def test_getAndSet(data):
model = PrinterOutputDevice("whatever")
def test_getAndSet(data, printer_output_device):
model = printer_output_device
# Convert the first letter into a capital
attribute = list(data["attribute"])
@ -35,3 +44,21 @@ def test_getAndSet(data):
getattr(model, "set" + attribute)(data["value"])
# The signal should not fire again
assert signal.emit.call_count == 1
def test_uniqueConfigurations(printer_output_device):
printer = PrinterOutputModel(MagicMock())
# Add a printer and fire the signal that ensures they get hooked up correctly.
printer_output_device._printers = [printer]
printer_output_device._onPrintersChanged()
assert printer_output_device.uniqueConfigurations == []
configuration = PrinterConfigurationModel()
printer.addAvailableConfiguration(configuration)
assert printer_output_device.uniqueConfigurations == [configuration]
# Once the type of printer is set, it's active configuration counts as being set.
# In that case, that should also be added to the list of available configurations
printer.updateType("blarg!")
assert printer_output_device.uniqueConfigurations == [configuration, printer.printerConfiguration]