mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
CURA-4525 solved merge conflicts
This commit is contained in:
commit
bfa33c721c
39 changed files with 11005 additions and 337 deletions
70
Jenkinsfile
vendored
70
Jenkinsfile
vendored
|
@ -1,45 +1,47 @@
|
||||||
parallel_nodes(['linux && cura', 'windows && cura']) {
|
timeout(time: 2, unit: "HOURS") {
|
||||||
// Prepare building
|
parallel_nodes(['linux && cura', 'windows && cura']) {
|
||||||
stage('Prepare') {
|
// Prepare building
|
||||||
// Ensure we start with a clean build directory.
|
stage('Prepare') {
|
||||||
step([$class: 'WsCleanup'])
|
// Ensure we start with a clean build directory.
|
||||||
|
step([$class: 'WsCleanup'])
|
||||||
|
|
||||||
// Checkout whatever sources are linked to this pipeline.
|
// Checkout whatever sources are linked to this pipeline.
|
||||||
checkout scm
|
checkout scm
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any error occurs during building, we want to catch it and continue with the "finale" stage.
|
// If any error occurs during building, we want to catch it and continue with the "finale" stage.
|
||||||
catchError {
|
catchError {
|
||||||
// Building and testing should happen in a subdirectory.
|
// Building and testing should happen in a subdirectory.
|
||||||
dir('build') {
|
dir('build') {
|
||||||
// Perform the "build". Since Uranium is Python code, this basically only ensures CMake is setup.
|
// Perform the "build". Since Uranium is Python code, this basically only ensures CMake is setup.
|
||||||
stage('Build') {
|
stage('Build') {
|
||||||
def branch = env.BRANCH_NAME
|
def branch = env.BRANCH_NAME
|
||||||
if(!fileExists("${env.CURA_ENVIRONMENT_PATH}/${branch}")) {
|
if(!fileExists("${env.CURA_ENVIRONMENT_PATH}/${branch}")) {
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure CMake is setup. Note that since this is Python code we do not really "build" it.
|
||||||
|
def uranium_dir = get_workspace_dir("Ultimaker/Uranium/${branch}")
|
||||||
|
cmake("..", "-DCMAKE_PREFIX_PATH=\"${env.CURA_ENVIRONMENT_PATH}/${branch}\" -DCMAKE_BUILD_TYPE=Release -DURANIUM_DIR=\"${uranium_dir}\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure CMake is setup. Note that since this is Python code we do not really "build" it.
|
// Try and run the unit tests. If this stage fails, we consider the build to be "unstable".
|
||||||
def uranium_dir = get_workspace_dir("Ultimaker/Uranium/${branch}")
|
stage('Unit Test') {
|
||||||
cmake("..", "-DCMAKE_PREFIX_PATH=\"${env.CURA_ENVIRONMENT_PATH}/${branch}\" -DCMAKE_BUILD_TYPE=Release -DURANIUM_DIR=\"${uranium_dir}\"")
|
try {
|
||||||
}
|
make('test')
|
||||||
|
} catch(e) {
|
||||||
// Try and run the unit tests. If this stage fails, we consider the build to be "unstable".
|
currentBuild.result = "UNSTABLE"
|
||||||
stage('Unit Test') {
|
}
|
||||||
try {
|
|
||||||
make('test')
|
|
||||||
} catch(e) {
|
|
||||||
currentBuild.result = "UNSTABLE"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Perform any post-build actions like notification and publishing of unit tests.
|
// Perform any post-build actions like notification and publishing of unit tests.
|
||||||
stage('Finalize') {
|
stage('Finalize') {
|
||||||
// Publish the test results to Jenkins.
|
// Publish the test results to Jenkins.
|
||||||
junit allowEmptyResults: true, testResults: 'build/junit*.xml'
|
junit allowEmptyResults: true, testResults: 'build/junit*.xml'
|
||||||
|
|
||||||
notify_build_result(env.CURA_EMAIL_RECIPIENTS, '#cura-dev', ['master', '2.'])
|
notify_build_result(env.CURA_EMAIL_RECIPIENTS, '#cura-dev', ['master', '2.'])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,16 +24,23 @@ function(cura_add_test)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
string(REPLACE "|" "\\;" _PYTHONPATH ${_PYTHONPATH})
|
string(REPLACE "|" "\\;" _PYTHONPATH ${_PYTHONPATH})
|
||||||
|
set(_PYTHONPATH "${_PYTHONPATH}\\;$ENV{PYTHONPATH}")
|
||||||
else()
|
else()
|
||||||
string(REPLACE "|" ":" _PYTHONPATH ${_PYTHONPATH})
|
string(REPLACE "|" ":" _PYTHONPATH ${_PYTHONPATH})
|
||||||
|
set(_PYTHONPATH "${_PYTHONPATH}:$ENV{PYTHONPATH}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_test(
|
get_test_property(${_NAME} ENVIRONMENT test_exists) #Find out if the test exists by getting a property from it that always exists (such as ENVIRONMENT because we set that ourselves).
|
||||||
NAME ${_NAME}
|
if (NOT ${test_exists})
|
||||||
COMMAND ${PYTHON_EXECUTABLE} -m pytest --junitxml=${CMAKE_BINARY_DIR}/junit-${_NAME}.xml ${_DIRECTORY}
|
add_test(
|
||||||
)
|
NAME ${_NAME}
|
||||||
set_tests_properties(${_NAME} PROPERTIES ENVIRONMENT LANG=C)
|
COMMAND ${PYTHON_EXECUTABLE} -m pytest --junitxml=${CMAKE_BINARY_DIR}/junit-${_NAME}.xml ${_DIRECTORY}
|
||||||
set_tests_properties(${_NAME} PROPERTIES ENVIRONMENT "PYTHONPATH=${_PYTHONPATH}")
|
)
|
||||||
|
set_tests_properties(${_NAME} PROPERTIES ENVIRONMENT LANG=C)
|
||||||
|
set_tests_properties(${_NAME} PROPERTIES ENVIRONMENT "PYTHONPATH=${_PYTHONPATH}")
|
||||||
|
else()
|
||||||
|
message(WARNING "Duplicate test ${_NAME}!")
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
cura_add_test(NAME pytest-main DIRECTORY ${CMAKE_SOURCE_DIR}/tests PYTHONPATH "${CMAKE_SOURCE_DIR}|${URANIUM_DIR}")
|
cura_add_test(NAME pytest-main DIRECTORY ${CMAKE_SOURCE_DIR}/tests PYTHONPATH "${CMAKE_SOURCE_DIR}|${URANIUM_DIR}")
|
||||||
|
|
|
@ -329,7 +329,7 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
preferences.addPreference("view/invert_zoom", False)
|
preferences.addPreference("view/invert_zoom", False)
|
||||||
preferences.addPreference("view/filter_current_build_plate", False)
|
preferences.addPreference("view/filter_current_build_plate", False)
|
||||||
preferences.addPreference("cura/sidebar_collapse", False)
|
preferences.addPreference("cura/sidebar_collapsed", False)
|
||||||
|
|
||||||
self._need_to_show_user_agreement = not Preferences.getInstance().getValue("general/accepted_user_agreement")
|
self._need_to_show_user_agreement = not Preferences.getInstance().getValue("general/accepted_user_agreement")
|
||||||
|
|
||||||
|
@ -422,6 +422,14 @@ class CuraApplication(QtApplication):
|
||||||
else:
|
else:
|
||||||
self.exit(0)
|
self.exit(0)
|
||||||
|
|
||||||
|
## Signal to connect preferences action in QML
|
||||||
|
showPreferencesWindow = pyqtSignal()
|
||||||
|
|
||||||
|
## Show the preferences window
|
||||||
|
@pyqtSlot()
|
||||||
|
def showPreferences(self):
|
||||||
|
self.showPreferencesWindow.emit()
|
||||||
|
|
||||||
## A reusable dialogbox
|
## A reusable dialogbox
|
||||||
#
|
#
|
||||||
showMessageBox = pyqtSignal(str, str, str, str, int, int, arguments = ["title", "text", "informativeText", "detailedText", "buttons", "icon"])
|
showMessageBox = pyqtSignal(str, str, str, str, int, int, arguments = ["title", "text", "informativeText", "detailedText", "buttons", "icon"])
|
||||||
|
@ -703,7 +711,7 @@ class CuraApplication(QtApplication):
|
||||||
self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
|
self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
|
||||||
self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles))
|
self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles))
|
||||||
|
|
||||||
run_without_gui = self.getCommandLineOption("headless", False) or self.getCommandLineOption("invisible", False)
|
run_without_gui = self.getCommandLineOption("headless", False)
|
||||||
if not run_without_gui:
|
if not run_without_gui:
|
||||||
self.initializeEngine()
|
self.initializeEngine()
|
||||||
controller.setActiveStage("PrepareStage")
|
controller.setActiveStage("PrepareStage")
|
||||||
|
@ -1449,7 +1457,7 @@ class CuraApplication(QtApplication):
|
||||||
if arrange_objects_on_load:
|
if arrange_objects_on_load:
|
||||||
if node.callDecoration("isSliceable"):
|
if node.callDecoration("isSliceable"):
|
||||||
# Only check position if it's not already blatantly obvious that it won't fit.
|
# Only check position if it's not already blatantly obvious that it won't fit.
|
||||||
if node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
|
if node.getBoundingBox() is None or self._volume.getBoundingBox() is None or node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
|
||||||
# Find node location
|
# Find node location
|
||||||
offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(node, min_offset = min_offset)
|
offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(node, min_offset = min_offset)
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ class PlatformPhysics:
|
||||||
self._change_timer.timeout.connect(self._onChangeTimerFinished)
|
self._change_timer.timeout.connect(self._onChangeTimerFinished)
|
||||||
self._move_factor = 1.1 # By how much should we multiply overlap to calculate a new spot?
|
self._move_factor = 1.1 # By how much should we multiply overlap to calculate a new spot?
|
||||||
self._max_overlap_checks = 10 # How many times should we try to find a new spot per tick?
|
self._max_overlap_checks = 10 # How many times should we try to find a new spot per tick?
|
||||||
|
self._minimum_gap = 2 # It is a minimum distance between two models, applicable for small models
|
||||||
|
|
||||||
Preferences.getInstance().addPreference("physics/automatic_push_free", True)
|
Preferences.getInstance().addPreference("physics/automatic_push_free", True)
|
||||||
Preferences.getInstance().addPreference("physics/automatic_drop_down", True)
|
Preferences.getInstance().addPreference("physics/automatic_drop_down", True)
|
||||||
|
@ -77,7 +78,8 @@ class PlatformPhysics:
|
||||||
if not node.getDecorator(ConvexHullDecorator):
|
if not node.getDecorator(ConvexHullDecorator):
|
||||||
node.addDecorator(ConvexHullDecorator())
|
node.addDecorator(ConvexHullDecorator())
|
||||||
|
|
||||||
if Preferences.getInstance().getValue("physics/automatic_push_free"):
|
# only push away objects if this node is a printing mesh
|
||||||
|
if not node.callDecoration("isNonPrintingMesh") and Preferences.getInstance().getValue("physics/automatic_push_free"):
|
||||||
# Check for collisions between convex hulls
|
# Check for collisions between convex hulls
|
||||||
for other_node in BreadthFirstIterator(root):
|
for other_node in BreadthFirstIterator(root):
|
||||||
# Ignore root, ourselves and anything that is not a normal SceneNode.
|
# Ignore root, ourselves and anything that is not a normal SceneNode.
|
||||||
|
@ -99,6 +101,9 @@ class PlatformPhysics:
|
||||||
if other_node in transformed_nodes:
|
if other_node in transformed_nodes:
|
||||||
continue # Other node is already moving, wait for next pass.
|
continue # Other node is already moving, wait for next pass.
|
||||||
|
|
||||||
|
if other_node.callDecoration("isNonPrintingMesh"):
|
||||||
|
continue
|
||||||
|
|
||||||
overlap = (0, 0) # Start loop with no overlap
|
overlap = (0, 0) # Start loop with no overlap
|
||||||
current_overlap_checks = 0
|
current_overlap_checks = 0
|
||||||
# Continue to check the overlap until we no longer find one.
|
# Continue to check the overlap until we no longer find one.
|
||||||
|
@ -113,26 +118,41 @@ class PlatformPhysics:
|
||||||
overlap = node.callDecoration("getConvexHull").translate(move_vector.x, move_vector.z).intersectsPolygon(other_head_hull)
|
overlap = node.callDecoration("getConvexHull").translate(move_vector.x, move_vector.z).intersectsPolygon(other_head_hull)
|
||||||
if overlap:
|
if overlap:
|
||||||
# Moving ensured that overlap was still there. Try anew!
|
# Moving ensured that overlap was still there. Try anew!
|
||||||
move_vector = move_vector.set(x=move_vector.x + overlap[0] * self._move_factor,
|
move_vector = move_vector.set(x = move_vector.x + overlap[0] * self._move_factor,
|
||||||
z=move_vector.z + overlap[1] * self._move_factor)
|
z = move_vector.z + overlap[1] * self._move_factor)
|
||||||
else:
|
else:
|
||||||
# Moving ensured that overlap was still there. Try anew!
|
# Moving ensured that overlap was still there. Try anew!
|
||||||
move_vector = move_vector.set(x=move_vector.x + overlap[0] * self._move_factor,
|
move_vector = move_vector.set(x = move_vector.x + overlap[0] * self._move_factor,
|
||||||
z=move_vector.z + overlap[1] * self._move_factor)
|
z = move_vector.z + overlap[1] * self._move_factor)
|
||||||
else:
|
else:
|
||||||
own_convex_hull = node.callDecoration("getConvexHull")
|
own_convex_hull = node.callDecoration("getConvexHull")
|
||||||
other_convex_hull = other_node.callDecoration("getConvexHull")
|
other_convex_hull = other_node.callDecoration("getConvexHull")
|
||||||
if own_convex_hull and other_convex_hull:
|
if own_convex_hull and other_convex_hull:
|
||||||
overlap = own_convex_hull.translate(move_vector.x, move_vector.z).intersectsPolygon(other_convex_hull)
|
overlap = own_convex_hull.translate(move_vector.x, move_vector.z).intersectsPolygon(other_convex_hull)
|
||||||
if overlap: # Moving ensured that overlap was still there. Try anew!
|
if overlap: # Moving ensured that overlap was still there. Try anew!
|
||||||
move_vector = move_vector.set(x=move_vector.x + overlap[0] * self._move_factor,
|
temp_move_vector = move_vector.set(x = move_vector.x + overlap[0] * self._move_factor,
|
||||||
z=move_vector.z + overlap[1] * self._move_factor)
|
z = move_vector.z + overlap[1] * self._move_factor)
|
||||||
|
|
||||||
|
# if the distance between two models less than 2mm then try to find a new factor
|
||||||
|
if abs(temp_move_vector.x - overlap[0]) < self._minimum_gap and abs(temp_move_vector.y - overlap[1]) < self._minimum_gap:
|
||||||
|
temp_scale_factor = self._move_factor
|
||||||
|
temp_x_factor = (abs(overlap[0]) + self._minimum_gap) / overlap[0] if overlap[0] != 0 else 0 # find x move_factor, like (3.4 + 2) / 3.4 = 1.58
|
||||||
|
temp_y_factor = (abs(overlap[1]) + self._minimum_gap) / overlap[1] if overlap[1] != 0 else 0 # find y move_factor
|
||||||
|
if abs(temp_x_factor) > abs(temp_y_factor):
|
||||||
|
temp_scale_factor = temp_x_factor
|
||||||
|
else:
|
||||||
|
temp_scale_factor = temp_y_factor
|
||||||
|
|
||||||
|
move_vector = move_vector.set(x = move_vector.x + overlap[0] * temp_scale_factor,
|
||||||
|
z = move_vector.z + overlap[1] * temp_scale_factor)
|
||||||
|
else:
|
||||||
|
move_vector = temp_move_vector
|
||||||
else:
|
else:
|
||||||
# This can happen in some cases if the object is not yet done with being loaded.
|
# This can happen in some cases if the object is not yet done with being loaded.
|
||||||
# Simply waiting for the next tick seems to resolve this correctly.
|
# Simply waiting for the next tick seems to resolve this correctly.
|
||||||
overlap = None
|
overlap = None
|
||||||
|
|
||||||
if not Vector.Null.equals(move_vector, epsilon=1e-5):
|
if not Vector.Null.equals(move_vector, epsilon = 1e-5):
|
||||||
transformed_nodes.append(node)
|
transformed_nodes.append(node)
|
||||||
op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector)
|
op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector)
|
||||||
op.push()
|
op.push()
|
||||||
|
|
|
@ -14,6 +14,7 @@ from UM.Decorators import override
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
from UM.Settings.ContainerStack import ContainerStack
|
from UM.Settings.ContainerStack import ContainerStack
|
||||||
from UM.Settings.InstanceContainer import InstanceContainer
|
from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
|
from UM.Settings.SettingInstance import SettingInstance
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
|
@ -224,7 +225,7 @@ class CuraContainerRegistry(ContainerRegistry):
|
||||||
# This is assumed to be the global profile
|
# This is assumed to be the global profile
|
||||||
profile_id = (global_container_stack.getBottom().getId() + "_" + name_seed).lower().replace(" ", "_")
|
profile_id = (global_container_stack.getBottom().getId() + "_" + name_seed).lower().replace(" ", "_")
|
||||||
|
|
||||||
elif len(machine_extruders) > profile_index:
|
elif profile_index < len(machine_extruders) + 1:
|
||||||
# This is assumed to be an extruder profile
|
# This is assumed to be an extruder profile
|
||||||
extruder_id = Application.getInstance().getMachineManager().getQualityDefinitionId(machine_extruders[profile_index - 1].getBottom())
|
extruder_id = Application.getInstance().getMachineManager().getQualityDefinitionId(machine_extruders[profile_index - 1].getBottom())
|
||||||
if not profile.getMetaDataEntry("extruder"):
|
if not profile.getMetaDataEntry("extruder"):
|
||||||
|
@ -430,11 +431,42 @@ class CuraContainerRegistry(ContainerRegistry):
|
||||||
extruder_stack.setDefinition(extruder_definition)
|
extruder_stack.setDefinition(extruder_definition)
|
||||||
extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position"))
|
extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position"))
|
||||||
|
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
|
|
||||||
|
# create a new definition_changes container for the extruder stack
|
||||||
|
definition_changes_id = self.uniqueName(extruder_stack.getId() + "_settings")
|
||||||
|
definition_changes_name = definition_changes_id
|
||||||
|
definition_changes = InstanceContainer(definition_changes_id)
|
||||||
|
definition_changes.setName(definition_changes_name)
|
||||||
|
definition_changes.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
|
||||||
|
definition_changes.addMetaDataEntry("type", "definition_changes")
|
||||||
|
definition_changes.addMetaDataEntry("definition", extruder_definition.getId())
|
||||||
|
|
||||||
|
# move definition_changes settings if exist
|
||||||
|
for setting_key in definition_changes.getAllKeys():
|
||||||
|
if machine.definition.getProperty(setting_key, "settable_per_extruder"):
|
||||||
|
setting_value = machine.definitionChanges.getProperty(setting_key, "value")
|
||||||
|
if setting_value is not None:
|
||||||
|
# move it to the extruder stack's definition_changes
|
||||||
|
setting_definition = machine.getSettingDefinition(setting_key)
|
||||||
|
new_instance = SettingInstance(setting_definition, definition_changes)
|
||||||
|
new_instance.setProperty("value", setting_value)
|
||||||
|
new_instance.resetState() # Ensure that the state is not seen as a user state.
|
||||||
|
definition_changes.addInstance(new_instance)
|
||||||
|
definition_changes.setDirty(True)
|
||||||
|
|
||||||
|
machine.definitionChanges.removeInstance(setting_key, postpone_emit = True)
|
||||||
|
|
||||||
|
self.addContainer(definition_changes)
|
||||||
|
extruder_stack.setDefinitionChanges(definition_changes)
|
||||||
|
|
||||||
# create empty user changes container otherwise
|
# create empty user changes container otherwise
|
||||||
user_container = InstanceContainer(extruder_stack.id + "_user")
|
user_container_id = self.uniqueName(extruder_stack.getId() + "_user")
|
||||||
|
user_container_name = user_container_id
|
||||||
|
user_container = InstanceContainer(user_container_id)
|
||||||
|
user_container.setName(user_container_name)
|
||||||
user_container.addMetaDataEntry("type", "user")
|
user_container.addMetaDataEntry("type", "user")
|
||||||
user_container.addMetaDataEntry("machine", extruder_stack.getId())
|
user_container.addMetaDataEntry("machine", extruder_stack.getId())
|
||||||
from cura.CuraApplication import CuraApplication
|
|
||||||
user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
|
user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
|
||||||
user_container.setDefinition(machine.definition.getId())
|
user_container.setDefinition(machine.definition.getId())
|
||||||
|
|
||||||
|
@ -444,7 +476,15 @@ class CuraContainerRegistry(ContainerRegistry):
|
||||||
for user_setting_key in machine.userChanges.getAllKeys():
|
for user_setting_key in machine.userChanges.getAllKeys():
|
||||||
settable_per_extruder = machine.getProperty(user_setting_key, "settable_per_extruder")
|
settable_per_extruder = machine.getProperty(user_setting_key, "settable_per_extruder")
|
||||||
if settable_per_extruder:
|
if settable_per_extruder:
|
||||||
user_container.addInstance(machine.userChanges.getInstance(user_setting_key))
|
setting_value = machine.getProperty(user_setting_key, "value")
|
||||||
|
|
||||||
|
setting_definition = machine.getSettingDefinition(user_setting_key)
|
||||||
|
new_instance = SettingInstance(setting_definition, definition_changes)
|
||||||
|
new_instance.setProperty("value", setting_value)
|
||||||
|
new_instance.resetState() # Ensure that the state is not seen as a user state.
|
||||||
|
user_container.addInstance(new_instance)
|
||||||
|
user_container.setDirty(True)
|
||||||
|
|
||||||
machine.userChanges.removeInstance(user_setting_key, postpone_emit = True)
|
machine.userChanges.removeInstance(user_setting_key, postpone_emit = True)
|
||||||
|
|
||||||
self.addContainer(user_container)
|
self.addContainer(user_container)
|
||||||
|
|
|
@ -8,6 +8,7 @@ from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
|
||||||
from UM.Settings.ContainerStack import ContainerStack
|
from UM.Settings.ContainerStack import ContainerStack
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
from UM.Settings.Interfaces import ContainerInterface, PropertyEvaluationContext
|
from UM.Settings.Interfaces import ContainerInterface, PropertyEvaluationContext
|
||||||
|
from UM.Settings.SettingInstance import SettingInstance
|
||||||
|
|
||||||
from . import Exceptions
|
from . import Exceptions
|
||||||
from .CuraContainerStack import CuraContainerStack
|
from .CuraContainerStack import CuraContainerStack
|
||||||
|
@ -16,6 +17,11 @@ from .ExtruderManager import ExtruderManager
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from cura.Settings.GlobalStack import GlobalStack
|
from cura.Settings.GlobalStack import GlobalStack
|
||||||
|
|
||||||
|
|
||||||
|
_EXTRUDER_SPECIFIC_DEFINITION_CHANGES_SETTINGS = ["machine_nozzle_size",
|
||||||
|
"material_diameter"]
|
||||||
|
|
||||||
|
|
||||||
## Represents an Extruder and its related containers.
|
## Represents an Extruder and its related containers.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -39,6 +45,29 @@ class ExtruderStack(CuraContainerStack):
|
||||||
# For backward compatibility: Register the extruder with the Extruder Manager
|
# For backward compatibility: Register the extruder with the Extruder Manager
|
||||||
ExtruderManager.getInstance().registerExtruder(self, stack.id)
|
ExtruderManager.getInstance().registerExtruder(self, stack.id)
|
||||||
|
|
||||||
|
# Now each machine will have at least one extruder stack. If this is the first extruder, the extruder-specific
|
||||||
|
# settings such as nozzle size and material diameter should be moved from the machine's definition_changes to
|
||||||
|
# the this extruder's definition_changes.
|
||||||
|
#
|
||||||
|
# We do this here because it is tooooo expansive to do it in the version upgrade: During the version upgrade,
|
||||||
|
# when we are upgrading a definition_changes container file, there is NO guarantee that other files such as
|
||||||
|
# machine an extruder stack files are upgraded before this, so we cannot read those files assuming they are in
|
||||||
|
# the latest format.
|
||||||
|
if self.getMetaDataEntry("position") == "0":
|
||||||
|
for key in _EXTRUDER_SPECIFIC_DEFINITION_CHANGES_SETTINGS:
|
||||||
|
setting_value = stack.definitionChanges.getProperty(key, "value")
|
||||||
|
if setting_value is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
setting_definition = stack.getSettingDefinition(key)
|
||||||
|
new_instance = SettingInstance(setting_definition, self.definitionChanges)
|
||||||
|
new_instance.setProperty("value", setting_value)
|
||||||
|
new_instance.resetState() # Ensure that the state is not seen as a user state.
|
||||||
|
self.definitionChanges.addInstance(new_instance)
|
||||||
|
self.definitionChanges.setDirty(True)
|
||||||
|
|
||||||
|
stack.definitionChanges.removeInstance(key, postpone_emit = True)
|
||||||
|
|
||||||
@override(ContainerStack)
|
@override(ContainerStack)
|
||||||
def getNextStack(self) -> Optional["GlobalStack"]:
|
def getNextStack(self) -> Optional["GlobalStack"]:
|
||||||
return super().getNextStack()
|
return super().getNextStack()
|
||||||
|
|
|
@ -43,13 +43,12 @@ class ShapeArray:
|
||||||
transform_x = transform._data[0][3]
|
transform_x = transform._data[0][3]
|
||||||
transform_y = transform._data[2][3]
|
transform_y = transform._data[2][3]
|
||||||
hull_verts = node.callDecoration("getConvexHull")
|
hull_verts = node.callDecoration("getConvexHull")
|
||||||
|
# If a model is too small then it will not contain any points
|
||||||
|
if hull_verts is None or not hull_verts.getPoints().any():
|
||||||
|
return None, None
|
||||||
# For one_at_a_time printing you need the convex hull head.
|
# For one_at_a_time printing you need the convex hull head.
|
||||||
hull_head_verts = node.callDecoration("getConvexHullHead") or hull_verts
|
hull_head_verts = node.callDecoration("getConvexHullHead") or hull_verts
|
||||||
|
|
||||||
# If a model is to small then it will not contain any points
|
|
||||||
if not hull_verts.getPoints().any():
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
offset_verts = hull_head_verts.getMinkowskiHull(Polygon.approximatedCircle(min_offset))
|
offset_verts = hull_head_verts.getMinkowskiHull(Polygon.approximatedCircle(min_offset))
|
||||||
offset_points = copy.deepcopy(offset_verts._points) # x, y
|
offset_points = copy.deepcopy(offset_verts._points) # x, y
|
||||||
offset_points[:, 0] = numpy.add(offset_points[:, 0], -transform_x)
|
offset_points[:, 0] = numpy.add(offset_points[:, 0], -transform_x)
|
||||||
|
|
|
@ -682,12 +682,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
file_name = global_stack_file)
|
file_name = global_stack_file)
|
||||||
|
|
||||||
# Ensure a unique ID and name
|
# Ensure a unique ID and name
|
||||||
stack._id = global_stack_id_new
|
stack.setMetaDataEntry("id", global_stack_id_new)
|
||||||
|
|
||||||
# Extruder stacks are "bound" to a machine. If we add the machine as a new one, the id of the
|
|
||||||
# bound machine also needs to change.
|
|
||||||
if stack.getMetaDataEntry("machine", None):
|
|
||||||
stack.setMetaDataEntry("machine", global_stack_id_new)
|
|
||||||
|
|
||||||
# Only machines need a new name, stacks may be non-unique
|
# Only machines need a new name, stacks may be non-unique
|
||||||
stack.setName(global_stack_name_new)
|
stack.setName(global_stack_name_new)
|
||||||
|
@ -741,7 +736,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
stack.deserialize(extruder_file_content, file_name = extruder_stack_file)
|
stack.deserialize(extruder_file_content, file_name = extruder_stack_file)
|
||||||
|
|
||||||
# Ensure a unique ID and name
|
# Ensure a unique ID and name
|
||||||
stack._id = new_id
|
stack.setMetaDataEntry("id", new_id)
|
||||||
|
|
||||||
self._container_registry.addContainer(stack)
|
self._container_registry.addContainer(stack)
|
||||||
extruder_stacks_added.append(stack)
|
extruder_stacks_added.append(stack)
|
||||||
|
|
|
@ -153,10 +153,11 @@ class StartSliceJob(Job):
|
||||||
is_non_printing_mesh = any(per_object_stack.getProperty(key, "value") for key in NON_PRINTING_MESH_SETTINGS)
|
is_non_printing_mesh = any(per_object_stack.getProperty(key, "value") for key in NON_PRINTING_MESH_SETTINGS)
|
||||||
|
|
||||||
if (node.callDecoration("getBuildPlateNumber") == self._build_plate_number):
|
if (node.callDecoration("getBuildPlateNumber") == self._build_plate_number):
|
||||||
if not getattr(node, "_outside_buildarea", False) or not is_non_printing_mesh:
|
if not getattr(node, "_outside_buildarea", False) or is_non_printing_mesh:
|
||||||
temp_list.append(node)
|
temp_list.append(node)
|
||||||
if not is_non_printing_mesh:
|
if not is_non_printing_mesh:
|
||||||
has_printing_mesh = True
|
has_printing_mesh = True
|
||||||
|
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
|
||||||
#If the list doesn't have any model with suitable settings then clean the list
|
#If the list doesn't have any model with suitable settings then clean the list
|
||||||
|
|
|
@ -7,14 +7,11 @@ from UM.FlameProfiler import pyqtSlot
|
||||||
from cura.MachineAction import MachineAction
|
from cura.MachineAction import MachineAction
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Preferences import Preferences
|
|
||||||
from UM.Settings.InstanceContainer import InstanceContainer
|
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
from UM.Settings.DefinitionContainer import DefinitionContainer
|
from UM.Settings.DefinitionContainer import DefinitionContainer
|
||||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
|
||||||
from cura.CuraApplication import CuraApplication
|
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
from cura.Settings.CuraStackBuilder import CuraStackBuilder
|
from cura.Settings.CuraStackBuilder import CuraStackBuilder
|
||||||
|
|
||||||
|
@ -36,7 +33,6 @@ class MachineSettingsAction(MachineAction):
|
||||||
self._container_registry.containerAdded.connect(self._onContainerAdded)
|
self._container_registry.containerAdded.connect(self._onContainerAdded)
|
||||||
self._container_registry.containerRemoved.connect(self._onContainerRemoved)
|
self._container_registry.containerRemoved.connect(self._onContainerRemoved)
|
||||||
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
|
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
|
||||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
|
|
||||||
|
|
||||||
self._empty_container = self._container_registry.getEmptyInstanceContainer()
|
self._empty_container = self._container_registry.getEmptyInstanceContainer()
|
||||||
|
|
||||||
|
@ -67,7 +63,9 @@ class MachineSettingsAction(MachineAction):
|
||||||
self._global_container_stack, self._global_container_stack.getName() + "_settings")
|
self._global_container_stack, self._global_container_stack.getName() + "_settings")
|
||||||
|
|
||||||
# Notify the UI in which container to store the machine settings data
|
# Notify the UI in which container to store the machine settings data
|
||||||
container_index = self._global_container_stack.getContainerIndex(definition_changes_container)
|
from cura.Settings.CuraContainerStack import CuraContainerStack, _ContainerIndexes
|
||||||
|
|
||||||
|
container_index = _ContainerIndexes.DefinitionChanges
|
||||||
if container_index != self._container_index:
|
if container_index != self._container_index:
|
||||||
self._container_index = container_index
|
self._container_index = container_index
|
||||||
self.containerIndexChanged.emit()
|
self.containerIndexChanged.emit()
|
||||||
|
@ -82,17 +80,6 @@ class MachineSettingsAction(MachineAction):
|
||||||
if self._backend and self._backend.determineAutoSlicing():
|
if self._backend and self._backend.determineAutoSlicing():
|
||||||
self._backend.tickle()
|
self._backend.tickle()
|
||||||
|
|
||||||
def _onActiveExtruderStackChanged(self):
|
|
||||||
extruder_container_stack = ExtruderManager.getInstance().getActiveExtruderStack()
|
|
||||||
if not self._global_container_stack or not extruder_container_stack:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Make sure there is a definition_changes container to store the machine settings
|
|
||||||
definition_changes_container = extruder_container_stack.definitionChanges
|
|
||||||
if definition_changes_container == self._empty_container:
|
|
||||||
definition_changes_container = CuraStackBuilder.createDefinitionChangesContainer(
|
|
||||||
extruder_container_stack, extruder_container_stack.getId() + "_settings")
|
|
||||||
|
|
||||||
containerIndexChanged = pyqtSignal()
|
containerIndexChanged = pyqtSignal()
|
||||||
|
|
||||||
@pyqtProperty(int, notify = containerIndexChanged)
|
@pyqtProperty(int, notify = containerIndexChanged)
|
||||||
|
@ -217,8 +204,8 @@ class MachineSettingsAction(MachineAction):
|
||||||
|
|
||||||
Application.getInstance().globalContainerStackChanged.emit()
|
Application.getInstance().globalContainerStackChanged.emit()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot(int)
|
||||||
def updateMaterialForDiameter(self):
|
def updateMaterialForDiameter(self, extruder_position: int):
|
||||||
# Updates the material container to a material that matches the material diameter set for the printer
|
# Updates the material container to a material that matches the material diameter set for the printer
|
||||||
if not self._global_container_stack:
|
if not self._global_container_stack:
|
||||||
return
|
return
|
||||||
|
@ -226,24 +213,22 @@ class MachineSettingsAction(MachineAction):
|
||||||
if not self._global_container_stack.getMetaDataEntry("has_materials", False):
|
if not self._global_container_stack.getMetaDataEntry("has_materials", False):
|
||||||
return
|
return
|
||||||
|
|
||||||
material = ExtruderManager.getInstance().getActiveExtruderStack().material
|
extruder_stack = self._global_container_stack.extruders[str(extruder_position)]
|
||||||
material_diameter = material.getProperty("material_diameter", "value")
|
|
||||||
|
material_diameter = extruder_stack.material.getProperty("material_diameter", "value")
|
||||||
if not material_diameter:
|
if not material_diameter:
|
||||||
# in case of "empty" material
|
# in case of "empty" material
|
||||||
material_diameter = 0
|
material_diameter = 0
|
||||||
|
|
||||||
material_approximate_diameter = str(round(material_diameter))
|
material_approximate_diameter = str(round(material_diameter))
|
||||||
definition_changes = self._global_container_stack.definitionChanges
|
machine_diameter = extruder_stack.definitionChanges.getProperty("material_diameter", "value")
|
||||||
machine_diameter = definition_changes.getProperty("material_diameter", "value")
|
|
||||||
if not machine_diameter:
|
if not machine_diameter:
|
||||||
machine_diameter = self._global_container_stack.definition.getProperty("material_diameter", "value")
|
machine_diameter = extruder_stack.definition.getProperty("material_diameter", "value")
|
||||||
machine_approximate_diameter = str(round(machine_diameter))
|
machine_approximate_diameter = str(round(machine_diameter))
|
||||||
|
|
||||||
if material_approximate_diameter != machine_approximate_diameter:
|
if material_approximate_diameter != machine_approximate_diameter:
|
||||||
Logger.log("i", "The the currently active material(s) do not match the diameter set for the printer. Finding alternatives.")
|
Logger.log("i", "The the currently active material(s) do not match the diameter set for the printer. Finding alternatives.")
|
||||||
|
|
||||||
stacks = ExtruderManager.getInstance().getExtruderStacks()
|
|
||||||
|
|
||||||
if self._global_container_stack.getMetaDataEntry("has_machine_materials", False):
|
if self._global_container_stack.getMetaDataEntry("has_machine_materials", False):
|
||||||
materials_definition = self._global_container_stack.definition.getId()
|
materials_definition = self._global_container_stack.definition.getId()
|
||||||
has_material_variants = self._global_container_stack.getMetaDataEntry("has_variants", False)
|
has_material_variants = self._global_container_stack.getMetaDataEntry("has_variants", False)
|
||||||
|
@ -251,45 +236,44 @@ class MachineSettingsAction(MachineAction):
|
||||||
materials_definition = "fdmprinter"
|
materials_definition = "fdmprinter"
|
||||||
has_material_variants = False
|
has_material_variants = False
|
||||||
|
|
||||||
for stack in stacks:
|
old_material = extruder_stack.material
|
||||||
old_material = stack.material
|
search_criteria = {
|
||||||
search_criteria = {
|
"type": "material",
|
||||||
"type": "material",
|
"approximate_diameter": machine_approximate_diameter,
|
||||||
"approximate_diameter": machine_approximate_diameter,
|
"material": old_material.getMetaDataEntry("material", "value"),
|
||||||
"material": old_material.getMetaDataEntry("material", "value"),
|
"supplier": old_material.getMetaDataEntry("supplier", "value"),
|
||||||
"supplier": old_material.getMetaDataEntry("supplier", "value"),
|
"color_name": old_material.getMetaDataEntry("color_name", "value"),
|
||||||
"color_name": old_material.getMetaDataEntry("color_name", "value"),
|
"definition": materials_definition
|
||||||
"definition": materials_definition
|
}
|
||||||
}
|
if has_material_variants:
|
||||||
if has_material_variants:
|
search_criteria["variant"] = extruder_stack.variant.getId()
|
||||||
search_criteria["variant"] = stack.variant.getId()
|
|
||||||
|
|
||||||
if old_material == self._empty_container:
|
if old_material == self._empty_container:
|
||||||
search_criteria.pop("material", None)
|
search_criteria.pop("material", None)
|
||||||
search_criteria.pop("supplier", None)
|
search_criteria.pop("supplier", None)
|
||||||
search_criteria.pop("definition", None)
|
search_criteria.pop("definition", None)
|
||||||
search_criteria["id"] = stack.getMetaDataEntry("preferred_material")
|
search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material")
|
||||||
|
|
||||||
|
materials = self._container_registry.findInstanceContainers(**search_criteria)
|
||||||
|
if not materials:
|
||||||
|
# Same material with new diameter is not found, search for generic version of the same material type
|
||||||
|
search_criteria.pop("supplier", None)
|
||||||
|
search_criteria["color_name"] = "Generic"
|
||||||
materials = self._container_registry.findInstanceContainers(**search_criteria)
|
materials = self._container_registry.findInstanceContainers(**search_criteria)
|
||||||
if not materials:
|
if not materials:
|
||||||
# Same material with new diameter is not found, search for generic version of the same material type
|
# Generic material with new diameter is not found, search for preferred material
|
||||||
search_criteria.pop("supplier", None)
|
search_criteria.pop("color_name", None)
|
||||||
search_criteria["color_name"] = "Generic"
|
search_criteria.pop("material", None)
|
||||||
materials = self._container_registry.findInstanceContainers(**search_criteria)
|
search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material")
|
||||||
if not materials:
|
materials = self._container_registry.findInstanceContainers(**search_criteria)
|
||||||
# Generic material with new diameter is not found, search for preferred material
|
if not materials:
|
||||||
search_criteria.pop("color_name", None)
|
# Preferred material with new diameter is not found, search for any material
|
||||||
search_criteria.pop("material", None)
|
search_criteria.pop("id", None)
|
||||||
search_criteria["id"] = stack.getMetaDataEntry("preferred_material")
|
materials = self._container_registry.findInstanceContainers(**search_criteria)
|
||||||
materials = self._container_registry.findInstanceContainers(**search_criteria)
|
if not materials:
|
||||||
if not materials:
|
# Just use empty material as a final fallback
|
||||||
# Preferred material with new diameter is not found, search for any material
|
materials = [self._empty_container]
|
||||||
search_criteria.pop("id", None)
|
|
||||||
materials = self._container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if not materials:
|
|
||||||
# Just use empty material as a final fallback
|
|
||||||
materials = [self._empty_container]
|
|
||||||
|
|
||||||
Logger.log("i", "Selecting new material: %s" % materials[0].getId())
|
Logger.log("i", "Selecting new material: %s" % materials[0].getId())
|
||||||
|
|
||||||
stack.material = materials[0]
|
extruder_stack.material = materials[0]
|
||||||
|
|
|
@ -292,18 +292,6 @@ Cura.MachineAction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader
|
|
||||||
{
|
|
||||||
id: materialDiameterField
|
|
||||||
visible: Cura.MachineManager.hasMaterials
|
|
||||||
sourceComponent: numericTextFieldWithUnit
|
|
||||||
property string settingKey: "material_diameter"
|
|
||||||
property string unit: catalog.i18nc("@label", "mm")
|
|
||||||
property string tooltip: catalog.i18nc("@tooltip", "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile.")
|
|
||||||
property var afterOnEditingFinished: manager.updateMaterialForDiameter
|
|
||||||
property string label: catalog.i18nc("@label", "Material diameter")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +348,6 @@ Cura.MachineAction
|
||||||
if(currentIndex > 0)
|
if(currentIndex > 0)
|
||||||
{
|
{
|
||||||
contentItem.forceActiveFocus();
|
contentItem.forceActiveFocus();
|
||||||
Cura.ExtruderManager.setActiveExtruderIndex(currentIndex - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,6 +384,25 @@ Cura.MachineAction
|
||||||
property bool isExtruderSetting: true
|
property bool isExtruderSetting: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader
|
||||||
|
{
|
||||||
|
id: materialDiameterField
|
||||||
|
visible: Cura.MachineManager.hasMaterials
|
||||||
|
sourceComponent: numericTextFieldWithUnit
|
||||||
|
property string settingKey: "material_diameter"
|
||||||
|
property string label: catalog.i18nc("@label", "Material diameter")
|
||||||
|
property string unit: catalog.i18nc("@label", "mm")
|
||||||
|
property string tooltip: catalog.i18nc("@tooltip", "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile.")
|
||||||
|
property var afterOnEditingFinished:
|
||||||
|
{
|
||||||
|
if (settingsTabs.currentIndex > 0)
|
||||||
|
{
|
||||||
|
manager.updateMaterialForDiameter(settingsTabs.currentIndex - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
property bool isExtruderSetting: true
|
||||||
|
}
|
||||||
|
|
||||||
Loader
|
Loader
|
||||||
{
|
{
|
||||||
id: extruderOffsetXField
|
id: extruderOffsetXField
|
||||||
|
@ -495,7 +501,7 @@ Cura.MachineAction
|
||||||
{
|
{
|
||||||
if(settingsTabs.currentIndex > 0)
|
if(settingsTabs.currentIndex > 0)
|
||||||
{
|
{
|
||||||
return Cura.MachineManager.activeStackId;
|
return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -513,11 +519,11 @@ Cura.MachineAction
|
||||||
checked: String(propertyProvider.properties.value).toLowerCase() != 'false'
|
checked: String(propertyProvider.properties.value).toLowerCase() != 'false'
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
propertyProvider.setPropertyValue("value", checked);
|
propertyProvider.setPropertyValue("value", checked);
|
||||||
if(_forceUpdateOnChange)
|
if(_forceUpdateOnChange)
|
||||||
{
|
{
|
||||||
manager.forceUpdate();
|
manager.forceUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -548,7 +554,7 @@ Cura.MachineAction
|
||||||
{
|
{
|
||||||
if(settingsTabs.currentIndex > 0)
|
if(settingsTabs.currentIndex > 0)
|
||||||
{
|
{
|
||||||
return Cura.MachineManager.activeStackId;
|
return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -581,7 +587,10 @@ Cura.MachineAction
|
||||||
TextField
|
TextField
|
||||||
{
|
{
|
||||||
id: textField
|
id: textField
|
||||||
text: (propertyProvider.properties.value) ? propertyProvider.properties.value : ""
|
text: {
|
||||||
|
const value = propertyProvider.properties.value;
|
||||||
|
return value ? value : "";
|
||||||
|
}
|
||||||
validator: RegExpValidator { regExp: _allowNegative ? /-?[0-9\.]{0,6}/ : /[0-9\.]{0,6}/ }
|
validator: RegExpValidator { regExp: _allowNegative ? /-?[0-9\.]{0,6}/ : /[0-9\.]{0,6}/ }
|
||||||
onEditingFinished:
|
onEditingFinished:
|
||||||
{
|
{
|
||||||
|
@ -590,12 +599,7 @@ Cura.MachineAction
|
||||||
propertyProvider.setPropertyValue("value", text);
|
propertyProvider.setPropertyValue("value", text);
|
||||||
if(_forceUpdateOnChange)
|
if(_forceUpdateOnChange)
|
||||||
{
|
{
|
||||||
var extruderIndex = Cura.ExtruderManager.activeExtruderIndex;
|
|
||||||
manager.forceUpdate();
|
manager.forceUpdate();
|
||||||
if(Cura.ExtruderManager.activeExtruderIndex != extruderIndex)
|
|
||||||
{
|
|
||||||
Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(_afterOnEditingFinished)
|
if(_afterOnEditingFinished)
|
||||||
{
|
{
|
||||||
|
@ -641,7 +645,7 @@ Cura.MachineAction
|
||||||
{
|
{
|
||||||
if(settingsTabs.currentIndex > 0)
|
if(settingsTabs.currentIndex > 0)
|
||||||
{
|
{
|
||||||
return Cura.MachineManager.activeStackId;
|
return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
|
from PyQt5.QtGui import QOpenGLContext
|
||||||
from PyQt5.QtWidgets import QApplication
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
@ -13,6 +14,7 @@ from UM.Logger import Logger
|
||||||
from UM.Math.Color import Color
|
from UM.Math.Color import Color
|
||||||
from UM.Mesh.MeshBuilder import MeshBuilder
|
from UM.Mesh.MeshBuilder import MeshBuilder
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
|
from UM.Platform import Platform
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
from UM.Preferences import Preferences
|
from UM.Preferences import Preferences
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
|
@ -24,6 +26,7 @@ from UM.View.GL.OpenGLContext import OpenGLContext
|
||||||
from UM.View.View import View
|
from UM.View.View import View
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
from cura.ConvexHullNode import ConvexHullNode
|
from cura.ConvexHullNode import ConvexHullNode
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
|
|
||||||
from .NozzleNode import NozzleNode
|
from .NozzleNode import NozzleNode
|
||||||
from .SimulationPass import SimulationPass
|
from .SimulationPass import SimulationPass
|
||||||
|
@ -414,6 +417,23 @@ class SimulationView(View):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if event.type == Event.ViewActivateEvent:
|
if event.type == Event.ViewActivateEvent:
|
||||||
|
# FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching.
|
||||||
|
# This can happen when you do the following steps:
|
||||||
|
# 1. Start Cura
|
||||||
|
# 2. Load a model
|
||||||
|
# 3. Switch to Custom mode
|
||||||
|
# 4. Select the model and click on the per-object tool icon
|
||||||
|
# 5. Switch view to Layer view or X-Ray
|
||||||
|
# 6. Cura will very likely crash
|
||||||
|
# It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why.
|
||||||
|
# This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL
|
||||||
|
# context is None.
|
||||||
|
if Platform.isOSX():
|
||||||
|
if QOpenGLContext.currentContext() is None:
|
||||||
|
Logger.log("d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later")
|
||||||
|
CuraApplication.getInstance().callLater(lambda e=event: self.event(e))
|
||||||
|
return
|
||||||
|
|
||||||
# Make sure the SimulationPass is created
|
# Make sure the SimulationPass is created
|
||||||
layer_pass = self.getSimulationPass()
|
layer_pass = self.getSimulationPass()
|
||||||
self.getRenderer().addRenderPass(layer_pass)
|
self.getRenderer().addRenderPass(layer_pass)
|
||||||
|
|
|
@ -187,7 +187,7 @@ geometry41core =
|
||||||
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
|
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
|
||||||
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
|
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
|
||||||
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert));
|
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert));
|
||||||
//And reverse so that the line is also visible from the back side.
|
//And reverse so that the line is also visible from the back side.
|
||||||
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
|
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
|
||||||
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
|
myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
|
||||||
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
|
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
|
||||||
|
@ -212,17 +212,17 @@ geometry41core =
|
||||||
EndPrimitive();
|
EndPrimitive();
|
||||||
|
|
||||||
// left side
|
// left side
|
||||||
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
|
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
|
||||||
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert));
|
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert));
|
||||||
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
|
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
|
||||||
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
|
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
|
||||||
|
|
||||||
EndPrimitive();
|
EndPrimitive();
|
||||||
|
|
||||||
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
|
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
|
||||||
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert));
|
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert));
|
||||||
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
|
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
|
||||||
myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
|
myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
|
||||||
|
|
||||||
EndPrimitive();
|
EndPrimitive();
|
||||||
|
|
||||||
|
|
|
@ -39,19 +39,26 @@ class SliceInfo(Extension):
|
||||||
Preferences.getInstance().addPreference("info/send_slice_info", True)
|
Preferences.getInstance().addPreference("info/send_slice_info", True)
|
||||||
Preferences.getInstance().addPreference("info/asked_send_slice_info", False)
|
Preferences.getInstance().addPreference("info/asked_send_slice_info", False)
|
||||||
|
|
||||||
if not Preferences.getInstance().getValue("info/asked_send_slice_info") and Preferences.getInstance().getValue("info/send_slice_info"):
|
if not Preferences.getInstance().getValue("info/asked_send_slice_info"):
|
||||||
self.send_slice_info_message = Message(catalog.i18nc("@info", "Cura collects anonymised slicing statistics. You can disable this in the preferences."),
|
self.send_slice_info_message = Message(catalog.i18nc("@info", "Cura collects anonymized usage statistics."),
|
||||||
lifetime = 0,
|
lifetime = 0,
|
||||||
dismissable = False,
|
dismissable = False,
|
||||||
title = catalog.i18nc("@info:title", "Collecting Data"))
|
title = catalog.i18nc("@info:title", "Collecting Data"))
|
||||||
|
|
||||||
self.send_slice_info_message.addAction("Dismiss", catalog.i18nc("@action:button", "Dismiss"), None, "")
|
self.send_slice_info_message.addAction("Dismiss", name = catalog.i18nc("@action:button", "Allow"), icon = None,
|
||||||
|
description = catalog.i18nc("@action:tooltip", "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."))
|
||||||
|
self.send_slice_info_message.addAction("Disable", name = catalog.i18nc("@action:button", "Disable"), icon = None,
|
||||||
|
description = catalog.i18nc("@action:tooltip", "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences."), button_style = Message.ActionButtonStyle.LINK)
|
||||||
self.send_slice_info_message.actionTriggered.connect(self.messageActionTriggered)
|
self.send_slice_info_message.actionTriggered.connect(self.messageActionTriggered)
|
||||||
self.send_slice_info_message.show()
|
self.send_slice_info_message.show()
|
||||||
|
|
||||||
|
## Perform action based on user input.
|
||||||
|
# Note that clicking "Disable" won't actually disable the data sending, but rather take the user to preferences where they can disable it.
|
||||||
def messageActionTriggered(self, message_id, action_id):
|
def messageActionTriggered(self, message_id, action_id):
|
||||||
self.send_slice_info_message.hide()
|
|
||||||
Preferences.getInstance().setValue("info/asked_send_slice_info", True)
|
Preferences.getInstance().setValue("info/asked_send_slice_info", True)
|
||||||
|
if action_id == "Disable":
|
||||||
|
CuraApplication.getInstance().showPreferences()
|
||||||
|
self.send_slice_info_message.hide()
|
||||||
|
|
||||||
def _onWriteStarted(self, output_device):
|
def _onWriteStarted(self, output_device):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -122,26 +122,6 @@ class VersionUpgrade30to31(VersionUpgrade):
|
||||||
if len(all_quality_changes) <= 1 and not parser.has_option("metadata", "extruder"):
|
if len(all_quality_changes) <= 1 and not parser.has_option("metadata", "extruder"):
|
||||||
self._createExtruderQualityChangesForSingleExtrusionMachine(filename, parser)
|
self._createExtruderQualityChangesForSingleExtrusionMachine(filename, parser)
|
||||||
|
|
||||||
if parser["metadata"]["type"] == "definition_changes":
|
|
||||||
if parser["general"]["definition"] == "custom":
|
|
||||||
|
|
||||||
# We are only interested in machine_nozzle_size
|
|
||||||
if parser.has_option("values", "machine_nozzle_size"):
|
|
||||||
machine_nozzle_size = parser["values"]["machine_nozzle_size"]
|
|
||||||
|
|
||||||
machine_extruder_count = '1' # by default it is 1 and the value cannot be stored in the global stack
|
|
||||||
if parser.has_option("values", "machine_extruder_count"):
|
|
||||||
machine_extruder_count = parser["values"]["machine_extruder_count"]
|
|
||||||
|
|
||||||
if machine_extruder_count == '1':
|
|
||||||
definition_name = parser["general"]["name"]
|
|
||||||
machine_extruders = self._getSingleExtrusionMachineExtruders(definition_name)
|
|
||||||
|
|
||||||
# For single extruder machine we need only first extruder
|
|
||||||
if len(machine_extruders) !=0:
|
|
||||||
self._updateSingleExtruderDefinitionFile(machine_extruders, machine_nozzle_size)
|
|
||||||
parser.remove_option("values", "machine_nozzle_size")
|
|
||||||
|
|
||||||
# Update version numbers
|
# Update version numbers
|
||||||
parser["general"]["version"] = "2"
|
parser["general"]["version"] = "2"
|
||||||
parser["metadata"]["setting_version"] = "4"
|
parser["metadata"]["setting_version"] = "4"
|
||||||
|
@ -220,123 +200,6 @@ class VersionUpgrade30to31(VersionUpgrade):
|
||||||
|
|
||||||
return quality_changes_containers
|
return quality_changes_containers
|
||||||
|
|
||||||
def _getSingleExtrusionMachineExtruders(self, definition_name):
|
|
||||||
|
|
||||||
machine_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.MachineStack)
|
|
||||||
|
|
||||||
machine_instance_id = None
|
|
||||||
|
|
||||||
# Find machine instances
|
|
||||||
for item in os.listdir(machine_instances_dir):
|
|
||||||
file_path = os.path.join(machine_instances_dir, item)
|
|
||||||
if not os.path.isfile(file_path):
|
|
||||||
continue
|
|
||||||
|
|
||||||
parser = configparser.ConfigParser(interpolation=None)
|
|
||||||
try:
|
|
||||||
parser.read([file_path])
|
|
||||||
except:
|
|
||||||
# skip, it is not a valid stack file
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not parser.has_option("metadata", "type"):
|
|
||||||
continue
|
|
||||||
if "machine" != parser["metadata"]["type"]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not parser.has_option("general", "id"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
id = parser["general"]["id"]
|
|
||||||
if id + "_settings" != definition_name:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
machine_instance_id = id
|
|
||||||
break
|
|
||||||
|
|
||||||
if machine_instance_id is not None:
|
|
||||||
|
|
||||||
extruders_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.ExtruderStack)
|
|
||||||
#"machine",[extruders]
|
|
||||||
extruder_instances = []
|
|
||||||
|
|
||||||
# Find all custom extruders for found machines
|
|
||||||
for item in os.listdir(extruders_instances_dir):
|
|
||||||
file_path = os.path.join(extruders_instances_dir, item)
|
|
||||||
if not os.path.isfile(file_path):
|
|
||||||
continue
|
|
||||||
|
|
||||||
parser = configparser.ConfigParser(interpolation=None)
|
|
||||||
try:
|
|
||||||
parser.read([file_path])
|
|
||||||
except:
|
|
||||||
# skip, it is not a valid stack file
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not parser.has_option("metadata", "type"):
|
|
||||||
continue
|
|
||||||
if "extruder_train" != parser["metadata"]["type"]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not parser.has_option("metadata", "machine"):
|
|
||||||
continue
|
|
||||||
if not parser.has_option("metadata", "position"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if machine_instance_id != parser["metadata"]["machine"]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
extruder_instances.append(parser)
|
|
||||||
|
|
||||||
return extruder_instances
|
|
||||||
|
|
||||||
# Find extruder definition at index 0 and update its values
|
|
||||||
def _updateSingleExtruderDefinitionFile(self, extruder_instances_per_machine, machine_nozzle_size):
|
|
||||||
|
|
||||||
defintion_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.DefinitionChangesContainer)
|
|
||||||
|
|
||||||
for item in os.listdir(defintion_instances_dir):
|
|
||||||
file_path = os.path.join(defintion_instances_dir, item)
|
|
||||||
if not os.path.isfile(file_path):
|
|
||||||
continue
|
|
||||||
|
|
||||||
parser = configparser.ConfigParser(interpolation=None)
|
|
||||||
try:
|
|
||||||
parser.read([file_path])
|
|
||||||
except:
|
|
||||||
# skip, it is not a valid stack file
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not parser.has_option("general", "name"):
|
|
||||||
continue
|
|
||||||
name = parser["general"]["name"]
|
|
||||||
custom_extruder_at_0_position = None
|
|
||||||
for extruder_instance in extruder_instances_per_machine:
|
|
||||||
|
|
||||||
definition_position = extruder_instance["metadata"]["position"]
|
|
||||||
|
|
||||||
if definition_position == "0":
|
|
||||||
custom_extruder_at_0_position = extruder_instance
|
|
||||||
break
|
|
||||||
|
|
||||||
# If not null, then parsed file is for first extuder and then can be updated. I need to update only
|
|
||||||
# first, because this update for single extuder machine
|
|
||||||
if custom_extruder_at_0_position is not None:
|
|
||||||
|
|
||||||
#Add new value
|
|
||||||
parser["values"]["machine_nozzle_size"] = machine_nozzle_size
|
|
||||||
|
|
||||||
definition_output = io.StringIO()
|
|
||||||
parser.write(definition_output)
|
|
||||||
|
|
||||||
with open(file_path, "w") as f:
|
|
||||||
f.write(definition_output.getvalue())
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def _createExtruderQualityChangesForSingleExtrusionMachine(self, filename, global_quality_changes):
|
def _createExtruderQualityChangesForSingleExtrusionMachine(self, filename, global_quality_changes):
|
||||||
suffix = "_" + quote_plus(global_quality_changes["general"]["name"].lower())
|
suffix = "_" + quote_plus(global_quality_changes["general"]["name"].lower())
|
||||||
machine_name = os.path.os.path.basename(filename).replace(".inst.cfg", "").replace(suffix, "")
|
machine_name = os.path.os.path.basename(filename).replace(".inst.cfg", "").replace(suffix, "")
|
||||||
|
|
|
@ -185,7 +185,7 @@ class X3DReader(MeshReader):
|
||||||
got_center = (center.x != 0 or center.y != 0 or center.z != 0)
|
got_center = (center.x != 0 or center.y != 0 or center.z != 0)
|
||||||
|
|
||||||
T = self.transform
|
T = self.transform
|
||||||
if trans.x != 0 or trans.y != 0 or trans.z !=0:
|
if trans.x != 0 or trans.y != 0 or trans.z != 0:
|
||||||
T.translate(trans)
|
T.translate(trans)
|
||||||
if got_center:
|
if got_center:
|
||||||
T.translate(center)
|
T.translate(center)
|
||||||
|
|
|
@ -2,10 +2,13 @@
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
from PyQt5.QtGui import QOpenGLContext
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
from UM.Logger import Logger
|
||||||
from UM.Math.Color import Color
|
from UM.Math.Color import Color
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
from UM.Platform import Platform
|
||||||
from UM.Event import Event
|
from UM.Event import Event
|
||||||
from UM.View.View import View
|
from UM.View.View import View
|
||||||
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
|
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
|
||||||
|
@ -13,6 +16,8 @@ from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
|
||||||
from UM.View.RenderBatch import RenderBatch
|
from UM.View.RenderBatch import RenderBatch
|
||||||
from UM.View.GL.OpenGL import OpenGL
|
from UM.View.GL.OpenGL import OpenGL
|
||||||
|
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
|
|
||||||
from . import XRayPass
|
from . import XRayPass
|
||||||
|
|
||||||
## View used to display a see-through version of objects with errors highlighted.
|
## View used to display a see-through version of objects with errors highlighted.
|
||||||
|
@ -52,6 +57,23 @@ class XRayView(View):
|
||||||
|
|
||||||
def event(self, event):
|
def event(self, event):
|
||||||
if event.type == Event.ViewActivateEvent:
|
if event.type == Event.ViewActivateEvent:
|
||||||
|
# FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching.
|
||||||
|
# This can happen when you do the following steps:
|
||||||
|
# 1. Start Cura
|
||||||
|
# 2. Load a model
|
||||||
|
# 3. Switch to Custom mode
|
||||||
|
# 4. Select the model and click on the per-object tool icon
|
||||||
|
# 5. Switch view to Layer view or X-Ray
|
||||||
|
# 6. Cura will very likely crash
|
||||||
|
# It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why.
|
||||||
|
# This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL
|
||||||
|
# context is None.
|
||||||
|
if Platform.isOSX():
|
||||||
|
if QOpenGLContext.currentContext() is None:
|
||||||
|
Logger.log("d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later")
|
||||||
|
CuraApplication.getInstance().callLater(lambda e = event: self.event(e))
|
||||||
|
return
|
||||||
|
|
||||||
if not self._xray_pass:
|
if not self._xray_pass:
|
||||||
# Currently the RenderPass constructor requires a size > 0
|
# Currently the RenderPass constructor requires a size > 0
|
||||||
# This should be fixed in RenderPass's constructor.
|
# This should be fixed in RenderPass's constructor.
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{
|
{
|
||||||
"id": "builder_premium_large",
|
|
||||||
"version": 2,
|
"version": 2,
|
||||||
"name": "Builder Premium Large",
|
"name": "Builder Premium Large",
|
||||||
"inherits": "fdmprinter",
|
"inherits": "fdmprinter",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{
|
{
|
||||||
"id": "builder_premium_medium",
|
|
||||||
"version": 2,
|
"version": 2,
|
||||||
"name": "Builder Premium Medium",
|
"name": "Builder Premium Medium",
|
||||||
"inherits": "fdmprinter",
|
"inherits": "fdmprinter",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{
|
{
|
||||||
"id": "builder_premium_small",
|
|
||||||
"version": 2,
|
"version": 2,
|
||||||
"name": "Builder Premium Small",
|
"name": "Builder Premium Small",
|
||||||
"inherits": "fdmprinter",
|
"inherits": "fdmprinter",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{
|
{
|
||||||
"id": "deltacomb",
|
|
||||||
"version": 2,
|
"version": 2,
|
||||||
"name": "Deltacomb 3D",
|
"name": "Deltacomb 3D",
|
||||||
"inherits": "fdmprinter",
|
"inherits": "fdmprinter",
|
||||||
|
|
|
@ -181,6 +181,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"material": {
|
||||||
|
"label": "Material",
|
||||||
|
"icon": "category_material",
|
||||||
|
"description": "Material",
|
||||||
|
"type": "category",
|
||||||
|
"children": {
|
||||||
|
"material_diameter": {
|
||||||
|
"label": "Diameter",
|
||||||
|
"description": "Adjusts the diameter of the filament used. Match this value with the diameter of the used filament.",
|
||||||
|
"unit": "mm",
|
||||||
|
"type": "float",
|
||||||
|
"default_value": 2.85,
|
||||||
|
"minimum_value": "0.0001",
|
||||||
|
"minimum_value_warning": "0.4",
|
||||||
|
"maximum_value_warning": "3.5",
|
||||||
|
"enabled": "machine_gcode_flavor != \"UltiGCode\"",
|
||||||
|
"settable_per_mesh": false,
|
||||||
|
"settable_per_extruder": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"platform_adhesion":
|
"platform_adhesion":
|
||||||
{
|
{
|
||||||
"label": "Build Plate Adhesion",
|
"label": "Build Plate Adhesion",
|
||||||
|
|
|
@ -1614,7 +1614,7 @@
|
||||||
"infill_overlap":
|
"infill_overlap":
|
||||||
{
|
{
|
||||||
"label": "Infill Overlap Percentage",
|
"label": "Infill Overlap Percentage",
|
||||||
"description": "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill.",
|
"description": "The amount of overlap between the infill and the walls as a percentage of the infill line width. A slight overlap allows the walls to connect firmly to the infill.",
|
||||||
"unit": "%",
|
"unit": "%",
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"default_value": 10,
|
"default_value": 10,
|
||||||
|
@ -1635,7 +1635,7 @@
|
||||||
"default_value": 0.04,
|
"default_value": 0.04,
|
||||||
"minimum_value_warning": "-0.5 * machine_nozzle_size",
|
"minimum_value_warning": "-0.5 * machine_nozzle_size",
|
||||||
"maximum_value_warning": "machine_nozzle_size",
|
"maximum_value_warning": "machine_nozzle_size",
|
||||||
"value": "0.5 * ( infill_line_width + (wall_line_width_x if wall_line_count > 1 else wall_line_width_0) ) * infill_overlap / 100 if infill_sparse_density < 95 and infill_pattern != 'concentric' else 0",
|
"value": "0.5 * (infill_line_width + (wall_line_width_x if wall_line_count > 1 else wall_line_width_0)) * infill_overlap / 100 if infill_sparse_density < 95 and infill_pattern != 'concentric' else 0",
|
||||||
"enabled": "infill_sparse_density > 0 and infill_pattern != 'concentric'",
|
"enabled": "infill_sparse_density > 0 and infill_pattern != 'concentric'",
|
||||||
"settable_per_mesh": true
|
"settable_per_mesh": true
|
||||||
}
|
}
|
||||||
|
@ -1644,7 +1644,7 @@
|
||||||
"skin_overlap":
|
"skin_overlap":
|
||||||
{
|
{
|
||||||
"label": "Skin Overlap Percentage",
|
"label": "Skin Overlap Percentage",
|
||||||
"description": "The amount of overlap between the skin and the walls as a percentage of the line width. A slight overlap allows the walls to connect firmly to the skin. This is a percentage of the average line widths of the skin lines and the innermost wall.",
|
"description": "The amount of overlap between the skin and the walls as a percentage of the skin line width. A slight overlap allows the walls to connect firmly to the skin. This is a percentage of the average line widths of the skin lines and the innermost wall.",
|
||||||
"unit": "%",
|
"unit": "%",
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"default_value": 5,
|
"default_value": 5,
|
||||||
|
@ -1665,7 +1665,7 @@
|
||||||
"default_value": 0.02,
|
"default_value": 0.02,
|
||||||
"minimum_value_warning": "-0.5 * machine_nozzle_size",
|
"minimum_value_warning": "-0.5 * machine_nozzle_size",
|
||||||
"maximum_value_warning": "machine_nozzle_size",
|
"maximum_value_warning": "machine_nozzle_size",
|
||||||
"value": "0.5 * ( skin_line_width + (wall_line_width_x if wall_line_count > 1 else wall_line_width_0) ) * skin_overlap / 100 if top_bottom_pattern != 'concentric' else 0",
|
"value": "0.5 * (skin_line_width + (wall_line_width_x if wall_line_count > 1 else wall_line_width_0)) * skin_overlap / 100 if top_bottom_pattern != 'concentric' else 0",
|
||||||
"enabled": "top_bottom_pattern != 'concentric'",
|
"enabled": "top_bottom_pattern != 'concentric'",
|
||||||
"settable_per_mesh": true
|
"settable_per_mesh": true
|
||||||
}
|
}
|
||||||
|
|
4595
resources/i18n/pt_PT/cura.po
Normal file
4595
resources/i18n/pt_PT/cura.po
Normal file
File diff suppressed because it is too large
Load diff
210
resources/i18n/pt_PT/fdmextruder.def.json.po
Normal file
210
resources/i18n/pt_PT/fdmextruder.def.json.po
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
# Cura JSON setting files
|
||||||
|
# Copyright (C) 2017 Ultimaker
|
||||||
|
# This file is distributed under the same license as the Cura package.
|
||||||
|
# Ruben Dulek <r.dulek@ultimaker.com>, 2017.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Cura 3.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
|
||||||
|
"POT-Creation-Date: 2017-08-02 16:53+0000\n"
|
||||||
|
"PO-Revision-Date: 2017-12-07 13:41+0100\n"
|
||||||
|
"Last-Translator: Bothof <info@bothof.nl>\n"
|
||||||
|
"Language-Team: Bothof\n"
|
||||||
|
"Language: pt_PT\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_settings label"
|
||||||
|
msgid "Machine"
|
||||||
|
msgstr "Máquina"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_settings description"
|
||||||
|
msgid "Machine specific settings"
|
||||||
|
msgstr "Definições específicas da máquina"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "extruder_nr label"
|
||||||
|
msgid "Extruder"
|
||||||
|
msgstr "Extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "extruder_nr description"
|
||||||
|
msgid "The extruder train used for printing. This is used in multi-extrusion."
|
||||||
|
msgstr "A máquina extrusora utilizada para imprimir. Esta é utilizada em extrusões múltiplas."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_nozzle_id label"
|
||||||
|
msgid "Nozzle ID"
|
||||||
|
msgstr "ID do bocal"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_nozzle_id description"
|
||||||
|
msgid "The nozzle ID for an extruder train, such as \"AA 0.4\" and \"BB 0.8\"."
|
||||||
|
msgstr "A ID do bocal para uma máquina de extrusão, tal como \"AA 0.4\" e \"BB 0.8\"."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_nozzle_size label"
|
||||||
|
msgid "Nozzle Diameter"
|
||||||
|
msgstr "Diâmetro do bocal"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_nozzle_size description"
|
||||||
|
msgid ""
|
||||||
|
"The inner diameter of the nozzle. Change this setting when using a non-"
|
||||||
|
"standard nozzle size."
|
||||||
|
msgstr "O diâmetro interno do bocal. Altere esta definição ao utilizar um tamanho de bocal não convencional."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_nozzle_offset_x label"
|
||||||
|
msgid "Nozzle X Offset"
|
||||||
|
msgstr "Desvio X do bocal"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_nozzle_offset_x description"
|
||||||
|
msgid "The x-coordinate of the offset of the nozzle."
|
||||||
|
msgstr "A coordenada X do desvio do bocal."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_nozzle_offset_y label"
|
||||||
|
msgid "Nozzle Y Offset"
|
||||||
|
msgstr "Desvio Y do bocal"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_nozzle_offset_y description"
|
||||||
|
msgid "The y-coordinate of the offset of the nozzle."
|
||||||
|
msgstr "A coordenada Y do desvio do bocal."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_start_code label"
|
||||||
|
msgid "Extruder Start G-Code"
|
||||||
|
msgstr "G-Code inicial da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_start_code description"
|
||||||
|
msgid "Start g-code to execute whenever turning the extruder on."
|
||||||
|
msgstr "G-Code inicial a ser executado sempre que a extrusora for ligada."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_start_pos_abs label"
|
||||||
|
msgid "Extruder Start Position Absolute"
|
||||||
|
msgstr "Posição inicial absoluta da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_start_pos_abs description"
|
||||||
|
msgid ""
|
||||||
|
"Make the extruder starting position absolute rather than relative to the "
|
||||||
|
"last-known location of the head."
|
||||||
|
msgstr "Torne a posição inicial da extrusora absoluta em vez de relativa à última posição conhecida da cabeça."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_start_pos_x label"
|
||||||
|
msgid "Extruder Start Position X"
|
||||||
|
msgstr "X da posição inicial da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_start_pos_x description"
|
||||||
|
msgid "The x-coordinate of the starting position when turning the extruder on."
|
||||||
|
msgstr "A coordenada X da posição inicial ao ligar a extrusora."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_start_pos_y label"
|
||||||
|
msgid "Extruder Start Position Y"
|
||||||
|
msgstr "Y da posição inicial da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_start_pos_y description"
|
||||||
|
msgid "The y-coordinate of the starting position when turning the extruder on."
|
||||||
|
msgstr "A coordenada Y da posição inicial ao ligar a extrusora."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_end_code label"
|
||||||
|
msgid "Extruder End G-Code"
|
||||||
|
msgstr "G-Code final da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_end_code description"
|
||||||
|
msgid "End g-code to execute whenever turning the extruder off."
|
||||||
|
msgstr "G-Code final a ser executado sempre que a extrusora for desligada."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_end_pos_abs label"
|
||||||
|
msgid "Extruder End Position Absolute"
|
||||||
|
msgstr "Posição final absoluta da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_end_pos_abs description"
|
||||||
|
msgid ""
|
||||||
|
"Make the extruder ending position absolute rather than relative to the last-"
|
||||||
|
"known location of the head."
|
||||||
|
msgstr "Torne a posição final da extrusora absoluta em vez de relativa à última localização conhecida da cabeça."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_end_pos_x label"
|
||||||
|
msgid "Extruder End Position X"
|
||||||
|
msgstr "X da posição final da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_end_pos_x description"
|
||||||
|
msgid "The x-coordinate of the ending position when turning the extruder off."
|
||||||
|
msgstr "A coordenada X da posição final ao desligar a extrusora."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_end_pos_y label"
|
||||||
|
msgid "Extruder End Position Y"
|
||||||
|
msgstr "Y da posição final da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "machine_extruder_end_pos_y description"
|
||||||
|
msgid "The y-coordinate of the ending position when turning the extruder off."
|
||||||
|
msgstr "A coordenada Y da posição final ao desligar a extrusora."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "extruder_prime_pos_z label"
|
||||||
|
msgid "Extruder Prime Z Position"
|
||||||
|
msgstr "Posição Z de preparação da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "extruder_prime_pos_z description"
|
||||||
|
msgid ""
|
||||||
|
"The Z coordinate of the position where the nozzle primes at the start of "
|
||||||
|
"printing."
|
||||||
|
msgstr "A coordenada Z da posição de preparação do bocal ao iniciar a impressão."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "platform_adhesion label"
|
||||||
|
msgid "Build Plate Adhesion"
|
||||||
|
msgstr "Aderência à placa de construção"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "platform_adhesion description"
|
||||||
|
msgid "Adhesion"
|
||||||
|
msgstr "Aderência"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "extruder_prime_pos_x label"
|
||||||
|
msgid "Extruder Prime X Position"
|
||||||
|
msgstr "Posição X de preparação da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "extruder_prime_pos_x description"
|
||||||
|
msgid ""
|
||||||
|
"The X coordinate of the position where the nozzle primes at the start of "
|
||||||
|
"printing."
|
||||||
|
msgstr "A coordenada X da posição de preparação do bocal ao iniciar a impressão."
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "extruder_prime_pos_y label"
|
||||||
|
msgid "Extruder Prime Y Position"
|
||||||
|
msgstr "Posição Y de preparação da extrusora"
|
||||||
|
|
||||||
|
#: fdmextruder.def.json
|
||||||
|
msgctxt "extruder_prime_pos_y description"
|
||||||
|
msgid ""
|
||||||
|
"The Y coordinate of the position where the nozzle primes at the start of "
|
||||||
|
"printing."
|
||||||
|
msgstr "A coordenada Y da posição de preparação do bocal ao iniciar a impressão."
|
5814
resources/i18n/pt_PT/fdmprinter.def.json.po
Normal file
5814
resources/i18n/pt_PT/fdmprinter.def.json.po
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2016 Ultimaker B.V.
|
// Copyright (c) 2017 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
|
@ -25,6 +25,15 @@ UM.Dialog
|
||||||
width: minimumWidth
|
width: minimumWidth
|
||||||
height: minimumHeight
|
height: minimumHeight
|
||||||
|
|
||||||
|
flags: {
|
||||||
|
var window_flags = Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint;
|
||||||
|
if (Cura.MachineManager.activeDefinitionId !== "") //Disallow closing the window if we have no active printer yet. You MUST add a printer.
|
||||||
|
{
|
||||||
|
window_flags |= Qt.WindowCloseButtonHint;
|
||||||
|
}
|
||||||
|
return window_flags;
|
||||||
|
}
|
||||||
|
|
||||||
onVisibilityChanged:
|
onVisibilityChanged:
|
||||||
{
|
{
|
||||||
// Reset selection and machine name
|
// Reset selection and machine name
|
||||||
|
|
|
@ -413,7 +413,7 @@ UM.MainWindow
|
||||||
collapseSidebarAnimation.start();
|
collapseSidebarAnimation.start();
|
||||||
}
|
}
|
||||||
collapsed = !collapsed;
|
collapsed = !collapsed;
|
||||||
UM.Preferences.setValue("cura/sidebar_collapse", collapsed);
|
UM.Preferences.setValue("cura/sidebar_collapsed", collapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors
|
anchors
|
||||||
|
@ -444,9 +444,10 @@ UM.MainWindow
|
||||||
|
|
||||||
Component.onCompleted:
|
Component.onCompleted:
|
||||||
{
|
{
|
||||||
var sidebarCollapsed = UM.Preferences.getValue("cura/sidebar_collapse");
|
var sidebar_collapsed = UM.Preferences.getValue("cura/sidebar_collapsed");
|
||||||
|
|
||||||
if (sidebarCollapsed) {
|
if (sidebar_collapsed)
|
||||||
|
{
|
||||||
sidebar.collapsed = true;
|
sidebar.collapsed = true;
|
||||||
viewportRect = Qt.rect(0, 0, 1, 1.0)
|
viewportRect = Qt.rect(0, 0, 1, 1.0)
|
||||||
collapseSidebarAnimation.start();
|
collapseSidebarAnimation.start();
|
||||||
|
@ -540,6 +541,12 @@ UM.MainWindow
|
||||||
onTriggered: preferences.visible = true
|
onTriggered: preferences.visible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: CuraApplication
|
||||||
|
onShowPreferencesWindow: preferences.visible = true
|
||||||
|
}
|
||||||
|
|
||||||
MessageDialog
|
MessageDialog
|
||||||
{
|
{
|
||||||
id: newProjectDialog
|
id: newProjectDialog
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2017 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
|
@ -33,9 +33,10 @@ Menu
|
||||||
{
|
{
|
||||||
id: materialDiameterProvider
|
id: materialDiameterProvider
|
||||||
|
|
||||||
containerStackId: Cura.MachineManager.activeMachineId
|
containerStackId: Cura.ExtruderManager.activeExtruderStackId
|
||||||
key: "material_diameter"
|
key: "material_diameter"
|
||||||
watchedProperties: [ "value" ]
|
watchedProperties: [ "value" ]
|
||||||
|
storeIndex: 5
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuItem
|
MenuItem
|
||||||
|
@ -207,8 +208,8 @@ Menu
|
||||||
// Add to top section
|
// Add to top section
|
||||||
var materialId = items[i].id;
|
var materialId = items[i].id;
|
||||||
genericMaterialsModel.append({
|
genericMaterialsModel.append({
|
||||||
id:materialId,
|
id: materialId,
|
||||||
name:items[i].name
|
name: items[i].name
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -199,12 +199,12 @@ Item
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
updateAdditionalComponents("monitorButtons")
|
buttonsRow.updateAdditionalComponents("monitorButtons")
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: CuraApplication
|
target: CuraApplication
|
||||||
onAdditionalComponentsChanged: updateAdditionalComponents
|
onAdditionalComponentsChanged: buttonsRow.updateAdditionalComponents("monitorButtons")
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateAdditionalComponents (areaId) {
|
function updateAdditionalComponents (areaId) {
|
||||||
|
|
|
@ -159,6 +159,7 @@ UM.PreferencesPage
|
||||||
append({ text: "Nederlands", code: "nl_NL" })
|
append({ text: "Nederlands", code: "nl_NL" })
|
||||||
append({ text: "Polski", code: "pl_PL" })
|
append({ text: "Polski", code: "pl_PL" })
|
||||||
append({ text: "Português do Brasil", code: "pt_BR" })
|
append({ text: "Português do Brasil", code: "pt_BR" })
|
||||||
|
append({ text: "Português", code: "pt_PT" })
|
||||||
append({ text: "Русский", code: "ru_RU" })
|
append({ text: "Русский", code: "ru_RU" })
|
||||||
append({ text: "Türkçe", code: "tr_TR" })
|
append({ text: "Türkçe", code: "tr_TR" })
|
||||||
append({ text: "简体中文", code: "zh_CN" })
|
append({ text: "简体中文", code: "zh_CN" })
|
||||||
|
|
|
@ -387,9 +387,10 @@ UM.ManagementPage
|
||||||
{
|
{
|
||||||
id: materialDiameterProvider
|
id: materialDiameterProvider
|
||||||
|
|
||||||
containerStackId: Cura.MachineManager.activeMachineId
|
containerStackId: Cura.ExtruderManager.activeExtruderStackId
|
||||||
key: "material_diameter"
|
key: "material_diameter"
|
||||||
watchedProperties: [ "value" ]
|
watchedProperties: [ "value" ]
|
||||||
|
storeIndex: 5
|
||||||
}
|
}
|
||||||
|
|
||||||
UM.I18nCatalog { id: catalog; name: "cura"; }
|
UM.I18nCatalog { id: catalog; name: "cura"; }
|
||||||
|
|
|
@ -138,12 +138,12 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
addAdditionalComponents("saveButton")
|
saveRow.addAdditionalComponents("saveButton")
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: CuraApplication
|
target: CuraApplication
|
||||||
onAdditionalComponentsChanged: addAdditionalComponents
|
onAdditionalComponentsChanged: saveRow.addAdditionalComponents("saveButton")
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAdditionalComponents (areaId) {
|
function addAdditionalComponents (areaId) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Copyright (c) 2015 Ultimaker B.V.
|
// Copyright (c) 2017 Ultimaker B.V.
|
||||||
// Uranium is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.1
|
||||||
|
@ -31,13 +31,17 @@ Button {
|
||||||
|
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
forceActiveFocus();
|
|
||||||
if(definition.expanded)
|
if(definition.expanded)
|
||||||
{
|
{
|
||||||
settingDefinitionsModel.collapse(definition.key);
|
settingDefinitionsModel.collapse(definition.key);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
settingDefinitionsModel.expandAll(definition.key);
|
settingDefinitionsModel.expandAll(definition.key);
|
||||||
}
|
}
|
||||||
|
//Set focus so that tab navigation continues from this point on.
|
||||||
|
//NB: This must be set AFTER collapsing/expanding the category so that the scroll position is correct.
|
||||||
|
forceActiveFocus();
|
||||||
}
|
}
|
||||||
onActiveFocusChanged:
|
onActiveFocusChanged:
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Copyright (c) 2015 Ultimaker B.V.
|
// Copyright (c) 2017 Ultimaker B.V.
|
||||||
// Uranium is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.1
|
import QtQuick 2.1
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
|
@ -154,7 +154,7 @@ Item {
|
||||||
|
|
||||||
onEntered: {
|
onEntered: {
|
||||||
hoverTimer.stop();
|
hoverTimer.stop();
|
||||||
var tooltipText = catalog.i18nc("@label", "This setting is always shared between all extruders. Changing it here will change the value for all extruders") + ".";
|
var tooltipText = catalog.i18nc("@label", "This setting is always shared between all extruders. Changing it here will change the value for all extruders.");
|
||||||
if ((resolve != "None") && (stackLevel != 0)) {
|
if ((resolve != "None") && (stackLevel != 0)) {
|
||||||
// We come here if a setting has a resolve and the setting is not manually edited.
|
// We come here if a setting has a resolve and the setting is not manually edited.
|
||||||
tooltipText += " " + catalog.i18nc("@label", "The value is resolved from per-extruder values ") + "[" + Cura.ExtruderManager.getInstanceExtruderValues(definition.key) + "].";
|
tooltipText += " " + catalog.i18nc("@label", "The value is resolved from per-extruder values ") + "[" + Cura.ExtruderManager.getInstanceExtruderValues(definition.key) + "].";
|
||||||
|
|
|
@ -372,7 +372,7 @@ Item
|
||||||
{
|
{
|
||||||
id: provider
|
id: provider
|
||||||
|
|
||||||
containerStackId: Cura.MachineManager.activeMachineId
|
containerStackId: Cura.ExtruderManager.activeExtruderStackId
|
||||||
key: model.key ? model.key : ""
|
key: model.key ? model.key : ""
|
||||||
watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder", "resolve" ]
|
watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder", "resolve" ]
|
||||||
storeIndex: 0
|
storeIndex: 0
|
||||||
|
|
|
@ -340,6 +340,8 @@ Item
|
||||||
text: catalog.i18nc("@label", "Print Speed")
|
text: catalog.i18nc("@label", "Print Speed")
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
|
width: parseInt(UM.Theme.getSize("sidebar").width * 0.35)
|
||||||
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
|
|
||||||
Label
|
Label
|
||||||
|
|
|
@ -25,9 +25,12 @@ Rectangle
|
||||||
property int allItemsWidth: 0;
|
property int allItemsWidth: 0;
|
||||||
|
|
||||||
function updateMarginsAndSizes() {
|
function updateMarginsAndSizes() {
|
||||||
if (UM.Preferences.getValue("cura/sidebar_collapse")) {
|
if (UM.Preferences.getValue("cura/sidebar_collapsed"))
|
||||||
|
{
|
||||||
rightMargin = UM.Theme.getSize("default_margin").width;
|
rightMargin = UM.Theme.getSize("default_margin").width;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
rightMargin = UM.Theme.getSize("sidebar").width + UM.Theme.getSize("default_margin").width;
|
rightMargin = UM.Theme.getSize("sidebar").width + UM.Theme.getSize("default_margin").width;
|
||||||
}
|
}
|
||||||
allItemsWidth = (
|
allItemsWidth = (
|
||||||
|
|
|
@ -202,9 +202,8 @@ QtObject {
|
||||||
height: Theme.getSize("topbar_button_icon").height
|
height: Theme.getSize("topbar_button_icon").height
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
id: button_label
|
||||||
text: control.text;
|
text: control.text;
|
||||||
anchors.right: (icon.visible || overlayIcon.visible) ? icon.left : parent.right
|
|
||||||
anchors.rightMargin: (icon.visible || overlayIcon.visible) ? Theme.getSize("default_margin").width : 0
|
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
font: control.checked ? UM.Theme.getFont("large") : UM.Theme.getFont("large_nonbold")
|
font: control.checked ? UM.Theme.getFont("large") : UM.Theme.getFont("large_nonbold")
|
||||||
color:
|
color:
|
||||||
|
@ -227,6 +226,8 @@ QtObject {
|
||||||
{
|
{
|
||||||
visible: control.iconSource != ""
|
visible: control.iconSource != ""
|
||||||
id: icon
|
id: icon
|
||||||
|
anchors.left: button_label.right
|
||||||
|
anchors.leftMargin: (icon.visible || overlayIcon.visible) ? Theme.getSize("default_margin").width : 0
|
||||||
color: UM.Theme.getColor("text_emphasis")
|
color: UM.Theme.getColor("text_emphasis")
|
||||||
opacity: !control.enabled ? 0.2 : 1.0
|
opacity: !control.enabled ? 0.2 : 1.0
|
||||||
source: control.iconSource
|
source: control.iconSource
|
||||||
|
@ -238,6 +239,8 @@ QtObject {
|
||||||
UM.RecolorImage
|
UM.RecolorImage
|
||||||
{
|
{
|
||||||
id: overlayIcon
|
id: overlayIcon
|
||||||
|
anchors.left: button_label.right
|
||||||
|
anchors.leftMargin: (icon.visible || overlayIcon.visible) ? Theme.getSize("default_margin").width : 0
|
||||||
visible: control.overlayIconSource != "" && control.iconSource != ""
|
visible: control.overlayIconSource != "" && control.iconSource != ""
|
||||||
color: control.overlayColor
|
color: control.overlayColor
|
||||||
opacity: !control.enabled ? 0.2 : 1.0
|
opacity: !control.enabled ? 0.2 : 1.0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue