mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-12 02:09:02 +08:00
Merge branch 'master' of https://github.com/Ultimaker/PluggableCura
Conflicts: plugins/CuraEngineBackend/CuraEngineBackend.py
This commit is contained in:
commit
7d88d800b2
190
PrintInformation.py
Normal file
190
PrintInformation.py
Normal file
@ -0,0 +1,190 @@
|
||||
from PyQt5.QtCore import QObject, QDateTime, QTimer, pyqtSignal, pyqtSlot, pyqtProperty
|
||||
|
||||
from UM.Application import Application
|
||||
from UM.Settings.MachineSettings import MachineSettings
|
||||
from UM.Resources import Resources
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
|
||||
## A class for processing and calculating minimum, currrent and maximum print time.
|
||||
#
|
||||
# This class contains all the logic relating to calculation and slicing for the
|
||||
# time/quality slider concept. It is a rather tricky combination of event handling
|
||||
# and state management. The logic behind this is as follows:
|
||||
#
|
||||
# - A scene change or settting change event happens.
|
||||
# We track what the source was of the change, either a scene change, a setting change, an active machine change or something else.
|
||||
# - This triggers a new slice with the current settings - this is the "current settings pass".
|
||||
# - When the slice is done, we update the current print time and material amount.
|
||||
# - If the source of the slice was not a Setting change, we start the second slice pass, the "low quality settings pass". Otherwise we stop here.
|
||||
# - When that is done, we update the minimum print time and start the final slcice pass, the "high quality settings pass".
|
||||
# - When the high quality pass is done, we update the maximum print time.
|
||||
#
|
||||
class PrintInformation(QObject):
|
||||
class SlicePass:
|
||||
CurrentSettings = 1
|
||||
LowQualitySettings = 2
|
||||
HighQualitySettings = 3
|
||||
|
||||
class SliceReason:
|
||||
SceneChanged = 1
|
||||
SettingChanged = 2
|
||||
ActiveMachineChanged = 3
|
||||
Other = 4
|
||||
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
|
||||
self._minimum_print_time = QDateTime()
|
||||
self._current_print_time = QDateTime()
|
||||
self._maximum_print_time = QDateTime()
|
||||
|
||||
self._material_amount = -1
|
||||
|
||||
self._time_quality_value = 50
|
||||
self._time_quality_changed_timer = QTimer()
|
||||
self._time_quality_changed_timer.setInterval(500)
|
||||
self._time_quality_changed_timer.setSingleShot(True)
|
||||
self._time_quality_changed_timer.timeout.connect(self._updateTimeQualitySettings)
|
||||
|
||||
self._interpolation_settings = {
|
||||
"layer_height": { "minimum": "low", "maximum": "high", "curve": "linear" }
|
||||
}
|
||||
|
||||
self._low_quality_settings = None
|
||||
self._current_settings = None
|
||||
self._high_quality_settings = None
|
||||
|
||||
self._slice_pass = None
|
||||
self._slice_reason = None
|
||||
|
||||
Application.getInstance().activeMachineChanged.connect(self._onActiveMachineChanged)
|
||||
self._onActiveMachineChanged()
|
||||
|
||||
Application.getInstance().getController().getScene().sceneChanged.connect(self._onSceneChanged)
|
||||
|
||||
self._backend = Application.getInstance().getBackend()
|
||||
if self._backend:
|
||||
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
|
||||
self._backend.slicingStarted.connect(self._onSlicingStarted)
|
||||
|
||||
minimumPrintTimeChanged = pyqtSignal()
|
||||
@pyqtProperty(QDateTime, notify = minimumPrintTimeChanged)
|
||||
def minimumPrintTime(self):
|
||||
return self._minimum_print_time
|
||||
|
||||
currentPrintTimeChanged = pyqtSignal()
|
||||
@pyqtProperty(QDateTime, notify = currentPrintTimeChanged)
|
||||
def currentPrintTime(self):
|
||||
return self._current_print_time
|
||||
|
||||
maximumPrintTimeChanged = pyqtSignal()
|
||||
@pyqtProperty(QDateTime, notify = maximumPrintTimeChanged)
|
||||
def maximumPrintTime(self):
|
||||
return self._maximum_print_time
|
||||
|
||||
materialAmountChanged = pyqtSignal()
|
||||
@pyqtProperty(float, notify = materialAmountChanged)
|
||||
def materialAmount(self):
|
||||
return self._material_amount
|
||||
|
||||
timeQualityValueChanged = pyqtSignal()
|
||||
@pyqtProperty(int, notify = timeQualityValueChanged)
|
||||
def timeQualityValue(self):
|
||||
return self._time_quality_value
|
||||
|
||||
@pyqtSlot(int)
|
||||
def setTimeQualityValue(self, value):
|
||||
if value != self._time_quality_value:
|
||||
self._time_quality_value = value
|
||||
self.timeQualityValueChanged.emit()
|
||||
|
||||
self._time_quality_changed_timer.start()
|
||||
|
||||
def _onSlicingStarted(self):
|
||||
if self._slice_pass is None:
|
||||
self._slice_pass = self.SlicePass.CurrentSettings
|
||||
|
||||
if self._slice_reason is None:
|
||||
self._slice_reason = self.SliceReason.Other
|
||||
|
||||
def _onPrintDurationMessage(self, time, amount):
|
||||
if self._slice_pass == self.SlicePass.CurrentSettings:
|
||||
self._current_print_time = QDateTime.fromMSecsSinceEpoch(round(time * 1000))
|
||||
self.currentPrintTimeChanged.emit()
|
||||
|
||||
self._material_amount = round(amount / 10) / 100
|
||||
self.materialAmountChanged.emit()
|
||||
|
||||
if self._slice_reason != self.SliceReason.SettingChanged:
|
||||
self._slice_pass = self.SlicePass.LowQualitySettings
|
||||
self._backend.slice(settings = self._low_quality_settings, save_gcode = False, save_polygons = False, force_restart = False, report_progress = False)
|
||||
else:
|
||||
self._slice_pass = None
|
||||
self._slice_reason = None
|
||||
|
||||
elif self._slice_pass == self.SlicePass.LowQualitySettings:
|
||||
self._minimum_print_time = QDateTime.fromMSecsSinceEpoch(round(time * 1000))
|
||||
self.minimumPrintTimeChanged.emit()
|
||||
|
||||
self._slice_pass = self.SlicePass.HighQualitySettings
|
||||
self._backend.slice(settings = self._high_quality_settings, save_gcode = False, save_polygons = False, force_restart = False, report_progress = False)
|
||||
elif self._slice_pass == self.SlicePass.HighQualitySettings:
|
||||
self._maximum_print_time = QDateTime.fromMSecsSinceEpoch(round(time * 1000))
|
||||
self.maximumPrintTimeChanged.emit()
|
||||
|
||||
self._slice_pass = None
|
||||
self._slice_reason = None
|
||||
|
||||
def _onActiveMachineChanged(self):
|
||||
if self._current_settings:
|
||||
self._current_settings.settingChanged.disconnect(self._onSettingChanged)
|
||||
|
||||
self._current_settings = Application.getInstance().getActiveMachine()
|
||||
|
||||
if self._current_settings:
|
||||
self._current_settings.settingChanged.connect(self._onSettingChanged)
|
||||
self._low_quality_settings = None
|
||||
self._high_quality_settings = None
|
||||
self._updateTimeQualitySettings()
|
||||
|
||||
self._slice_reason = self.SliceReason.ActiveMachineChanged
|
||||
|
||||
def _updateTimeQualitySettings(self):
|
||||
if not self._current_settings:
|
||||
return
|
||||
|
||||
if not self._low_quality_settings:
|
||||
self._low_quality_settings = MachineSettings()
|
||||
self._low_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + '.json'))
|
||||
self._low_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, 'profiles', 'low_quality.conf'))
|
||||
|
||||
if not self._high_quality_settings:
|
||||
self._high_quality_settings = MachineSettings()
|
||||
self._high_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + '.json'))
|
||||
self._high_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, 'profiles', 'high_quality.conf'))
|
||||
|
||||
for key, options in self._interpolation_settings.items():
|
||||
minimum_value = None
|
||||
if options['minimum'] == 'low':
|
||||
minimum_value = self._low_quality_settings.getSettingValueByKey(key)
|
||||
elif options['minimum'] == 'high':
|
||||
minimum_value = self._high_quality_settings.getSettingValueByKey(key)
|
||||
else:
|
||||
continue
|
||||
|
||||
maximum_value = None
|
||||
if options['maximum'] == 'low':
|
||||
maximum_value = self._low_quality_settings.getSettingValueByKey(key)
|
||||
elif options['maximum'] == 'high':
|
||||
maximum_value = self._high_quality_settings.getSettingValueByKey(key)
|
||||
else:
|
||||
continue
|
||||
|
||||
setting_value = minimum_value + (maximum_value - minimum_value) * (self._time_quality_value / 100)
|
||||
self._current_settings.setSettingValueByKey(key, setting_value)
|
||||
|
||||
def _onSceneChanged(self, source):
|
||||
self._slice_reason = self.SliceReason.SceneChanged
|
||||
|
||||
def _onSettingChanged(self, source):
|
||||
self._slice_reason = self.SliceReason.SettingChanged
|
@ -23,6 +23,7 @@ from UM.Operations.SetTransformOperation import SetTransformOperation
|
||||
from PlatformPhysics import PlatformPhysics
|
||||
from BuildVolume import BuildVolume
|
||||
from CameraAnimation import CameraAnimation
|
||||
from PrintInformation import PrintInformation
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, QUrl, Qt, pyqtSignal, pyqtProperty
|
||||
from PyQt5.QtGui import QColor
|
||||
@ -56,8 +57,7 @@ class PrinterApplication(QtApplication):
|
||||
'priority': 0
|
||||
}
|
||||
}
|
||||
self._print_duration = -1
|
||||
self._print_material_amount = -1
|
||||
self._print_information = None
|
||||
|
||||
self.activeMachineChanged.connect(self._onActiveMachineChanged)
|
||||
|
||||
@ -117,8 +117,6 @@ class PrinterApplication(QtApplication):
|
||||
|
||||
self.getStorageDevice('LocalFileStorage').removableDrivesChanged.connect(self._removableDrivesChanged)
|
||||
|
||||
self.getBackend().printDurationMessage.connect(self._onPrintDurationMessage)
|
||||
|
||||
if self.getMachines():
|
||||
active_machine_pref = Preferences.getInstance().getValue('cura/active_machine')
|
||||
if active_machine_pref:
|
||||
@ -139,6 +137,8 @@ class PrinterApplication(QtApplication):
|
||||
|
||||
def registerObjects(self, engine):
|
||||
engine.rootContext().setContextProperty('Printer', self)
|
||||
self._print_information = PrintInformation()
|
||||
engine.rootContext().setContextProperty('PrintInformation', self._print_information)
|
||||
|
||||
def onSelectionChanged(self):
|
||||
if Selection.hasSelection():
|
||||
@ -263,16 +263,6 @@ class PrinterApplication(QtApplication):
|
||||
|
||||
return log
|
||||
|
||||
printDurationChanged = pyqtSignal()
|
||||
|
||||
@pyqtProperty(float, notify = printDurationChanged)
|
||||
def printDuration(self):
|
||||
return self._print_duration
|
||||
|
||||
@pyqtProperty(float, notify = printDurationChanged)
|
||||
def printMaterialAmount(self):
|
||||
return self._print_material_amount
|
||||
|
||||
def _onActiveMachineChanged(self):
|
||||
machine = self.getActiveMachine()
|
||||
if machine:
|
||||
|
@ -19,9 +19,8 @@ Button {
|
||||
property bool defaultOverride: false;
|
||||
property bool defaultAmbiguous: false;
|
||||
|
||||
property real printDurationHours: Math.floor(Printer.printDuration / 3600);
|
||||
property real printDurationMinutes: Math.round(((Printer.printDuration / 3600) - printDurationHours) * 60);
|
||||
property real printMaterialAmount: Printer.printMaterialAmount < 0 ? -1 : Math.round(Printer.printMaterialAmount / 10) / 100;
|
||||
property variant printDuration: PrintInformation.currentPrintTime;
|
||||
property real printMaterialAmount: PrintInformation.materialAmount < 0 ? -1 : PrintInformation.materialAmount;
|
||||
|
||||
iconSource: UM.Theme.icons[Printer.outputDevices[base.currentDevice].icon];
|
||||
tooltip: Printer.outputDevices[base.currentDevice].description;
|
||||
@ -138,23 +137,31 @@ Button {
|
||||
font: UM.Theme.fonts.default;
|
||||
|
||||
text: {
|
||||
if(control.printDurationHours < 0 || control.printDurationMinutes < 0)
|
||||
if(!control.printDuration)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if(control.printDurationHours > 1)
|
||||
var days = ""
|
||||
var day_count = control.printDuration.getDate() - 1;
|
||||
if(day_count > 0)
|
||||
{
|
||||
return qsTr("%1 hours %2 minutes").arg(control.printDurationHours).arg(control.printDurationMinutes);
|
||||
days = Qt.formatDateTime(control.printDuration, qsTr("d 'day(s)'", "", day_count));
|
||||
}
|
||||
else if(control.printDurationHours > 0)
|
||||
|
||||
var hours = ""
|
||||
if(control.printDuration.getHours() > 0)
|
||||
{
|
||||
return qsTr("1 hour %1 minutes").arg(control.printDurationMinutes);
|
||||
hours = Qt.formatDateTime(control.printDuration, qsTr("h 'hour(s)'", "", control.printDuration.getHours()));
|
||||
}
|
||||
else
|
||||
|
||||
var minutes = ""
|
||||
if(control.printDuration.getMinutes() > 0)
|
||||
{
|
||||
return qsTr("%2 minutes").arg(control.printDurationMinutes);
|
||||
minutes = Qt.formatDateTime(control.printDuration, qsTr("m 'minute(s)'", "", control.printDuration.getMinutes()));
|
||||
}
|
||||
|
||||
return [days, hours, minutes].join(" ");
|
||||
}
|
||||
}
|
||||
Label {
|
||||
|
@ -6,12 +6,17 @@ import QtQuick.Layouts 1.1
|
||||
import UM 1.0 as UM
|
||||
|
||||
Item {
|
||||
id: base;
|
||||
|
||||
anchors.fill: parent;
|
||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||
anchors.rightMargin: UM.Theme.sizes.default_margin.width;
|
||||
|
||||
property Action configureSettings;
|
||||
|
||||
property variant minimumPrintTime: PrintInformation.minimumPrintTime;
|
||||
property variant maximumPrintTime: PrintInformation.maximumPrintTime;
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent;
|
||||
|
||||
@ -22,15 +27,33 @@ Item {
|
||||
Label {
|
||||
anchors.left: parent.left;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
text: "00:00";
|
||||
text:Qt.formatTime(base.minimumPrintTime, "hh:mm");
|
||||
font: UM.Theme.fonts.timeslider_time;
|
||||
color: UM.Theme.colors.primary;
|
||||
}
|
||||
Label { anchors.centerIn: parent; text: "Estimated Print Time"; color: UM.Theme.colors.text; font: UM.Theme.fonts.default; }
|
||||
Label {
|
||||
anchors.centerIn: parent;
|
||||
text: {
|
||||
if (UM.Backend.progress < 0)
|
||||
{
|
||||
return qsTr("No Model Loaded");
|
||||
}
|
||||
else if (base.minimumPrintTime == null || base.maximumPrintTime == null)
|
||||
{
|
||||
return qsTr("Calculating...")
|
||||
}
|
||||
else
|
||||
{
|
||||
return qsTr("Estimated Print Time");
|
||||
}
|
||||
}
|
||||
color: UM.Theme.colors.text;
|
||||
font: UM.Theme.fonts.default;
|
||||
}
|
||||
Label {
|
||||
anchors.right: parent.right;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
text: "21:00";
|
||||
text: Qt.formatTime(base.maximumPrintTime, "hh:mm");
|
||||
font: UM.Theme.fonts.timeslider_time;
|
||||
color: UM.Theme.colors.primary;
|
||||
}
|
||||
@ -43,6 +66,9 @@ Item {
|
||||
minimumValue: 0;
|
||||
maximumValue: 100;
|
||||
|
||||
value: PrintInformation.timeQualityValue;
|
||||
onValueChanged: PrintInformation.setTimeQualityValue(value);
|
||||
|
||||
style: UM.Theme.styles.slider;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user