This commit is contained in:
fieldOfView 2016-06-02 16:38:41 +02:00
commit 184247ced6
17 changed files with 312 additions and 265 deletions

View File

@ -101,7 +101,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
if key == "print_sequence" and property_name == "value":
self._onChanged()
def _onChanged(self):
def _onChanged(self, *args):
if self._convex_hull_job:
self._convex_hull_job.cancel()
self.setConvexHull(None)

View File

@ -18,6 +18,7 @@ from UM.JobQueue import JobQueue
from UM.SaveFile import SaveFile
from UM.Scene.Selection import Selection
from UM.Scene.GroupDecorator import GroupDecorator
import UM.Settings.Validator
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
@ -30,7 +31,7 @@ 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
@ -89,6 +90,7 @@ class CuraApplication(QtApplication):
# Need to do this before ContainerRegistry tries to load the machines
SettingDefinition.addSupportedProperty("global_only", DefinitionPropertyType.Function, default = False)
SettingDefinition.addSettingType("extruder", int, str, UM.Settings.Validator)
super().__init__(name = "cura", version = CuraVersion)
@ -327,8 +329,6 @@ class CuraApplication(QtApplication):
qmlRegisterSingletonType(MachineManagerModel.MachineManagerModel, "Cura", 1, 0, "MachineManager",
MachineManagerModel.createMachineManagerModel)
self._extruder_manager = ExtruderManager.ExtruderManager()
self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles))
self.initializeEngine()
@ -368,6 +368,8 @@ class CuraApplication(QtApplication):
qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
qmlRegisterType(ExtrudersModel.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
qmlRegisterSingletonType(QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")), "Cura", 1, 0, "Actions")
for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles):

View File

@ -25,8 +25,8 @@ class Extruder:
self._nozzles += container_registry.findInstanceContainers(type = "nozzle", definitions = self._definition.getId())
#Create a container stack for this extruder.
name = self._uniqueName(self._definition.getId())
self._container_stack = UM.Settings.ContainerStack(name)
self._name = self._uniqueName(self._definition.getId())
self._container_stack = UM.Settings.ContainerStack(self._name)
self._container_stack.addMetaDataEntry("type", "extruder_train")
self._container_stack.addContainer(self._definition)
@ -73,15 +73,38 @@ class Extruder:
self._container_stack.addContainer(self._quality)
#Add an empty user profile.
self._user_profile = UM.Settings.InstanceContainer(name + "_current_settings")
self._user_profile = UM.Settings.InstanceContainer(self._name + "_current_settings")
self._user_profile.addMetaDataEntry("type", "user")
self._container_stack.addContainer(self._user_profile)
self._container_stack.setNextStack(UM.Application.getInstance().getGlobalContainerStack())
nozzle_changed = UM.Signal.Signal()
material_changed = UM.Signal.Signal()
quality_changed = UM.Signal.Signal()
definition_changed = UM.Signal()
material_changed = UM.Signal()
name_changed = UM.Signal()
nozzle_changed = UM.Signal()
quality_changed = UM.Signal()
## Gets the definition container of this extruder.
#
# \return The definition container of this extruder.
@property
def definition(self):
return self._definition
## Changes the definition container of this extruder.
#
# \param value The new definition for this extruder.
@definition.setter
def definition(self, value):
try:
position = self._container_stack.index(self._definition)
except ValueError: #Definition is not in the list. Big trouble!
UM.Logger.log("e", "I've lost my old extruder definition, so I can't find where to insert the new definition.")
return
self._container_stack.replaceContainer(position, value)
self._definition = value
self.definition_changed.emit()
## Gets the currently active material on this extruder.
#
@ -104,6 +127,22 @@ class Extruder:
self._material = value
self.material_changed.emit()
## Gets the name of this extruder.
#
# \return The name of this extruder.
@property
def name(self):
return self._name
## Changes the name of this extruder.
#
# \param value The new name for this extruder.
@name.setter
def name(self, value):
self._name = value
self._container_stack.setName(value) #Also update in container stack, being defensive.
self.name_changed.emit()
## Gets the currently active nozzle on this extruder.
#
# \return The currently active nozzle on this extruder.

View File

@ -1,13 +1,11 @@
# Copyright (c) 2016 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
import re
from cura.Extruder import Extruder #The individual extruders managed by this manager.
from UM.Application import Application #To get the global container stack to find the current machine.
from UM.Logger import Logger
from UM.Settings.ContainerStack import ContainerStack #To create container stacks for each extruder.
from UM.Settings.ContainerRegistry import ContainerRegistry #Finding containers by ID.
import UM.Application #To get the global container stack to find the current machine.
import UM.Logger
import UM.Settings.ContainerRegistry #Finding containers by ID.
import UM.Signal #To notify other components of changes in the extruders.
## Class that handles the current extruder stack.
@ -16,19 +14,42 @@ from UM.Settings.ContainerRegistry import ContainerRegistry #Finding containers
# and makes sure that whenever the machine is swapped, this list is kept up to
# date. It also contains and updates the setting stacks for the extruders.
class ExtruderManager:
## The singleton instance of this manager.
__instance = None
## Signal to notify other components when the list of extruders changes.
extrudersChanged = UM.Signal()
## Registers listeners and such to listen to changes to the extruders.
def __init__(self):
self._extruders = [] #Extruders for the current machine.
self._global_container_stack = None
self._next_item = 0 #For when you use this class as iterator.
Application.getInstance().globalContainerStackChanged.connect(self._reconnectExtruderReload) #When the current machine changes, we need to reload all extruders belonging to the new machine.
UM.Application.getInstance().globalContainerStackChanged.connect(self._reconnectExtruderReload) #When the current machine changes, we need to reload all extruders belonging to the new machine.
## Gets an instance of this extruder manager.
#
# If an instance was already created, the old instance is returned. This
# implements the singleton pattern.
@classmethod
def getInstance(cls):
if not cls.__instance:
cls.__instance = ExtruderManager()
return cls.__instance
## Creates an iterator over the extruders in this manager.
#
# \return An iterator over the extruders in this manager.
def __iter__(self):
return iter(self._extruders)
## When the global container stack changes, this reconnects to the new
# signal for containers changing.
def _reconnectExtruderReload(self):
if self._global_container_stack:
self._global_container_stack.containersChanged.disconnect(self._reloadExtruders) #Disconnect from the old global container stack.
self._global_container_stack = Application.getInstance().getGlobalContainerStack()
self._global_container_stack = UM.Application.getInstance().getGlobalContainerStack()
self._global_container_stack.containersChanged.connect(self._reloadExtruders) #When the current machine changes, we need to reload all extruders belonging to the new machine.
## (Re)loads all extruders of the currently active machine.
@ -36,18 +57,20 @@ class ExtruderManager:
# This looks at the global container stack to see which machine is active.
# Then it loads the extruders for that machine and loads each of them in a
# list of extruders.
def _reloadExtruders(self):
def _reloadExtruders(self, *args):
self._extruders = []
if not self._global_container_stack: #No machine has been added yet.
self.extrudersChanged.emit() #Yes, we just cleared the _extruders list!
return #Then leave them empty!
#Get the extruder definitions belonging to the current machine.
machine = self._global_container_stack.getBottom()
extruder_train_ids = machine.getMetaData("machine_extruder_trains")
extruder_train_ids = machine.getMetaDataEntry("machine_extruder_trains")
for extruder_train_id in extruder_train_ids:
extruder_definitions = ContainerRegistry.getInstance().findDefinitionContainers(id = extruder_train_id) #Should be only 1 definition if IDs are unique, but add the whole list anyway.
extruder_definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id = extruder_train_id) #Should be only 1 definition if IDs are unique, but add the whole list anyway.
if not extruder_definitions: #Empty list or error.
Logger.log("w", "Machine definition %s refers to an extruder train \"%s\", but no such extruder was found.", machine.getId(), extruder_train_id)
UM.Logger.log("w", "Machine definition %s refers to an extruder train \"%s\", but no such extruder was found.", machine.getId(), extruder_train_id)
continue
for extruder_definition in extruder_definitions:
self._extruders.append(Extruder(extruder_definition))
self.extrudersChanged.emit()

56
cura/ExtrudersModel.py Normal file
View File

@ -0,0 +1,56 @@
# Copyright (c) 2016 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from PyQt5.QtCore import Qt
import cura.ExtruderManager
import UM.Qt.ListModel
## Model that holds extruders.
#
# This model is designed for use by any list of extruders, but specifically
# intended for drop-down lists of extruders in place of settings.
class ExtrudersModel(UM.Qt.ListModel.ListModel):
## Human-readable name of the extruder.
NameRole = Qt.UserRole + 1
## Colour of the material loaded in the extruder.
ColourRole = Qt.UserRole + 2
## Index of the extruder, which is also the value of the setting itself.
#
# An index of 0 indicates the first extruder, an index of 1 the second
# one, and so on. This is the value that will be saved in instance
# containers.
IndexRole = Qt.UserRole + 3
## Initialises the extruders model, defining the roles and listening for
# changes in the data.
#
# \param parent Parent QtObject of this list.
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.ColourRole, "colour")
self.addRoleName(self.IndexRole, "index")
#Listen to changes.
manager = cura.ExtruderManager.ExtruderManager.getInstance()
manager.extrudersChanged.connect(self._updateExtruders)
self._updateExtruders()
## Update the list of extruders.
#
# This should be called whenever the list of extruders changes.
def _updateExtruders(self):
self.clear()
manager = cura.ExtruderManager.ExtruderManager.getInstance()
for index, extruder in enumerate(manager):
item = { #Construct an item with only the relevant information.
"name": extruder.name,
"colour": extruder.material.getMetaDataEntry("color_code", default = "#FFFF00"),
"index": index
}
self.appendItem(item)
self.sort(lambda item: item["index"])

View File

@ -18,11 +18,17 @@ class SettingOverrideDecorator(SceneNodeDecorator):
self._instance = InstanceContainer(container_id = "SettingOverrideInstanceContainer")
self._stack.addContainer(self._instance)
self._stack.propertyChanged.connect(self._onSettingChanged)
ContainerRegistry.getInstance().addContainer(self._stack)
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerStackChanged)
self._onGlobalContainerStackChanged()
def _onSettingChanged(self, instance, property):
if property == "value": # Only reslice if the value has changed.
Application.getInstance().getBackend().forceSlice()
def _onGlobalContainerStackChanged(self):
## Ensure that the next stack is always the global stack.
self._stack.setNextStack(Application.getInstance().getGlobalContainerStack())

View File

@ -3,7 +3,6 @@
import numpy
from string import Formatter
import traceback
from enum import IntEnum
from UM.Job import Job
@ -59,7 +58,7 @@ class StartSliceJob(Job):
self.setResult(StartJobResult.Error)
return
#Don't slice if there is a setting with an error value.
# Don't slice if there is a setting with an error value.
for key in stack.getAllKeys():
validation_state = stack.getProperty(key, "validationState")
if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
@ -69,6 +68,22 @@ class StartSliceJob(Job):
Job.yieldThread()
# Don't slice if there is a per object setting with an error value.
for node in DepthFirstIterator(self._scene.getRoot()):
if type(node) is not SceneNode or not node.isSelectable():
continue
node_stack = node.callDecoration("getStack")
if node_stack:
for key in node_stack.getAllKeys():
validation_state = node_stack.getProperty(key, "validationState")
if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
Logger.log("w", "Per object setting %s is not valid, but %s. Aborting slicing.", key, validation_state)
self.setResult(StartJobResult.SettingError)
return
Job.yieldThread()
with self._scene.getSceneLock():
# Remove old layer data.
for node in DepthFirstIterator(self._scene.getRoot()):

View File

@ -5,7 +5,8 @@ from UM.Logger import Logger
from cura.SettingOverrideDecorator import SettingOverrideDecorator
## The per object setting visibility handler ensures that only setting defintions that have a matching instance Container
# are returned as visible.
class PerObjectSettingVisibilityHandler(QObject):
def __init__(self, parent = None, *args, **kwargs):
super().__init__(parent = parent, *args, **kwargs)

View File

@ -1,75 +0,0 @@
# Copyright (c) 2015 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.
from PyQt5.QtCore import Qt, pyqtSlot, QUrl
from UM.Application import Application
from UM.Qt.ListModel import ListModel
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
from UM.Scene.SceneNode import SceneNode
#from UM.Settings.SettingOverrideDecorator import SettingOverrideDecorator
#from UM.Settings.ProfileOverrideDecorator import ProfileOverrideDecorator
from . import SettingOverrideModel
class PerObjectSettingsModel(ListModel):
IdRole = Qt.UserRole + 1 # ID of the node
def __init__(self, parent = None):
super().__init__(parent)
self._scene = Application.getInstance().getController().getScene()
self._root = self._scene.getRoot()
self.addRoleName(self.IdRole,"id")
self._updateModel()
@pyqtSlot("quint64", str)
def setObjectProfile(self, object_id, profile_name):
self.setProperty(self.find("id", object_id), "profile", profile_name)
profile = None
'''if profile_name != "global":
profile = Application.getInstance().getMachineManager().findProfile(profile_name)
node = self._scene.findObject(object_id)
if profile:
if not node.getDecorator(ProfileOverrideDecorator):
node.addDecorator(ProfileOverrideDecorator())
node.callDecoration("setProfile", profile)
else:
if node.getDecorator(ProfileOverrideDecorator):
node.removeDecorator(ProfileOverrideDecorator)'''
@pyqtSlot("quint64", str)
def addOverride(self, object_id, key):
machine = Application.getInstance().getMachineManager().getActiveMachineInstance()
if not machine:
return
node = self._scene.findObject(object_id)
#if not node.getDecorator(SettingOverrideDecorator):
# node.addDecorator(SettingOverrideDecorator())
node.callDecoration("addSetting", key)
@pyqtSlot("quint64", str)
def removerOverride(self, object_id, key):
node = self._scene.findObject(object_id)
node.callDecoration("removeSetting", key)
#if len(node.callDecoration("getAllSettings")) == 0:
# node.removeDecorator(SettingOverrideDecorator)
def _updateModel(self):
self.clear()
for node in BreadthFirstIterator(self._root):
if type(node) is not SceneNode or not node.isSelectable():
continue
node_stack = node.callDecoration("getStack")
if not node_stack:
self.appendItem({
"id": id(node)
})

View File

@ -45,6 +45,7 @@ Item {
{
Loader
{
id: settingLoader
width: UM.Theme.getSize("setting").width;
height: UM.Theme.getSize("section").height;
@ -57,6 +58,12 @@ Item {
//causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
asynchronous: model.type != "enum"
onLoaded: {
settingLoader.item.showRevertButton = false
settingLoader.item.showInheritButton = false
settingLoader.item.doDepthIdentation = false
}
source:
{
switch(model.type) // TODO: This needs to be fixed properly. Got frustrated with it not working, so this is the patch job!

View File

@ -6,14 +6,15 @@ from UM.Scene.Selection import Selection
from UM.Application import Application
from UM.Preferences import Preferences
from . import PerObjectSettingsModel
## 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.
class PerObjectSettingsTool(Tool):
def __init__(self):
super().__init__()
self._model = None
self.setExposedProperties("SelectedObjectId","ContainerID")
self.setExposedProperties("SelectedObjectId", "ContainerID")
Preferences.getInstance().preferenceChanged.connect(self._onPreferenceChanged)
Selection.selectionChanged.connect(self.propertyChanged)
@ -33,21 +34,13 @@ class PerObjectSettingsTool(Tool):
return selected_object_id
def getContainerID(self):
try:
selected_object = Selection.getSelectedObject(0)
if selected_object.getParent().callDecoration("isGroup"):
selected_object = selected_object.getParent()
try:
return selected_object.callDecoration("getStack").getId()
except:
print(":(")
return
except:
print(":((")
return
def setContainerID(self, value):
pass
except AttributeError:
return ""
def _onPreferenceChanged(self, preference):
if preference == "cura/active_mode":

View File

@ -1,138 +0,0 @@
# Copyright (c) 2015 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.
from PyQt5.QtCore import Qt, pyqtSlot, QUrl
from UM.Application import Application
from UM.Qt.ListModel import ListModel
#from UM.Settings.SettingOverrideDecorator import SettingOverrideDecorator
class SettingOverrideModel(ListModel):
KeyRole = Qt.UserRole + 1
LabelRole = Qt.UserRole + 2
DescriptionRole = Qt.UserRole + 3
ValueRole = Qt.UserRole + 4
TypeRole = Qt.UserRole + 5
UnitRole = Qt.UserRole + 6
ValidRole = Qt.UserRole + 7
OptionsRole = Qt.UserRole + 8
WarningDescriptionRole = Qt.UserRole + 9
ErrorDescriptionRole = Qt.UserRole + 10
GlobalOnlyRole = Qt.UserRole + 11
def __init__(self, node, parent = None):
super().__init__(parent)
self._ignore_setting_change = None
self._node = node
self._node.decoratorsChanged.connect(self._onDecoratorsChanged)
self._onDecoratorsChanged(None)
#self._activeProfile = Application.getInstance().getMachineManager().getWorkingProfile() #To be able to get notified when a setting changes.
#self._activeProfile.settingValueChanged.connect(self._onProfileSettingValueChanged)
#Application.getInstance().getMachineManager().activeProfileChanged.connect(self._onProfileChanged)
self.addRoleName(self.KeyRole, "key")
self.addRoleName(self.LabelRole, "label")
self.addRoleName(self.DescriptionRole, "description")
self.addRoleName(self.ValueRole,"value")
self.addRoleName(self.TypeRole, "type")
self.addRoleName(self.UnitRole, "unit")
self.addRoleName(self.ValidRole, "valid")
self.addRoleName(self.OptionsRole, "options")
self.addRoleName(self.WarningDescriptionRole, "warning_description")
self.addRoleName(self.ErrorDescriptionRole, "error_description")
self.addRoleName(self.GlobalOnlyRole, "global_only")
@pyqtSlot(str, "QVariant")
def setSettingValue(self, key, value):
if not self._decorator:
return
self._decorator.setSettingValue(key, value)
def _onDecoratorsChanged(self, node):
return
'''if not self._node.getDecorator(SettingOverrideDecorator):
self.clear()
return
self._decorator = self._node.getDecorator(SettingOverrideDecorator)
self._decorator.settingAdded.connect(self._onSettingsChanged)
self._decorator.settingRemoved.connect(self._onSettingsChanged)
self._decorator.settingValueChanged.connect(self._onSettingValueChanged)
self._onSettingsChanged()'''
def _createOptionsModel(self, options):
if not options:
return None
model = ListModel()
model.addRoleName(Qt.UserRole + 1, "value")
model.addRoleName(Qt.UserRole + 2, "name")
for value, name in options.items():
model.appendItem({"value": str(value), "name": str(name)})
return model
## Updates the active profile in this model if the active profile is
# changed.
#
# This links the settingValueChanged of the new profile to this model's
# _onSettingValueChanged function, so that it properly listens to those
# events again.
def _onProfileChanged(self):
if self._activeProfile: #Unlink from the old profile.
self._activeProfile.settingValueChanged.disconnect(self._onProfileSettingValueChanged)
old_profile = self._activeProfile
self._activeProfile = Application.getInstance().getMachineManager().getWorkingProfile()
self._activeProfile.settingValueChanged.connect(self._onProfileSettingValueChanged) #Re-link to the new profile.
for setting_name in old_profile.getChangedSettings().keys(): #Update all changed settings in the old and new profiles.
self._onProfileSettingValueChanged(setting_name)
for setting_name in self._activeProfile.getChangedSettings().keys():
self._onProfileSettingValueChanged(setting_name)
## Updates the global_only property of a setting once a setting value
# changes.
#
# This method should only get called on settings that are dependent on the
# changed setting.
#
# \param setting_name The setting that needs to be updated.
def _onProfileSettingValueChanged(self, setting_name):
index = self.find("key", setting_name)
if index != -1:
self.setProperty(index, "global_only", Application.getInstance().getMachineManager().getActiveMachineInstance().getMachineDefinition().getSetting(setting_name).getGlobalOnly())
def _onSettingsChanged(self):
self.clear()
items = []
for key, setting in self._decorator.getAllSettings().items():
value = self._decorator.getSettingValue(key)
items.append({
"key": key,
"label": setting.getLabel(),
"description": setting.getDescription(),
"value": str(value),
"type": setting.getType(),
"unit": setting.getUnit(),
"valid": setting.validate(value),
"options": self._createOptionsModel(setting.getOptions()),
"warning_description": setting.getWarningDescription(),
"error_description": setting.getErrorDescription(),
"global_only": setting.getGlobalOnly()
})
items.sort(key = lambda i: i["key"])
for item in items:
self.appendItem(item)
def _onSettingValueChanged(self, setting):
index = self.find("key", setting.getKey())
value = self._decorator.getSettingValue(setting.getKey())
if index != -1:
self.setProperty(index, "value", str(value))
self.setProperty(index, "valid", setting.validate(value))
self.setProperty(index, "global_only", setting.getGlobalOnly())

View File

@ -22,7 +22,7 @@
{
"label": "Extruder",
"description": "The extruder train used for printing. This is used in multi-extrusion.",
"type": "int",
"type": "extruder",
"default_value": 0,
"minimum_value": "0"
},

View File

@ -2125,7 +2125,7 @@
{
"label": "Platform Adhesion Extruder",
"description": "The extruder train to use for printing the skirt/brim/raft. This is used in multi-extrusion.",
"type": "int",
"type": "extruder",
"default_value": 0,
"minimum_value": "0",
"maximum_value": "machine_extruder_count - 1",
@ -2135,7 +2135,7 @@
{
"label": "Support Extruder",
"description": "The extruder train to use for printing the support. This is used in multi-extrusion.",
"type": "int",
"type": "extruder",
"default_value": 0,
"minimum_value": "0",
"maximum_value": "machine_extruder_count - 1",
@ -2145,7 +2145,7 @@
{
"label": "Support Infill Extruder",
"description": "The extruder train to use for printing the infill of the support. This is used in multi-extrusion.",
"type": "int",
"type": "extruder",
"default_value": 0,
"value": "support_extruder_nr",
"minimum_value": "0",
@ -2156,7 +2156,7 @@
{
"label": "First Layer Support Extruder",
"description": "The extruder train to use for printing the first layer of support infill. This is used in multi-extrusion.",
"type": "int",
"type": "extruder",
"default_value": 0,
"value": "support_extruder_nr",
"minimum_value": "0",
@ -2167,7 +2167,7 @@
{
"label": "Support Roof Extruder",
"description": "The extruder train to use for printing the roof of the support. This is used in multi-extrusion.",
"type": "int",
"type": "extruder",
"default_value": 0,
"value": "support_extruder_nr",
"minimum_value": "0",

View File

@ -0,0 +1,112 @@
// 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.Controls.Styles 1.1
import UM 1.1 as UM
import Cura 1.0 as Cura
SettingItem
{
id: base
contents: ComboBox
{
id: control
model: Cura.ExtrudersModel {
id: extruders_model
}
textRole: "name";
anchors.fill: parent
MouseArea
{
anchors.fill: parent;
acceptedButtons: Qt.NoButton;
onWheel: wheel.accepted = true;
}
style: ComboBoxStyle
{
background: Rectangle
{
color:
{
if (!enabled)
{
return UM.Theme.getColor("setting_control_disabled")
}
if(control.hovered || base.activeFocus)
{
return UM.Theme.getColor("setting_control_highlight")
}
else
{
return UM.Theme.getColor("setting_control")
}
}
border.width: UM.Theme.getSize("default_lining").width;
border.color: !enabled ? UM.Theme.getColor("setting_control_disabled_border") : control.hovered ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border");
}
label: Item
{
Label
{
anchors.left: parent.left;
anchors.leftMargin: UM.Theme.getSize("default_lining").width
anchors.right: downArrow.left;
anchors.rightMargin: UM.Theme.getSize("default_lining").width;
anchors.verticalCenter: parent.verticalCenter;
text: control.currentText;
font: UM.Theme.getFont("default");
color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text");
elide: Text.ElideRight;
verticalAlignment: Text.AlignVCenter;
}
UM.RecolorImage
{
id: downArrow
anchors.right: parent.right;
anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2;
anchors.verticalCenter: parent.verticalCenter;
source: UM.Theme.getIcon("arrow_bottom")
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
sourceSize.width: width + 5
sourceSize.height: width + 5
color: UM.Theme.getColor("setting_control_text");
}
}
}
onActivated: provider.setPropertyValue("value", extruders_model.getItem(index).index)
onModelChanged: updateCurrentIndex();
Connections
{
target: provider
onPropertiesChanged: control.updateCurrentIndex()
}
function updateCurrentIndex() {
for(var i = 0; i < extruders_model.rowCount(); ++i) {
if(extruders_model.getItem(i).index == provider.properties.value) {
currentIndex = i;
return;
}
}
currentIndex = -1;
}
}
}

View File

@ -18,6 +18,10 @@ Item {
property alias contents: controlContainer.children;
property alias hovered: mouse.containsMouse
property var showRevertButton: true
property var showInheritButton: true
property var doDepthIdentation: true
signal contextMenuRequested()
signal showTooltip(string text);
signal hideTooltip();
@ -93,7 +97,7 @@ Item {
id: label;
anchors.left: parent.left;
anchors.leftMargin: (UM.Theme.getSize("section_icon_column").width + 5) + ((definition.depth - 1) * UM.Theme.getSize("setting_control_depth_margin").width)
anchors.leftMargin: doDepthIdentation ? (UM.Theme.getSize("section_icon_column").width + 5) + ((definition.depth - 1) * UM.Theme.getSize("setting_control_depth_margin").width) : 0
anchors.right: settingControls.left;
anchors.verticalCenter: parent.verticalCenter
@ -124,7 +128,7 @@ Item {
{
id: revertButton;
visible: propertyProvider.stackLevel == 0
visible: propertyProvider.stackLevel == 0 && base.showRevertButton
height: parent.height;
width: height;
@ -151,7 +155,7 @@ Item {
id: inheritButton;
//visible: has_profile_value && base.has_inherit_function && base.is_enabled
visible: propertyProvider.properties.state == "InstanceState.User" && propertyProvider.stackLevel > 0
visible: propertyProvider.properties.state == "InstanceState.User" && propertyProvider.stackLevel > 0 && base.showInheritButton
height: parent.height;
width: height;

View File

@ -48,7 +48,7 @@ ScrollView
//Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
//In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
//causing nasty issues when selecting differnt options. So disable asynchronous loading of enum type completely.
//causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
asynchronous: model.type != "enum"
active: model.type != undefined
@ -62,6 +62,8 @@ ScrollView
return "SettingTextField.qml"
case "enum":
return "SettingComboBox.qml"
case "extruder":
return "SettingExtruder.qml"
case "bool":
return "SettingCheckBox.qml"
case "str":