mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-24 13:39:05 +08:00
Merge branch 'master' of github.com:Ultimaker/Cura
This commit is contained in:
commit
af8176d309
@ -252,6 +252,8 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte
|
|||||||
self._error_message.show()
|
self._error_message.show()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.writeStarted.emit(self) # Allow postprocessing before sending data to the printer
|
||||||
|
|
||||||
if len(self._printers) > 1:
|
if len(self._printers) > 1:
|
||||||
self.spawnPrintView() # Ask user how to print it.
|
self.spawnPrintView() # Ask user how to print it.
|
||||||
elif len(self._printers) == 1:
|
elif len(self._printers) == 1:
|
||||||
|
@ -13,6 +13,7 @@ from UM.Application import Application
|
|||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState
|
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
|
from UM.Qt.Duration import DurationFormat
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrl, pyqtSlot, pyqtSignal, pyqtProperty
|
from PyQt5.QtCore import QUrl, pyqtSlot, pyqtSignal, pyqtProperty
|
||||||
|
|
||||||
@ -52,6 +53,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
|
|
||||||
self._heatup_wait_start_time = time.time()
|
self._heatup_wait_start_time = time.time()
|
||||||
|
|
||||||
|
self.jobStateChanged.connect(self._onJobStateChanged)
|
||||||
|
|
||||||
## Queue for commands that need to be send. Used when command is sent when a print is active.
|
## Queue for commands that need to be send. Used when command is sent when a print is active.
|
||||||
self._command_queue = queue.Queue()
|
self._command_queue = queue.Queue()
|
||||||
|
|
||||||
@ -60,7 +63,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
|
|
||||||
## Set when print is started in order to check running time.
|
## Set when print is started in order to check running time.
|
||||||
self._print_start_time = None
|
self._print_start_time = None
|
||||||
self._print_start_time_100 = None
|
self._print_estimated_time = None
|
||||||
|
|
||||||
## Keep track where in the provided g-code the print is
|
## Keep track where in the provided g-code the print is
|
||||||
self._gcode_position = 0
|
self._gcode_position = 0
|
||||||
@ -125,6 +128,29 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
def _homeBed(self):
|
def _homeBed(self):
|
||||||
self._sendCommand("G28 Z")
|
self._sendCommand("G28 Z")
|
||||||
|
|
||||||
|
## Updates the target bed temperature from the printer, and emit a signal if it was changed.
|
||||||
|
#
|
||||||
|
# /param temperature The new target temperature of the bed.
|
||||||
|
# /return boolean, True if the temperature was changed, false if the new temperature has the same value as the already stored temperature
|
||||||
|
def _updateTargetBedTemperature(self, temperature):
|
||||||
|
if self._target_bed_temperature == temperature:
|
||||||
|
return False
|
||||||
|
self._target_bed_temperature = temperature
|
||||||
|
self.targetBedTemperatureChanged.emit()
|
||||||
|
return True
|
||||||
|
|
||||||
|
## Updates the target hotend temperature from the printer, and emit a signal if it was changed.
|
||||||
|
#
|
||||||
|
# /param index The index of the hotend.
|
||||||
|
# /param temperature The new target temperature of the hotend.
|
||||||
|
# /return boolean, True if the temperature was changed, false if the new temperature has the same value as the already stored temperature
|
||||||
|
def _updateTargetHotendTemperature(self, index, temperature):
|
||||||
|
if self._target_hotend_temperatures[index] == temperature:
|
||||||
|
return False
|
||||||
|
self._target_hotend_temperatures[index] = temperature
|
||||||
|
self.targetHotendTemperaturesChanged.emit()
|
||||||
|
return True
|
||||||
|
|
||||||
## A name for the device.
|
## A name for the device.
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def name(self):
|
def name(self):
|
||||||
@ -164,7 +190,6 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
# Reset line number. If this is not done, first line is sometimes ignored
|
# Reset line number. If this is not done, first line is sometimes ignored
|
||||||
self._gcode.insert(0, "M110")
|
self._gcode.insert(0, "M110")
|
||||||
self._gcode_position = 0
|
self._gcode_position = 0
|
||||||
self._print_start_time_100 = None
|
|
||||||
self._is_printing = True
|
self._is_printing = True
|
||||||
self._print_start_time = time.time()
|
self._print_start_time = time.time()
|
||||||
|
|
||||||
@ -447,7 +472,6 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
#
|
#
|
||||||
# \param nodes A collection of scene nodes to send. This is ignored.
|
# \param nodes A collection of scene nodes to send. This is ignored.
|
||||||
# \param file_name \type{string} A suggestion for a file name to write.
|
# \param file_name \type{string} A suggestion for a file name to write.
|
||||||
# This is ignored.
|
|
||||||
# \param filter_by_machine Whether to filter MIME types by machine. This
|
# \param filter_by_machine Whether to filter MIME types by machine. This
|
||||||
# is ignored.
|
# is ignored.
|
||||||
# \param kwargs Keyword arguments.
|
# \param kwargs Keyword arguments.
|
||||||
@ -463,6 +487,9 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
self._error_message.show()
|
self._error_message.show()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.setJobName(file_name)
|
||||||
|
self._print_estimated_time = int(Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.Seconds))
|
||||||
|
|
||||||
Application.getInstance().showPrintMonitor.emit(True)
|
Application.getInstance().showPrintMonitor.emit(True)
|
||||||
self.startPrint()
|
self.startPrint()
|
||||||
|
|
||||||
@ -483,6 +510,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
## Listen thread function.
|
## Listen thread function.
|
||||||
def _listen(self):
|
def _listen(self):
|
||||||
Logger.log("i", "Printer connection listen thread started for %s" % self._serial_port)
|
Logger.log("i", "Printer connection listen thread started for %s" % self._serial_port)
|
||||||
|
container_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
temperature_request_timeout = time.time()
|
temperature_request_timeout = time.time()
|
||||||
ok_timeout = time.time()
|
ok_timeout = time.time()
|
||||||
while self._connection_state == ConnectionState.connected:
|
while self._connection_state == ConnectionState.connected:
|
||||||
@ -512,16 +540,40 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
self._setErrorState(line[6:])
|
self._setErrorState(line[6:])
|
||||||
|
|
||||||
elif b" T:" in line or line.startswith(b"T:"): # Temperature message
|
elif b" T:" in line or line.startswith(b"T:"): # Temperature message
|
||||||
|
temperature_matches = re.findall(b"T(\d*): ?([\d\.]+) ?\/?([\d\.]+)?", line)
|
||||||
|
temperature_set = False
|
||||||
try:
|
try:
|
||||||
self._setHotendTemperature(self._temperature_requested_extruder_index, float(re.search(b"T: *([0-9\.]*)", line).group(1)))
|
for match in temperature_matches:
|
||||||
|
if match[0]:
|
||||||
|
extruder_nr = int(match[0])
|
||||||
|
if extruder_nr >= container_stack.getProperty("machine_extruder_count", "value"):
|
||||||
|
continue
|
||||||
|
if match[1]:
|
||||||
|
self._setHotendTemperature(extruder_nr, float(match[1]))
|
||||||
|
temperature_set = True
|
||||||
|
if match[2]:
|
||||||
|
self._updateTargetHotendTemperature(extruder_nr, float(match[2]))
|
||||||
|
else:
|
||||||
|
requested_temperatures = match
|
||||||
|
if not temperature_set and requested_temperatures:
|
||||||
|
if requested_temperatures[1]:
|
||||||
|
self._setHotendTemperature(self._temperature_requested_extruder_index, float(requested_temperatures[1]))
|
||||||
|
if requested_temperatures[2]:
|
||||||
|
self._updateTargetHotendTemperature(self._temperature_requested_extruder_index, float(requested_temperatures[2]))
|
||||||
except:
|
except:
|
||||||
pass
|
Logger.log("w", "Could not parse hotend temperatures from response: %s", line)
|
||||||
if b"B:" in line: # Check if it's a bed temperature
|
# Check if there's also a bed temperature
|
||||||
|
temperature_matches = re.findall(b"B: ?([\d\.]+) ?\/?([\d\.]+)?", line)
|
||||||
|
if container_stack.getProperty("machine_heated_bed", "value") and len(temperature_matches) > 0:
|
||||||
|
match = temperature_matches[0]
|
||||||
try:
|
try:
|
||||||
self._setBedTemperature(float(re.search(b"B: *([0-9\.]*)", line).group(1)))
|
if match[0]:
|
||||||
except Exception as e:
|
self._setBedTemperature(float(match[0]))
|
||||||
pass
|
if match[1]:
|
||||||
#TODO: temperature changed callback
|
self._updateTargetBedTemperature(float(match[1]))
|
||||||
|
except:
|
||||||
|
Logger.log("w", "Could not parse bed temperature from response: %s", line)
|
||||||
|
|
||||||
elif b"_min" in line or b"_max" in line:
|
elif b"_min" in line or b"_max" in line:
|
||||||
tag, value = line.split(b":", 1)
|
tag, value = line.split(b":", 1)
|
||||||
self._setEndstopState(tag,(b"H" in value or b"TRIGGERED" in value))
|
self._setEndstopState(tag,(b"H" in value or b"TRIGGERED" in value))
|
||||||
@ -560,8 +612,6 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
def _sendNextGcodeLine(self):
|
def _sendNextGcodeLine(self):
|
||||||
if self._gcode_position >= len(self._gcode):
|
if self._gcode_position >= len(self._gcode):
|
||||||
return
|
return
|
||||||
if self._gcode_position == 100:
|
|
||||||
self._print_start_time_100 = time.time()
|
|
||||||
line = self._gcode[self._gcode_position]
|
line = self._gcode[self._gcode_position]
|
||||||
|
|
||||||
if ";" in line:
|
if ";" in line:
|
||||||
@ -585,8 +635,18 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
checksum = functools.reduce(lambda x,y: x^y, map(ord, "N%d%s" % (self._gcode_position, line)))
|
checksum = functools.reduce(lambda x,y: x^y, map(ord, "N%d%s" % (self._gcode_position, line)))
|
||||||
|
|
||||||
self._sendCommand("N%d%s*%d" % (self._gcode_position, line, checksum))
|
self._sendCommand("N%d%s*%d" % (self._gcode_position, line, checksum))
|
||||||
|
|
||||||
|
progress = (self._gcode_position / len(self._gcode))
|
||||||
|
|
||||||
|
elapsed_time = int(time.time() - self._print_start_time)
|
||||||
|
self.setTimeElapsed(elapsed_time)
|
||||||
|
estimated_time = self._print_estimated_time
|
||||||
|
if progress > .1:
|
||||||
|
estimated_time = self._print_estimated_time * (1-progress) + elapsed_time
|
||||||
|
self.setTimeTotal(estimated_time)
|
||||||
|
|
||||||
self._gcode_position += 1
|
self._gcode_position += 1
|
||||||
self.setProgress((self._gcode_position / len(self._gcode)) * 100)
|
self.setProgress(progress * 100)
|
||||||
self.progressChanged.emit()
|
self.progressChanged.emit()
|
||||||
|
|
||||||
## Set the state of the print.
|
## Set the state of the print.
|
||||||
@ -601,6 +661,13 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
elif job_state == "abort":
|
elif job_state == "abort":
|
||||||
self.cancelPrint()
|
self.cancelPrint()
|
||||||
|
|
||||||
|
def _onJobStateChanged(self):
|
||||||
|
# clear the job name & times when printing is done or aborted
|
||||||
|
if self._job_state == "ready":
|
||||||
|
self.setJobName("")
|
||||||
|
self.setTimeElapsed(0)
|
||||||
|
self.setTimeTotal(0)
|
||||||
|
|
||||||
## Set the progress of the print.
|
## Set the progress of the print.
|
||||||
# It will be normalized (based on max_progress) to range 0 - 100
|
# It will be normalized (based on max_progress) to range 0 - 100
|
||||||
def setProgress(self, progress, max_progress = 100):
|
def setProgress(self, progress, max_progress = 100):
|
||||||
|
@ -350,21 +350,20 @@ Rectangle
|
|||||||
var total_seconds = parseInt(base.printDuration.getDisplayString(UM.DurationFormat.Seconds))
|
var total_seconds = parseInt(base.printDuration.getDisplayString(UM.DurationFormat.Seconds))
|
||||||
|
|
||||||
// A message is created and displayed when the user hover the time label
|
// A message is created and displayed when the user hover the time label
|
||||||
var content = catalog.i18nc("@tooltip", "<b>Time specification</b><br/><table>");
|
var tooltip_html = "<b>%1</b><br/><table width=\"100%\">".arg(catalog.i18nc("@tooltip", "Time specification"));
|
||||||
for(var feature in print_time)
|
for(var feature in print_time)
|
||||||
{
|
{
|
||||||
if(!print_time[feature].isTotalDurationZero)
|
if(!print_time[feature].isTotalDurationZero)
|
||||||
{
|
{
|
||||||
content += "<tr><td colspan='2'>" + feature + "</td></tr>" +
|
tooltip_html += "<tr><td>" + feature + ":</td>" +
|
||||||
"<tr>" +
|
"<td align=\"right\" valign=\"bottom\"> %1</td>".arg(print_time[feature].getDisplayString(UM.DurationFormat.ISO8601).slice(0,-3)) +
|
||||||
"<td width='60%'>" + print_time[feature].getDisplayString(UM.DurationFormat.Short) + "</td>" +
|
"<td align=\"right\" valign=\"bottom\"> %1%</td>".arg(Math.round(100 * parseInt(print_time[feature].getDisplayString(UM.DurationFormat.Seconds)) / total_seconds)) +
|
||||||
"<td width='40%'> " + Math.round(100 * parseInt(print_time[feature].getDisplayString(UM.DurationFormat.Seconds)) / total_seconds) + "%" +
|
|
||||||
"</td></tr>";
|
"</td></tr>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
content += "</table>";
|
tooltip_html += "</table>";
|
||||||
|
|
||||||
base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), content);
|
base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), tooltip_html);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onExited:
|
onExited:
|
||||||
@ -376,9 +375,26 @@ Rectangle
|
|||||||
|
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
function formatRow(items)
|
||||||
|
{
|
||||||
|
var row_html = "<tr>";
|
||||||
|
for(var item = 0; item < items.length; item++)
|
||||||
|
{
|
||||||
|
if (item == 0)
|
||||||
|
{
|
||||||
|
row_html += "<td valign=\"bottom\">%1</td>".arg(items[item]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
row_html += "<td align=\"right\" valign=\"bottom\"> %1</td>".arg(items[item]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row_html += "</tr>";
|
||||||
|
return row_html;
|
||||||
|
}
|
||||||
|
|
||||||
function getSpecsData(){
|
function getSpecsData()
|
||||||
|
{
|
||||||
var lengths = [];
|
var lengths = [];
|
||||||
var total_length = 0;
|
var total_length = 0;
|
||||||
var weights = [];
|
var weights = [];
|
||||||
@ -387,7 +403,8 @@ Rectangle
|
|||||||
var total_cost = 0;
|
var total_cost = 0;
|
||||||
var some_costs_known = false;
|
var some_costs_known = false;
|
||||||
var names = [];
|
var names = [];
|
||||||
if(base.printMaterialLengths) {
|
if(base.printMaterialLengths)
|
||||||
|
{
|
||||||
for(var index = 0; index < base.printMaterialLengths.length; index++)
|
for(var index = 0; index < base.printMaterialLengths.length; index++)
|
||||||
{
|
{
|
||||||
if(base.printMaterialLengths[index] > 0)
|
if(base.printMaterialLengths[index] > 0)
|
||||||
@ -415,34 +432,28 @@ Rectangle
|
|||||||
costs = ["0.00"];
|
costs = ["0.00"];
|
||||||
}
|
}
|
||||||
|
|
||||||
var tooltip_html = "<b>%1</b><br/><table>".arg(catalog.i18nc("@label", "Cost specification"));
|
var tooltip_html = "<b>%1</b><br/><table width=\"100%\">".arg(catalog.i18nc("@label", "Cost specification"));
|
||||||
for(var index = 0; index < lengths.length; index++)
|
for(var index = 0; index < lengths.length; index++)
|
||||||
{
|
{
|
||||||
var item_strings = [
|
tooltip_html += formatRow([
|
||||||
"%1:".arg(names[index]),
|
"%1:".arg(names[index]),
|
||||||
catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]),
|
catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]),
|
||||||
catalog.i18nc("@label g for grams", "%1g").arg(weights[index]),
|
catalog.i18nc("@label g for grams", "%1g").arg(weights[index]),
|
||||||
"%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]),
|
"%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]),
|
||||||
];
|
]);
|
||||||
tooltip_html += "<tr>";
|
|
||||||
for(var item = 0; item < item_strings.length; item++) {
|
|
||||||
tooltip_html += "<td>%1 </td>".arg(item_strings[item]);
|
|
||||||
}
|
}
|
||||||
}
|
if(lengths.length > 1)
|
||||||
var item_strings = [
|
{
|
||||||
|
tooltip_html += formatRow([
|
||||||
catalog.i18nc("@label", "Total:"),
|
catalog.i18nc("@label", "Total:"),
|
||||||
catalog.i18nc("@label m for meter", "%1m").arg(total_length.toFixed(2)),
|
catalog.i18nc("@label m for meter", "%1m").arg(total_length.toFixed(2)),
|
||||||
catalog.i18nc("@label g for grams", "%1g").arg(Math.round(total_weight)),
|
catalog.i18nc("@label g for grams", "%1g").arg(Math.round(total_weight)),
|
||||||
"%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(total_cost.toFixed(2)),
|
"%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(total_cost.toFixed(2)),
|
||||||
];
|
]);
|
||||||
tooltip_html += "<tr>";
|
|
||||||
for(var item = 0; item < item_strings.length; item++) {
|
|
||||||
tooltip_html += "<td>%1 </td>".arg(item_strings[item]);
|
|
||||||
}
|
}
|
||||||
tooltip_html += "</tr></table>";
|
tooltip_html += "</table>";
|
||||||
tooltipText = tooltip_html;
|
tooltipText = tooltip_html;
|
||||||
|
|
||||||
|
|
||||||
return tooltipText
|
return tooltipText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user