mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-06 21:44:01 -06:00
JSON feat: infill_mesh_order (CURA-833)
This commit is contained in:
commit
df780023ed
43 changed files with 1973 additions and 764 deletions
|
@ -32,8 +32,6 @@ from UM.Settings.ContainerRegistry import ContainerRegistry
|
|||
|
||||
from UM.i18n import i18nCatalog
|
||||
|
||||
from . import ExtruderManager
|
||||
from . import ExtrudersModel
|
||||
from . import PlatformPhysics
|
||||
from . import BuildVolume
|
||||
from . import CameraAnimation
|
||||
|
@ -42,11 +40,11 @@ from . import CuraActions
|
|||
from . import MultiMaterialDecorator
|
||||
from . import ZOffsetDecorator
|
||||
from . import CuraSplashScreen
|
||||
from . import MachineManagerModel
|
||||
from . import ContainerSettingsModel
|
||||
from . import CameraImageProvider
|
||||
from . import MachineActionManager
|
||||
|
||||
import cura.Settings
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
|
||||
from PyQt5.QtGui import QColor, QIcon
|
||||
from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType
|
||||
|
@ -274,7 +272,8 @@ class CuraApplication(QtApplication):
|
|||
Logger.logException("e", "An exception occurred when serializing container %s", instance.getId())
|
||||
continue
|
||||
|
||||
file_name = urllib.parse.quote_plus(instance.getId()) + ".inst.cfg"
|
||||
mime_type = ContainerRegistry.getMimeTypeForContainer(type(instance))
|
||||
file_name = urllib.parse.quote_plus(instance.getId()) + "." + mime_type.preferredSuffix
|
||||
instance_type = instance.getMetaDataEntry("type")
|
||||
path = None
|
||||
if instance_type == "material":
|
||||
|
@ -302,7 +301,8 @@ class CuraApplication(QtApplication):
|
|||
Logger.logException("e", "An exception occurred when serializing container %s", instance.getId())
|
||||
continue
|
||||
|
||||
file_name = urllib.parse.quote_plus(stack.getId()) + ".stack.cfg"
|
||||
mime_type = ContainerRegistry.getMimeTypeForContainer(type(stack))
|
||||
file_name = urllib.parse.quote_plus(stack.getId()) + "." + mime_type.preferredSuffix
|
||||
stack_type = stack.getMetaDataEntry("type", None)
|
||||
path = None
|
||||
if not stack_type or stack_type == "machine":
|
||||
|
@ -379,9 +379,9 @@ class CuraApplication(QtApplication):
|
|||
self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Loading interface..."))
|
||||
|
||||
# Initialise extruder so as to listen to global container stack changes before the first global container stack is set.
|
||||
ExtruderManager.ExtruderManager.getInstance()
|
||||
qmlRegisterSingletonType(MachineManagerModel.MachineManagerModel, "Cura", 1, 0, "MachineManager",
|
||||
MachineManagerModel.createMachineManagerModel)
|
||||
cura.Settings.ExtruderManager.getInstance()
|
||||
qmlRegisterSingletonType(cura.Settings.MachineManager, "Cura", 1, 0, "MachineManager",
|
||||
cura.Settings.MachineManager.createMachineManager)
|
||||
|
||||
qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager)
|
||||
self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
|
||||
|
@ -425,6 +425,7 @@ class CuraApplication(QtApplication):
|
|||
# \param engine The QML engine.
|
||||
def registerObjects(self, engine):
|
||||
engine.rootContext().setContextProperty("Printer", self)
|
||||
engine.rootContext().setContextProperty("CuraApplication", self)
|
||||
self._print_information = PrintInformation.PrintInformation()
|
||||
engine.rootContext().setContextProperty("PrintInformation", self._print_information)
|
||||
self._cura_actions = CuraActions.CuraActions(self)
|
||||
|
@ -432,13 +433,16 @@ class CuraApplication(QtApplication):
|
|||
|
||||
qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
|
||||
|
||||
qmlRegisterType(ExtrudersModel.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
|
||||
qmlRegisterType(cura.Settings.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
|
||||
|
||||
qmlRegisterType(ContainerSettingsModel.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
|
||||
qmlRegisterType(cura.Settings.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
|
||||
qmlRegisterType(cura.Settings.MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler")
|
||||
|
||||
qmlRegisterSingletonType(cura.Settings.ContainerManager, "Cura", 1, 0, "ContainerManager", cura.Settings.ContainerManager.createContainerManager)
|
||||
|
||||
qmlRegisterSingletonType(QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")), "Cura", 1, 0, "Actions")
|
||||
|
||||
engine.rootContext().setContextProperty("ExtruderManager", ExtruderManager.ExtruderManager.getInstance())
|
||||
engine.rootContext().setContextProperty("ExtruderManager", cura.Settings.ExtruderManager.getInstance())
|
||||
|
||||
for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles):
|
||||
type_name = os.path.splitext(os.path.basename(path))[0]
|
||||
|
|
383
cura/Settings/ContainerManager.py
Normal file
383
cura/Settings/ContainerManager.py
Normal file
|
@ -0,0 +1,383 @@
|
|||
# Copyright (c) 2016 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import os.path
|
||||
import urllib
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal, QUrl
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
import UM.PluginRegistry
|
||||
import UM.Settings
|
||||
import UM.SaveFile
|
||||
import UM.Platform
|
||||
import UM.MimeTypeDatabase
|
||||
import UM.Logger
|
||||
|
||||
from UM.MimeTypeDatabase import MimeTypeNotFoundError
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
## Manager class that contains common actions to deal with containers in Cura.
|
||||
#
|
||||
# This is primarily intended as a class to be able to perform certain actions
|
||||
# from within QML. We want to be able to trigger things like removing a container
|
||||
# when a certain action happens. This can be done through this class.
|
||||
class ContainerManager(QObject):
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
|
||||
self._registry = UM.Settings.ContainerRegistry.getInstance()
|
||||
self._container_name_filters = {}
|
||||
|
||||
## Create a duplicate of the specified container
|
||||
#
|
||||
# This will create and add a duplicate of the container corresponding
|
||||
# to the container ID.
|
||||
#
|
||||
# \param container_id \type{str} The ID of the container to duplicate.
|
||||
#
|
||||
# \return The ID of the new container, or an empty string if duplication failed.
|
||||
@pyqtSlot(str, result = str)
|
||||
def duplicateContainer(self, container_id):
|
||||
containers = self._registry.findContainers(None, id = container_id)
|
||||
if not containers:
|
||||
UM.Logger.log("w", "Could duplicate container %s because it was not found.", container_id)
|
||||
return ""
|
||||
|
||||
container = containers[0]
|
||||
|
||||
new_container = None
|
||||
new_name = self._registry.uniqueName(container.getName())
|
||||
# Only InstanceContainer has a duplicate method at the moment.
|
||||
# So fall back to serialize/deserialize when no duplicate method exists.
|
||||
if hasattr(container, "duplicate"):
|
||||
new_container = container.duplicate(new_name)
|
||||
else:
|
||||
new_container = container.__class__(new_name)
|
||||
new_container.deserialize(container.serialize())
|
||||
new_container.setName(new_name)
|
||||
|
||||
if new_container:
|
||||
self._registry.addContainer(new_container)
|
||||
|
||||
return new_container.getId()
|
||||
|
||||
## Change the name of a specified container to a new name.
|
||||
#
|
||||
# \param container_id \type{str} The ID of the container to change the name of.
|
||||
# \param new_id \type{str} The new ID of the container.
|
||||
# \param new_name \type{str} The new name of the specified container.
|
||||
#
|
||||
# \return True if successful, False if not.
|
||||
@pyqtSlot(str, str, str, result = bool)
|
||||
def renameContainer(self, container_id, new_id, new_name):
|
||||
containers = self._registry.findContainers(None, id = container_id)
|
||||
if not containers:
|
||||
UM.Logger.log("w", "Could rename container %s because it was not found.", container_id)
|
||||
return False
|
||||
|
||||
container = containers[0]
|
||||
# First, remove the container from the registry. This will clean up any files related to the container.
|
||||
self._registry.removeContainer(container)
|
||||
|
||||
# Ensure we have a unique name for the container
|
||||
new_name = self._registry.uniqueName(new_name)
|
||||
|
||||
# Then, update the name and ID of the container
|
||||
container.setName(new_name)
|
||||
container._id = new_id # TODO: Find a nicer way to set a new, unique ID
|
||||
|
||||
# Finally, re-add the container so it will be properly serialized again.
|
||||
self._registry.addContainer(container)
|
||||
|
||||
return True
|
||||
|
||||
## Remove the specified container.
|
||||
#
|
||||
# \param container_id \type{str} The ID of the container to remove.
|
||||
#
|
||||
# \return True if the container was successfully removed, False if not.
|
||||
@pyqtSlot(str, result = bool)
|
||||
def removeContainer(self, container_id):
|
||||
containers = self._registry.findContainers(None, id = container_id)
|
||||
if not containers:
|
||||
UM.Logger.log("w", "Could remove container %s because it was not found.", container_id)
|
||||
return False
|
||||
|
||||
self._registry.removeContainer(containers[0].getId())
|
||||
|
||||
return True
|
||||
|
||||
## Merge a container with another.
|
||||
#
|
||||
# This will try to merge one container into the other, by going through the container
|
||||
# and setting the right properties on the other container.
|
||||
#
|
||||
# \param merge_into_id \type{str} The ID of the container to merge into.
|
||||
# \param merge_id \type{str} The ID of the container to merge.
|
||||
#
|
||||
# \return True if successfully merged, False if not.
|
||||
@pyqtSlot(str, result = bool)
|
||||
def mergeContainers(self, merge_into_id, merge_id):
|
||||
containers = self._registry.findContainers(None, id = merge_into_id)
|
||||
if not containers:
|
||||
UM.Logger.log("w", "Could merge into container %s because it was not found.", merge_into_id)
|
||||
return False
|
||||
|
||||
merge_into = containers[0]
|
||||
|
||||
containers = self._registry.findContainers(None, id = merge_id)
|
||||
if not containers:
|
||||
UM.Logger.log("w", "Could not merge container %s because it was not found", merge_id)
|
||||
return False
|
||||
|
||||
merge = containers[0]
|
||||
|
||||
if type(merge) != type(merge_into):
|
||||
UM.Logger.log("w", "Cannot merge two containers of different types")
|
||||
return False
|
||||
|
||||
for key in merge.getAllKeys():
|
||||
merge_into.setProperty(key, "value", merge.getProperty(key, "value"))
|
||||
|
||||
return True
|
||||
|
||||
## Clear the contents of a container.
|
||||
#
|
||||
# \param container_id \type{str} The ID of the container to clear.
|
||||
#
|
||||
# \return True if successful, False if not.
|
||||
@pyqtSlot(str, result = bool)
|
||||
def clearContainer(self, container_id):
|
||||
containers = self._registry.findContainers(None, id = container_id)
|
||||
if not containers:
|
||||
UM.Logger.log("w", "Could clear container %s because it was not found.", container_id)
|
||||
return False
|
||||
|
||||
if containers[0].isReadOnly():
|
||||
UM.Logger.log("w", "Cannot clear read-only container %s", container_id)
|
||||
return False
|
||||
|
||||
containers[0].clear()
|
||||
|
||||
return True
|
||||
|
||||
## Set a metadata entry of the specified container.
|
||||
#
|
||||
# This will set the specified entry of the container's metadata to the specified
|
||||
# value. Note that entries containing dictionaries can have their entries changed
|
||||
# by using "/" as a separator. For example, to change an entry "foo" in a
|
||||
# dictionary entry "bar", you can specify "bar/foo" as entry name.
|
||||
#
|
||||
# \param container_id \type{str} The ID of the container to change.
|
||||
# \param entry_name \type{str} The name of the metadata entry to change.
|
||||
# \param entry_value The new value of the entry.
|
||||
#
|
||||
# \return True if successful, False if not.
|
||||
@pyqtSlot(str, str, str, result = bool)
|
||||
def setContainerMetaDataEntry(self, container_id, entry_name, entry_value):
|
||||
containers = UM.Settings.ContainerRegistry.getInstance().findContainers(None, id = container_id)
|
||||
if not containers:
|
||||
UM.Logger.log("w", "Could set metadata of container %s because it was not found.", container_id)
|
||||
return False
|
||||
|
||||
container = containers[0]
|
||||
|
||||
if container.isReadOnly():
|
||||
UM.Logger.log("w", "Cannot set metadata of read-only container %s.", container_id)
|
||||
return False
|
||||
|
||||
entries = entry_name.split("/")
|
||||
entry_name = entries.pop()
|
||||
|
||||
if entries:
|
||||
root_name = entries.pop(0)
|
||||
root = container.getMetaDataEntry(root_name)
|
||||
|
||||
item = root
|
||||
for entry in entries:
|
||||
item = item.get(entries.pop(0), { })
|
||||
|
||||
item[entry_name] = entry_value
|
||||
|
||||
entry_name = root_name
|
||||
entry_value = root
|
||||
|
||||
container.setMetaDataEntry(entry_name, entry_value)
|
||||
|
||||
return True
|
||||
|
||||
## Find instance containers matching certain criteria.
|
||||
#
|
||||
# This effectively forwards to ContainerRegistry::findInstanceContainers.
|
||||
#
|
||||
# \param criteria A dict of key - value pairs to search for.
|
||||
#
|
||||
# \return A list of container IDs that match the given criteria.
|
||||
@pyqtSlot("QVariantMap", result = "QVariantList")
|
||||
def findInstanceContainers(self, criteria):
|
||||
result = []
|
||||
for entry in self._registry.findInstanceContainers(**criteria):
|
||||
result.append(entry.getId())
|
||||
|
||||
return result
|
||||
|
||||
## Get a list of string that can be used as name filters for a Qt File Dialog
|
||||
#
|
||||
# This will go through the list of available container types and generate a list of strings
|
||||
# out of that. The strings are formatted as "description (*.extension)" and can be directly
|
||||
# passed to a nameFilters property of a Qt File Dialog.
|
||||
#
|
||||
# \param type_name Which types of containers to list. These types correspond to the "type"
|
||||
# key of the plugin metadata.
|
||||
#
|
||||
# \return A string list with name filters.
|
||||
@pyqtSlot(str, result = "QStringList")
|
||||
def getContainerNameFilters(self, type_name):
|
||||
if not self._container_name_filters:
|
||||
self._updateContainerNameFilters()
|
||||
|
||||
filters = []
|
||||
for filter_string, entry in self._container_name_filters.items():
|
||||
if not type_name or entry["type"] == type_name:
|
||||
filters.append(filter_string)
|
||||
|
||||
return filters
|
||||
|
||||
## Export a container to a file
|
||||
#
|
||||
# \param container_id The ID of the container to export
|
||||
# \param file_type The type of file to save as. Should be in the form of "description (*.extension, *.ext)"
|
||||
# \param file_url The URL where to save the file.
|
||||
#
|
||||
# \return A dictionary containing a key "status" with a status code and a key "message" with a message
|
||||
# explaining the status.
|
||||
# The status code can be one of "error", "cancelled", "success"
|
||||
@pyqtSlot(str, str, QUrl, result = "QVariantMap")
|
||||
def exportContainer(self, container_id, file_type, file_url):
|
||||
if not container_id or not file_type or not file_url:
|
||||
return { "status": "error", "message": "Invalid arguments"}
|
||||
|
||||
if isinstance(file_url, QUrl):
|
||||
file_url = file_url.toLocalFile()
|
||||
|
||||
if not file_url:
|
||||
return { "status": "error", "message": "Invalid path"}
|
||||
|
||||
mime_type = None
|
||||
if not file_type in self._container_name_filters:
|
||||
try:
|
||||
mime_type = UM.MimeTypeDatabase.getMimeTypeForFile(file_url)
|
||||
except MimeTypeNotFoundError:
|
||||
return { "status": "error", "message": "Unknown File Type" }
|
||||
else:
|
||||
mime_type = self._container_name_filters[file_type]["mime"]
|
||||
|
||||
containers = UM.Settings.ContainerRegistry.getInstance().findContainers(None, id = container_id)
|
||||
if not containers:
|
||||
return { "status": "error", "message": "Container not found"}
|
||||
container = containers[0]
|
||||
|
||||
for suffix in mime_type.suffixes:
|
||||
if file_url.endswith(suffix):
|
||||
break
|
||||
else:
|
||||
file_url += "." + mime_type.preferredSuffix
|
||||
|
||||
if not UM.Platform.isWindows():
|
||||
if os.path.exists(file_url):
|
||||
result = QMessageBox.question(None, catalog.i18nc("@title:window", "File Already Exists"),
|
||||
catalog.i18nc("@label", "The file <filename>{0}</filename> already exists. Are you sure you want to overwrite it?").format(file_url))
|
||||
if result == QMessageBox.No:
|
||||
return { "status": "cancelled", "message": "User cancelled"}
|
||||
|
||||
try:
|
||||
contents = container.serialize()
|
||||
except NotImplementedError:
|
||||
return { "status": "error", "message": "Unable to serialize container"}
|
||||
|
||||
with UM.SaveFile(file_url, "w") as f:
|
||||
f.write(contents)
|
||||
|
||||
return { "status": "success", "message": "Succesfully exported container"}
|
||||
|
||||
## Imports a profile from a file
|
||||
#
|
||||
# \param file_url A URL that points to the file to import.
|
||||
#
|
||||
# \return \type{Dict} dict with a 'status' key containing the string 'success' or 'error', and a 'message' key
|
||||
# containing a message for the user
|
||||
@pyqtSlot(QUrl, result = "QVariantMap")
|
||||
def importContainer(self, file_url):
|
||||
if not file_url:
|
||||
return { "status": "error", "message": "Invalid path"}
|
||||
|
||||
if isinstance(file_url, QUrl):
|
||||
file_url = file_url.toLocalFile()
|
||||
|
||||
if not file_url or not os.path.exists(file_url):
|
||||
return { "status": "error", "message": "Invalid path" }
|
||||
|
||||
try:
|
||||
mime_type = UM.MimeTypeDatabase.getMimeTypeForFile(file_url)
|
||||
except MimeTypeNotFoundError:
|
||||
return { "status": "error", "message": "Could not determine mime type of file" }
|
||||
|
||||
container_type = UM.Settings.ContainerRegistry.getContainerForMimeType(mime_type)
|
||||
if not container_type:
|
||||
return { "status": "error", "message": "Could not find a container to handle the specified file."}
|
||||
|
||||
container_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_url)))
|
||||
container_id = UM.Settings.ContainerRegistry.getInstance().uniqueName(container_id)
|
||||
|
||||
container = container_type(container_id)
|
||||
|
||||
try:
|
||||
with open(file_url, "rt") as f:
|
||||
container.deserialize(f.read())
|
||||
except PermissionError:
|
||||
return { "status": "error", "message": "Permission denied when trying to read the file"}
|
||||
|
||||
container.setName(container_id)
|
||||
|
||||
UM.Settings.ContainerRegistry.getInstance().addContainer(container)
|
||||
|
||||
return { "status": "success", "message": "Successfully imported container {0}".format(container.getName()) }
|
||||
|
||||
def _updateContainerNameFilters(self):
|
||||
self._container_name_filters = {}
|
||||
for plugin_id, container_type in UM.Settings.ContainerRegistry.getContainerTypes():
|
||||
serialize_type = ""
|
||||
try:
|
||||
plugin_metadata = UM.PluginRegistry.getInstance().getMetaData(plugin_id)
|
||||
if plugin_metadata:
|
||||
serialize_type = plugin_metadata["settings_container"]["type"]
|
||||
else:
|
||||
continue
|
||||
except KeyError as e:
|
||||
continue
|
||||
|
||||
mime_type = UM.Settings.ContainerRegistry.getMimeTypeForContainer(container_type)
|
||||
|
||||
entry = {
|
||||
"type": serialize_type,
|
||||
"mime": mime_type,
|
||||
"container": container_type
|
||||
}
|
||||
|
||||
suffix_list = "*." + mime_type.preferredSuffix
|
||||
for suffix in mime_type.suffixes:
|
||||
if suffix == mime_type.preferredSuffix:
|
||||
continue
|
||||
|
||||
suffix_list += ", *." + suffix
|
||||
|
||||
name_filter = "{0} ({1})".format(mime_type.comment, suffix_list)
|
||||
self._container_name_filters[name_filter] = entry
|
||||
|
||||
# Factory function, used by QML
|
||||
@staticmethod
|
||||
def createContainerManager(engine, js_engine):
|
||||
return ContainerManager()
|
|
@ -90,4 +90,4 @@ class ContainerSettingsModel(ListModel):
|
|||
containersChanged = pyqtSignal()
|
||||
@pyqtProperty("QVariantList", fset = setContainers, notify = containersChanged)
|
||||
def containers(self):
|
||||
return self.container_ids
|
||||
return self.container_ids
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
|
||||
|
||||
import cura.ExtruderManager
|
||||
import UM.Qt.ListModel
|
||||
|
||||
from . import ExtruderManager
|
||||
|
||||
## Model that holds extruders.
|
||||
#
|
||||
# This model is designed for use by any list of extruders, but specifically
|
||||
|
@ -49,7 +50,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
self._active_extruder_stack = None
|
||||
|
||||
#Listen to changes.
|
||||
manager = cura.ExtruderManager.ExtruderManager.getInstance()
|
||||
manager = ExtruderManager.getInstance()
|
||||
manager.extrudersChanged.connect(self._updateExtruders) #When the list of extruders changes in general.
|
||||
UM.Application.getInstance().globalContainerStackChanged.connect(self._updateExtruders) #When the current machine changes.
|
||||
self._updateExtruders()
|
||||
|
@ -69,7 +70,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
return self._add_global
|
||||
|
||||
def _onActiveExtruderChanged(self):
|
||||
manager = cura.ExtruderManager.ExtruderManager.getInstance()
|
||||
manager = ExtruderManager.getInstance()
|
||||
active_extruder_stack = manager.getActiveExtruderStack()
|
||||
if self._active_extruder_stack != active_extruder_stack:
|
||||
if self._active_extruder_stack:
|
||||
|
@ -93,7 +94,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
# This should be called whenever the list of extruders changes.
|
||||
def _updateExtruders(self):
|
||||
self.clear()
|
||||
manager = cura.ExtruderManager.ExtruderManager.getInstance()
|
||||
manager = ExtruderManager.getInstance()
|
||||
global_container_stack = UM.Application.getInstance().getGlobalContainerStack()
|
||||
if not global_container_stack:
|
||||
return #There is no machine to get the extruders of.
|
|
@ -2,22 +2,21 @@
|
|||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
|
||||
|
||||
from UM.Application import Application
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Logger import Logger
|
||||
|
||||
import UM.Settings
|
||||
from UM.Settings.Validator import ValidatorState
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice
|
||||
from UM.Settings.ContainerStack import ContainerStack
|
||||
|
||||
from . import ExtruderManager
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
class MachineManagerModel(QObject):
|
||||
class MachineManager(QObject):
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
|
||||
|
@ -28,7 +27,7 @@ class MachineManagerModel(QObject):
|
|||
self._global_stack_valid = None
|
||||
self._onGlobalContainerChanged()
|
||||
|
||||
ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
|
||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
|
||||
self.globalContainerChanged.connect(self._onActiveExtruderStackChanged)
|
||||
self._onActiveExtruderStackChanged()
|
||||
|
||||
|
@ -36,13 +35,13 @@ class MachineManagerModel(QObject):
|
|||
self.globalContainerChanged.connect(self.activeMaterialChanged)
|
||||
self.globalContainerChanged.connect(self.activeVariantChanged)
|
||||
self.globalContainerChanged.connect(self.activeQualityChanged)
|
||||
ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeMaterialChanged)
|
||||
ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeVariantChanged)
|
||||
ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeQualityChanged)
|
||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeMaterialChanged)
|
||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeVariantChanged)
|
||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeQualityChanged)
|
||||
|
||||
self.globalContainerChanged.connect(self.activeStackChanged)
|
||||
self.globalValueChanged.connect(self.activeStackChanged)
|
||||
ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeStackChanged)
|
||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeStackChanged)
|
||||
|
||||
self._empty_variant_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_variant")[0]
|
||||
self._empty_material_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_material")[0]
|
||||
|
@ -126,7 +125,7 @@ class MachineManagerModel(QObject):
|
|||
if property_name == "validationState":
|
||||
if self._global_stack_valid:
|
||||
changed_validation_state = self._active_container_stack.getProperty(key, property_name)
|
||||
if changed_validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
|
||||
if changed_validation_state in (UM.Settings.ValidatorState.Exception, UM.Settings.ValidatorState.MaximumError, UM.Settings.ValidatorState.MinimumError):
|
||||
self._global_stack_valid = False
|
||||
self.globalValidationChanged.emit()
|
||||
else:
|
||||
|
@ -155,7 +154,7 @@ class MachineManagerModel(QObject):
|
|||
self._active_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged)
|
||||
self._active_container_stack.propertyChanged.disconnect(self._onGlobalPropertyChanged)
|
||||
|
||||
self._active_container_stack = ExtruderManager.ExtruderManager.getInstance().getActiveExtruderStack()
|
||||
self._active_container_stack = ExtruderManager.getInstance().getActiveExtruderStack()
|
||||
if self._active_container_stack:
|
||||
self._active_container_stack.containersChanged.connect(self._onInstanceContainersChanged)
|
||||
self._active_container_stack.propertyChanged.connect(self._onGlobalPropertyChanged)
|
||||
|
@ -207,7 +206,7 @@ class MachineManagerModel(QObject):
|
|||
new_global_stack.addContainer(quality_instance_container)
|
||||
new_global_stack.addContainer(current_settings_instance_container)
|
||||
|
||||
ExtruderManager.ExtruderManager.getInstance().addMachineExtruders(definition)
|
||||
ExtruderManager.getInstance().addMachineExtruders(definition)
|
||||
|
||||
Application.getInstance().setGlobalContainerStack(new_global_stack)
|
||||
|
||||
|
@ -228,7 +227,7 @@ class MachineManagerModel(QObject):
|
|||
|
||||
for key in stack.getAllKeys():
|
||||
validation_state = stack.getProperty(key, "validationState")
|
||||
if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
|
||||
if validation_state in (UM.Settings.ValidatorState.Exception, UM.Settings.ValidatorState.MaximumError, UM.Settings.ValidatorState.MinimumError):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -552,6 +551,10 @@ class MachineManagerModel(QObject):
|
|||
if containers:
|
||||
return containers[0].getBottom().getId()
|
||||
|
||||
@staticmethod
|
||||
def createMachineManager(engine, script_engine):
|
||||
return MachineManager()
|
||||
|
||||
def _updateVariantContainer(self, definition):
|
||||
if not definition.getMetaDataEntry("has_variants"):
|
||||
return self._empty_variant_container
|
||||
|
@ -637,6 +640,3 @@ class MachineManagerModel(QObject):
|
|||
return containers[0]
|
||||
|
||||
return self._empty_quality_container
|
||||
|
||||
def createMachineManagerModel(engine, script_engine):
|
||||
return MachineManagerModel()
|
19
cura/Settings/MaterialSettingsVisibilityHandler.py
Normal file
19
cura/Settings/MaterialSettingsVisibilityHandler.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2016 Ultimaker B.V.
|
||||
# Uranium is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import UM.Settings.Models
|
||||
|
||||
class MaterialSettingsVisibilityHandler(UM.Settings.Models.SettingVisibilityHandler):
|
||||
def __init__(self, parent = None, *args, **kwargs):
|
||||
super().__init__(parent = parent, *args, **kwargs)
|
||||
|
||||
material_settings = set([
|
||||
"material_print_temperature",
|
||||
"material_bed_temperature",
|
||||
"material_standby_temperature",
|
||||
"cool_fan_speed",
|
||||
"retraction_amount",
|
||||
"retraction_speed",
|
||||
])
|
||||
|
||||
self.setVisible(material_settings)
|
12
cura/Settings/__init__.py
Normal file
12
cura/Settings/__init__.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Copyright (c) 2016 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from .MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
|
||||
from .ContainerManager import ContainerManager
|
||||
from .ContainerSettingsModel import ContainerSettingsModel
|
||||
from .CuraContainerRegistry import CuraContainerRegistry
|
||||
from .ExtruderManager import ExtruderManager
|
||||
from .ExtrudersModel import ExtrudersModel
|
||||
from .MachineManager import MachineManager
|
||||
from .MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
|
||||
from .SettingOverrideDecorator import SettingOverrideDecorator
|
|
@ -35,7 +35,7 @@ sys.excepthook = exceptHook
|
|||
import Arcus #@UnusedImport
|
||||
from UM.Platform import Platform
|
||||
import cura.CuraApplication
|
||||
import cura.CuraContainerRegistry
|
||||
import cura.Settings.CuraContainerRegistry
|
||||
|
||||
if Platform.isWindows() and hasattr(sys, "frozen"):
|
||||
dirpath = os.path.expanduser("~/AppData/Local/cura/")
|
||||
|
@ -44,7 +44,7 @@ if Platform.isWindows() and hasattr(sys, "frozen"):
|
|||
sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w")
|
||||
|
||||
# Force an instance of CuraContainerRegistry to be created and reused later.
|
||||
cura.CuraContainerRegistry.CuraContainerRegistry.getInstance()
|
||||
cura.Settings.CuraContainerRegistry.getInstance()
|
||||
|
||||
app = cura.CuraApplication.CuraApplication.getInstance()
|
||||
app.run()
|
||||
|
|
|
@ -13,7 +13,7 @@ from UM.Resources import Resources
|
|||
from UM.Settings.Validator import ValidatorState #To find if a setting is in an error state. We can't slice then.
|
||||
from UM.Platform import Platform
|
||||
|
||||
from cura.ExtruderManager import ExtruderManager
|
||||
import cura.Settings
|
||||
|
||||
from cura.OneAtATimeIterator import OneAtATimeIterator
|
||||
from . import ProcessSlicedLayersJob
|
||||
|
@ -63,7 +63,7 @@ class CuraEngineBackend(Backend):
|
|||
self._onGlobalStackChanged()
|
||||
|
||||
self._active_extruder_stack = None
|
||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
|
||||
cura.Settings.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
|
||||
self._onActiveExtruderChanged()
|
||||
|
||||
#When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired.
|
||||
|
@ -386,7 +386,8 @@ class CuraEngineBackend(Backend):
|
|||
self._active_extruder_stack.propertyChanged.disconnect(self._onSettingChanged)
|
||||
self._active_extruder_stack.containersChanged.disconnect(self._onChanged)
|
||||
|
||||
self._active_extruder_stack = ExtruderManager.getInstance().getActiveExtruderStack()
|
||||
self._active_extruder_stack = cura.Settings.ExtruderManager.getInstance().getActiveExtruderStack()
|
||||
if self._active_extruder_stack:
|
||||
self._active_extruder_stack.propertyChanged.connect(self._onSettingChanged) # Note: Only starts slicing when the value changed.
|
||||
self._active_extruder_stack.containersChanged.connect(self._onChanged)
|
||||
self._active_extruder_stack.containersChanged.connect(self._onChanged)
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
|||
from UM.Settings.Validator import ValidatorState
|
||||
|
||||
from cura.OneAtATimeIterator import OneAtATimeIterator
|
||||
from cura.ExtruderManager import ExtruderManager
|
||||
|
||||
import cura.Settings
|
||||
|
||||
class StartJobResult(IntEnum):
|
||||
Finished = 1
|
||||
|
@ -128,7 +129,7 @@ class StartSliceJob(Job):
|
|||
|
||||
self._buildGlobalSettingsMessage(stack)
|
||||
|
||||
for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getBottom().getId()):
|
||||
for extruder_stack in cura.Settings.ExtruderManager.getInstance().getMachineExtruders(stack.getBottom().getId()):
|
||||
self._buildExtruderMessage(extruder_stack)
|
||||
|
||||
for group in object_groups:
|
||||
|
@ -208,4 +209,4 @@ class StartSliceJob(Job):
|
|||
setting = message.addRepeatedMessage("settings")
|
||||
setting.name = key
|
||||
setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
|
||||
Job.yieldThread()
|
||||
Job.yieldThread()
|
||||
|
|
|
@ -135,8 +135,6 @@ class LayerView(View):
|
|||
|
||||
self.currentLayerNumChanged.emit()
|
||||
|
||||
currentLayerNumChanged = Signal()
|
||||
|
||||
def calculateMaxLayers(self):
|
||||
scene = self.getController().getScene()
|
||||
renderer = self.getRenderer() # TODO: @UnusedVariable
|
||||
|
|
|
@ -69,7 +69,7 @@ Item
|
|||
// Ensure that the cursor is at the first position. On some systems the text isnt fully visible
|
||||
// Seems to have to do something with different dpi densities that QML doesn't quite handle.
|
||||
// Another option would be to increase the size even further, but that gives pretty ugly results.
|
||||
onTextChanged: cursorPosition = 0
|
||||
onEditingFinished: cursorPosition = 0
|
||||
style: TextFieldStyle
|
||||
{
|
||||
textColor: UM.Theme.getColor("setting_control_text");
|
||||
|
|
|
@ -5,7 +5,7 @@ from UM.Logger import Logger
|
|||
|
||||
import UM.Settings.Models
|
||||
|
||||
from cura.SettingOverrideDecorator import SettingOverrideDecorator
|
||||
from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
||||
|
||||
## The per object setting visibility handler ensures that only setting defintions that have a matching instance Container
|
||||
# are returned as visible.
|
||||
|
|
|
@ -5,7 +5,7 @@ from UM.Tool import Tool
|
|||
from UM.Scene.Selection import Selection
|
||||
from UM.Application import Application
|
||||
from UM.Preferences import Preferences
|
||||
from cura.SettingOverrideDecorator import SettingOverrideDecorator
|
||||
from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
||||
|
||||
## This tool allows the user to add & change settings per node in the scene.
|
||||
# The settings per object are kept in a ContainerStack, which is linked to a node by decorator.
|
||||
|
|
|
@ -10,7 +10,7 @@ from UM.View.Renderer import Renderer
|
|||
|
||||
from UM.View.GL.OpenGL import OpenGL
|
||||
|
||||
from cura.ExtrudersModel import ExtrudersModel
|
||||
import cura.Settings
|
||||
|
||||
import math
|
||||
|
||||
|
@ -24,7 +24,7 @@ class SolidView(View):
|
|||
self._enabled_shader = None
|
||||
self._disabled_shader = None
|
||||
|
||||
self._extruders_model = ExtrudersModel()
|
||||
self._extruders_model = cura.Settings.ExtrudersModel()
|
||||
|
||||
def beginRendering(self):
|
||||
scene = self.getController().getScene()
|
||||
|
|
|
@ -3,6 +3,7 @@ from cura.PrinterOutputDevice import PrinterOutputDevice
|
|||
from UM.Application import Application
|
||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
@ -57,8 +58,9 @@ class UMOCheckupMachineAction(MachineAction):
|
|||
self._output_device.endstopStateChanged.disconnect(self._onEndstopStateChanged)
|
||||
try:
|
||||
self._output_device.stopPollEndstop()
|
||||
except AttributeError: # Connection is probably not a USB connection. Something went pretty wrong if this happens.
|
||||
pass
|
||||
except AttributeError as e: # Connection is probably not a USB connection. Something went pretty wrong if this happens.
|
||||
Logger.log("e", "An exception occurred while stopping end stop polling: %s" % str(e))
|
||||
|
||||
self._output_device = None
|
||||
|
||||
self._check_started = False
|
||||
|
@ -77,6 +79,8 @@ class UMOCheckupMachineAction(MachineAction):
|
|||
self._z_min_endstop_test_completed = False
|
||||
self.onZMinEndstopTestCompleted.emit()
|
||||
|
||||
self.heatedBedChanged.emit()
|
||||
|
||||
@pyqtProperty(bool, notify = onBedTestCompleted)
|
||||
def bedTestCompleted(self):
|
||||
return self._bed_test_completed
|
||||
|
@ -158,7 +162,17 @@ class UMOCheckupMachineAction(MachineAction):
|
|||
self._output_device.hotendTemperaturesChanged.connect(self._onHotendTemperatureChanged)
|
||||
self._output_device.endstopStateChanged.connect(self._onEndstopStateChanged)
|
||||
except AttributeError as e: # Connection is probably not a USB connection. Something went pretty wrong if this happens.
|
||||
pass
|
||||
Logger.log("e", "An exception occurred while starting end stop polling: %s" % str(e))
|
||||
|
||||
@pyqtSlot()
|
||||
def cooldownHotend(self):
|
||||
if self._output_device is not None:
|
||||
self._output_device.setTargetHotendTemperature(0, 0)
|
||||
|
||||
@pyqtSlot()
|
||||
def cooldownBed(self):
|
||||
if self._output_device is not None:
|
||||
self._output_device.setTargetBedTemperature(0)
|
||||
|
||||
@pyqtSlot()
|
||||
def heatupHotend(self):
|
||||
|
@ -168,4 +182,11 @@ class UMOCheckupMachineAction(MachineAction):
|
|||
@pyqtSlot()
|
||||
def heatupBed(self):
|
||||
if self._output_device is not None:
|
||||
self._output_device.setTargetBedTemperature(self._bed_target_temp)
|
||||
self._output_device.setTargetBedTemperature(self._bed_target_temp)
|
||||
|
||||
heatedBedChanged = pyqtSignal()
|
||||
|
||||
@pyqtProperty(bool, notify = heatedBedChanged)
|
||||
def hasHeatedBed(self):
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
return global_container_stack.getProperty("machine_heated_bed", "value")
|
|
@ -15,6 +15,10 @@ Cura.MachineAction
|
|||
anchors.fill: parent;
|
||||
property int leftRow: checkupMachineAction.width * 0.40
|
||||
property int rightRow: checkupMachineAction.width * 0.60
|
||||
property bool heatupHotendStarted: false
|
||||
property bool heatupBedStarted: false
|
||||
property bool usbConnected: Cura.USBPrinterManager.connectedPrinterList.rowCount() > 0
|
||||
|
||||
UM.I18nCatalog { id: catalog; name:"cura"}
|
||||
Label
|
||||
{
|
||||
|
@ -51,6 +55,8 @@ Cura.MachineAction
|
|||
text: catalog.i18nc("@action:button","Start Printer Check");
|
||||
onClicked:
|
||||
{
|
||||
checkupMachineAction.heatupHotendStarted = false
|
||||
checkupMachineAction.heatupBedStarted = false
|
||||
manager.startCheck()
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +98,7 @@ Cura.MachineAction
|
|||
anchors.left: connectionLabel.right
|
||||
anchors.top: parent.top
|
||||
wrapMode: Text.WordWrap
|
||||
text: Cura.USBPrinterManager.connectedPrinterList.rowCount() > 0 ? catalog.i18nc("@info:status","Connected"): catalog.i18nc("@info:status","Not connected")
|
||||
text: checkupMachineAction.usbConnected ? catalog.i18nc("@info:status","Connected"): catalog.i18nc("@info:status","Not connected")
|
||||
}
|
||||
//////////////////////////////////////////////////////////
|
||||
Label
|
||||
|
@ -103,6 +109,7 @@ Cura.MachineAction
|
|||
anchors.top: connectionLabel.bottom
|
||||
wrapMode: Text.WordWrap
|
||||
text: catalog.i18nc("@label","Min endstop X: ")
|
||||
visible: checkupMachineAction.usbConnected
|
||||
}
|
||||
Label
|
||||
{
|
||||
|
@ -112,6 +119,7 @@ Cura.MachineAction
|
|||
anchors.top: connectionLabel.bottom
|
||||
wrapMode: Text.WordWrap
|
||||
text: manager.xMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked")
|
||||
visible: checkupMachineAction.usbConnected
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
Label
|
||||
|
@ -122,6 +130,7 @@ Cura.MachineAction
|
|||
anchors.top: endstopXLabel.bottom
|
||||
wrapMode: Text.WordWrap
|
||||
text: catalog.i18nc("@label","Min endstop Y: ")
|
||||
visible: checkupMachineAction.usbConnected
|
||||
}
|
||||
Label
|
||||
{
|
||||
|
@ -131,6 +140,7 @@ Cura.MachineAction
|
|||
anchors.top: endstopXLabel.bottom
|
||||
wrapMode: Text.WordWrap
|
||||
text: manager.yMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked")
|
||||
visible: checkupMachineAction.usbConnected
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
Label
|
||||
|
@ -141,6 +151,7 @@ Cura.MachineAction
|
|||
anchors.top: endstopYLabel.bottom
|
||||
wrapMode: Text.WordWrap
|
||||
text: catalog.i18nc("@label","Min endstop Z: ")
|
||||
visible: checkupMachineAction.usbConnected
|
||||
}
|
||||
Label
|
||||
{
|
||||
|
@ -150,6 +161,7 @@ Cura.MachineAction
|
|||
anchors.top: endstopYLabel.bottom
|
||||
wrapMode: Text.WordWrap
|
||||
text: manager.zMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked")
|
||||
visible: checkupMachineAction.usbConnected
|
||||
}
|
||||
////////////////////////////////////////////////////////////
|
||||
Label
|
||||
|
@ -161,6 +173,7 @@ Cura.MachineAction
|
|||
anchors.top: endstopZLabel.bottom
|
||||
wrapMode: Text.WordWrap
|
||||
text: catalog.i18nc("@label","Nozzle temperature check: ")
|
||||
visible: checkupMachineAction.usbConnected
|
||||
}
|
||||
Label
|
||||
{
|
||||
|
@ -170,6 +183,7 @@ Cura.MachineAction
|
|||
anchors.left: nozzleTempLabel.right
|
||||
wrapMode: Text.WordWrap
|
||||
text: catalog.i18nc("@info:status","Not checked")
|
||||
visible: checkupMachineAction.usbConnected
|
||||
}
|
||||
Item
|
||||
{
|
||||
|
@ -179,12 +193,22 @@ Cura.MachineAction
|
|||
anchors.top: nozzleTempLabel.top
|
||||
anchors.left: bedTempStatus.right
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width/2
|
||||
visible: checkupMachineAction.usbConnected
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button","Start Heating")
|
||||
text: checkupMachineAction.heatupHotendStarted ? catalog.i18nc("@action:button","Stop Heating") : catalog.i18nc("@action:button","Start Heating")
|
||||
//
|
||||
onClicked:
|
||||
{
|
||||
manager.heatupHotend()
|
||||
if (checkupMachineAction.heatupHotendStarted)
|
||||
{
|
||||
manager.cooldownHotend()
|
||||
checkupMachineAction.heatupHotendStarted = false
|
||||
} else
|
||||
{
|
||||
manager.heatupHotend()
|
||||
checkupMachineAction.heatupHotendStarted = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,6 +222,7 @@ Cura.MachineAction
|
|||
wrapMode: Text.WordWrap
|
||||
text: manager.hotendTemperature + "°C"
|
||||
font.bold: true
|
||||
visible: checkupMachineAction.usbConnected
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Label
|
||||
|
@ -209,6 +234,7 @@ Cura.MachineAction
|
|||
anchors.top: nozzleTempLabel.bottom
|
||||
wrapMode: Text.WordWrap
|
||||
text: catalog.i18nc("@label","Bed temperature check:")
|
||||
visible: checkupMachineAction.usbConnected && manager.hasHeatedBed
|
||||
}
|
||||
|
||||
Label
|
||||
|
@ -219,6 +245,7 @@ Cura.MachineAction
|
|||
anchors.left: bedTempLabel.right
|
||||
wrapMode: Text.WordWrap
|
||||
text: manager.bedTestCompleted ? catalog.i18nc("@info:status","Not checked"): catalog.i18nc("@info:status","Checked")
|
||||
visible: checkupMachineAction.usbConnected && manager.hasHeatedBed
|
||||
}
|
||||
Item
|
||||
{
|
||||
|
@ -228,12 +255,21 @@ Cura.MachineAction
|
|||
anchors.top: bedTempLabel.top
|
||||
anchors.left: bedTempStatus.right
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width/2
|
||||
visible: checkupMachineAction.usbConnected && manager.hasHeatedBed
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button","Start Heating")
|
||||
text: checkupMachineAction.heatupBedStarted ?catalog.i18nc("@action:button","Stop Heating") : catalog.i18nc("@action:button","Start Heating")
|
||||
onClicked:
|
||||
{
|
||||
manager.heatupBed()
|
||||
if (checkupMachineAction.heatupBedStarted)
|
||||
{
|
||||
manager.cooldownBed()
|
||||
checkupMachineAction.heatupBedStarted = false
|
||||
} else
|
||||
{
|
||||
manager.heatupBed()
|
||||
checkupMachineAction.heatupBedStarted = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -247,6 +283,7 @@ Cura.MachineAction
|
|||
wrapMode: Text.WordWrap
|
||||
text: manager.bedTemperature + "°C"
|
||||
font.bold: true
|
||||
visible: checkupMachineAction.usbConnected && manager.hasHeatedBed
|
||||
}
|
||||
Label
|
||||
{
|
||||
|
|
|
@ -3,32 +3,224 @@
|
|||
|
||||
import math
|
||||
import copy
|
||||
import io
|
||||
import xml.etree.ElementTree as ET
|
||||
import uuid
|
||||
|
||||
from UM.Logger import Logger
|
||||
|
||||
import UM.Dictionary
|
||||
|
||||
import UM.Settings
|
||||
|
||||
# The namespace is prepended to the tag name but between {}.
|
||||
# We are only interested in the actual tag name, so discard everything
|
||||
# before the last }
|
||||
def _tag_without_namespace(element):
|
||||
return element.tag[element.tag.rfind("}") + 1:]
|
||||
|
||||
## Handles serializing and deserializing material containers from an XML file
|
||||
class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
||||
def __init__(self, container_id, *args, **kwargs):
|
||||
super().__init__(container_id, *args, **kwargs)
|
||||
|
||||
def serialize(self):
|
||||
raise NotImplementedError("Writing material profiles has not yet been implemented")
|
||||
## Overridden from InstanceContainer
|
||||
def duplicate(self, new_id, new_name = None):
|
||||
base_file = self.getMetaDataEntry("base_file", "")
|
||||
new_uuid = str(uuid.uuid4())
|
||||
|
||||
if base_file:
|
||||
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = base_file)
|
||||
if containers:
|
||||
new_basefile = containers[0].duplicate(self.getMetaDataEntry("brand") + "_" + new_id, new_name)
|
||||
new_basefile.setMetaDataEntry("GUID", new_uuid)
|
||||
base_file = new_basefile.id
|
||||
UM.Settings.ContainerRegistry.getInstance().addContainer(new_basefile)
|
||||
|
||||
new_id = self.getMetaDataEntry("brand") + "_" + new_id + "_" + self.getDefinition().getId()
|
||||
variant = self.getMetaDataEntry("variant")
|
||||
if variant:
|
||||
variant_containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = variant)
|
||||
if variant_containers:
|
||||
new_id += "_" + variant_containers[0].getName().replace(" ", "_")
|
||||
|
||||
result = super().duplicate(new_id, new_name)
|
||||
result.setMetaDataEntry("GUID", new_uuid)
|
||||
result.setMetaDataEntry("base_file", base_file)
|
||||
return result
|
||||
|
||||
## Overridden from InstanceContainer
|
||||
def setReadOnly(self, read_only):
|
||||
super().setReadOnly(read_only)
|
||||
|
||||
for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(GUID = self.getMetaDataEntry("GUID")):
|
||||
container._read_only = read_only
|
||||
|
||||
## Overridden from InstanceContainer
|
||||
def setMetaDataEntry(self, key, value):
|
||||
if self.isReadOnly():
|
||||
return
|
||||
|
||||
super().setMetaDataEntry(key, value)
|
||||
|
||||
for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(GUID = self.getMetaDataEntry("GUID")):
|
||||
container.setMetaData(copy.deepcopy(self._metadata))
|
||||
|
||||
## Overridden from InstanceContainer
|
||||
def setProperty(self, key, property_name, property_value, container = None):
|
||||
if self.isReadOnly():
|
||||
return
|
||||
|
||||
super().setProperty(key, property_name, property_value)
|
||||
|
||||
for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(GUID = self.getMetaDataEntry("GUID")):
|
||||
container._dirty = True
|
||||
|
||||
## Overridden from InstanceContainer
|
||||
def serialize(self):
|
||||
registry = UM.Settings.ContainerRegistry.getInstance()
|
||||
|
||||
base_file = self.getMetaDataEntry("base_file", "")
|
||||
if base_file and self.id != base_file:
|
||||
# Since we create an instance of XmlMaterialProfile for each machine and nozzle in the profile,
|
||||
# we should only serialize the "base" material definition, since that can then take care of
|
||||
# serializing the machine/nozzle specific profiles.
|
||||
raise NotImplementedError("Cannot serialize non-root XML materials")
|
||||
|
||||
builder = ET.TreeBuilder()
|
||||
|
||||
root = builder.start("fdmmaterial", { "xmlns": "http://www.ultimaker.com/material"})
|
||||
|
||||
## Begin Metadata Block
|
||||
builder.start("metadata")
|
||||
|
||||
metadata = copy.deepcopy(self.getMetaData())
|
||||
properties = metadata.pop("properties", {})
|
||||
|
||||
# Metadata properties that should not be serialized.
|
||||
metadata.pop("status", "")
|
||||
metadata.pop("variant", "")
|
||||
metadata.pop("type", "")
|
||||
metadata.pop("base_file", "")
|
||||
|
||||
## Begin Name Block
|
||||
builder.start("name")
|
||||
|
||||
builder.start("brand")
|
||||
builder.data(metadata.pop("brand", ""))
|
||||
builder.end("brand")
|
||||
|
||||
builder.start("material")
|
||||
builder.data(metadata.pop("material", ""))
|
||||
builder.end("material")
|
||||
|
||||
builder.start("color")
|
||||
builder.data(metadata.pop("color_name", ""))
|
||||
builder.end("color")
|
||||
|
||||
builder.end("name")
|
||||
## End Name Block
|
||||
|
||||
for key, value in metadata.items():
|
||||
builder.start(key)
|
||||
builder.data(value)
|
||||
builder.end(key)
|
||||
|
||||
builder.end("metadata")
|
||||
## End Metadata Block
|
||||
|
||||
## Begin Properties Block
|
||||
builder.start("properties")
|
||||
|
||||
for key, value in properties.items():
|
||||
builder.start(key)
|
||||
builder.data(value)
|
||||
builder.end(key)
|
||||
|
||||
builder.end("properties")
|
||||
## End Properties Block
|
||||
|
||||
## Begin Settings Block
|
||||
builder.start("settings")
|
||||
|
||||
if self.getDefinition().id == "fdmprinter":
|
||||
for instance in self.findInstances():
|
||||
self._addSettingElement(builder, instance)
|
||||
|
||||
machine_container_map = {}
|
||||
machine_nozzle_map = {}
|
||||
|
||||
all_containers = registry.findInstanceContainers(GUID = self.getMetaDataEntry("GUID"))
|
||||
for container in all_containers:
|
||||
definition_id = container.getDefinition().id
|
||||
if definition_id == "fdmprinter":
|
||||
continue
|
||||
|
||||
if definition_id not in machine_container_map:
|
||||
machine_container_map[definition_id] = container
|
||||
|
||||
if definition_id not in machine_nozzle_map:
|
||||
machine_nozzle_map[definition_id] = {}
|
||||
|
||||
variant = container.getMetaDataEntry("variant")
|
||||
if variant:
|
||||
machine_nozzle_map[definition_id][variant] = container
|
||||
continue
|
||||
|
||||
machine_container_map[definition_id] = container
|
||||
|
||||
for definition_id, container in machine_container_map.items():
|
||||
definition = container.getDefinition()
|
||||
try:
|
||||
product = UM.Dictionary.findKey(self.__product_id_map, definition_id)
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
builder.start("machine")
|
||||
builder.start("machine_identifier", { "manufacturer": definition.getMetaDataEntry("manufacturer", ""), "product": product})
|
||||
builder.end("machine_identifier")
|
||||
|
||||
for instance in container.findInstances():
|
||||
if self.getDefinition().id == "fdmprinter" and self.getInstance(instance.definition.key) and self.getProperty(instance.definition.key, "value") == instance.value:
|
||||
# If the settings match that of the base profile, just skip since we inherit the base profile.
|
||||
continue
|
||||
|
||||
self._addSettingElement(builder, instance)
|
||||
|
||||
# Find all hotend sub-profiles corresponding to this material and machine and add them to this profile.
|
||||
for hotend_id, hotend in machine_nozzle_map[definition_id].items():
|
||||
variant_containers = registry.findInstanceContainers(id = hotend.getMetaDataEntry("variant"))
|
||||
if not variant_containers:
|
||||
continue
|
||||
|
||||
builder.start("hotend", { "id": variant_containers[0].getName() })
|
||||
|
||||
for instance in hotend.findInstances():
|
||||
if container.getInstance(instance.definition.key) and container.getProperty(instance.definition.key, "value") == instance.value:
|
||||
# If the settings match that of the machine profile, just skip since we inherit the machine profile.
|
||||
continue
|
||||
|
||||
self._addSettingElement(builder, instance)
|
||||
|
||||
builder.end("hotend")
|
||||
|
||||
builder.end("machine")
|
||||
|
||||
builder.end("settings")
|
||||
## End Settings Block
|
||||
|
||||
builder.end("fdmmaterial")
|
||||
|
||||
root = builder.close()
|
||||
_indent(root)
|
||||
stream = io.StringIO()
|
||||
tree = ET.ElementTree(root)
|
||||
tree.write(stream, "unicode", True)
|
||||
|
||||
return stream.getvalue()
|
||||
|
||||
## Overridden from InstanceContainer
|
||||
def deserialize(self, serialized):
|
||||
data = ET.fromstring(serialized)
|
||||
|
||||
self.addMetaDataEntry("type", "material")
|
||||
|
||||
# TODO: Add material verfication
|
||||
self.addMetaDataEntry("status", "Unknown")
|
||||
self.addMetaDataEntry("status", "unknown")
|
||||
|
||||
metadata = data.iterfind("./um:metadata/*", self.__namespaces)
|
||||
for entry in metadata:
|
||||
|
@ -39,7 +231,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||
material = entry.find("./um:material", self.__namespaces)
|
||||
color = entry.find("./um:color", self.__namespaces)
|
||||
|
||||
self.setName("{0} {1} ({2})".format(brand.text, material.text, color.text))
|
||||
self.setName(material.text)
|
||||
|
||||
self.addMetaDataEntry("brand", brand.text)
|
||||
self.addMetaDataEntry("material", material.text)
|
||||
|
@ -49,6 +241,12 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||
|
||||
self.addMetaDataEntry(tag_name, entry.text)
|
||||
|
||||
if not "description" in self.getMetaData():
|
||||
self.addMetaDataEntry("description", "")
|
||||
|
||||
if not "adhesion_info" in self.getMetaData():
|
||||
self.addMetaDataEntry("adhesion_info", "")
|
||||
|
||||
property_values = {}
|
||||
properties = data.iterfind("./um:properties/*", self.__namespaces)
|
||||
for entry in properties:
|
||||
|
@ -58,17 +256,6 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||
diameter = float(property_values.get("diameter", 2.85)) # In mm
|
||||
density = float(property_values.get("density", 1.3)) # In g/cm3
|
||||
|
||||
weight_per_cm = (math.pi * (diameter / 20) ** 2 * 0.1) * density
|
||||
|
||||
spool_weight = property_values.get("spool_weight")
|
||||
spool_length = property_values.get("spool_length")
|
||||
if spool_weight:
|
||||
length = float(spool_weight) / weight_per_cm
|
||||
property_values["spool_length"] = str(length / 100)
|
||||
elif spool_length:
|
||||
weight = (float(spool_length) * 100) * weight_per_cm
|
||||
property_values["spool_weight"] = str(weight)
|
||||
|
||||
self.addMetaDataEntry("properties", property_values)
|
||||
|
||||
self.setDefinition(UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter")[0])
|
||||
|
@ -83,6 +270,8 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||
else:
|
||||
Logger.log("d", "Unsupported material setting %s", key)
|
||||
|
||||
self._dirty = False
|
||||
|
||||
machines = data.iterfind("./um:settings/um:machine", self.__namespaces)
|
||||
for machine in machines:
|
||||
machine_setting_values = {}
|
||||
|
@ -112,6 +301,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||
new_material.setName(self.getName())
|
||||
new_material.setMetaData(copy.deepcopy(self.getMetaData()))
|
||||
new_material.setDefinition(definition)
|
||||
new_material.addMetaDataEntry("base_file", self.id)
|
||||
|
||||
for key, value in global_setting_values.items():
|
||||
new_material.setProperty(key, "value", value, definition)
|
||||
|
@ -142,6 +332,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||
new_hotend_material.setName(self.getName())
|
||||
new_hotend_material.setMetaData(copy.deepcopy(self.getMetaData()))
|
||||
new_hotend_material.setDefinition(definition)
|
||||
new_hotend_material.addMetaDataEntry("base_file", self.id)
|
||||
|
||||
new_hotend_material.addMetaDataEntry("variant", variant_containers[0].id)
|
||||
|
||||
|
@ -162,6 +353,15 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||
new_hotend_material._dirty = False
|
||||
UM.Settings.ContainerRegistry.getInstance().addContainer(new_hotend_material)
|
||||
|
||||
def _addSettingElement(self, builder, instance):
|
||||
try:
|
||||
key = UM.Dictionary.findKey(self.__material_property_setting_map, instance.definition.key)
|
||||
except ValueError:
|
||||
return
|
||||
|
||||
builder.start("setting", { "key": key })
|
||||
builder.data(str(instance.value))
|
||||
builder.end("setting")
|
||||
|
||||
# Map XML file setting names to internal names
|
||||
__material_property_setting_map = {
|
||||
|
@ -174,6 +374,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||
}
|
||||
|
||||
# Map XML file product names to internal ids
|
||||
# TODO: Move this to definition's metadata
|
||||
__product_id_map = {
|
||||
"Ultimaker2": "ultimaker2",
|
||||
"Ultimaker2+": "ultimaker2_plus",
|
||||
|
@ -184,6 +385,30 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
|
|||
"Ultimaker Original+": "ultimaker_original_plus"
|
||||
}
|
||||
|
||||
# Map of recognised namespaces with a proper prefix.
|
||||
__namespaces = {
|
||||
"um": "http://www.ultimaker.com/material"
|
||||
}
|
||||
|
||||
## Helper function for pretty-printing XML because ETree is stupid
|
||||
def _indent(elem, level = 0):
|
||||
i = "\n" + level * " "
|
||||
if len(elem):
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = i + " "
|
||||
if not elem.tail or not elem.tail.strip():
|
||||
elem.tail = i
|
||||
for elem in elem:
|
||||
_indent(elem, level + 1)
|
||||
if not elem.tail or not elem.tail.strip():
|
||||
elem.tail = i
|
||||
else:
|
||||
if level and (not elem.tail or not elem.tail.strip()):
|
||||
elem.tail = i
|
||||
|
||||
|
||||
# The namespace is prepended to the tag name but between {}.
|
||||
# We are only interested in the actual tag name, so discard everything
|
||||
# before the last }
|
||||
def _tag_without_namespace(element):
|
||||
return element.tag[element.tag.rfind("}") + 1:]
|
||||
|
|
|
@ -17,6 +17,7 @@ def getMetaData():
|
|||
"api": 3
|
||||
},
|
||||
"settings_container": {
|
||||
"type": "material",
|
||||
"mimetype": "application/x-ultimaker-material-profile"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3045,7 +3045,7 @@
|
|||
"infill_mesh":
|
||||
{
|
||||
"label": "Infill Mesh",
|
||||
"description": "Use this mesh to modify the infill of other meshes with which it overlaps. Replaces infill regions of other meshes with regions for this mesh.",
|
||||
"description": "Use this mesh to modify the infill of other meshes with which it overlaps. Replaces infill regions of other meshes with regions for this mesh. It's suggested to only print one Wall and no Top/Bottom Skin for this mesh.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"settable_per_mesh": true,
|
||||
|
|
|
@ -39,6 +39,8 @@ Item
|
|||
property alias resetProfile: resetProfileAction;
|
||||
property alias manageProfiles: manageProfilesAction;
|
||||
|
||||
property alias manageMaterials: manageMaterialsAction;
|
||||
|
||||
property alias preferences: preferencesAction;
|
||||
|
||||
property alias showEngineLog: showEngineLogAction;
|
||||
|
@ -90,7 +92,7 @@ Item
|
|||
Action
|
||||
{
|
||||
id: preferencesAction;
|
||||
text: catalog.i18nc("@action:inmenu menubar:settings","&Preferences...");
|
||||
text: catalog.i18nc("@action:inmenu","Configure Cura...");
|
||||
iconName: "configure";
|
||||
}
|
||||
|
||||
|
@ -107,6 +109,13 @@ Item
|
|||
iconName: "configure";
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: manageMaterialsAction
|
||||
text: catalog.i18nc("@action:inmenu", "Manage Materials...")
|
||||
iconName: "configure"
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: updateProfileAction;
|
||||
|
@ -273,5 +282,6 @@ Item
|
|||
{
|
||||
id: configureSettingVisibilityAction
|
||||
text: catalog.i18nc("@action:menu", "Configure setting visiblity...");
|
||||
iconName: "configure"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import QtQuick.Dialogs 1.1
|
|||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
import "Menus"
|
||||
|
||||
UM.MainWindow
|
||||
{
|
||||
id: base
|
||||
|
@ -55,41 +57,13 @@ UM.MainWindow
|
|||
Menu
|
||||
{
|
||||
id: fileMenu
|
||||
//: File menu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&File");
|
||||
|
||||
MenuItem {
|
||||
action: Cura.Actions.open;
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
id: recentFilesMenu;
|
||||
title: catalog.i18nc("@title:menu menubar:file", "Open &Recent")
|
||||
iconName: "document-open-recent";
|
||||
|
||||
enabled: Printer.recentFiles.length > 0;
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: Printer.recentFiles
|
||||
MenuItem
|
||||
{
|
||||
text:
|
||||
{
|
||||
var path = modelData.toString()
|
||||
return (index + 1) + ". " + path.slice(path.lastIndexOf("/") + 1);
|
||||
}
|
||||
onTriggered: {
|
||||
UM.MeshFileHandler.readLocalFile(modelData);
|
||||
var meshName = backgroundItem.getMeshName(modelData.toString())
|
||||
backgroundItem.hasMesh(decodeURIComponent(meshName))
|
||||
}
|
||||
}
|
||||
onObjectAdded: recentFilesMenu.insertItem(index, object)
|
||||
onObjectRemoved: recentFilesMenu.removeItem(object)
|
||||
}
|
||||
}
|
||||
RecentFilesMenu { }
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
|
@ -130,7 +104,6 @@ UM.MainWindow
|
|||
|
||||
Menu
|
||||
{
|
||||
//: Edit menu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Edit");
|
||||
|
||||
MenuItem { action: Cura.Actions.undo; }
|
||||
|
@ -146,173 +119,45 @@ UM.MainWindow
|
|||
MenuItem { action: Cura.Actions.unGroupObjects;}
|
||||
}
|
||||
|
||||
ViewMenu { title: catalog.i18nc("@title:menu", "&View") }
|
||||
|
||||
Menu
|
||||
{
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&View");
|
||||
id: top_view_menu
|
||||
Instantiator
|
||||
{
|
||||
model: UM.ViewModel { }
|
||||
MenuItem
|
||||
{
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: model.active;
|
||||
exclusiveGroup: view_menu_top_group;
|
||||
onTriggered: UM.Controller.setActiveView(model.id);
|
||||
}
|
||||
onObjectAdded: top_view_menu.insertItem(index, object)
|
||||
onObjectRemoved: top_view_menu.removeItem(object)
|
||||
}
|
||||
ExclusiveGroup { id: view_menu_top_group; }
|
||||
}
|
||||
Menu
|
||||
{
|
||||
id: machineMenu;
|
||||
//: Machine menu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Printer");
|
||||
id: settingsMenu
|
||||
title: catalog.i18nc("@title:menu", "&Settings")
|
||||
|
||||
PrinterMenu { title: catalog.i18nc("@title:menu menubar:toplevel", "&Printer") }
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: UM.ContainerStacksModel
|
||||
{
|
||||
filter: {"type": "machine"}
|
||||
model: Cura.ExtrudersModel { }
|
||||
Menu {
|
||||
title: model.name
|
||||
|
||||
NozzleMenu { title: catalog.i18nc("@title:menu", "&Nozzle"); visible: Cura.MachineManager.hasVariants }
|
||||
MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.hasMaterials }
|
||||
ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); }
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
MenuItem { text: "Set as Active Extruder" }
|
||||
}
|
||||
MenuItem
|
||||
{
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: Cura.MachineManager.activeMachineId == model.id
|
||||
exclusiveGroup: machineMenuGroup;
|
||||
onTriggered: Cura.MachineManager.setActiveMachine(model.id);
|
||||
}
|
||||
onObjectAdded: machineMenu.insertItem(index, object)
|
||||
onObjectRemoved: machineMenu.removeItem(object)
|
||||
onObjectAdded: settingsMenu.insertItem(index, object)
|
||||
onObjectRemoved: settingsMenu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: machineMenuGroup; }
|
||||
NozzleMenu { title: catalog.i18nc("@title:menu", "&Nozzle"); visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasVariants }
|
||||
MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasMaterials }
|
||||
ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); visible: machineExtruderCount.properties.value <= 1 }
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: UM.InstanceContainersModel
|
||||
{
|
||||
filter:
|
||||
{
|
||||
"type": "variant",
|
||||
"definition": Cura.MachineManager.activeDefinitionId //Only show variants of this machine
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: model.id == Cura.MachineManager.activeVariantId;
|
||||
exclusiveGroup: machineVariantsGroup;
|
||||
onTriggered: Cura.MachineManager.setActiveVariant(model.id)
|
||||
}
|
||||
onObjectAdded: machineMenu.insertItem(index, object)
|
||||
onObjectRemoved: machineMenu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: machineVariantsGroup; }
|
||||
|
||||
MenuSeparator { visible: Cura.MachineManager.hasVariants; }
|
||||
|
||||
MenuItem { action: Cura.Actions.addMachine; }
|
||||
MenuItem { action: Cura.Actions.configureMachines; }
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
id: profileMenu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel", "P&rofile")
|
||||
|
||||
Instantiator
|
||||
{
|
||||
id: profileMenuInstantiator
|
||||
model: UM.InstanceContainersModel
|
||||
{
|
||||
filter:
|
||||
{
|
||||
var result = { "type": "quality" };
|
||||
if(Cura.MachineManager.filterQualityByMachine)
|
||||
{
|
||||
result.definition = Cura.MachineManager.activeDefinitionId;
|
||||
if(Cura.MachineManager.hasMaterials)
|
||||
{
|
||||
result.material = Cura.MachineManager.activeMaterialId;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.definition = "fdmprinter"
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
property int separatorIndex: -1
|
||||
|
||||
Loader {
|
||||
property QtObject model_data: model
|
||||
property int model_index: index
|
||||
sourceComponent: profileMenuItemDelegate
|
||||
}
|
||||
|
||||
onObjectAdded:
|
||||
{
|
||||
//Insert a separator between readonly and custom profiles
|
||||
if(separatorIndex < 0 && index > 0) {
|
||||
if(model.getItem(index-1).readOnly != model.getItem(index).readOnly) {
|
||||
profileMenu.insertSeparator(index);
|
||||
separatorIndex = index;
|
||||
}
|
||||
}
|
||||
//Because of the separator, custom profiles move one index lower
|
||||
profileMenu.insertItem((model.getItem(index).readOnly) ? index : index + 1, object.item);
|
||||
}
|
||||
onObjectRemoved:
|
||||
{
|
||||
//When adding a profile, the menu is rebuild by removing all items.
|
||||
//If a separator was added, we need to remove that too.
|
||||
if(separatorIndex >= 0)
|
||||
{
|
||||
profileMenu.removeItem(profileMenu.items[separatorIndex])
|
||||
separatorIndex = -1;
|
||||
}
|
||||
profileMenu.removeItem(object.item);
|
||||
}
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: profileMenuGroup; }
|
||||
|
||||
Component
|
||||
{
|
||||
id: profileMenuItemDelegate
|
||||
MenuItem
|
||||
{
|
||||
id: item
|
||||
text: model_data ? model_data.name : ""
|
||||
checkable: true
|
||||
checked: model_data != null ? Cura.MachineManager.activeQualityId == model_data.id : false
|
||||
exclusiveGroup: profileMenuGroup
|
||||
onTriggered: Cura.MachineManager.setActiveQuality(model_data.id)
|
||||
}
|
||||
}
|
||||
|
||||
MenuSeparator { id: profileMenuSeparator }
|
||||
|
||||
MenuItem { action: Cura.Actions.addProfile }
|
||||
MenuItem { action: Cura.Actions.updateProfile }
|
||||
MenuItem { action: Cura.Actions.resetProfile }
|
||||
MenuSeparator { }
|
||||
MenuItem { action: Cura.Actions.manageProfiles }
|
||||
MenuItem { action: Cura.Actions.configureSettingVisibility }
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
id: extension_menu
|
||||
//: Extensions menu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","E&xtensions");
|
||||
|
||||
Instantiator
|
||||
|
@ -346,8 +191,7 @@ UM.MainWindow
|
|||
|
||||
Menu
|
||||
{
|
||||
//: Settings menu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Settings");
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","P&references");
|
||||
|
||||
MenuItem { action: Cura.Actions.preferences; }
|
||||
}
|
||||
|
@ -365,6 +209,16 @@ UM.MainWindow
|
|||
}
|
||||
}
|
||||
|
||||
UM.SettingPropertyProvider
|
||||
{
|
||||
id: machineExtruderCount
|
||||
|
||||
containerStackId: Cura.MachineManager.activeMachineId
|
||||
key: "machine_extruder_count"
|
||||
watchedProperties: [ "value" ]
|
||||
storeIndex: 0
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: contentItem;
|
||||
|
@ -411,14 +265,9 @@ UM.MainWindow
|
|||
{
|
||||
id: view_panel
|
||||
|
||||
//anchors.left: parent.left;
|
||||
//anchors.right: parent.right;
|
||||
//anchors.bottom: parent.bottom
|
||||
anchors.top: viewModeButton.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height;
|
||||
anchors.left: viewModeButton.left;
|
||||
//anchors.bottom: buttons.top;
|
||||
//anchors.bottomMargin: UM.Theme.getSize("default_margin").height;
|
||||
|
||||
height: childrenRect.height;
|
||||
|
||||
|
@ -428,7 +277,6 @@ UM.MainWindow
|
|||
Button
|
||||
{
|
||||
id: openFileButton;
|
||||
//style: UM.Backend.progress < 0 ? UM.Theme.styles.open_file_button : UM.Theme.styles.tool_button;
|
||||
text: catalog.i18nc("@action:button","Open File");
|
||||
iconSource: UM.Theme.getIcon("load")
|
||||
style: UM.Theme.styles.tool_button
|
||||
|
@ -436,9 +284,7 @@ UM.MainWindow
|
|||
anchors
|
||||
{
|
||||
top: parent.top;
|
||||
//topMargin: UM.Theme.getSize("loadfile_margin").height
|
||||
left: parent.left;
|
||||
//leftMargin: UM.Theme.getSize("loadfile_margin").width
|
||||
}
|
||||
action: Cura.Actions.open;
|
||||
}
|
||||
|
@ -478,27 +324,7 @@ UM.MainWindow
|
|||
|
||||
style: UM.Theme.styles.tool_button;
|
||||
tooltip: '';
|
||||
menu: Menu
|
||||
{
|
||||
id: viewMenu;
|
||||
Instantiator
|
||||
{
|
||||
id: viewMenuInstantiator
|
||||
model: UM.ViewModel { }
|
||||
MenuItem
|
||||
{
|
||||
text: model.name
|
||||
checkable: true;
|
||||
checked: model.active
|
||||
exclusiveGroup: viewMenuGroup;
|
||||
onTriggered: UM.Controller.setActiveView(model.id);
|
||||
}
|
||||
onObjectAdded: viewMenu.insertItem(index, object)
|
||||
onObjectRemoved: viewMenu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: viewMenuGroup; }
|
||||
}
|
||||
menu: ViewMenu { }
|
||||
}
|
||||
|
||||
Toolbar
|
||||
|
@ -650,6 +476,16 @@ UM.MainWindow
|
|||
}
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.manageMaterials
|
||||
onTriggered:
|
||||
{
|
||||
preferences.visible = true;
|
||||
preferences.setPage(3)
|
||||
}
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.configureSettingVisibility
|
||||
|
|
72
resources/qml/Menus/MaterialMenu.qml
Normal file
72
resources/qml/Menus/MaterialMenu.qml
Normal file
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Menu
|
||||
{
|
||||
id: menu
|
||||
title: "Material"
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: UM.InstanceContainersModel
|
||||
{
|
||||
filter:
|
||||
{
|
||||
var result = { "type": "material" }
|
||||
if(Cura.MachineManager.filterMaterialsByMachine)
|
||||
{
|
||||
result.definition = Cura.MachineManager.activeDefinitionId
|
||||
if(Cura.MachineManager.hasVariants)
|
||||
{
|
||||
result.variant = Cura.MachineManager.activeVariantId
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.definition = "fdmprinter"
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
MenuItem
|
||||
{
|
||||
text:
|
||||
{
|
||||
var result = model.name
|
||||
|
||||
if(model.metadata.brand != undefined && model.metadata.brand != "Generic")
|
||||
{
|
||||
result = model.metadata.brand + " " + result
|
||||
}
|
||||
|
||||
if(model.metadata.color_name != undefined && model.metadata.color_name != "Generic")
|
||||
{
|
||||
result = result + " (%1)".arg(model.metadata.color_name)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
checkable: true;
|
||||
checked: model.id == Cura.MachineManager.activeMaterialId;
|
||||
exclusiveGroup: group;
|
||||
onTriggered:
|
||||
{
|
||||
Cura.MachineManager.setActiveMaterial(model.id);
|
||||
}
|
||||
}
|
||||
onObjectAdded: menu.insertItem(index, object)
|
||||
onObjectRemoved: menu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: group }
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
MenuItem { action: Cura.Actions.manageMaterials }
|
||||
}
|
37
resources/qml/Menus/NozzleMenu.qml
Normal file
37
resources/qml/Menus/NozzleMenu.qml
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Menu
|
||||
{
|
||||
id: menu
|
||||
title: "Nozzle"
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: UM.InstanceContainersModel
|
||||
{
|
||||
filter:
|
||||
{
|
||||
"type": "variant",
|
||||
"definition": Cura.MachineManager.activeDefinitionId //Only show variants of this machine
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: model.id == Cura.MachineManager.activeVariantId;
|
||||
exclusiveGroup: group
|
||||
onTriggered: Cura.MachineManager.setActiveVariant(model.id)
|
||||
}
|
||||
onObjectAdded: menu.insertItem(index, object)
|
||||
onObjectRemoved: menu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: group }
|
||||
}
|
38
resources/qml/Menus/PrinterMenu.qml
Normal file
38
resources/qml/Menus/PrinterMenu.qml
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Menu
|
||||
{
|
||||
id: menu;
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: UM.ContainerStacksModel
|
||||
{
|
||||
filter: {"type": "machine"}
|
||||
}
|
||||
MenuItem
|
||||
{
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: Cura.MachineManager.activeMachineId == model.id
|
||||
exclusiveGroup: group;
|
||||
onTriggered: Cura.MachineManager.setActiveMachine(model.id);
|
||||
}
|
||||
onObjectAdded: menu.insertItem(index, object)
|
||||
onObjectRemoved: menu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: group; }
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
MenuItem { action: Cura.Actions.addMachine; }
|
||||
MenuItem { action: Cura.Actions.configureMachines; }
|
||||
}
|
86
resources/qml/Menus/ProfileMenu.qml
Normal file
86
resources/qml/Menus/ProfileMenu.qml
Normal file
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Menu
|
||||
{
|
||||
id: menu
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: UM.InstanceContainersModel { filter: menu.getFilter({ "read_only": true }); }
|
||||
|
||||
MenuItem
|
||||
{
|
||||
text: model.name
|
||||
checkable: true
|
||||
checked: Cura.MachineManager.activeQualityId == model.id
|
||||
exclusiveGroup: group
|
||||
onTriggered: Cura.MachineManager.setActiveQuality(model.id)
|
||||
}
|
||||
|
||||
onObjectAdded: menu.insertItem(index, object);
|
||||
onObjectRemoved: menu.removeItem(object);
|
||||
}
|
||||
|
||||
MenuSeparator { id: customSeparator }
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: UM.InstanceContainersModel
|
||||
{
|
||||
id: customProfilesModel;
|
||||
filter: menu.getFilter({ "read_only": false });
|
||||
onRowsInserted: customSeparator.visible = rowCount() > 1
|
||||
onRowsRemoved: customSeparator.visible = rowCount() > 1
|
||||
onModelReset: customSeparator.visible = rowCount() > 1
|
||||
}
|
||||
|
||||
MenuItem
|
||||
{
|
||||
text: model.name
|
||||
checkable: true
|
||||
checked: Cura.MachineManager.activeQualityId == model.id
|
||||
exclusiveGroup: group
|
||||
onTriggered: Cura.MachineManager.setActiveQuality(model.id)
|
||||
}
|
||||
|
||||
onObjectAdded: menu.insertItem(index, object);
|
||||
onObjectRemoved: menu.removeItem(object);
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: group; }
|
||||
|
||||
MenuSeparator { id: profileMenuSeparator }
|
||||
|
||||
MenuItem { action: Cura.Actions.addProfile }
|
||||
MenuItem { action: Cura.Actions.updateProfile }
|
||||
MenuItem { action: Cura.Actions.resetProfile }
|
||||
MenuSeparator { }
|
||||
MenuItem { action: Cura.Actions.manageProfiles }
|
||||
|
||||
function getFilter(initial_conditions)
|
||||
{
|
||||
var result = initial_conditions;
|
||||
result.type = "quality"
|
||||
|
||||
if(Cura.MachineManager.filterQualityByMachine)
|
||||
{
|
||||
result.definition = Cura.MachineManager.activeDefinitionId;
|
||||
if(Cura.MachineManager.hasMaterials)
|
||||
{
|
||||
result.material = Cura.MachineManager.activeMaterialId;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.definition = "fdmprinter"
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
37
resources/qml/Menus/RecentFilesMenu.qml
Normal file
37
resources/qml/Menus/RecentFilesMenu.qml
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Menu
|
||||
{
|
||||
id: menu
|
||||
title: catalog.i18nc("@title:menu menubar:file", "Open &Recent")
|
||||
iconName: "document-open-recent";
|
||||
|
||||
enabled: Printer.recentFiles.length > 0;
|
||||
|
||||
Instantiator
|
||||
{
|
||||
model: Printer.recentFiles
|
||||
MenuItem
|
||||
{
|
||||
text:
|
||||
{
|
||||
var path = modelData.toString()
|
||||
return (index + 1) + ". " + path.slice(path.lastIndexOf("/") + 1);
|
||||
}
|
||||
onTriggered: {
|
||||
UM.MeshFileHandler.readLocalFile(modelData);
|
||||
var meshName = backgroundItem.getMeshName(modelData.toString())
|
||||
backgroundItem.hasMesh(decodeURIComponent(meshName))
|
||||
}
|
||||
}
|
||||
onObjectAdded: menu.insertItem(index, object)
|
||||
onObjectRemoved: menu.removeItem(object)
|
||||
}
|
||||
}
|
29
resources/qml/Menus/ViewMenu.qml
Normal file
29
resources/qml/Menus/ViewMenu.qml
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Menu
|
||||
{
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel", "&View");
|
||||
id: menu
|
||||
Instantiator
|
||||
{
|
||||
model: UM.ViewModel { }
|
||||
MenuItem
|
||||
{
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: model.active;
|
||||
exclusiveGroup: group;
|
||||
onTriggered: UM.Controller.setActiveView(model.id);
|
||||
}
|
||||
onObjectAdded: menu.insertItem(index, object)
|
||||
onObjectRemoved: menu.removeItem(object)
|
||||
}
|
||||
ExclusiveGroup { id: group; }
|
||||
}
|
|
@ -246,7 +246,7 @@ UM.PreferencesPage
|
|||
UM.TooltipArea {
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip","Should objects be scaled up if they are extremely small?")
|
||||
text: catalog.i18nc("@info:tooltip","An object may appear extremely small if its unit is for example in meters rather than millimeters. Should these objects be scaled up?")
|
||||
|
||||
CheckBox
|
||||
{
|
||||
|
|
|
@ -27,14 +27,35 @@ UM.ManagementPage
|
|||
return -1;
|
||||
}
|
||||
|
||||
onAddObject: Printer.requestAddPrinter()
|
||||
onRemoveObject: confirmDialog.open();
|
||||
onRenameObject: renameDialog.open();
|
||||
onActivateObject: Cura.MachineManager.setActiveMachine(base.currentItem.id)
|
||||
|
||||
removeEnabled: base.currentItem != null && model.rowCount() > 1
|
||||
renameEnabled: base.currentItem != null
|
||||
activateEnabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMachineId
|
||||
buttons: [
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Activate");
|
||||
iconName: "list-activate";
|
||||
enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId
|
||||
onClicked: Cura.MachineManager.setActiveMachine(base.currentItem.id)
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Add");
|
||||
iconName: "list-add";
|
||||
onClicked: Printer.requestAddPrinter()
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Remove");
|
||||
iconName: "list-remove";
|
||||
enabled: base.currentItem != null && model.rowCount() > 1
|
||||
onClicked: confirmDialog.open();
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Rename");
|
||||
iconName: "edit-rename";
|
||||
enabled: base.currentItem != null
|
||||
onClicked: renameDialog.open();
|
||||
}
|
||||
]
|
||||
|
||||
Item
|
||||
{
|
||||
|
|
252
resources/qml/Preferences/MaterialView.qml
Normal file
252
resources/qml/Preferences/MaterialView.qml
Normal file
|
@ -0,0 +1,252 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Uranium is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Dialogs 1.2
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
TabView
|
||||
{
|
||||
id: base
|
||||
|
||||
property QtObject properties;
|
||||
|
||||
property bool editingEnabled: false;
|
||||
property string currency: UM.Preferences.getValue("general/currency") ? UM.Preferences.getValue("general/currency") : "€"
|
||||
property real firstColumnWidth: width * 0.45
|
||||
property real secondColumnWidth: width * 0.45
|
||||
property string containerId: ""
|
||||
|
||||
Tab
|
||||
{
|
||||
title: "Information"
|
||||
anchors
|
||||
{
|
||||
leftMargin: UM.Theme.getSize("default_margin").width
|
||||
topMargin: UM.Theme.getSize("default_margin").height
|
||||
bottomMargin: UM.Theme.getSize("default_margin").height
|
||||
rightMargin: 0
|
||||
}
|
||||
|
||||
ScrollView
|
||||
{
|
||||
anchors.fill: parent
|
||||
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
|
||||
|
||||
Flow
|
||||
{
|
||||
id: containerGrid
|
||||
|
||||
width: base.width;
|
||||
|
||||
property real rowHeight: textField.height;
|
||||
|
||||
Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") }
|
||||
ReadOnlyTextField
|
||||
{
|
||||
id: textField;
|
||||
width: base.secondColumnWidth;
|
||||
text: properties.supplier;
|
||||
readOnly: !base.editingEnabled;
|
||||
onEditingFinished: Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, "brand", text)
|
||||
}
|
||||
|
||||
Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") }
|
||||
ReadOnlyTextField
|
||||
{
|
||||
width: base.secondColumnWidth;
|
||||
text: properties.material_type;
|
||||
readOnly: !base.editingEnabled;
|
||||
onEditingFinished: Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, "material", text)
|
||||
}
|
||||
|
||||
Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") }
|
||||
|
||||
Row
|
||||
{
|
||||
width: base.secondColumnWidth;
|
||||
height: parent.rowHeight;
|
||||
spacing: UM.Theme.getSize("default_margin").width/2
|
||||
|
||||
Rectangle
|
||||
{
|
||||
id: colorSelector
|
||||
color: properties.color_code
|
||||
onColorChanged: Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, "color_code", color)
|
||||
|
||||
width: colorLabel.height * 0.75
|
||||
height: colorLabel.height * 0.75
|
||||
border.width: UM.Theme.getSize("default_lining").height
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
MouseArea { anchors.fill: parent; onClicked: colorDialog.open(); enabled: base.editingEnabled }
|
||||
}
|
||||
ReadOnlyTextField
|
||||
{
|
||||
id: colorLabel;
|
||||
text: properties.color_name;
|
||||
readOnly: !base.editingEnabled
|
||||
onEditingFinished: Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, "color_name", text)
|
||||
}
|
||||
|
||||
ColorDialog { id: colorDialog; color: properties.color_code; onAccepted: colorSelector.color = color }
|
||||
}
|
||||
|
||||
Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
|
||||
|
||||
Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: "<b>" + catalog.i18nc("@label", "Properties") + "</b>" }
|
||||
|
||||
Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Density") }
|
||||
ReadOnlySpinBox
|
||||
{
|
||||
width: base.secondColumnWidth;
|
||||
value: properties.density;
|
||||
decimals: 2
|
||||
suffix: "g/cm"
|
||||
stepSize: 0.01
|
||||
readOnly: !base.editingEnabled;
|
||||
|
||||
onEditingFinished: Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, "properties/density", value)
|
||||
}
|
||||
|
||||
Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Diameter") }
|
||||
ReadOnlySpinBox
|
||||
{
|
||||
width: base.secondColumnWidth;
|
||||
value: properties.diameter;
|
||||
decimals: 2
|
||||
suffix: "mm³"
|
||||
stepSize: 0.01
|
||||
readOnly: !base.editingEnabled;
|
||||
|
||||
onEditingFinished: Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, "properties/diameter", value)
|
||||
}
|
||||
|
||||
Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") }
|
||||
SpinBox
|
||||
{
|
||||
width: base.secondColumnWidth;
|
||||
value: properties.spool_cost;
|
||||
prefix: base.currency
|
||||
enabled: false
|
||||
}
|
||||
|
||||
Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") }
|
||||
SpinBox
|
||||
{
|
||||
width: base.secondColumnWidth;
|
||||
value: properties.spool_weight;
|
||||
suffix: "g";
|
||||
stepSize: 10
|
||||
enabled: false
|
||||
}
|
||||
|
||||
Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament length") }
|
||||
SpinBox
|
||||
{
|
||||
width: base.secondColumnWidth;
|
||||
value: parseFloat(properties.spool_length);
|
||||
suffix: "m";
|
||||
enabled: false
|
||||
}
|
||||
|
||||
Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Cost per Meter (Approx.)") }
|
||||
SpinBox
|
||||
{
|
||||
width: base.secondColumnWidth;
|
||||
value: parseFloat(properties.cost_per_meter);
|
||||
suffix: catalog.i18nc("@label", "%1/m".arg(base.currency));
|
||||
enabled: false
|
||||
}
|
||||
|
||||
Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
|
||||
|
||||
Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Description") }
|
||||
|
||||
ReadOnlyTextArea
|
||||
{
|
||||
text: properties.description;
|
||||
width: base.firstColumnWidth + base.secondColumnWidth
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
readOnly: !base.editingEnabled;
|
||||
|
||||
onEditingFinished: Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, "description", text)
|
||||
}
|
||||
|
||||
Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Adhesion Information") }
|
||||
|
||||
ReadOnlyTextArea
|
||||
{
|
||||
text: properties.adhesion_info;
|
||||
width: base.firstColumnWidth + base.secondColumnWidth
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
readOnly: !base.editingEnabled;
|
||||
|
||||
onEditingFinished: Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, "adhesion_info", text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tab
|
||||
{
|
||||
title: catalog.i18nc("@label", "Print settings")
|
||||
anchors
|
||||
{
|
||||
leftMargin: UM.Theme.getSize("default_margin").width
|
||||
topMargin: UM.Theme.getSize("default_margin").height
|
||||
bottomMargin: UM.Theme.getSize("default_margin").height
|
||||
rightMargin: 0
|
||||
}
|
||||
|
||||
ScrollView
|
||||
{
|
||||
anchors.fill: parent;
|
||||
|
||||
ListView
|
||||
{
|
||||
model: UM.SettingDefinitionsModel
|
||||
{
|
||||
containerId: Cura.MachineManager.activeDefinitionId
|
||||
visibilityHandler: Cura.MaterialSettingsVisibilityHandler { }
|
||||
expanded: ["*"]
|
||||
}
|
||||
|
||||
delegate: UM.TooltipArea
|
||||
{
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
text: model.description
|
||||
Label
|
||||
{
|
||||
id: label
|
||||
width: base.firstColumnWidth;
|
||||
height: spinBox.height
|
||||
text: model.label
|
||||
}
|
||||
ReadOnlySpinBox
|
||||
{
|
||||
id: spinBox
|
||||
anchors.left: label.right
|
||||
value: parseFloat(provider.properties.value);
|
||||
width: base.secondColumnWidth;
|
||||
readOnly: !base.editingEnabled
|
||||
suffix: model.unit
|
||||
maximumValue: 99999
|
||||
decimals: model.unit == "mm" ? 2 : 0
|
||||
|
||||
onEditingFinished: provider.setPropertyValue("value", value)
|
||||
}
|
||||
|
||||
UM.ContainerPropertyProvider { id: provider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,6 +33,8 @@ UM.ManagementPage
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
sectionProperty: "brand"
|
||||
}
|
||||
|
||||
activeId: Cura.MachineManager.activeMaterialId
|
||||
|
@ -45,14 +47,64 @@ UM.ManagementPage
|
|||
return -1;
|
||||
}
|
||||
|
||||
addEnabled: false
|
||||
removeEnabled: false
|
||||
renameEnabled: false
|
||||
|
||||
scrollviewCaption: " "
|
||||
scrollviewCaption: "Printer: %1, Nozzle: %2".arg(Cura.MachineManager.activeMachineName).arg(Cura.MachineManager.activeVariantName)
|
||||
detailsVisible: true
|
||||
|
||||
property string currency: UM.Preferences.getValue("general/currency")
|
||||
section.property: "section"
|
||||
section.delegate: Label { text: section }
|
||||
|
||||
buttons: [
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Activate");
|
||||
iconName: "list-activate";
|
||||
enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId
|
||||
onClicked: Cura.MachineManager.setActiveMaterial(base.currentItem.id)
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Duplicate");
|
||||
iconName: "list-add";
|
||||
enabled: base.currentItem != null
|
||||
onClicked:
|
||||
{
|
||||
var material_id = Cura.ContainerManager.duplicateContainer(base.currentItem.id)
|
||||
if(material_id == "")
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
if(Cura.MachineManager.filterQualityByMachine)
|
||||
{
|
||||
var quality_id = Cura.ContainerManager.duplicateContainer(Cura.MachineManager.activeQualityId)
|
||||
Cura.ContainerManager.setContainerMetaDataEntry(quality_id, "material", material_id)
|
||||
Cura.MachineManager.setActiveQuality(quality_id)
|
||||
}
|
||||
|
||||
Cura.MachineManager.setActiveMaterial(material_id)
|
||||
}
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Remove");
|
||||
iconName: "list-remove";
|
||||
enabled: base.currentItem != null && !base.currentItem.readOnly
|
||||
onClicked: confirmDialog.open()
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Import");
|
||||
iconName: "document-import";
|
||||
onClicked: importDialog.open();
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Export")
|
||||
iconName: "document-export"
|
||||
onClicked: exportDialog.open()
|
||||
enabled: currentItem != null
|
||||
}
|
||||
]
|
||||
|
||||
Item {
|
||||
UM.I18nCatalog { id: catalog; name: "cura"; }
|
||||
|
@ -60,126 +112,42 @@ UM.ManagementPage
|
|||
visible: base.currentItem != null
|
||||
anchors.fill: parent
|
||||
|
||||
Label { id: profileName; text: materialProperties.name; font: UM.Theme.getFont("large"); width: parent.width; }
|
||||
Item
|
||||
{
|
||||
id: profileName
|
||||
|
||||
TabView {
|
||||
id: scrollView
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: profileName.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width;
|
||||
height: childrenRect.height
|
||||
|
||||
Tab {
|
||||
title: "Information"
|
||||
anchors.margins: UM.Theme.getSize("default_margin").height
|
||||
Label { text: materialProperties.name; font: UM.Theme.getFont("large"); }
|
||||
Button
|
||||
{
|
||||
id: editButton
|
||||
anchors.right: parent.right;
|
||||
text: catalog.i18nc("@action:button", "Edit");
|
||||
iconName: "document-edit";
|
||||
|
||||
Flow {
|
||||
id: containerGrid
|
||||
enabled: base.currentItem != null && !base.currentItem.readOnly
|
||||
|
||||
width: scrollView.width;
|
||||
property real columnWidth: width / 2
|
||||
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "Profile Type") }
|
||||
Label { width: parent.columnWidth; text: materialProperties.profile_type }
|
||||
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "Supplier") }
|
||||
Label { width: parent.columnWidth; text: materialProperties.supplier }
|
||||
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "Material Type") }
|
||||
Label { width: parent.columnWidth; text: materialProperties.material_type }
|
||||
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "Color") }
|
||||
|
||||
Row {
|
||||
width: parent.columnWidth;
|
||||
spacing: UM.Theme.getSize("default_margin").width/2
|
||||
Rectangle {
|
||||
color: materialProperties.color_code
|
||||
width: colorLabel.height
|
||||
height: colorLabel.height
|
||||
border.width: UM.Theme.getSize("default_lining").height
|
||||
}
|
||||
Label { id: colorLabel; text: materialProperties.color_name }
|
||||
}
|
||||
|
||||
Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
|
||||
|
||||
Label { width: parent.width; text: "<b>" + catalog.i18nc("@label", "Properties") + "</b>" }
|
||||
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "Density") }
|
||||
Label { width: parent.columnWidth; text: materialProperties.density }
|
||||
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "Diameter") }
|
||||
Label { width: parent.columnWidth; text: materialProperties.diameter }
|
||||
|
||||
Label {
|
||||
text: catalog.i18nc("@label", "Filament cost")
|
||||
width: parent.columnWidth;
|
||||
height: spoolCostInput.height
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.columnWidth;
|
||||
Label {
|
||||
text: base.currency ? base.currency + " " : " "
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
TextField {
|
||||
id: spoolCostInput
|
||||
text: materialProperties.spool_cost
|
||||
}
|
||||
}
|
||||
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "Filament weight") }
|
||||
Label { width: parent.columnWidth; text: materialProperties.spool_weight + " " + "g" }
|
||||
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "Filament length") }
|
||||
Label { width: parent.columnWidth; text: materialProperties.spool_length + " " + "m" }
|
||||
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "Cost per meter") }
|
||||
Label { width: parent.columnWidth; text: catalog.i18nc("@label", "approx. %1 %2/m").arg(materialProperties.cost_per_meter).arg(base.currency); }
|
||||
|
||||
Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
|
||||
|
||||
Label {
|
||||
text: materialProperties.description ? "<b>" + catalog.i18nc("@label", "Information") + "</b><br>" + materialProperties.description : "";
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
Label {
|
||||
text: materialProperties.adhesion_info ? "<b>" + catalog.i18nc("@label", "Adhesion") + "</b><br>" + materialProperties.adhesion_info : "";
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
checkable: true
|
||||
}
|
||||
Tab {
|
||||
title: catalog.i18nc("@label", "Print settings")
|
||||
anchors.margins: UM.Theme.getSize("default_margin").height
|
||||
}
|
||||
|
||||
Grid {
|
||||
columns: 2
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
|
||||
Column {
|
||||
Repeater {
|
||||
model: base.currentItem ? base.currentItem.settings : null
|
||||
Label {
|
||||
text: modelData.name.toString();
|
||||
elide: Text.ElideMiddle;
|
||||
}
|
||||
}
|
||||
}
|
||||
Column {
|
||||
Repeater {
|
||||
model: base.currentItem ? base.currentItem.settings : null
|
||||
Label { text: modelData.value.toString() + " " + modelData.unit.toString(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
MaterialView
|
||||
{
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: profileName.bottom
|
||||
topMargin: UM.Theme.getSize("default_margin").height
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
editingEnabled: base.currentItem != null && !base.currentItem.readOnly && editButton.checked;
|
||||
|
||||
properties: materialProperties
|
||||
containerId: base.currentItem.id
|
||||
}
|
||||
|
||||
QtObject
|
||||
|
@ -194,17 +162,100 @@ UM.ManagementPage
|
|||
property string color_name: "Yellow";
|
||||
property color color_code: "yellow";
|
||||
|
||||
property string density: "Unknown";
|
||||
property string diameter: "Unknown";
|
||||
property real density: 0.0;
|
||||
property real diameter: 0.0;
|
||||
|
||||
property string spool_cost: "Unknown";
|
||||
property string spool_weight: "Unknown";
|
||||
property string spool_length: "Unknown";
|
||||
property string cost_per_meter: "Unknown";
|
||||
property real spool_cost: 0.0;
|
||||
property real spool_weight: 0.0;
|
||||
property real spool_length: 0.0;
|
||||
property real cost_per_meter: 0.0;
|
||||
|
||||
property string description: "";
|
||||
property string adhesion_info: "";
|
||||
}
|
||||
|
||||
UM.ConfirmRemoveDialog
|
||||
{
|
||||
id: confirmDialog
|
||||
object: base.currentItem != null ? base.currentItem.name : ""
|
||||
onYes:
|
||||
{
|
||||
var containers = Cura.ContainerManager.findInstanceContainers({"GUID": base.currentItem.metadata.GUID})
|
||||
for(var i in containers)
|
||||
{
|
||||
Cura.ContainerManager.removeContainer(containers[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileDialog
|
||||
{
|
||||
id: importDialog;
|
||||
title: catalog.i18nc("@title:window", "Import Material");
|
||||
selectExisting: true;
|
||||
nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
|
||||
folder: CuraApplication.getDefaultPath()
|
||||
onAccepted:
|
||||
{
|
||||
var result = Cura.ContainerManager.importContainer(fileUrl)
|
||||
|
||||
messageDialog.title = catalog.i18nc("@title:window", "Import Material")
|
||||
messageDialog.text = catalog.i18nc("@info:status", "Could not import material <filename>%1</filename>: <message>%2</message>").arg(fileUrl).arg(result.message)
|
||||
if(result.status == "success")
|
||||
{
|
||||
messageDialog.icon = StandardIcon.Information
|
||||
messageDialog.text = catalog.i18nc("@info:status", "Successfully imported material <filename>%1</filename>").arg(fileUrl)
|
||||
}
|
||||
else if(result.status == "duplicate")
|
||||
{
|
||||
messageDialog.icon = StandardIcon.Warning
|
||||
}
|
||||
else
|
||||
{
|
||||
messageDialog.icon = StandardIcon.Critical
|
||||
}
|
||||
messageDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
FileDialog
|
||||
{
|
||||
id: exportDialog;
|
||||
title: catalog.i18nc("@title:window", "Export Material");
|
||||
selectExisting: false;
|
||||
nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
|
||||
folder: CuraApplication.getDefaultPath()
|
||||
onAccepted:
|
||||
{
|
||||
if(base.currentItem.metadata.base_file)
|
||||
{
|
||||
var result = Cura.ContainerManager.exportContainer(base.currentItem.metadata.base_file, selectedNameFilter, fileUrl)
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = Cura.ContainerManager.exportContainer(base.currentItem.id, selectedNameFilter, fileUrl)
|
||||
}
|
||||
|
||||
messageDialog.title = catalog.i18nc("@title:window", "Export Material")
|
||||
if(result.status == "error")
|
||||
{
|
||||
messageDialog.icon = StandardIcon.Critical
|
||||
messageDialog.text = catalog.i18nc("@info:status", "Failed to export material to <filename>%1</filename>: <message>%2</message>").arg(fileUrl).arg(result.message)
|
||||
messageDialog.open()
|
||||
}
|
||||
else if(result.status == "success")
|
||||
{
|
||||
messageDialog.icon = StandardIcon.Information
|
||||
messageDialog.text = catalog.i18nc("@info:status", "Successfully exported material to <filename>%1</filename>").arg(fileUrl)
|
||||
messageDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog
|
||||
{
|
||||
id: messageDialog
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentItemChanged:
|
||||
|
@ -228,13 +279,13 @@ UM.ManagementPage
|
|||
|
||||
if(currentItem.metadata.properties != undefined && currentItem.metadata.properties != null)
|
||||
{
|
||||
materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : "Unknown";
|
||||
materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : "Unknown";
|
||||
materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : 0.0;
|
||||
materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
materialProperties.density = "Unknown";
|
||||
materialProperties.diameter = "Unknown";
|
||||
materialProperties.density = 0.0;
|
||||
materialProperties.diameter = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ UM.ManagementPage
|
|||
id: base;
|
||||
|
||||
title: catalog.i18nc("@title:tab", "Profiles");
|
||||
addText: base.currentItem && (base.currentItem.id == Cura.MachineManager.activeQualityId) ? catalog.i18nc("@label", "Create") : catalog.i18nc("@label", "Duplicate")
|
||||
|
||||
model: UM.InstanceContainersModel
|
||||
{
|
||||
|
@ -60,27 +59,62 @@ UM.ManagementPage
|
|||
return -1;
|
||||
}
|
||||
|
||||
onActivateObject: Cura.MachineManager.setActiveQuality(currentItem.id)
|
||||
onAddObject: {
|
||||
var selectedContainer;
|
||||
if (objectList.currentItem.id == Cura.MachineManager.activeQualityId) {
|
||||
selectedContainer = Cura.MachineManager.newQualityContainerFromQualityAndUser();
|
||||
} else {
|
||||
selectedContainer = Cura.MachineManager.duplicateContainer(base.currentItem.id);
|
||||
buttons: [
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Activate");
|
||||
iconName: "list-activate";
|
||||
enabled: base.currentItem != null ? base.currentItem.id != Cura.MachineManager.activeQualityId : false;
|
||||
onClicked: Cura.MachineManager.setActiveQuality(base.currentItem.id)
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: base.currentItem && (base.currentItem.id == Cura.MachineManager.activeQualityId) ? catalog.i18nc("@label", "Create") : catalog.i18nc("@label", "Duplicate")
|
||||
iconName: "list-add";
|
||||
|
||||
onClicked:
|
||||
{
|
||||
var selectedContainer;
|
||||
if (objectList.currentItem.id == Cura.MachineManager.activeQualityId) {
|
||||
selectedContainer = Cura.MachineManager.newQualityContainerFromQualityAndUser();
|
||||
} else {
|
||||
selectedContainer = Cura.MachineManager.duplicateContainer(base.currentItem.id);
|
||||
}
|
||||
base.selectContainer(selectedContainer);
|
||||
|
||||
renameDialog.removeWhenRejected = true;
|
||||
renameDialog.open();
|
||||
renameDialog.selectText();
|
||||
}
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Remove");
|
||||
iconName: "list-remove";
|
||||
enabled: base.currentItem != null ? !base.currentItem.readOnly : false;
|
||||
onClicked: confirmDialog.open();
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Rename");
|
||||
iconName: "edit-rename";
|
||||
enabled: base.currentItem != null ? !base.currentItem.readOnly : false;
|
||||
onClicked: { renameDialog.removeWhenRejected = false; renameDialog.open(); renameDialog.selectText(); }
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Import");
|
||||
iconName: "document-import";
|
||||
onClicked: importDialog.open();
|
||||
},
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Export")
|
||||
iconName: "document-export"
|
||||
onClicked: exportDialog.open()
|
||||
enabled: currentItem != null
|
||||
}
|
||||
base.selectContainer(selectedContainer);
|
||||
|
||||
renameDialog.removeWhenRejected = true;
|
||||
renameDialog.open();
|
||||
renameDialog.selectText();
|
||||
}
|
||||
onRemoveObject: confirmDialog.open();
|
||||
onRenameObject: { renameDialog.removeWhenRejected = false; renameDialog.open(); renameDialog.selectText(); }
|
||||
|
||||
activateEnabled: currentItem != null ? currentItem.id != Cura.MachineManager.activeQualityId : false;
|
||||
addEnabled: currentItem != null;
|
||||
removeEnabled: currentItem != null ? !currentItem.readOnly : false;
|
||||
renameEnabled: currentItem != null ? !currentItem.readOnly : false;
|
||||
]
|
||||
|
||||
scrollviewCaption: catalog.i18nc("@label %1 is printer name","Printer: %1").arg(Cura.MachineManager.activeMachineName)
|
||||
|
||||
|
@ -211,24 +245,6 @@ UM.ManagementPage
|
|||
}
|
||||
}
|
||||
|
||||
buttons: Row {
|
||||
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Import");
|
||||
iconName: "document-import";
|
||||
onClicked: importDialog.open();
|
||||
}
|
||||
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Export")
|
||||
iconName: "document-export"
|
||||
onClicked: exportDialog.open()
|
||||
enabled: currentItem != null
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
UM.I18nCatalog { id: catalog; name: "uranium"; }
|
||||
|
|
52
resources/qml/Preferences/ReadOnlySpinBox.qml
Normal file
52
resources/qml/Preferences/ReadOnlySpinBox.qml
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Uranium is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Dialogs 1.2
|
||||
|
||||
Item
|
||||
{
|
||||
id: base
|
||||
|
||||
property alias value: spinBox.value
|
||||
property alias minimumValue: spinBox.minimumValue
|
||||
property alias maximumValue: spinBox.maximumValue
|
||||
property alias stepSize: spinBox.stepSize
|
||||
property alias prefix: spinBox.prefix
|
||||
property alias suffix: spinBox.suffix
|
||||
property alias decimals: spinBox.decimals
|
||||
|
||||
signal editingFinished();
|
||||
|
||||
property bool readOnly: false
|
||||
|
||||
width: spinBox.width
|
||||
height: spinBox.height
|
||||
|
||||
SpinBox
|
||||
{
|
||||
id: spinBox
|
||||
|
||||
enabled: !base.readOnly
|
||||
opacity: base.readOnly ? 0.5 : 1.0
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
onEditingFinished: base.editingFinished()
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
visible: base.readOnly
|
||||
text: base.prefix + base.value.toFixed(spinBox.decimals) + base.suffix
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: spinBox.__style ? spinBox.__style.padding.left : 0
|
||||
|
||||
color: palette.buttonText
|
||||
}
|
||||
|
||||
SystemPalette { id: palette }
|
||||
}
|
46
resources/qml/Preferences/ReadOnlyTextArea.qml
Normal file
46
resources/qml/Preferences/ReadOnlyTextArea.qml
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Uranium is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Dialogs 1.2
|
||||
|
||||
Item
|
||||
{
|
||||
id: base
|
||||
|
||||
property alias text: textArea.text
|
||||
property alias wrapMode: textArea.wrapMode
|
||||
|
||||
signal editingFinished();
|
||||
|
||||
property bool readOnly: false
|
||||
|
||||
width: textArea.width
|
||||
height: textArea.height
|
||||
|
||||
TextArea
|
||||
{
|
||||
id: textArea
|
||||
|
||||
enabled: !base.readOnly
|
||||
opacity: base.readOnly ? 0.5 : 1.0
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
onEditingFinished: base.editingFinished()
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
visible: base.readOnly
|
||||
text: textArea.text
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: textArea.__style ? textArea.__style.textMargin : 4
|
||||
|
||||
color: palette.buttonText
|
||||
}
|
||||
|
||||
SystemPalette { id: palette }
|
||||
}
|
46
resources/qml/Preferences/ReadOnlyTextField.qml
Normal file
46
resources/qml/Preferences/ReadOnlyTextField.qml
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Uranium is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Dialogs 1.2
|
||||
|
||||
Item
|
||||
{
|
||||
id: base
|
||||
|
||||
property alias text: textField.text
|
||||
|
||||
signal editingFinished();
|
||||
|
||||
property bool readOnly: false
|
||||
|
||||
width: textField.width
|
||||
height: textField.height
|
||||
|
||||
TextField
|
||||
{
|
||||
id: textField
|
||||
|
||||
enabled: !base.readOnly
|
||||
opacity: base.readOnly ? 0.5 : 1.0
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
onEditingFinished: base.editingFinished()
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
visible: base.readOnly
|
||||
text: textField.text
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: textField.__panel ? textField.__panel.leftMargin : 0
|
||||
|
||||
color: palette.buttonText
|
||||
}
|
||||
|
||||
SystemPalette { id: palette }
|
||||
}
|
118
resources/qml/PrintMonitor.qml
Normal file
118
resources/qml/PrintMonitor.qml
Normal file
|
@ -0,0 +1,118 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Column
|
||||
{
|
||||
id: printMonitor
|
||||
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorSection
|
||||
property string label: catalog.i18nc("@label", "Temperatures")
|
||||
}
|
||||
Repeater
|
||||
{
|
||||
model: machineExtruderCount.properties.value
|
||||
delegate: Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: machineExtruderCount.properties.value > 1 ? catalog.i18nc("@label", "Hotend Temperature %1").arg(index + 1) : catalog.i18nc("@label", "Hotend Temperature")
|
||||
property string value: printerConnected ? Math.round(Cura.MachineManager.printerOutputDevices[0].hotendTemperatures[index]) + "°C" : ""
|
||||
}
|
||||
}
|
||||
Repeater
|
||||
{
|
||||
model: machineHeatedBed.properties.value == "True" ? 1 : 0
|
||||
delegate: Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Bed Temperature")
|
||||
property string value: printerConnected ? Math.round(Cura.MachineManager.printerOutputDevices[0].bedTemperature) + "°C" : ""
|
||||
}
|
||||
}
|
||||
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorSection
|
||||
property string label: catalog.i18nc("@label", "Active print")
|
||||
}
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Job Name")
|
||||
property string value: printerConnected ? Cura.MachineManager.printerOutputDevices[0].jobName : ""
|
||||
}
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Printing Time")
|
||||
property string value: printerConnected ? getPrettyTime(Cura.MachineManager.printerOutputDevices[0].timeTotal) : ""
|
||||
}
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Estimated time left")
|
||||
property string value: printerConnected ? getPrettyTime(Cura.MachineManager.printerOutputDevices[0].timeTotal - Cura.MachineManager.printerOutputDevices[0].timeElapsed) : ""
|
||||
}
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Current Layer")
|
||||
property string value: printerConnected ? "0" : ""
|
||||
}
|
||||
|
||||
Component
|
||||
{
|
||||
id: monitorItem
|
||||
|
||||
Row
|
||||
{
|
||||
height: UM.Theme.getSize("setting_control").height
|
||||
Label
|
||||
{
|
||||
text: label
|
||||
color: printerConnected ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
width: base.width * 0.4
|
||||
elide: Text.ElideRight
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: value
|
||||
color: printerConnected ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
Component
|
||||
{
|
||||
id: monitorSection
|
||||
|
||||
Rectangle
|
||||
{
|
||||
color: UM.Theme.getColor("setting_category")
|
||||
width: base.width - 2 * UM.Theme.getSize("default_margin").width
|
||||
height: UM.Theme.getSize("section").height
|
||||
|
||||
Label
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
text: label
|
||||
font: UM.Theme.getFont("setting_category")
|
||||
color: UM.Theme.getColor("setting_category_text")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -285,122 +285,16 @@ Rectangle
|
|||
}
|
||||
}
|
||||
|
||||
// Item that shows the print monitor properties
|
||||
Column
|
||||
Loader
|
||||
{
|
||||
id: printMonitor
|
||||
|
||||
anchors.bottom: footerSeparator.top
|
||||
anchors.top: monitorLabel.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
anchors.left: base.left
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
anchors.right: base.right
|
||||
visible: monitoringPrint
|
||||
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorSection
|
||||
property string label: catalog.i18nc("@label", "Temperatures")
|
||||
}
|
||||
Repeater
|
||||
{
|
||||
model: machineExtruderCount.properties.value
|
||||
delegate: Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: machineExtruderCount.properties.value > 1 ? catalog.i18nc("@label", "Hotend Temperature %1").arg(index + 1) : catalog.i18nc("@label", "Hotend Temperature")
|
||||
property string value: printerConnected ? Math.round(Cura.MachineManager.printerOutputDevices[0].hotendTemperatures[index]) + "°C" : ""
|
||||
}
|
||||
}
|
||||
Repeater
|
||||
{
|
||||
model: machineHeatedBed.properties.value == "True" ? 1 : 0
|
||||
delegate: Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Bed Temperature")
|
||||
property string value: printerConnected ? Math.round(Cura.MachineManager.printerOutputDevices[0].bedTemperature) + "°C" : ""
|
||||
}
|
||||
}
|
||||
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorSection
|
||||
property string label: catalog.i18nc("@label", "Active print")
|
||||
}
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Job Name")
|
||||
property string value: printerConnected ? Cura.MachineManager.printerOutputDevices[0].jobName : ""
|
||||
}
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Printing Time")
|
||||
property string value: printerConnected ? getPrettyTime(Cura.MachineManager.printerOutputDevices[0].timeTotal) : ""
|
||||
}
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Estimated time left")
|
||||
property string value: printerConnected ? getPrettyTime(Cura.MachineManager.printerOutputDevices[0].timeTotal - Cura.MachineManager.printerOutputDevices[0].timeElapsed) : ""
|
||||
}
|
||||
Loader
|
||||
{
|
||||
sourceComponent: monitorItem
|
||||
property string label: catalog.i18nc("@label", "Current Layer")
|
||||
property string value: printerConnected ? "0" : ""
|
||||
}
|
||||
|
||||
Component
|
||||
{
|
||||
id: monitorItem
|
||||
|
||||
Row
|
||||
{
|
||||
height: UM.Theme.getSize("setting_control").height
|
||||
Label
|
||||
{
|
||||
text: label
|
||||
color: printerConnected ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
width: base.width * 0.4
|
||||
elide: Text.ElideRight
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: value
|
||||
color: printerConnected ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
|
||||
font: UM.Theme.getFont("default")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
Component
|
||||
{
|
||||
id: monitorSection
|
||||
|
||||
Rectangle
|
||||
{
|
||||
color: UM.Theme.getColor("setting_category")
|
||||
width: base.width - 2 * UM.Theme.getSize("default_margin").width
|
||||
height: UM.Theme.getSize("section").height
|
||||
|
||||
Label
|
||||
{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
text: label
|
||||
font: UM.Theme.getFont("setting_category")
|
||||
color: UM.Theme.getColor("setting_category_text")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
source: monitoringPrint ? "PrintMonitor.qml": "SidebarContents.qml"
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
|
|
43
resources/qml/SidebarContents.qml
Normal file
43
resources/qml/SidebarContents.qml
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
StackView
|
||||
{
|
||||
id: sidebarContents
|
||||
|
||||
delegate: StackViewDelegate
|
||||
{
|
||||
function transitionFinished(properties)
|
||||
{
|
||||
properties.exitItem.opacity = 1
|
||||
}
|
||||
|
||||
pushTransition: StackViewTransition
|
||||
{
|
||||
PropertyAnimation
|
||||
{
|
||||
target: enterItem
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
PropertyAnimation
|
||||
{
|
||||
target: exitItem
|
||||
property: "opacity"
|
||||
from: 1
|
||||
to: 0
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ import QtQuick.Controls.Styles 1.1
|
|||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
import "Menus"
|
||||
|
||||
Column
|
||||
{
|
||||
id: base;
|
||||
|
@ -56,34 +58,7 @@ Column
|
|||
|
||||
width: parent.width * 0.55 + UM.Theme.getSize("default_margin").width
|
||||
|
||||
menu: Menu
|
||||
{
|
||||
id: machineSelectionMenu
|
||||
Instantiator
|
||||
{
|
||||
model: UM.ContainerStacksModel
|
||||
{
|
||||
filter: {"type": "machine"}
|
||||
}
|
||||
MenuItem
|
||||
{
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: Cura.MachineManager.activeMachineId == model.id
|
||||
exclusiveGroup: machineSelectionMenuGroup;
|
||||
onTriggered: Cura.MachineManager.setActiveMachine(model.id);
|
||||
}
|
||||
onObjectAdded: machineSelectionMenu.insertItem(index, object)
|
||||
onObjectRemoved: machineSelectionMenu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: machineSelectionMenuGroup; }
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
MenuItem { action: Cura.Actions.addMachine; }
|
||||
MenuItem { action: Cura.Actions.configureMachines; }
|
||||
}
|
||||
menu: PrinterMenu { }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,37 +211,7 @@ Column
|
|||
anchors.left: parent.left
|
||||
style: UM.Theme.styles.sidebar_header_button
|
||||
|
||||
menu: Menu
|
||||
{
|
||||
id: variantsSelectionMenu
|
||||
Instantiator
|
||||
{
|
||||
id: variantSelectionInstantiator
|
||||
model: UM.InstanceContainersModel
|
||||
{
|
||||
filter:
|
||||
{
|
||||
"type": "variant",
|
||||
"definition": Cura.MachineManager.activeDefinitionId //Only show variants of this machine
|
||||
}
|
||||
}
|
||||
MenuItem
|
||||
{
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: model.id == Cura.MachineManager.activeVariantId;
|
||||
exclusiveGroup: variantSelectionMenuGroup;
|
||||
onTriggered:
|
||||
{
|
||||
Cura.MachineManager.setActiveVariant(model.id);
|
||||
}
|
||||
}
|
||||
onObjectAdded: variantsSelectionMenu.insertItem(index, object)
|
||||
onObjectRemoved: variantsSelectionMenu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: variantSelectionMenuGroup; }
|
||||
}
|
||||
menu: NozzleMenu { }
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
|
@ -281,49 +226,7 @@ Column
|
|||
anchors.right: parent.right
|
||||
style: UM.Theme.styles.sidebar_header_button
|
||||
|
||||
menu: Menu
|
||||
{
|
||||
id: materialSelectionMenu
|
||||
Instantiator
|
||||
{
|
||||
id: materialSelectionInstantiator
|
||||
model: UM.InstanceContainersModel
|
||||
{
|
||||
filter:
|
||||
{
|
||||
var result = { "type": "material" }
|
||||
if(Cura.MachineManager.filterMaterialsByMachine)
|
||||
{
|
||||
result.definition = Cura.MachineManager.activeDefinitionId
|
||||
if(Cura.MachineManager.hasVariants)
|
||||
{
|
||||
result.variant = Cura.MachineManager.activeVariantId
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.definition = "fdmprinter"
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
MenuItem
|
||||
{
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: model.id == Cura.MachineManager.activeMaterialId;
|
||||
exclusiveGroup: materialSelectionMenuGroup;
|
||||
onTriggered:
|
||||
{
|
||||
Cura.MachineManager.setActiveMaterial(model.id);
|
||||
}
|
||||
}
|
||||
onObjectAdded: materialSelectionMenu.insertItem(index, object)
|
||||
onObjectRemoved: materialSelectionMenu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: materialSelectionMenuGroup; }
|
||||
}
|
||||
menu: MaterialMenu { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -360,88 +263,7 @@ Column
|
|||
tooltip: Cura.MachineManager.activeQualityName
|
||||
style: UM.Theme.styles.sidebar_header_button
|
||||
|
||||
menu: Menu
|
||||
{
|
||||
id: profileSelectionMenu
|
||||
Instantiator
|
||||
{
|
||||
id: profileSelectionInstantiator
|
||||
model: UM.InstanceContainersModel
|
||||
{
|
||||
filter:
|
||||
{
|
||||
var result = { "type": "quality" };
|
||||
if(Cura.MachineManager.filterQualityByMachine)
|
||||
{
|
||||
result.definition = Cura.MachineManager.activeDefinitionId;
|
||||
if(Cura.MachineManager.hasMaterials)
|
||||
{
|
||||
result.material = Cura.MachineManager.activeMaterialId;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.definition = "fdmprinter"
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
property int separatorIndex: -1
|
||||
|
||||
Loader {
|
||||
property QtObject model_data: model
|
||||
property int model_index: index
|
||||
sourceComponent: menuItemDelegate
|
||||
}
|
||||
onObjectAdded:
|
||||
{
|
||||
//Insert a separator between readonly and custom profiles
|
||||
if(separatorIndex < 0 && index > 0)
|
||||
{
|
||||
if(model.getItem(index-1).readOnly != model.getItem(index).readOnly)
|
||||
{
|
||||
profileSelectionMenu.insertSeparator(index);
|
||||
separatorIndex = index;
|
||||
}
|
||||
}
|
||||
//Because of the separator, custom profiles move one index lower
|
||||
profileSelectionMenu.insertItem((model.getItem(index).readOnly) ? index : index + 1, object.item);
|
||||
}
|
||||
onObjectRemoved:
|
||||
{
|
||||
//When adding a profile, the menu is rebuilt by removing all items.
|
||||
//If a separator was added, we need to remove that too.
|
||||
if(separatorIndex >= 0)
|
||||
{
|
||||
profileSelectionMenu.removeItem(profileSelectionMenu.items[separatorIndex])
|
||||
separatorIndex = -1;
|
||||
}
|
||||
profileSelectionMenu.removeItem(object.item);
|
||||
}
|
||||
}
|
||||
ExclusiveGroup { id: profileSelectionMenuGroup; }
|
||||
|
||||
Component
|
||||
{
|
||||
id: menuItemDelegate
|
||||
MenuItem
|
||||
{
|
||||
id: item
|
||||
text: model_data ? model_data.name : ""
|
||||
checkable: true
|
||||
checked: model_data != null ? Cura.MachineManager.activeQualityId == model_data.id : false
|
||||
exclusiveGroup: profileSelectionMenuGroup;
|
||||
onTriggered: Cura.MachineManager.setActiveQuality(model_data.id)
|
||||
}
|
||||
}
|
||||
|
||||
MenuSeparator { }
|
||||
MenuItem { action: Cura.Actions.addProfile }
|
||||
MenuItem { action: Cura.Actions.updateProfile }
|
||||
MenuItem { action: Cura.Actions.resetProfile }
|
||||
MenuSeparator { }
|
||||
MenuItem { action: Cura.Actions.manageProfiles }
|
||||
}
|
||||
menu: ProfileMenu { }
|
||||
|
||||
UM.SimpleButton
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue