mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-05 21:13:58 -06:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
ac2ef48d46
21 changed files with 227 additions and 251 deletions
|
@ -533,7 +533,7 @@ class CuraApplication(QtApplication):
|
|||
preferences.addPreference("cura/active_mode", "simple")
|
||||
|
||||
preferences.addPreference("cura/categories_expanded", "")
|
||||
preferences.addPreference("cura/job_name_template", "{machine_name_short}_{project_name}")
|
||||
preferences.addPreference("cura/jobname_prefix", True)
|
||||
preferences.addPreference("cura/select_models_on_load", False)
|
||||
preferences.addPreference("view/center_on_select", False)
|
||||
preferences.addPreference("mesh/scale_to_fit", False)
|
||||
|
|
|
@ -202,7 +202,11 @@ class PrintInformation(QObject):
|
|||
self._material_costs[build_plate_number] = []
|
||||
self._material_names[build_plate_number] = []
|
||||
|
||||
material_preference_values = json.loads(self._application.getInstance().getPreferences().getValue("cura/material_settings"))
|
||||
try:
|
||||
material_preference_values = json.loads(self._application.getInstance().getPreferences().getValue("cura/material_settings"))
|
||||
except json.JSONDecodeError:
|
||||
Logger.warning("Material preference values are corrupt. Will revert to defaults!")
|
||||
material_preference_values = {}
|
||||
|
||||
for index, extruder_stack in enumerate(global_stack.extruderList):
|
||||
if index >= len(self._material_amounts):
|
||||
|
@ -252,11 +256,11 @@ class PrintInformation(QObject):
|
|||
self.materialNamesChanged.emit()
|
||||
|
||||
def _onPreferencesChanged(self, preference: str) -> None:
|
||||
if preference == "cura/job_name_template":
|
||||
self._updateJobName()
|
||||
elif preference == "cura/material_settings":
|
||||
for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
|
||||
self._calculateInformation(build_plate_number)
|
||||
if preference != "cura/material_settings":
|
||||
return
|
||||
|
||||
for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
|
||||
self._calculateInformation(build_plate_number)
|
||||
|
||||
def _onActiveBuildPlateChanged(self) -> None:
|
||||
new_active_build_plate = self._multi_build_plate_model.activeBuildPlate
|
||||
|
@ -305,8 +309,12 @@ class PrintInformation(QObject):
|
|||
|
||||
# Only update the job name when it's not user-specified.
|
||||
if not self._is_user_specified_job_name:
|
||||
if not self._pre_sliced:
|
||||
self._job_name = self.parseTemplate()
|
||||
if self._application.getInstance().getPreferences().getValue("cura/jobname_prefix") and not self._pre_sliced:
|
||||
# Don't add abbreviation if it already has the exact same abbreviation.
|
||||
if base_name.startswith(self._abbr_machine + "_"):
|
||||
self._job_name = base_name
|
||||
else:
|
||||
self._job_name = self._abbr_machine + "_" + base_name
|
||||
else:
|
||||
self._job_name = base_name
|
||||
|
||||
|
@ -436,28 +444,3 @@ class PrintInformation(QObject):
|
|||
"""Listen to scene changes to check if we need to reset the print information"""
|
||||
|
||||
self.setToZeroPrintInformation(self._active_build_plate)
|
||||
|
||||
def parseTemplate(self) -> str:
|
||||
"""Generate a print job name from the job name template
|
||||
|
||||
The template is a user preference: "cura/job_name_template"
|
||||
"""
|
||||
template = self._application.getInstance().getPreferences().getValue("cura/job_name_template")
|
||||
output = template
|
||||
|
||||
output = output.replace("{machine_name_short}", self._abbr_machine)
|
||||
|
||||
if "{machine_name}" in template:
|
||||
global_container_stack = self._application.getGlobalContainerStack()
|
||||
active_machine_type_name = global_container_stack.definition.getName() \
|
||||
if global_container_stack \
|
||||
else "no_machine"
|
||||
|
||||
active_machine_type_name = active_machine_type_name.replace(" ", "_")
|
||||
output = output.replace("{machine_name}", active_machine_type_name)
|
||||
|
||||
if "{project_name}" in template:
|
||||
base_name = self._stripAccents(self._base_name)
|
||||
output = output.replace("{project_name}", base_name)
|
||||
|
||||
return output
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import os.path
|
||||
import zipfile
|
||||
from typing import List, Optional, Union, TYPE_CHECKING
|
||||
from typing import List, Optional, Union, TYPE_CHECKING, cast
|
||||
|
||||
import Savitar
|
||||
import numpy
|
||||
|
@ -169,8 +169,16 @@ class ThreeMFReader(MeshReader):
|
|||
setting_container.setProperty(key, "value", setting_value)
|
||||
|
||||
if len(um_node.getChildren()) > 0 and um_node.getMeshData() is None:
|
||||
group_decorator = GroupDecorator()
|
||||
um_node.addDecorator(group_decorator)
|
||||
if len(um_node.getAllChildren()) == 1:
|
||||
# We don't want groups of one, so move the node up one "level"
|
||||
child_node = um_node.getChildren()[0]
|
||||
parent_transformation = um_node.getLocalTransformation()
|
||||
child_transformation = child_node.getLocalTransformation()
|
||||
child_node.setTransformation(parent_transformation.multiply(child_transformation))
|
||||
um_node = cast(CuraSceneNode, um_node.getChildren()[0])
|
||||
else:
|
||||
group_decorator = GroupDecorator()
|
||||
um_node.addDecorator(group_decorator)
|
||||
um_node.setSelectable(True)
|
||||
if um_node.getMeshData():
|
||||
# Assuming that all nodes with mesh data are printable objects
|
||||
|
@ -192,8 +200,8 @@ class ThreeMFReader(MeshReader):
|
|||
um_node = self._convertSavitarNodeToUMNode(node, file_name)
|
||||
if um_node is None:
|
||||
continue
|
||||
# compensate for original center position, if object(s) is/are not around its zero position
|
||||
|
||||
# compensate for original center position, if object(s) is/are not around its zero position
|
||||
transform_matrix = Matrix()
|
||||
mesh_data = um_node.getMeshData()
|
||||
if mesh_data is not None:
|
||||
|
|
|
@ -172,7 +172,7 @@ class ImageReaderUI(QObject):
|
|||
|
||||
@pyqtSlot(int)
|
||||
def onColorModelChanged(self, value):
|
||||
self.use_transparency_model = (value == 0)
|
||||
self.use_transparency_model = (value == 1)
|
||||
|
||||
@pyqtSlot(int)
|
||||
def onTransmittanceChanged(self, value):
|
||||
|
|
130
plugins/PostProcessingPlugin/scripts/DisplayProgressOnLCD.py
Normal file
130
plugins/PostProcessingPlugin/scripts/DisplayProgressOnLCD.py
Normal file
|
@ -0,0 +1,130 @@
|
|||
# Cura PostProcessingPlugin
|
||||
# Author: Mathias Lyngklip Kjeldgaard, Alexander Gee
|
||||
# Date: July 31, 2019
|
||||
# Modified: May 22, 2020
|
||||
|
||||
# Description: This plugin displays progress on the LCD. It can output the estimated time remaining and the completion percentage.
|
||||
|
||||
from ..Script import Script
|
||||
|
||||
import re
|
||||
import datetime
|
||||
|
||||
class DisplayProgressOnLCD(Script):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
"name": "Display Progress On LCD",
|
||||
"key": "DisplayProgressOnLCD",
|
||||
"metadata": {},
|
||||
"version": 2,
|
||||
"settings":
|
||||
{
|
||||
"time_remaining":
|
||||
{
|
||||
"label": "Time Remaining",
|
||||
"description": "When enabled, write Time Left: HHMMSS on the display using M117. This is updated every layer.",
|
||||
"type": "bool",
|
||||
"default_value": false
|
||||
},
|
||||
"percentage":
|
||||
{
|
||||
"label": "Percentage",
|
||||
"description": "When enabled, set the completion bar percentage on the LCD using Marlin's M73 command.",
|
||||
"type": "bool",
|
||||
"default_value": false
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
# Get the time value from a line as a float.
|
||||
# Example line ;TIME_ELAPSED:1234.6789 or ;TIME:1337
|
||||
def getTimeValue(self, line):
|
||||
list_split = re.split(":", line) # Split at ":" so we can get the numerical value
|
||||
return float(list_split[1]) # Convert the numerical portion to a float
|
||||
|
||||
def outputTime(self, lines, line_index, time_left):
|
||||
# Do some math to get the time left in seconds into the right format. (HH,MM,SS)
|
||||
m, s = divmod(time_left, 60)
|
||||
h, m = divmod(m, 60)
|
||||
# Create the string
|
||||
current_time_string = "{:d}h{:02d}m{:02d}s".format(int(h), int(m), int(s))
|
||||
# And now insert that into the GCODE
|
||||
lines.insert(line_index, "M117 Time Left {}".format(current_time_string))
|
||||
|
||||
def execute(self, data):
|
||||
output_time = self.getSettingValueByKey("time_remaining")
|
||||
output_percentage = self.getSettingValueByKey("percentage")
|
||||
line_set = {}
|
||||
if output_percentage or output_time:
|
||||
total_time = -1
|
||||
previous_layer_end_percentage = 0
|
||||
for layer in data:
|
||||
layer_index = data.index(layer)
|
||||
lines = layer.split("\n")
|
||||
|
||||
for line in lines:
|
||||
if line.startswith(";TIME:") and total_time == -1:
|
||||
# This line represents the total time required to print the gcode
|
||||
total_time = self.getTimeValue(line)
|
||||
line_index = lines.index(line)
|
||||
|
||||
if output_time:
|
||||
self.outputTime(lines, line_index, total_time)
|
||||
if output_percentage:
|
||||
# Emit 0 percent to sure Marlin knows we are overriding the completion percentage
|
||||
lines.insert(line_index, "M73 P0")
|
||||
|
||||
elif line.startswith(";TIME_ELAPSED:"):
|
||||
# We've found one of the time elapsed values which are added at the end of layers
|
||||
|
||||
# If we have seen this line before then skip processing it. We can see lines multiple times because we are adding
|
||||
# intermediate percentages before the line being processed. This can cause the current line to shift back and be
|
||||
# encountered more than once
|
||||
if line in line_set:
|
||||
continue
|
||||
line_set[line] = True
|
||||
|
||||
# If total_time was not already found then noop
|
||||
if total_time == -1:
|
||||
continue
|
||||
|
||||
current_time = self.getTimeValue(line)
|
||||
line_index = lines.index(line)
|
||||
|
||||
if output_time:
|
||||
# Here we calculate remaining time
|
||||
self.outputTime(lines, line_index, total_time - current_time)
|
||||
|
||||
if output_percentage:
|
||||
# Calculate percentage value this layer ends at
|
||||
layer_end_percentage = int((current_time / total_time) * 100)
|
||||
|
||||
# Figure out how many percent of the total time is spent in this layer
|
||||
layer_percentage_delta = layer_end_percentage - previous_layer_end_percentage
|
||||
|
||||
# If this layer represents less than 1 percent then we don't need to emit anything, continue to the next layer
|
||||
if layer_percentage_delta != 0:
|
||||
# Grab the index of the current line and figure out how many lines represent one percent
|
||||
step = line_index / layer_percentage_delta
|
||||
|
||||
for percentage in range(1, layer_percentage_delta + 1):
|
||||
# We add the percentage value here as while processing prior lines we will have inserted
|
||||
# percentage lines before the current one. Failing to do this will upset the spacing
|
||||
percentage_line_index = int((percentage * step) + percentage)
|
||||
|
||||
# Due to integer truncation of the total time value in the gcode the percentage we
|
||||
# calculate may slightly exceed 100, as that is not valid we cap the value here
|
||||
output = min(percentage + previous_layer_end_percentage, 100)
|
||||
|
||||
# Now insert the sanitized percentage into the GCODE
|
||||
lines.insert(percentage_line_index, "M73 P{}".format(output))
|
||||
|
||||
previous_layer_end_percentage = layer_end_percentage
|
||||
|
||||
# Join up the lines for this layer again and store them in the data array
|
||||
data[layer_index] = "\n".join(lines)
|
||||
return data
|
|
@ -1,94 +0,0 @@
|
|||
# Cura PostProcessingPlugin
|
||||
# Author: Mathias Lyngklip Kjeldgaard
|
||||
# Date: July 31, 2019
|
||||
# Modified: November 26, 2019
|
||||
|
||||
# Description: This plugin displayes the remaining time on the LCD of the printer
|
||||
# using the estimated print-time generated by Cura.
|
||||
|
||||
|
||||
|
||||
|
||||
from ..Script import Script
|
||||
|
||||
import re
|
||||
import datetime
|
||||
|
||||
|
||||
class DisplayRemainingTimeOnLCD(Script):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
"name":"Display Remaining Time on LCD",
|
||||
"key":"DisplayRemainingTimeOnLCD",
|
||||
"metadata": {},
|
||||
"version": 2,
|
||||
"settings":
|
||||
{
|
||||
"TurnOn":
|
||||
{
|
||||
"label": "Enable",
|
||||
"description": "When enabled, It will write Time Left: HHMMSS on the display. This is updated every layer.",
|
||||
"type": "bool",
|
||||
"default_value": false
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
def execute(self, data):
|
||||
if self.getSettingValueByKey("TurnOn"):
|
||||
total_time = 0
|
||||
total_time_string = ""
|
||||
for layer in data:
|
||||
layer_index = data.index(layer)
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if line.startswith(";TIME:"):
|
||||
# At this point, we have found a line in the GCODE with ";TIME:"
|
||||
# which is the indication of total_time. Looks like: ";TIME:1337", where
|
||||
# 1337 is the total print time in seconds.
|
||||
line_index = lines.index(line) # We take a hold of that line
|
||||
split_string = re.split(":", line) # Then we split it, so we can get the number
|
||||
|
||||
string_with_numbers = "{}".format(split_string[1]) # Here we insert that number from the
|
||||
# list into a string.
|
||||
total_time = int(string_with_numbers) # Only to contert it to a int.
|
||||
|
||||
m, s = divmod(total_time, 60) # Math to calculate
|
||||
h, m = divmod(m, 60) # hours, minutes and seconds.
|
||||
total_time_string = "{:d}h{:02d}m{:02d}s".format(h, m, s) # Now we put it into the string
|
||||
lines[line_index] = "M117 Time Left {}".format(total_time_string) # And print that string instead of the original one
|
||||
|
||||
|
||||
|
||||
|
||||
elif line.startswith(";TIME_ELAPSED:"):
|
||||
|
||||
# As we didnt find the total time (";TIME:"), we have found a elapsed time mark
|
||||
# This time represents the time the printer have printed. So with some math;
|
||||
# totalTime - printTime = RemainingTime.
|
||||
line_index = lines.index(line) # We get a hold of the line
|
||||
list_split = re.split(":", line) # Again, we split at ":" so we can get the number
|
||||
string_with_numbers = "{}".format(list_split[1]) # Then we put that number from the list, into a string
|
||||
|
||||
current_time = float(string_with_numbers) # This time we convert to a float, as the line looks something like:
|
||||
# ;TIME_ELAPSED:1234.6789
|
||||
# which is total time in seconds
|
||||
|
||||
time_left = total_time - current_time # Here we calculate remaining time
|
||||
m1, s1 = divmod(time_left, 60) # And some math to get the total time in seconds into
|
||||
h1, m1 = divmod(m1, 60) # the right format. (HH,MM,SS)
|
||||
current_time_string = "{:d}h{:2d}m{:2d}s".format(int(h1), int(m1), int(s1)) # Here we create the string holding our time
|
||||
lines[line_index] = "M117 Time Left {}".format(current_time_string) # And now insert that into the GCODE
|
||||
|
||||
|
||||
# Here we are OUT of the second for-loop
|
||||
# Which means we have found and replaces all the occurences.
|
||||
# Which also means we are ready to join the lines for that section of the GCODE file.
|
||||
final_lines = "\n".join(lines)
|
||||
data[layer_index] = final_lines
|
||||
return data
|
|
@ -44,13 +44,6 @@ class VersionUpgrade462to47(VersionUpgrade):
|
|||
parser["general"]["visible_settings"] = ";".join(
|
||||
set(parser["general"]["visible_settings"].split(";")).difference(_removed_settings))
|
||||
|
||||
if "cura" in parser and "jobname_prefix" in parser["cura"]:
|
||||
if not parseBool(parser["cura"]["jobname_prefix"]):
|
||||
parser["cura"]["job_name_template"] = "{project_name}"
|
||||
del parser["cura"]["jobname_prefix"]
|
||||
# else: When the jobname_prefix preference is True or not set,
|
||||
# the default value for job_name_template ("{machine_name_short}_{project_name}") will be used
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
@ -161,6 +154,17 @@ class VersionUpgrade462to47(VersionUpgrade):
|
|||
if "redo_layers" in script_parser["PauseAtHeight"]:
|
||||
script_parser["PauseAtHeight"]["redo_layer"] = str(int(script_parser["PauseAtHeight"]["redo_layers"]) > 0)
|
||||
del script_parser["PauseAtHeight"]["redo_layers"] # Has been renamed to without the S.
|
||||
|
||||
# Migrate DisplayCompleteOnLCD to DisplayProgressOnLCD
|
||||
if script_id == "DisplayRemainingTimeOnLCD":
|
||||
was_enabled = parseBool(script_parser[script_id]["TurnOn"]) if "TurnOn" in script_parser[script_id] else False
|
||||
script_parser.remove_section(script_id)
|
||||
|
||||
script_id = "DisplayProgressOnLCD"
|
||||
script_parser.add_section(script_id)
|
||||
if was_enabled:
|
||||
script_parser.set(script_id, "time_remaining", "True")
|
||||
|
||||
script_io = io.StringIO()
|
||||
script_parser.write(script_io)
|
||||
script_str = script_io.getvalue()
|
||||
|
|
|
@ -866,6 +866,7 @@ UM.MainWindow
|
|||
title: catalog.i18nc("@title:window", "What's New")
|
||||
model: CuraApplication.getWhatsNewPagesModel()
|
||||
progressBarVisible: false
|
||||
visible: false
|
||||
}
|
||||
|
||||
Connections
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
@ -24,7 +24,15 @@ Menu
|
|||
title: modelData.name
|
||||
property var extruder: (base.activeMachine === null) ? null : activeMachine.extruderList[model.index]
|
||||
NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.activeMachine.hasVariants; extruderIndex: index }
|
||||
MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.activeMachine.hasMaterials; extruderIndex: index }
|
||||
MaterialMenu
|
||||
{
|
||||
title: catalog.i18nc("@title:menu", "&Material")
|
||||
visible: Cura.MachineManager.activeMachine.hasMaterials
|
||||
extruderIndex: index
|
||||
updateModels: false
|
||||
onAboutToShow: updateModels = true
|
||||
onAboutToHide: updateModels = false
|
||||
}
|
||||
|
||||
MenuSeparator
|
||||
{
|
||||
|
|
|
@ -85,8 +85,8 @@ UM.PreferencesPage
|
|||
scaleTinyCheckbox.checked = boolCheck(UM.Preferences.getValue("mesh/scale_tiny_meshes"))
|
||||
UM.Preferences.resetPreference("cura/select_models_on_load")
|
||||
selectModelsOnLoadCheckbox.checked = boolCheck(UM.Preferences.getValue("cura/select_models_on_load"))
|
||||
UM.Preferences.resetPreference("cura/job_name_template")
|
||||
jobnameTemplateTextField.text = UM.Preferences.getValue("cura/job_name_template")
|
||||
UM.Preferences.resetPreference("cura/jobname_prefix")
|
||||
prefixJobNameCheckbox.checked = boolCheck(UM.Preferences.getValue("cura/jobname_prefix"))
|
||||
UM.Preferences.resetPreference("view/show_overhang");
|
||||
showOverhangCheckbox.checked = boolCheck(UM.Preferences.getValue("view/show_overhang"))
|
||||
UM.Preferences.resetPreference("view/show_xray_warning");
|
||||
|
@ -627,25 +627,14 @@ UM.PreferencesPage
|
|||
{
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip. Note variable names themselves (ie. machine_name_short, project_name) should not be translated", "Variables: machine_name_short, machine_name, project_name")
|
||||
text: catalog.i18nc("@info:tooltip", "Should a prefix based on the printer name be added to the print job name automatically?")
|
||||
|
||||
Column
|
||||
CheckBox
|
||||
{
|
||||
spacing: 4 * screenScaleFactor
|
||||
|
||||
Label
|
||||
{
|
||||
id: jobNameTemplateLabel
|
||||
text: catalog.i18nc("@label","Print job template:")
|
||||
}
|
||||
|
||||
TextField
|
||||
{
|
||||
id: jobNameTemplateTextField
|
||||
width: 250 * screenScaleFactor
|
||||
text: UM.Preferences.getValue("cura/job_name_template")
|
||||
onTextChanged: UM.Preferences.setValue("cura/job_name_template", text)
|
||||
}
|
||||
id: prefixJobNameCheckbox
|
||||
text: catalog.i18nc("@option:check", "Add machine prefix to job name")
|
||||
checked: boolCheck(UM.Preferences.getValue("cura/jobname_prefix"))
|
||||
onCheckedChanged: UM.Preferences.setValue("cura/jobname_prefix", checked)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -681,7 +670,7 @@ UM.PreferencesPage
|
|||
ComboBox
|
||||
{
|
||||
id: choiceOnOpenProjectDropDownButton
|
||||
width: 250 * screenScaleFactor
|
||||
width: 200 * screenScaleFactor
|
||||
|
||||
model: ListModel
|
||||
{
|
||||
|
@ -747,7 +736,7 @@ UM.PreferencesPage
|
|||
ComboBox
|
||||
{
|
||||
id: choiceOnProfileOverrideDropDownButton
|
||||
width: 250 * screenScaleFactor
|
||||
width: 200 * screenScaleFactor
|
||||
|
||||
model: ListModel
|
||||
{
|
||||
|
|
|
@ -22,22 +22,10 @@ Button
|
|||
height: UM.Theme.getSize("section").height
|
||||
color:
|
||||
{
|
||||
if (base.color)
|
||||
{
|
||||
return base.color
|
||||
}
|
||||
else if (!base.enabled)
|
||||
if (!base.enabled)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_disabled")
|
||||
}
|
||||
else if (base.hovered && base.expanded)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_active_hover")
|
||||
}
|
||||
else if (base.pressed || base.expanded)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_active")
|
||||
}
|
||||
else if (base.hovered)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_hover")
|
||||
|
@ -57,6 +45,21 @@ Button
|
|||
property var focusItem: base
|
||||
property bool expanded: definition.expanded
|
||||
|
||||
|
||||
property color text_color:
|
||||
{
|
||||
if (!base.enabled)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_disabled_text")
|
||||
} else if (base.hovered || base.pressed || base.activeFocus)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_active_text")
|
||||
}
|
||||
|
||||
return UM.Theme.getColor("setting_category_text")
|
||||
|
||||
}
|
||||
|
||||
contentItem: Item
|
||||
{
|
||||
anchors.fill: parent
|
||||
|
@ -75,25 +78,7 @@ Button
|
|||
textFormat: Text.PlainText
|
||||
renderType: Text.NativeRendering
|
||||
font: UM.Theme.getFont("medium_bold")
|
||||
color:
|
||||
{
|
||||
if (!base.enabled)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_disabled_text")
|
||||
} else if ((base.hovered || base.activeFocus) && base.expanded)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_active_hover_text")
|
||||
} else if (base.pressed || base.expanded)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_active_text")
|
||||
} else if (base.hovered || base.activeFocus)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_hover_text")
|
||||
} else
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_text")
|
||||
}
|
||||
}
|
||||
color: base.text_color
|
||||
fontSizeMode: Text.HorizontalFit
|
||||
minimumPointSize: 8
|
||||
}
|
||||
|
@ -118,26 +103,7 @@ Button
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.getSize("thin_margin").width
|
||||
color:
|
||||
{
|
||||
if (!base.enabled)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_disabled_text")
|
||||
}
|
||||
else if((base.hovered || base.activeFocus) && base.expanded)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_active_hover_text")
|
||||
}
|
||||
else if(base.pressed || base.expanded)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_active_text")
|
||||
}
|
||||
else if(base.hovered || base.activeFocus)
|
||||
{
|
||||
return UM.Theme.getColor("setting_category_hover_text")
|
||||
}
|
||||
return UM.Theme.getColor("setting_category_text")
|
||||
}
|
||||
color: base.text_color
|
||||
source: UM.Theme.getIcon(definition.icon)
|
||||
width: UM.Theme.getSize("section_icon").width
|
||||
height: UM.Theme.getSize("section_icon").height
|
||||
|
|
|
@ -156,7 +156,7 @@ Item
|
|||
{
|
||||
id: settingControls
|
||||
|
||||
height: Math.round(parent.height / 2)
|
||||
height: UM.Theme.getSize("section_control").height
|
||||
spacing: Math.round(UM.Theme.getSize("thick_margin").height / 2)
|
||||
|
||||
anchors
|
||||
|
|
|
@ -153,7 +153,7 @@ SettingItem
|
|||
selectByMouse: true
|
||||
|
||||
maximumLength: (definition.type == "str" || definition.type == "[int]") ? -1 : 10
|
||||
clip: true; //Hide any text that exceeds the width of the text box.
|
||||
clip: definition.type == "[int]" // Only clip for the list
|
||||
|
||||
validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[?(\s*-?[0-9]{0,9}\s*,)*(\s*-?[0-9]{0,9})\s*\]?$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : (definition.type == "float") ? /^-?[0-9]{0,9}[.,]?[0-9]{0,3}$/ : /^.*$/ } // definition.type property from parent loader used to disallow fractional number entry
|
||||
|
||||
|
|
|
@ -246,25 +246,18 @@ Item
|
|||
}
|
||||
|
||||
property int indexWithFocus: -1
|
||||
property double delegateHeight: UM.Theme.getSize("section").height + 2 * UM.Theme.getSize("default_lining").height
|
||||
property string activeMachineId: Cura.MachineManager.activeMachine !== null ? Cura.MachineManager.activeMachine.id : ""
|
||||
delegate: Loader
|
||||
{
|
||||
id: delegate
|
||||
|
||||
width: scrollView.width
|
||||
height: provider.properties.enabled === "True" ? UM.Theme.getSize("section").height + 2 * UM.Theme.getSize("default_lining").height : 0
|
||||
height: enabled ? contents.delegateHeight: 0
|
||||
Behavior on height { NumberAnimation { duration: 100 } }
|
||||
opacity: provider.properties.enabled === "True" ? 1 : 0
|
||||
opacity: enabled ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
enabled:
|
||||
{
|
||||
if (!Cura.ExtruderManager.activeExtruderStackId && machineExtruderCount.properties.value > 1)
|
||||
{
|
||||
// disable all controls on the global tab, except categories
|
||||
return model.type === "category"
|
||||
}
|
||||
return provider.properties.enabled === "True"
|
||||
}
|
||||
enabled: provider.properties.enabled === "True"
|
||||
|
||||
property var definition: model
|
||||
property var settingDefinitionsModel: definitionsModel
|
||||
|
@ -272,10 +265,7 @@ Item
|
|||
property var globalPropertyProvider: inheritStackProvider
|
||||
property bool externalResetHandler: false
|
||||
|
||||
//Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
|
||||
//In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
|
||||
//causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
|
||||
asynchronous: model.type !== "enum" && model.type !== "extruder" && model.type !== "optional_extruder"
|
||||
asynchronous: true
|
||||
active: model.type !== undefined
|
||||
|
||||
source:
|
||||
|
@ -355,7 +345,7 @@ Item
|
|||
id: provider
|
||||
|
||||
containerStackId: contents.activeMachineId
|
||||
key: model.key ? model.key : ""
|
||||
key: model.key
|
||||
watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder", "resolve" ]
|
||||
storeIndex: 0
|
||||
removeUnusedValue: model.resolve === undefined
|
||||
|
|
|
@ -78,6 +78,10 @@ Item
|
|||
{
|
||||
base.activeY = y;
|
||||
}
|
||||
//Clear focus when tools change. This prevents the tool grabbing focus when activated.
|
||||
//Grabbing focus prevents items from being deleted.
|
||||
//Apparently this was only a problem on MacOS.
|
||||
forceActiveFocus();
|
||||
}
|
||||
|
||||
//Workaround since using ToolButton's onClicked would break the binding of the checked property, instead
|
||||
|
|
|
@ -40,6 +40,7 @@ Window
|
|||
id: wizardPanel
|
||||
anchors.fill: parent
|
||||
model: dialog.model
|
||||
visible: dialog.visible
|
||||
}
|
||||
|
||||
// Close this dialog when there's no more page to show
|
||||
|
|
|
@ -71,7 +71,7 @@ Item
|
|||
right: parent.right
|
||||
}
|
||||
source: base.pageUrl
|
||||
enabled: base.visible
|
||||
active: base.visible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ A new performance enhancement that limits re-rendering of the application interf
|
|||
Previous versions used different ways of handling HTTP requests. This version uses a unified method, for better performance.
|
||||
|
||||
* Job names less sensitive to being touched.
|
||||
A contribution from fieldOfview has fixed an issue where the job name in the bottom-left of the scene is no longer made static by clicking on it. If you load a model and change to another printer, the prefix is now correctly updated.
|
||||
A contribution from fieldOfview has fixed an issue where the jobname in the bottom-left of the scene is no longer made static by clicking on it. If you load a model and change to another printer, the prefix is now correctly updated.
|
||||
|
||||
* Property checks on instance containers.
|
||||
A new speed optimization for reading setting values from profiles.
|
||||
|
|
|
@ -99,13 +99,9 @@
|
|||
"setting_category": [75, 80, 83, 255],
|
||||
"setting_category_disabled": [75, 80, 83, 255],
|
||||
"setting_category_hover": [75, 80, 83, 255],
|
||||
"setting_category_active": [75, 80, 83, 255],
|
||||
"setting_category_active_hover": [75, 80, 83, 255],
|
||||
"setting_category_text": [255, 255, 255, 152],
|
||||
"setting_category_disabled_text": [255, 255, 255, 101],
|
||||
"setting_category_hover_text": [255, 255, 255, 204],
|
||||
"setting_category_active_text": [255, 255, 255, 204],
|
||||
"setting_category_active_hover_text": [255, 255, 255, 204],
|
||||
"setting_category_border": [39, 44, 48, 0],
|
||||
"setting_category_disabled_border": [39, 44, 48, 0],
|
||||
"setting_category_hover_border": [12, 169, 227, 255],
|
||||
|
|
|
@ -274,13 +274,9 @@
|
|||
"setting_category": [240, 240, 240, 255],
|
||||
"setting_category_disabled": [255, 255, 255, 255],
|
||||
"setting_category_hover": [232, 242, 252, 255],
|
||||
"setting_category_active": [240, 240, 240, 255],
|
||||
"setting_category_active_hover": [232, 242, 252, 255],
|
||||
"setting_category_text": [35, 35, 35, 255],
|
||||
"setting_category_disabled_text": [24, 41, 77, 101],
|
||||
"setting_category_hover_text": [35, 35, 35, 255],
|
||||
"setting_category_active_text": [35, 35, 35, 255],
|
||||
"setting_category_active_hover_text": [35, 35, 35, 255],
|
||||
"setting_category_border": [240, 240, 240, 255],
|
||||
"setting_category_disabled_border": [240, 240, 240, 255],
|
||||
"setting_category_hover_border": [50, 130, 255, 255],
|
||||
|
@ -502,6 +498,7 @@
|
|||
"extruder_icon": [2.33, 2.33],
|
||||
|
||||
"section": [0.0, 2],
|
||||
"section_control": [0, 1],
|
||||
"section_icon": [1.6, 1.6],
|
||||
"section_icon_column": [2.8, 0.0],
|
||||
"rating_star": [1.0, 1.0],
|
||||
|
|
|
@ -8,13 +8,6 @@ from unittest.mock import MagicMock, patch
|
|||
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
||||
|
||||
|
||||
def preferencesGetValue(key: str):
|
||||
if key == "cura/job_name_template":
|
||||
return "{machine_name_short}_{project_name}"
|
||||
|
||||
return '{"omgzomg": {"spool_weight": 10, "spool_cost": 9}}'
|
||||
|
||||
|
||||
def getPrintInformation(printer_name) -> PrintInformation:
|
||||
|
||||
mock_application = MagicMock(name = "mock_application")
|
||||
|
@ -26,7 +19,7 @@ def getPrintInformation(printer_name) -> PrintInformation:
|
|||
mocked_extruder_stack.material = mocked_material
|
||||
|
||||
mock_application.getInstance = MagicMock(return_value = mock_application)
|
||||
mocked_preferences.getValue = MagicMock(side_effect = preferencesGetValue)
|
||||
mocked_preferences.getValue = MagicMock(return_value = '{"omgzomg": {"spool_weight": 10, "spool_cost": 9}}')
|
||||
|
||||
global_container_stack = MagicMock()
|
||||
global_container_stack.definition.getName = MagicMock(return_value = printer_name)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue