Add typing

Because of boyscouting. CURA-5814
This commit is contained in:
Jaime van Kessel 2018-10-17 13:31:03 +02:00
parent f013450195
commit 6555f4d4f3

View File

@ -6,7 +6,7 @@ import math
import os import os
import unicodedata import unicodedata
import re # To create abbreviations for printer names. import re # To create abbreviations for printer names.
from typing import Dict from typing import Dict, List, Optional
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
@ -16,6 +16,12 @@ from UM.Scene.SceneNode import SceneNode
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.MimeTypeDatabase import MimeTypeDatabase from UM.MimeTypeDatabase import MimeTypeDatabase
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
@ -47,24 +53,26 @@ class PrintInformation(QObject):
ActiveMachineChanged = 3 ActiveMachineChanged = 3
Other = 4 Other = 4
def __init__(self, application, parent = None): UNTITLED_JOB_NAME = "Untitled"
def __init__(self, application: "CuraApplication", parent = None) -> None:
super().__init__(parent) super().__init__(parent)
self._application = application self._application = application
self.UNTITLED_JOB_NAME = "Untitled"
self.initializeCuraMessagePrintTimeProperties() self.initializeCuraMessagePrintTimeProperties()
self._material_lengths = {} # indexed by build plate number # Indexed by build plate number
self._material_weights = {} self._material_lengths = {} # type: Dict[int, List[float]]
self._material_costs = {} self._material_weights = {} # type: Dict[int, List[float]]
self._material_names = {} self._material_costs = {} # type: Dict[int, List[float]]
self._material_names = {} # type: Dict[int, List[str]]
self._pre_sliced = False self._pre_sliced = False
self._backend = self._application.getBackend() self._backend = self._application.getBackend()
if self._backend: if self._backend:
self._backend.printDurationMessage.connect(self._onPrintDurationMessage) self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
self._application.getController().getScene().sceneChanged.connect(self._onSceneChanged) self._application.getController().getScene().sceneChanged.connect(self._onSceneChanged)
self._is_user_specified_job_name = False self._is_user_specified_job_name = False
@ -76,25 +84,23 @@ class PrintInformation(QObject):
self._multi_build_plate_model = self._application.getMultiBuildPlateModel() self._multi_build_plate_model = self._application.getMultiBuildPlateModel()
ss = self._multi_build_plate_model.maxBuildPlate
self._application.globalContainerStackChanged.connect(self._updateJobName) self._application.globalContainerStackChanged.connect(self._updateJobName)
self._application.globalContainerStackChanged.connect(self.setToZeroPrintInformation) self._application.globalContainerStackChanged.connect(self.setToZeroPrintInformation)
self._application.fileLoaded.connect(self.setBaseName) self._application.fileLoaded.connect(self.setBaseName)
self._application.workspaceLoaded.connect(self.setProjectName) self._application.workspaceLoaded.connect(self.setProjectName)
self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveBuildPlateChanged) self._application.getMachineManager().rootMaterialChanged.connect(self._onActiveMaterialsChanged)
self._application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferencesChanged) self._application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferencesChanged)
self._application.getMachineManager().rootMaterialChanged.connect(self._onActiveMaterialsChanged) self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveBuildPlateChanged)
self._onActiveMaterialsChanged() self._onActiveMaterialsChanged()
self._material_amounts = [] self._material_amounts = [] # type: List[float]
# Crate cura message translations and using translation keys initialize empty time Duration object for total time # Crate cura message translations and using translation keys initialize empty time Duration object for total time
# and time for each feature # and time for each feature
def initializeCuraMessagePrintTimeProperties(self): def initializeCuraMessagePrintTimeProperties(self) -> None:
self._current_print_time = {} # Duration(None, self) self._current_print_time = {} # type: Dict[int, Duration]
self._print_time_message_translations = { self._print_time_message_translations = {
"inset_0": catalog.i18nc("@tooltip", "Outer Wall"), "inset_0": catalog.i18nc("@tooltip", "Outer Wall"),
@ -110,15 +116,15 @@ class PrintInformation(QObject):
"none": catalog.i18nc("@tooltip", "Other") "none": catalog.i18nc("@tooltip", "Other")
} }
self._print_time_message_values = {} self._print_time_message_values = {} # type: Dict[int, Dict[str, Duration]]
def _initPrintTimeMessageValues(self, build_plate_number): def _initPrintTimeMessageValues(self, build_plate_number: int) -> None:
# Full fill message values using keys from _print_time_message_translations # Full fill message values using keys from _print_time_message_translations
self._print_time_message_values[build_plate_number] = {} self._print_time_message_values[build_plate_number] = {}
for key in self._print_time_message_translations.keys(): for key in self._print_time_message_translations.keys():
self._print_time_message_values[build_plate_number][key] = Duration(None, self) self._print_time_message_values[build_plate_number][key] = Duration(None, self)
def _initVariablesWithBuildPlate(self, build_plate_number): def _initVariablesWithBuildPlate(self, build_plate_number: int) -> None:
if build_plate_number not in self._print_time_message_values: if build_plate_number not in self._print_time_message_values:
self._initPrintTimeMessageValues(build_plate_number) self._initPrintTimeMessageValues(build_plate_number)
if self._active_build_plate not in self._material_lengths: if self._active_build_plate not in self._material_lengths:
@ -130,23 +136,24 @@ class PrintInformation(QObject):
if self._active_build_plate not in self._material_names: if self._active_build_plate not in self._material_names:
self._material_names[self._active_build_plate] = [] self._material_names[self._active_build_plate] = []
if self._active_build_plate not in self._current_print_time: if self._active_build_plate not in self._current_print_time:
self._current_print_time[self._active_build_plate] = Duration(None, self) self._current_print_time[self._active_build_plate] = Duration(parent = self)
currentPrintTimeChanged = pyqtSignal() currentPrintTimeChanged = pyqtSignal()
preSlicedChanged = pyqtSignal() preSlicedChanged = pyqtSignal()
@pyqtProperty(bool, notify=preSlicedChanged) @pyqtProperty(bool, notify=preSlicedChanged)
def preSliced(self): def preSliced(self) -> bool:
return self._pre_sliced return self._pre_sliced
def setPreSliced(self, pre_sliced): def setPreSliced(self, pre_sliced: bool) -> None:
self._pre_sliced = pre_sliced if self._pre_sliced != pre_sliced:
self._updateJobName() self._pre_sliced = pre_sliced
self.preSlicedChanged.emit() self._updateJobName()
self.preSlicedChanged.emit()
@pyqtProperty(Duration, notify = currentPrintTimeChanged) @pyqtProperty(Duration, notify = currentPrintTimeChanged)
def currentPrintTime(self): def currentPrintTime(self) -> Duration:
return self._current_print_time[self._active_build_plate] return self._current_print_time[self._active_build_plate]
materialLengthsChanged = pyqtSignal() materialLengthsChanged = pyqtSignal()
@ -176,33 +183,37 @@ class PrintInformation(QObject):
def printTimes(self): def printTimes(self):
return self._print_time_message_values[self._active_build_plate] return self._print_time_message_values[self._active_build_plate]
def _onPrintDurationMessage(self, build_plate_number, print_time: Dict[str, int], material_amounts: list): def _onPrintDurationMessage(self, build_plate_number: int, print_time: Dict[str, int], material_amounts: List[float]) -> None:
self._updateTotalPrintTimePerFeature(build_plate_number, print_time) self._updateTotalPrintTimePerFeature(build_plate_number, print_time)
self.currentPrintTimeChanged.emit() self.currentPrintTimeChanged.emit()
self._material_amounts = material_amounts self._material_amounts = material_amounts
self._calculateInformation(build_plate_number) self._calculateInformation(build_plate_number)
def _updateTotalPrintTimePerFeature(self, build_plate_number, print_time: Dict[str, int]): def _updateTotalPrintTimePerFeature(self, build_plate_number: int, print_times: Dict[str, int]) -> None:
total_estimated_time = 0 total_estimated_time = 0
if build_plate_number not in self._print_time_message_values: if build_plate_number not in self._print_time_message_values:
self._initPrintTimeMessageValues(build_plate_number) self._initPrintTimeMessageValues(build_plate_number)
for feature, time in print_time.items(): for feature, time in print_times.items():
if feature not in self._print_time_message_values[build_plate_number]:
self._print_time_message_values[build_plate_number][feature] = Duration(parent=self)
duration = self._print_time_message_values[build_plate_number][feature]
if time != time: # Check for NaN. Engine can sometimes give us weird values. if time != time: # Check for NaN. Engine can sometimes give us weird values.
self._print_time_message_values[build_plate_number].get(feature).setDuration(0) duration.setDuration(0)
Logger.log("w", "Received NaN for print duration message") Logger.log("w", "Received NaN for print duration message")
continue continue
total_estimated_time += time total_estimated_time += time
self._print_time_message_values[build_plate_number].get(feature).setDuration(time) duration.setDuration(time)
if build_plate_number not in self._current_print_time: if build_plate_number not in self._current_print_time:
self._current_print_time[build_plate_number] = Duration(None, self) self._current_print_time[build_plate_number] = Duration(None, self)
self._current_print_time[build_plate_number].setDuration(total_estimated_time) self._current_print_time[build_plate_number].setDuration(total_estimated_time)
def _calculateInformation(self, build_plate_number): def _calculateInformation(self, build_plate_number: int) -> None:
global_stack = self._application.getGlobalContainerStack() global_stack = self._application.getGlobalContainerStack()
if global_stack is None: if global_stack is None:
return return
@ -227,7 +238,7 @@ class PrintInformation(QObject):
radius = extruder_stack.getProperty("material_diameter", "value") / 2 radius = extruder_stack.getProperty("material_diameter", "value") / 2
weight = float(amount) * float(density) / 1000 weight = float(amount) * float(density) / 1000
cost = 0 cost = 0.
material_name = catalog.i18nc("@label unknown material", "Unknown") material_name = catalog.i18nc("@label unknown material", "Unknown")
if material: if material:
material_guid = material.getMetaDataEntry("GUID") material_guid = material.getMetaDataEntry("GUID")
@ -258,14 +269,14 @@ class PrintInformation(QObject):
self.materialCostsChanged.emit() self.materialCostsChanged.emit()
self.materialNamesChanged.emit() self.materialNamesChanged.emit()
def _onPreferencesChanged(self, preference): def _onPreferencesChanged(self, preference: str) -> None:
if preference != "cura/material_settings": if preference != "cura/material_settings":
return return
for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1): for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
self._calculateInformation(build_plate_number) self._calculateInformation(build_plate_number)
def _onActiveBuildPlateChanged(self): def _onActiveBuildPlateChanged(self) -> None:
new_active_build_plate = self._multi_build_plate_model.activeBuildPlate new_active_build_plate = self._multi_build_plate_model.activeBuildPlate
if new_active_build_plate != self._active_build_plate: if new_active_build_plate != self._active_build_plate:
self._active_build_plate = new_active_build_plate self._active_build_plate = new_active_build_plate
@ -279,14 +290,14 @@ class PrintInformation(QObject):
self.materialNamesChanged.emit() self.materialNamesChanged.emit()
self.currentPrintTimeChanged.emit() self.currentPrintTimeChanged.emit()
def _onActiveMaterialsChanged(self, *args, **kwargs): def _onActiveMaterialsChanged(self, *args, **kwargs) -> None:
for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1): for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
self._calculateInformation(build_plate_number) self._calculateInformation(build_plate_number)
# Manual override of job name should also set the base name so that when the printer prefix is updated, it the # Manual override of job name should also set the base name so that when the printer prefix is updated, it the
# prefix can be added to the manually added name, not the old base name # prefix can be added to the manually added name, not the old base name
@pyqtSlot(str, bool) @pyqtSlot(str, bool)
def setJobName(self, name, is_user_specified_job_name = False): def setJobName(self, name: str, is_user_specified_job_name = False) -> None:
self._is_user_specified_job_name = is_user_specified_job_name self._is_user_specified_job_name = is_user_specified_job_name
self._job_name = name self._job_name = name
self._base_name = name.replace(self._abbr_machine + "_", "") self._base_name = name.replace(self._abbr_machine + "_", "")
@ -300,7 +311,7 @@ class PrintInformation(QObject):
def jobName(self): def jobName(self):
return self._job_name return self._job_name
def _updateJobName(self): def _updateJobName(self) -> None:
if self._base_name == "": if self._base_name == "":
self._job_name = self.UNTITLED_JOB_NAME self._job_name = self.UNTITLED_JOB_NAME
self._is_user_specified_job_name = False self._is_user_specified_job_name = False
@ -335,12 +346,12 @@ class PrintInformation(QObject):
self.jobNameChanged.emit() self.jobNameChanged.emit()
@pyqtSlot(str) @pyqtSlot(str)
def setProjectName(self, name): def setProjectName(self, name: str) -> None:
self.setBaseName(name, is_project_file = True) self.setBaseName(name, is_project_file = True)
baseNameChanged = pyqtSignal() baseNameChanged = pyqtSignal()
def setBaseName(self, base_name: str, is_project_file: bool = False): def setBaseName(self, base_name: str, is_project_file: bool = False) -> None:
self._is_user_specified_job_name = False self._is_user_specified_job_name = False
# Ensure that we don't use entire path but only filename # Ensure that we don't use entire path but only filename
@ -384,7 +395,7 @@ class PrintInformation(QObject):
## Created an acronym-like abbreviated machine name from the currently ## Created an acronym-like abbreviated machine name from the currently
# active machine name. # active machine name.
# Called each time the global stack is switched. # Called each time the global stack is switched.
def _defineAbbreviatedMachineName(self): def _defineAbbreviatedMachineName(self) -> None:
global_container_stack = self._application.getGlobalContainerStack() global_container_stack = self._application.getGlobalContainerStack()
if not global_container_stack: if not global_container_stack:
self._abbr_machine = "" self._abbr_machine = ""
@ -408,8 +419,8 @@ class PrintInformation(QObject):
self._abbr_machine = abbr_machine self._abbr_machine = abbr_machine
## Utility method that strips accents from characters (eg: â -> a) ## Utility method that strips accents from characters (eg: â -> a)
def _stripAccents(self, str): def _stripAccents(self, to_strip: str) -> str:
return ''.join(char for char in unicodedata.normalize('NFD', str) if unicodedata.category(char) != 'Mn') return ''.join(char for char in unicodedata.normalize('NFD', to_strip) if unicodedata.category(char) != 'Mn')
@pyqtSlot(result = "QVariantMap") @pyqtSlot(result = "QVariantMap")
def getFeaturePrintTimes(self): def getFeaturePrintTimes(self):
@ -424,7 +435,7 @@ class PrintInformation(QObject):
return result return result
# Simulate message with zero time duration # Simulate message with zero time duration
def setToZeroPrintInformation(self, build_plate = None): def setToZeroPrintInformation(self, build_plate: Optional[int] = None) -> None:
if build_plate is None: if build_plate is None:
build_plate = self._active_build_plate build_plate = self._active_build_plate
@ -434,12 +445,12 @@ class PrintInformation(QObject):
self._print_time_message_values[build_plate] = {} self._print_time_message_values[build_plate] = {}
for key in self._print_time_message_values[build_plate].keys(): for key in self._print_time_message_values[build_plate].keys():
temp_message[key] = 0 temp_message[key] = 0
temp_material_amounts = [0] temp_material_amounts = [0.]
self._onPrintDurationMessage(build_plate, temp_message, temp_material_amounts) self._onPrintDurationMessage(build_plate, temp_message, temp_material_amounts)
## Listen to scene changes to check if we need to reset the print information ## Listen to scene changes to check if we need to reset the print information
def _onSceneChanged(self, scene_node): def _onSceneChanged(self, scene_node: SceneNode) -> None:
# Ignore any changes that are not related to sliceable objects # Ignore any changes that are not related to sliceable objects
if not isinstance(scene_node, SceneNode)\ if not isinstance(scene_node, SceneNode)\
or not scene_node.callDecoration("isSliceable")\ or not scene_node.callDecoration("isSliceable")\