Merge branch 'CURA-5829-Add-preview-stage' into ui_rework_4_0

This commit is contained in:
Remco Burema 2018-11-08 13:23:56 +01:00
commit 215fc4e8ec
19 changed files with 1081 additions and 960 deletions

View File

@ -438,6 +438,7 @@ class CuraApplication(QtApplication):
"XmlMaterialProfile", #Cura crashes without this one.
"Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back.
"PrepareStage", #Cura is useless without this one since you can't load models.
"PreviewStage", #This shows the list of the plugin views that are installed in Cura.
"MonitorStage", #Major part of Cura's functionality.
"LocalFileOutputDevice", #Major part of Cura's functionality.
"LocalContainerProvider", #Cura is useless without any profiles or setting definitions.

24
cura/CuraView.py Normal file
View File

@ -0,0 +1,24 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtProperty, QUrl
from UM.View.View import View
# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
# to indicate this.
# MainComponent works in the same way the MainComponent of a stage.
# the stageMenuComponent returns an item that should be used somehwere in the stage menu. It's up to the active stage
# to actually do something with this.
class CuraView(View):
def __init__(self, parent = None) -> None:
super().__init__(parent)
@pyqtProperty(QUrl, constant = True)
def mainComponent(self) -> QUrl:
return self.getDisplayComponent("main")
@pyqtProperty(QUrl, constant = True)
def stageMenuComponent(self) -> QUrl:
return self.getDisplayComponent("menu")

View File

@ -7,14 +7,16 @@ from . import MonitorStage
from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("cura")
def getMetaData():
return {
"stage": {
"name": i18n_catalog.i18nc("@item:inmenu", "Monitor"),
"weight": 1
"weight": 2
}
}
def register(app):
return {
"stage": MonitorStage.MonitorStage()

View File

@ -0,0 +1,18 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import UM 1.0 as UM
import Cura 1.0 as Cura
Loader
{
id: previewMain
source: UM.Controller.activeView != null && UM.Controller.activeView.mainComponent != null ? UM.Controller.activeView.mainComponent : ""
}

View File

@ -0,0 +1,94 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import UM 1.3 as UM
import Cura 1.1 as Cura
Item
{
id: previewMenu
// This widget doesn't show tooltips by itself. Instead it emits signals so others can do something with it.
signal showTooltip(Item item, point location, string text)
signal hideTooltip()
UM.I18nCatalog
{
id: catalog
name: "cura"
}
Row
{
anchors.horizontalCenter: parent.horizontalCenter
spacing: UM.Theme.getSize("default_margin").width
ComboBox
{
// This item contains the views selector, a combobox that is dynamically created from
// the list of available Views (packages that create different visualizations of the
// scene).
id: viewModeButton
style: UM.Theme.styles.combobox
model: UM.ViewModel { }
textRole: "name"
// update the model's active index
function updateItemActiveFlags()
{
currentIndex = getActiveIndex()
for (var i = 0; i < model.rowCount(); i++)
{
model.getItem(i).active = (i == currentIndex)
}
}
// get the index of the active model item on start
function getActiveIndex()
{
for (var i = 0; i < model.rowCount(); i++)
{
if (model.getItem(i).active)
{
return i;
}
}
return 0
}
onCurrentIndexChanged:
{
if (model.getItem(currentIndex).id != undefined)
{
UM.Controller.setActiveView(model.getItem(currentIndex).id)
}
}
currentIndex: getActiveIndex()
}
Loader
{
// TODO: Make this panel collapsable and ensure it has a standardised background.
id: viewPanel
property var buttonTarget: Qt.point(viewModeButton.x + Math.round(viewModeButton.width / 2), viewModeButton.y + Math.round(viewModeButton.height / 2))
height: childrenRect.height
width: childrenRect.width
source: UM.Controller.activeView != null && UM.Controller.activeView.stageMenuComponent != null ? UM.Controller.activeView.stageMenuComponent : ""
}
Cura.PrintSetupSelector
{
width: UM.Theme.getSize("print_setup_widget").width
onShowTooltip: previewMenu.showTooltip(item, location, text)
onHideTooltip: previewMenu.hideTooltip()
}
}
}

View File

@ -0,0 +1,51 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import os.path
from UM.Qt.QtApplication import QtApplication
from cura.Stages.CuraStage import CuraStage
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
from UM.View.View import View
## Displays a preview of what you're about to print.
#
# The Python component of this stage just loads PreviewMain.qml for display
# when the stage is selected, and makes sure that it reverts to the previous
# view when the previous stage is activated.
class PreviewStage(CuraStage):
def __init__(self, application: QtApplication, parent = None) -> None:
super().__init__(parent)
self._application = application
self._application.engineCreatedSignal.connect(self._engineCreated)
self._previously_active_view = None # type: Optional[View]
## When selecting the stage, remember which was the previous view so that
# we can revert to that view when we go out of the stage later.
def onStageSelected(self) -> None:
self._previously_active_view = self._application.getController().getActiveView()
## Called when going to a different stage (away from the Preview Stage).
#
# When going to a different stage, the view should be reverted to what it
# was before. Normally, that just reverts it to solid view.
def onStageDeselected(self) -> None:
if self._previously_active_view is not None:
self._application.getController().setActiveView(self._previously_active_view.getPluginId())
self._previously_active_view = None
## Delayed load of the QML files.
#
# We need to make sure that the QML engine is running before we can load
# these.
def _engineCreated(self) -> None:
plugin_path = self._application.getPluginRegistry().getPluginPath(self.getPluginId())
if plugin_path is not None:
menu_component_path = os.path.join(plugin_path, "PreviewMenu.qml")
main_component_path = os.path.join(plugin_path, "PreviewMain.qml")
self.addDisplayComponent("menu", menu_component_path)
self.addDisplayComponent("main", main_component_path)

View File

@ -0,0 +1,22 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from . import PreviewStage
from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("cura")
def getMetaData():
return {
"stage": {
"name": i18n_catalog.i18nc("@item:inmenu", "Preview"),
"weight": 1
}
}
def register(app):
return {
"stage": PreviewStage.PreviewStage(app)
}

View File

@ -0,0 +1,8 @@
{
"name": "Preview Stage",
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Provides a preview stage in Cura.",
"api": 5,
"i18n-catalog": "cura"
}

View File

@ -13,23 +13,23 @@ Item
{
id: sliderRoot
// handle properties
property real handleSize: 10
// Handle properties
property real handleSize: UM.Theme.getSize("slider_handle").width
property real handleRadius: handleSize / 2
property real minimumRangeHandleSize: handleSize / 2
property color upperHandleColor: "black"
property color lowerHandleColor: "black"
property color rangeHandleColor: "black"
property color handleActiveColor: "white"
property real handleLabelWidth: width
property color upperHandleColor: UM.Theme.getColor("slider_handle")
property color lowerHandleColor: UM.Theme.getColor("slider_handle")
property color rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
property real handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width
property var activeHandle: upperHandle
// track properties
property real trackThickness: 4 // width of the slider track
// Track properties
property real trackThickness: UM.Theme.getSize("slider_groove").width // width of the slider track
property real trackRadius: trackThickness / 2
property color trackColor: "white"
property real trackBorderWidth: 1 // width of the slider track border
property color trackBorderColor: "black"
property color trackColor: UM.Theme.getColor("slider_groove")
property real trackBorderWidth: 1
property color trackBorderColor: UM.Theme.getColor("slider_groove_border")
// value properties
property real maximumValue: 100
@ -80,7 +80,7 @@ Item
return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue)
}
// slider track
// Slider track
Rectangle
{
id: track
@ -106,7 +106,7 @@ Item
anchors.horizontalCenter: sliderRoot.horizontalCenter
visible: sliderRoot.layersVisible
// set the new value when dragging
// Set the new value when dragging
function onHandleDragged()
{
sliderRoot.manuallyChanged = true
@ -169,7 +169,7 @@ Item
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
x: parent.x + parent.width + UM.Theme.getSize("default_margin").width
anchors.verticalCenter: parent.verticalCenter
target: Qt.point(sliderRoot.width, y + height / 2)
target: Qt.point(sliderRoot.width + width, y + height / 2)
visible: sliderRoot.activeHandle == parent
// custom properties
@ -275,7 +275,7 @@ Item
id: upperHandleLabel
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
x: parent.x + parent.width + UM.Theme.getSize("default_margin").width
x: parent.x - parent.width - width
anchors.verticalCenter: parent.verticalCenter
target: Qt.point(sliderRoot.width, y + height / 2)
visible: sliderRoot.activeHandle == parent
@ -385,9 +385,9 @@ Item
id: lowerHandleLabel
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
x: parent.x + parent.width + UM.Theme.getSize("default_margin").width
x: parent.x - parent.width - width
anchors.verticalCenter: parent.verticalCenter
target: Qt.point(sliderRoot.width, y + height / 2)
target: Qt.point(sliderRoot.width + width, y + height / 2)
visible: sliderRoot.activeHandle == parent
// custom properties

View File

@ -14,19 +14,19 @@ Item
id: sliderRoot
// handle properties
property real handleSize: 10
property real handleSize: UM.Theme.getSize("slider_handle").width
property real handleRadius: handleSize / 2
property color handleColor: "black"
property color handleActiveColor: "white"
property color rangeColor: "black"
property color handleColor: UM.Theme.getColor("slider_handle")
property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
property color rangeColor: UM.Theme.getColor("slider_groove_fill")
property real handleLabelWidth: width
// track properties
property real trackThickness: 4 // width of the slider track
property real trackThickness: UM.Theme.getSize("slider_groove").width
property real trackRadius: trackThickness / 2
property color trackColor: "white"
property color trackColor: UM.Theme.getColor("slider_groove")
property real trackBorderWidth: 1 // width of the slider track border
property color trackBorderColor: "black"
property color trackBorderColor: UM.Theme.getColor("slider_groove_border")
// value properties
property real maximumValue: 100

View File

@ -16,6 +16,7 @@ from UM.Mesh.MeshBuilder import MeshBuilder
from UM.Message import Message
from UM.Platform import Platform
from UM.PluginRegistry import PluginRegistry
from UM.Qt.QtApplication import QtApplication
from UM.Resources import Resources
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
@ -26,8 +27,8 @@ from UM.View.GL.OpenGL import OpenGL
from UM.View.GL.OpenGLContext import OpenGLContext
from UM.View.GL.ShaderProgram import ShaderProgram
from UM.View.View import View
from UM.i18n import i18nCatalog
from cura.CuraView import CuraView
from cura.Scene.ConvexHullNode import ConvexHullNode
from cura.CuraApplication import CuraApplication
@ -48,15 +49,15 @@ catalog = i18nCatalog("cura")
## View used to display g-code paths.
class SimulationView(View):
class SimulationView(CuraView):
# Must match SimulationView.qml
LAYER_VIEW_TYPE_MATERIAL_TYPE = 0
LAYER_VIEW_TYPE_LINE_TYPE = 1
LAYER_VIEW_TYPE_FEEDRATE = 2
LAYER_VIEW_TYPE_THICKNESS = 3
def __init__(self) -> None:
super().__init__()
def __init__(self, parent = None) -> None:
super().__init__(parent)
self._max_layers = 0
self._current_layer_num = 0
@ -113,6 +114,16 @@ class SimulationView(View):
self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled"),
title = catalog.i18nc("@info:title", "Simulation View"))
QtApplication.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
def _onEngineCreated(self) -> None:
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
if plugin_path:
self.addDisplayComponent("main", os.path.join(plugin_path, "SimulationViewMainComponent.qml"))
self.addDisplayComponent("menu", os.path.join(plugin_path, "SimulationViewMenuComponent.qml"))
else:
Logger.log("e", "Unable to find the path for %s", self.getPluginId())
def _evaluateCompatibilityMode(self) -> bool:
return OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode"))

View File

@ -1,815 +0,0 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import UM 1.0 as UM
import Cura 1.0 as Cura
Item
{
id: base
width:
{
if (UM.SimulationView.compatibilityMode)
{
return UM.Theme.getSize("layerview_menu_size_compatibility").width;
}
else
{
return UM.Theme.getSize("layerview_menu_size").width;
}
}
height: {
if (viewSettings.collapsed)
{
if (UM.SimulationView.compatibilityMode)
{
return UM.Theme.getSize("layerview_menu_size_compatibility_collapsed").height;
}
return UM.Theme.getSize("layerview_menu_size_collapsed").height;
}
else if (UM.SimulationView.compatibilityMode)
{
return UM.Theme.getSize("layerview_menu_size_compatibility").height;
}
else if (UM.Preferences.getValue("layerview/layer_view_type") == 0)
{
return UM.Theme.getSize("layerview_menu_size_material_color_mode").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
}
else
{
return UM.Theme.getSize("layerview_menu_size").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
}
}
Behavior on height { NumberAnimation { duration: 100 } }
property var buttonTarget:
{
if(parent != null)
{
var force_binding = parent.y; // ensure this gets reevaluated when the panel moves
return base.mapFromItem(parent.parent, parent.buttonTarget.x, parent.buttonTarget.y)
}
return Qt.point(0,0)
}
Rectangle
{
id: layerViewMenu
anchors.right: parent.right
anchors.top: parent.top
width: parent.width
height: parent.height
clip: true
z: layerSlider.z - 1
color: UM.Theme.getColor("tool_panel_background")
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
Button {
id: collapseButton
anchors.top: parent.top
anchors.topMargin: Math.round(UM.Theme.getSize("default_margin").height + (UM.Theme.getSize("layerview_row").height - UM.Theme.getSize("default_margin").height) / 2)
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_margin").width
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
onClicked: viewSettings.collapsed = !viewSettings.collapsed
style: ButtonStyle
{
background: UM.RecolorImage
{
width: control.width
height: control.height
sourceSize.width: width
sourceSize.height: width
color: UM.Theme.getColor("setting_control_text")
source: viewSettings.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom")
}
label: Label{ }
}
}
ColumnLayout
{
id: viewSettings
property bool collapsed: false
property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
// if we are in compatibility mode, we only show the "line type"
property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1
property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3
property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2
property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3
property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
anchors.top: parent.top
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_margin").width
spacing: UM.Theme.getSize("layerview_row_spacing").height
Label
{
id: layerViewTypesLabel
anchors.left: parent.left
text: catalog.i18nc("@label","Color scheme")
font: UM.Theme.getFont("default");
visible: !UM.SimulationView.compatibilityMode
Layout.fillWidth: true
color: UM.Theme.getColor("setting_control_text")
}
ListModel // matches SimulationView.py
{
id: layerViewTypes
}
Component.onCompleted:
{
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Material Color"),
type_id: 0
})
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Line Type"),
type_id: 1
})
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Feedrate"),
type_id: 2
})
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Layer thickness"),
type_id: 3 // these ids match the switching in the shader
})
}
ComboBox
{
id: layerTypeCombobox
anchors.left: parent.left
Layout.fillWidth: true
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
model: layerViewTypes
visible: !UM.SimulationView.compatibilityMode
style: UM.Theme.styles.combobox
anchors.right: parent.right
onActivated:
{
UM.Preferences.setValue("layerview/layer_view_type", index);
}
Component.onCompleted:
{
currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
updateLegends(currentIndex);
}
function updateLegends(type_id)
{
// update visibility of legends
viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3);
viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2);
viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3);
}
}
Label
{
id: compatibilityModeLabel
anchors.left: parent.left
text: catalog.i18nc("@label","Compatibility Mode")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
visible: UM.SimulationView.compatibilityMode
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
}
Item
{
height: Math.round(UM.Theme.getSize("default_margin").width / 2)
width: width
}
Connections
{
target: UM.Preferences
onPreferenceChanged:
{
layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex);
playButton.pauseSimulation();
viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|");
viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves");
viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers");
viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin");
viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill");
viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers");
viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count");
}
}
Repeater
{
model: Cura.ExtrudersModel{}
CheckBox
{
id: extrudersModelCheckBox
checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == ""
onClicked:
{
viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0
UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|"));
}
visible: !UM.SimulationView.compatibilityMode
enabled: index + 1 <= 4
Rectangle
{
anchors.verticalCenter: parent.verticalCenter
anchors.right: extrudersModelCheckBox.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: model.color
radius: Math.round(width / 2)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: !viewSettings.show_legend & !viewSettings.show_gradient
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
style: UM.Theme.styles.checkbox
Label
{
text: model.name
elide: Text.ElideRight
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
anchors.verticalCenter: parent.verticalCenter
anchors.left: extrudersModelCheckBox.left;
anchors.right: extrudersModelCheckBox.right;
anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2)
anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
}
}
}
Repeater
{
model: ListModel
{
id: typesLegendModel
Component.onCompleted:
{
typesLegendModel.append({
label: catalog.i18nc("@label", "Show Travels"),
initialValue: viewSettings.show_travel_moves,
preference: "layerview/show_travel_moves",
colorId: "layerview_move_combing"
});
typesLegendModel.append({
label: catalog.i18nc("@label", "Show Helpers"),
initialValue: viewSettings.show_helpers,
preference: "layerview/show_helpers",
colorId: "layerview_support"
});
typesLegendModel.append({
label: catalog.i18nc("@label", "Show Shell"),
initialValue: viewSettings.show_skin,
preference: "layerview/show_skin",
colorId: "layerview_inset_0"
});
typesLegendModel.append({
label: catalog.i18nc("@label", "Show Infill"),
initialValue: viewSettings.show_infill,
preference: "layerview/show_infill",
colorId: "layerview_infill"
});
}
}
CheckBox
{
id: legendModelCheckBox
checked: model.initialValue
onClicked:
{
UM.Preferences.setValue(model.preference, checked);
}
Rectangle
{
anchors.verticalCenter: parent.verticalCenter
anchors.right: legendModelCheckBox.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor(model.colorId)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: viewSettings.show_legend
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
style: UM.Theme.styles.checkbox
Label
{
text: label
font: UM.Theme.getFont("default")
elide: Text.ElideRight
color: UM.Theme.getColor("setting_control_text")
anchors.verticalCenter: parent.verticalCenter
anchors.left: legendModelCheckBox.left;
anchors.right: legendModelCheckBox.right;
anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2)
anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
}
}
}
CheckBox
{
checked: viewSettings.only_show_top_layers
onClicked:
{
UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0);
}
text: catalog.i18nc("@label", "Only Show Top Layers")
visible: UM.SimulationView.compatibilityMode
style: UM.Theme.styles.checkbox
}
CheckBox
{
checked: viewSettings.top_layer_count == 5
onClicked:
{
UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1);
}
text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
visible: UM.SimulationView.compatibilityMode
style: UM.Theme.styles.checkbox
}
Repeater
{
model: ListModel
{
id: typesLegendModelNoCheck
Component.onCompleted:
{
typesLegendModelNoCheck.append({
label: catalog.i18nc("@label", "Top / Bottom"),
colorId: "layerview_skin",
});
typesLegendModelNoCheck.append({
label: catalog.i18nc("@label", "Inner Wall"),
colorId: "layerview_inset_x",
});
}
}
Label
{
text: label
visible: viewSettings.show_legend
id: typesLegendModelLabel
Rectangle
{
anchors.verticalCenter: parent.verticalCenter
anchors.right: typesLegendModelLabel.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor(model.colorId)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: viewSettings.show_legend
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
}
}
// Text for the minimum, maximum and units for the feedrates and layer thickness
Item
{
id: gradientLegend
visible: viewSettings.show_gradient
width: parent.width
height: UM.Theme.getSize("layerview_row").height
anchors
{
topMargin: UM.Theme.getSize("slider_layerview_margin").height
horizontalCenter: parent.horizontalCenter
}
Label
{
text: minText()
anchors.left: parent.left
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
function minText()
{
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
{
// Feedrate selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
{
return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
}
// Layer thickness selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
{
return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
}
}
return catalog.i18nc("@label","min")
}
}
Label
{
text: unitsText()
anchors.horizontalCenter: parent.horizontalCenter
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
function unitsText()
{
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
{
// Feedrate selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
{
return "mm/s"
}
// Layer thickness selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
{
return "mm"
}
}
return ""
}
}
Label
{
text: maxText()
anchors.right: parent.right
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
function maxText()
{
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
{
// Feedrate selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
{
return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
}
// Layer thickness selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
{
return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
}
}
return catalog.i18nc("@label","max")
}
}
}
// Gradient colors for feedrate
Rectangle
{ // In QML 5.9 can be changed by LinearGradient
// Invert values because then the bar is rotated 90 degrees
id: feedrateGradient
visible: viewSettings.show_feedrate_gradient
anchors.left: parent.right
height: parent.width
width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
transform: Rotation {origin.x: 0; origin.y: 0; angle: 90}
gradient: Gradient
{
GradientStop
{
position: 0.000
color: Qt.rgba(1, 0.5, 0, 1)
}
GradientStop
{
position: 0.625
color: Qt.rgba(0.375, 0.5, 0, 1)
}
GradientStop
{
position: 0.75
color: Qt.rgba(0.25, 1, 0, 1)
}
GradientStop
{
position: 1.0
color: Qt.rgba(0, 0, 1, 1)
}
}
}
// Gradient colors for layer thickness (similar to parula colormap)
Rectangle // In QML 5.9 can be changed by LinearGradient
{
// Invert values because then the bar is rotated 90 degrees
id: thicknessGradient
visible: viewSettings.show_thickness_gradient
anchors.left: parent.right
height: parent.width
width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
transform: Rotation {origin.x: 0; origin.y: 0; angle: 90}
gradient: Gradient
{
GradientStop
{
position: 0.000
color: Qt.rgba(1, 1, 0, 1)
}
GradientStop
{
position: 0.25
color: Qt.rgba(1, 0.75, 0.25, 1)
}
GradientStop
{
position: 0.5
color: Qt.rgba(0, 0.75, 0.5, 1)
}
GradientStop
{
position: 0.75
color: Qt.rgba(0, 0.375, 0.75, 1)
}
GradientStop
{
position: 1.0
color: Qt.rgba(0, 0, 0.5, 1)
}
}
}
}
}
Item
{
id: slidersBox
width: parent.width
height: parent.height
visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
anchors
{
top: parent.top
leftMargin: UM.Theme.getSize("slider_layerview_margin").height
left: parent.right
}
PathSlider
{
id: pathSlider
height: UM.Theme.getSize("slider_handle").width
anchors
{
verticalCenter: playButton.verticalCenter
left: playButton.right
leftMargin: UM.Theme.getSize("default_margin").width
right: parent.right
}
visible: !UM.SimulationView.compatibilityMode
// custom properties
handleValue: UM.SimulationView.currentPath
maximumValue: UM.SimulationView.numPaths
handleSize: UM.Theme.getSize("slider_handle").width
trackThickness: UM.Theme.getSize("slider_groove").width
trackColor: UM.Theme.getColor("slider_groove")
trackBorderColor: UM.Theme.getColor("slider_groove_border")
handleColor: UM.Theme.getColor("slider_handle")
handleActiveColor: UM.Theme.getColor("slider_handle_active")
rangeColor: UM.Theme.getColor("slider_groove_fill")
// update values when layer data changes
Connections
{
target: UM.SimulationView
onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
onCurrentPathChanged:
{
// Only pause the simulation when the layer was changed manually, not when the simulation is running
if (pathSlider.manuallyChanged)
{
playButton.pauseSimulation()
}
pathSlider.setHandleValue(UM.SimulationView.currentPath)
}
}
// make sure the slider handlers show the correct value after switching views
Component.onCompleted:
{
pathSlider.setHandleValue(UM.SimulationView.currentPath)
}
}
LayerSlider
{
id: layerSlider
width: UM.Theme.getSize("slider_handle").width
height: UM.Theme.getSize("layerview_menu_size").height
anchors
{
bottom: !UM.SimulationView.compatibilityMode ? pathSlider.top : parent.bottom
top: parent.top
bottomMargin: !UM.SimulationView.compatibilityMode ? UM.Theme.getSize("default_margin").height : 0
left: parent.left
leftMargin: Math.round(UM.Theme.getSize("slider_layerview_margin").width / 2)
}
// custom properties
upperValue: UM.SimulationView.currentLayer
lowerValue: UM.SimulationView.minimumLayer
maximumValue: UM.SimulationView.numLayers
handleSize: UM.Theme.getSize("slider_handle").width
trackThickness: UM.Theme.getSize("slider_groove").width
trackColor: UM.Theme.getColor("slider_groove")
trackBorderColor: UM.Theme.getColor("slider_groove_border")
upperHandleColor: UM.Theme.getColor("slider_handle")
lowerHandleColor: UM.Theme.getColor("slider_handle")
rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
handleActiveColor: UM.Theme.getColor("slider_handle_active")
handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width
// update values when layer data changes
Connections
{
target: UM.SimulationView
onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
onCurrentLayerChanged:
{
// Only pause the simulation when the layer was changed manually, not when the simulation is running
if (layerSlider.manuallyChanged)
{
playButton.pauseSimulation()
}
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
}
}
// make sure the slider handlers show the correct value after switching views
Component.onCompleted:
{
layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
}
}
// Play simulation button
Button
{
id: playButton
iconSource: "./resources/simulation_resume.svg"
style: UM.Theme.styles.small_tool_button
visible: !UM.SimulationView.compatibilityMode
anchors
{
left: parent.left
bottom: parent.bottom
}
property var status: 0 // indicates if it's stopped (0) or playing (1)
onClicked:
{
switch(status)
{
case 0:
{
resumeSimulation()
break
}
case 1:
{
pauseSimulation()
break
}
}
}
function pauseSimulation()
{
UM.SimulationView.setSimulationRunning(false)
iconSource = "./resources/simulation_resume.svg"
simulationTimer.stop()
status = 0
layerSlider.manuallyChanged = true
pathSlider.manuallyChanged = true
}
function resumeSimulation()
{
UM.SimulationView.setSimulationRunning(true)
iconSource = "./resources/simulation_pause.svg"
simulationTimer.start()
layerSlider.manuallyChanged = false
pathSlider.manuallyChanged = false
}
}
Timer
{
id: simulationTimer
interval: 100
running: false
repeat: true
onTriggered:
{
var currentPath = UM.SimulationView.currentPath
var numPaths = UM.SimulationView.numPaths
var currentLayer = UM.SimulationView.currentLayer
var numLayers = UM.SimulationView.numLayers
// When the user plays the simulation, if the path slider is at the end of this layer, we start
// the simulation at the beginning of the current layer.
if (playButton.status == 0)
{
if (currentPath >= numPaths)
{
UM.SimulationView.setCurrentPath(0)
}
else
{
UM.SimulationView.setCurrentPath(currentPath+1)
}
}
// If the simulation is already playing and we reach the end of a layer, then it automatically
// starts at the beginning of the next layer.
else
{
if (currentPath >= numPaths)
{
// At the end of the model, the simulation stops
if (currentLayer >= numLayers)
{
playButton.pauseSimulation()
}
else
{
UM.SimulationView.setCurrentLayer(currentLayer+1)
UM.SimulationView.setCurrentPath(0)
}
}
else
{
UM.SimulationView.setCurrentPath(currentPath+1)
}
}
// The status must be set here instead of in the resumeSimulation function otherwise it won't work
// correctly, because part of the logic is in this trigger function.
playButton.status = 1
}
}
}
FontMetrics
{
id: fontMetrics
font: UM.Theme.getFont("default")
}
}

View File

@ -0,0 +1,207 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import UM 1.0 as UM
import Cura 1.0 as Cura
Item
{
property bool is_simulation_playing: false
visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
PathSlider
{
id: pathSlider
height: UM.Theme.getSize("slider_handle").width
width: UM.Theme.getSize("layerview_menu_size").width
anchors.bottom: parent.bottom
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
anchors.horizontalCenter: parent.horizontalCenter
visible: !UM.SimulationView.compatibilityMode
// Custom properties
handleValue: UM.SimulationView.currentPath
maximumValue: UM.SimulationView.numPaths
// Update values when layer data changes.
Connections
{
target: UM.SimulationView
onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
onCurrentPathChanged:
{
// Only pause the simulation when the layer was changed manually, not when the simulation is running
if (pathSlider.manuallyChanged)
{
playButton.pauseSimulation()
}
pathSlider.setHandleValue(UM.SimulationView.currentPath)
}
}
// Ensure that the slider handlers show the correct value after switching views.
Component.onCompleted:
{
pathSlider.setHandleValue(UM.SimulationView.currentPath)
}
}
Button
{
id: playButton
iconSource: !is_simulation_playing ? "./resources/simulation_resume.svg": "./resources/simulation_pause.svg"
style: UM.Theme.styles.small_tool_button
visible: !UM.SimulationView.compatibilityMode
Connections
{
target: UM.Preferences
onPreferenceChanged:
{
playButton.pauseSimulation()
}
}
anchors
{
right: pathSlider.left
verticalCenter: pathSlider.verticalCenter
}
onClicked:
{
if(is_simulation_playing)
{
pauseSimulation()
}
else
{
resumeSimulation()
}
}
function pauseSimulation()
{
UM.SimulationView.setSimulationRunning(false)
simulationTimer.stop()
is_simulation_playing = false
layerSlider.manuallyChanged = true
pathSlider.manuallyChanged = true
}
function resumeSimulation()
{
UM.SimulationView.setSimulationRunning(true)
simulationTimer.start()
layerSlider.manuallyChanged = false
pathSlider.manuallyChanged = false
}
}
Timer
{
id: simulationTimer
interval: 100
running: false
repeat: true
onTriggered:
{
var currentPath = UM.SimulationView.currentPath
var numPaths = UM.SimulationView.numPaths
var currentLayer = UM.SimulationView.currentLayer
var numLayers = UM.SimulationView.numLayers
// When the user plays the simulation, if the path slider is at the end of this layer, we start
// the simulation at the beginning of the current layer.
if (!is_simulation_playing)
{
if (currentPath >= numPaths)
{
UM.SimulationView.setCurrentPath(0)
}
else
{
UM.SimulationView.setCurrentPath(currentPath + 1)
}
}
// If the simulation is already playing and we reach the end of a layer, then it automatically
// starts at the beginning of the next layer.
else
{
if (currentPath >= numPaths)
{
// At the end of the model, the simulation stops
if (currentLayer >= numLayers)
{
playButton.pauseSimulation()
}
else
{
UM.SimulationView.setCurrentLayer(currentLayer + 1)
UM.SimulationView.setCurrentPath(0)
}
}
else
{
UM.SimulationView.setCurrentPath(currentPath + 1)
}
}
// The status must be set here instead of in the resumeSimulation function otherwise it won't work
// correctly, because part of the logic is in this trigger function.
is_simulation_playing = true
}
}
LayerSlider
{
id: layerSlider
width: UM.Theme.getSize("slider_handle").width
height: UM.Theme.getSize("layerview_menu_size").height
anchors
{
right: parent.right
verticalCenter: parent.verticalCenter
rightMargin: UM.Theme.getSize("default_margin").width
}
// Custom properties
upperValue: UM.SimulationView.currentLayer
lowerValue: UM.SimulationView.minimumLayer
maximumValue: UM.SimulationView.numLayers
// Update values when layer data changes
Connections
{
target: UM.SimulationView
onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
onCurrentLayerChanged:
{
// Only pause the simulation when the layer was changed manually, not when the simulation is running
if (layerSlider.manuallyChanged)
{
playButton.pauseSimulation()
}
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
}
}
// Make sure the slider handlers show the correct value after switching views
Component.onCompleted:
{
layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
}
}
}

View File

@ -0,0 +1,588 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import QtGraphicalEffects 1.0
import UM 1.0 as UM
import Cura 1.0 as Cura
Rectangle
{
id: base
color: UM.Theme.getColor("tool_panel_background")
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
width: UM.Theme.getSize("layerview_menu_size").width
height: viewSettings.collapsed ? layerViewTypesLabel.height + 2 * UM.Theme.getSize("default_margin").height : childrenRect.height + 2 * UM.Theme.getSize("default_margin").height
Behavior on height { NumberAnimation { duration: 100 } }
property var buttonTarget:
{
if(parent != null)
{
var force_binding = parent.y; // ensure this gets reevaluated when the panel moves
return base.mapFromItem(parent.parent, parent.buttonTarget.x, parent.buttonTarget.y)
}
return Qt.point(0,0)
}
Connections
{
target: UM.Preferences
onPreferenceChanged:
{
layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type")
layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex)
viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|")
viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves")
viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers")
viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin")
viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill")
viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers")
viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count")
}
}
Label
{
id: layerViewTypesLabel
text: catalog.i18nc("@label","Color scheme")
font: UM.Theme.getFont("default");
visible: !UM.SimulationView.compatibilityMode
color: UM.Theme.getColor("setting_control_text")
height: contentHeight
anchors
{
top: parent.top
margins: UM.Theme.getSize("default_margin").height
right: collapseButton.left
left: parent.left
}
}
Button
{
id: collapseButton
anchors
{
top: parent.top
margins: UM.Theme.getSize("default_margin").width
right: parent.right
}
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
onClicked: viewSettings.collapsed = !viewSettings.collapsed
style: ButtonStyle
{
background: UM.RecolorImage
{
width: control.width
height: control.height
sourceSize.width: width
sourceSize.height: width
color: UM.Theme.getColor("setting_control_text")
source: viewSettings.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom")
}
label: Label{ }
}
}
Column
{
id: viewSettings
property bool collapsed: false
property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
// If we are in compatibility mode, we only show the "line type"
property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1
property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3
property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2
property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3
property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
anchors
{
top: layerViewTypesLabel.bottom
left: parent.left
right: parent.right
margins: UM.Theme.getSize("default_margin").height
}
spacing: UM.Theme.getSize("layerview_row_spacing").height
visible: !collapsed
ListModel // matches SimulationView.py
{
id: layerViewTypes
}
Component.onCompleted:
{
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Material Color"),
type_id: 0
})
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Line Type"),
type_id: 1
})
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Feedrate"),
type_id: 2
})
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Layer thickness"),
type_id: 3 // these ids match the switching in the shader
})
}
ComboBox
{
id: layerTypeCombobox
width: parent.width
model: layerViewTypes
visible: !UM.SimulationView.compatibilityMode
style: UM.Theme.styles.combobox
onActivated:
{
UM.Preferences.setValue("layerview/layer_view_type", index);
}
Component.onCompleted:
{
currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
updateLegends(currentIndex);
}
function updateLegends(type_id)
{
// Update the visibility of the legends.
viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3);
viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2);
viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3);
}
}
Label
{
id: compatibilityModeLabel
text: catalog.i18nc("@label","Compatibility Mode")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
visible: UM.SimulationView.compatibilityMode
height: UM.Theme.getSize("layerview_row").height
width: parent.width
}
Item // Spacer
{
height: Math.round(UM.Theme.getSize("default_margin").width / 2)
width: width
}
Repeater
{
model: Cura.ExtrudersModel{}
CheckBox
{
id: extrudersModelCheckBox
checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == ""
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
width: parent.width
visible: !UM.SimulationView.compatibilityMode
enabled: index < 4
onClicked:
{
viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0
UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|"));
}
style: UM.Theme.styles.checkbox
Rectangle
{
anchors.verticalCenter: parent.verticalCenter
anchors.right: extrudersModelCheckBox.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: model.color
radius: Math.round(width / 2)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: !viewSettings.show_legend && !viewSettings.show_gradient
}
Label
{
text: model.name
elide: Text.ElideRight
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
anchors
{
verticalCenter: parent.verticalCenter
left: extrudersModelCheckBox.left
right: extrudersModelCheckBox.right
leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2)
rightMargin: UM.Theme.getSize("default_margin").width * 2
}
}
}
}
Repeater
{
model: ListModel
{
id: typesLegendModel
Component.onCompleted:
{
typesLegendModel.append({
label: catalog.i18nc("@label", "Show Travels"),
initialValue: viewSettings.show_travel_moves,
preference: "layerview/show_travel_moves",
colorId: "layerview_move_combing"
});
typesLegendModel.append({
label: catalog.i18nc("@label", "Show Helpers"),
initialValue: viewSettings.show_helpers,
preference: "layerview/show_helpers",
colorId: "layerview_support"
});
typesLegendModel.append({
label: catalog.i18nc("@label", "Show Shell"),
initialValue: viewSettings.show_skin,
preference: "layerview/show_skin",
colorId: "layerview_inset_0"
});
typesLegendModel.append({
label: catalog.i18nc("@label", "Show Infill"),
initialValue: viewSettings.show_infill,
preference: "layerview/show_infill",
colorId: "layerview_infill"
});
}
}
CheckBox
{
id: legendModelCheckBox
checked: model.initialValue
onClicked: UM.Preferences.setValue(model.preference, checked)
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
width: parent.width
style: UM.Theme.styles.checkbox
Rectangle
{
anchors.verticalCenter: parent.verticalCenter
anchors.right: legendModelCheckBox.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor(model.colorId)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: viewSettings.show_legend
}
Label
{
text: label
font: UM.Theme.getFont("default")
elide: Text.ElideRight
color: UM.Theme.getColor("setting_control_text")
anchors.verticalCenter: parent.verticalCenter
anchors.left: legendModelCheckBox.left
anchors.right: legendModelCheckBox.right
anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2)
anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
}
}
}
CheckBox
{
checked: viewSettings.only_show_top_layers
onClicked: UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0)
text: catalog.i18nc("@label", "Only Show Top Layers")
visible: UM.SimulationView.compatibilityMode
style: UM.Theme.styles.checkbox
}
CheckBox
{
checked: viewSettings.top_layer_count == 5
onClicked: UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1)
text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
visible: UM.SimulationView.compatibilityMode
style: UM.Theme.styles.checkbox
}
Repeater
{
model: ListModel
{
id: typesLegendModelNoCheck
Component.onCompleted:
{
typesLegendModelNoCheck.append({
label: catalog.i18nc("@label", "Top / Bottom"),
colorId: "layerview_skin",
});
typesLegendModelNoCheck.append({
label: catalog.i18nc("@label", "Inner Wall"),
colorId: "layerview_inset_x",
});
}
}
Label
{
text: label
visible: viewSettings.show_legend
id: typesLegendModelLabel
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
width: parent.width
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
Rectangle
{
anchors.verticalCenter: parent.verticalCenter
anchors.right: typesLegendModelLabel.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor(model.colorId)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
}
}
}
// Text for the minimum, maximum and units for the feedrates and layer thickness
Item
{
id: gradientLegend
visible: viewSettings.show_gradient
width: parent.width
height: UM.Theme.getSize("layerview_row").height
Label
{
text:
{
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
{
// Feedrate selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
{
return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
}
// Layer thickness selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
{
return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
}
}
return catalog.i18nc("@label","min")
}
anchors.left: parent.left
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
}
Label
{
text: {
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
{
// Feedrate selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
{
return "mm/s"
}
// Layer thickness selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
{
return "mm"
}
}
return ""
}
anchors.horizontalCenter: parent.horizontalCenter
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
}
Label
{
text: {
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
{
// Feedrate selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
{
return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
}
// Layer thickness selected
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
{
return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
}
}
return catalog.i18nc("@label","max")
}
anchors.right: parent.right
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
}
}
// Gradient colors for feedrate
Rectangle
{
id: feedrateGradient
visible: viewSettings.show_feedrate_gradient
anchors.left: parent.left
anchors.right: parent.right
height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
LinearGradient
{
anchors
{
left: parent.left
leftMargin: UM.Theme.getSize("default_lining").width
right: parent.right
rightMargin: UM.Theme.getSize("default_lining").width
top: parent.top
topMargin: UM.Theme.getSize("default_lining").width
bottom: parent.bottom
bottomMargin: UM.Theme.getSize("default_lining").width
}
start: Qt.point(0, 0)
end: Qt.point(parent.width, 0)
gradient: Gradient
{
GradientStop
{
position: 0.000
color: Qt.rgba(0, 0, 1, 1)
}
GradientStop
{
position: 0.25
color: Qt.rgba(0.25, 1, 0, 1)
}
GradientStop
{
position: 0.375
color: Qt.rgba(0.375, 0.5, 0, 1)
}
GradientStop
{
position: 1.0
color: Qt.rgba(1, 0.5, 0, 1)
}
}
}
}
// Gradient colors for layer thickness (similar to parula colormap)
Rectangle
{
id: thicknessGradient
visible: viewSettings.show_thickness_gradient
anchors.left: parent.left
anchors.right: parent.right
height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
LinearGradient
{
anchors
{
left: parent.left
leftMargin: UM.Theme.getSize("default_lining").width
right: parent.right
rightMargin: UM.Theme.getSize("default_lining").width
top: parent.top
topMargin: UM.Theme.getSize("default_lining").width
bottom: parent.bottom
bottomMargin: UM.Theme.getSize("default_lining").width
}
start: Qt.point(0, 0)
end: Qt.point(parent.width, 0)
gradient: Gradient
{
GradientStop
{
position: 0.000
color: Qt.rgba(0, 0, 0.5, 1)
}
GradientStop
{
position: 0.25
color: Qt.rgba(0, 0.375, 0.75, 1)
}
GradientStop
{
position: 0.5
color: Qt.rgba(0, 0.75, 0.5, 1)
}
GradientStop
{
position: 0.75
color: Qt.rgba(1, 0.75, 0.25, 1)
}
GradientStop
{
position: 1.0
color: Qt.rgba(1, 1, 0, 1)
}
}
}
}
}
FontMetrics
{
id: fontMetrics
font: UM.Theme.getFont("default")
}
}

View File

@ -8,19 +8,21 @@ from . import SimulationViewProxy, SimulationView
catalog = i18nCatalog("cura")
def getMetaData():
return {
"view": {
"name": catalog.i18nc("@item:inlistbox", "Layer view"),
"view_panel": "SimulationView.qml",
"weight": 2
"weight": 0
}
}
def createSimulationViewProxy(engine, script_engine):
return SimulationViewProxy.SimulationViewProxy()
def register(app):
simulation_view = SimulationView.SimulationView()
qmlRegisterSingletonType(SimulationViewProxy.SimulationViewProxy, "UM", 1, 0, "SimulationView", simulation_view.getProxy)
return { "view": SimulationView.SimulationView()}
return { "view": simulation_view}

View File

@ -10,7 +10,8 @@ def getMetaData():
return {
"view": {
"name": i18n_catalog.i18nc("@item:inmenu", "Solid view"),
"weight": 0
"weight": 0,
"visible": False
}
}

View File

@ -155,24 +155,6 @@ UM.MainWindow
color: UM.Theme.getColor("main_window_header_background")
}
Loader
{
// The stage menu is, as the name implies, a menu that is defined by the active stage.
// Note that this menu does not need to be set at all! It's perfectly acceptable to have a stage
// without this menu!
id: stageMenu
anchors
{
left: parent.left
right: parent.right
top: parent.top
}
height: UM.Theme.getSize("stage_menu").height
source: UM.Controller.activeStage != null ? UM.Controller.activeStage.stageMenuComponent : ""
}
Connections
{
target: stageMenu.item
@ -231,68 +213,6 @@ UM.MainWindow
}
}
ComboBox
{
// This item contains the views selector, a combobox that is dynamically created from
// the list of available Views (packages that create different visualizations of the
// scene).
id: viewModeButton
anchors.left: viewOrientationControls.right
anchors.bottom: viewOrientationControls.bottom
style: UM.Theme.styles.combobox
model: UM.ViewModel { }
textRole: "name"
// update the model's active index
function updateItemActiveFlags()
{
currentIndex = getActiveIndex()
for (var i = 0; i < model.rowCount(); i++)
{
model.getItem(i).active = (i == currentIndex)
}
}
// get the index of the active model item on start
function getActiveIndex ()
{
for (var i = 0; i < model.rowCount(); i++)
{
if (model.getItem(i).active)
{
return i;
}
}
return 0
}
// set the active index
function setActiveIndex(index)
{
UM.Controller.setActiveView(index)
// the connection to UM.ActiveView will trigger update so there is no reason to call it manually here
}
onCurrentIndexChanged:
{
if (model.getItem(currentIndex).id != undefined)
{
viewModeButton.setActiveIndex(model.getItem(currentIndex).id)
}
}
currentIndex: getActiveIndex()
// watch the active view proxy for changes made from the menu item
Connections
{
target: UM.ActiveView
onActiveViewChanged: viewModeButton.updateItemActiveFlags()
}
}
Loader
{
id: viewPanel
@ -324,15 +244,26 @@ UM.MainWindow
anchors.fill: parent
MouseArea
source: UM.Controller.activeStage != null ? UM.Controller.activeStage.mainComponent : ""
}
Loader
{
// The stage menu is, as the name implies, a menu that is defined by the active stage.
// Note that this menu does not need to be set at all! It's perfectly acceptable to have a stage
// without this menu!
id: stageMenu
anchors
{
visible: parent.source != ""
anchors.fill: parent
acceptedButtons: Qt.AllButtons
onWheel: wheel.accepted = true
left: parent.left
right: parent.right
top: parent.top
}
source: UM.Controller.activeStage != null ? UM.Controller.activeStage.mainComponent : ""
height: UM.Theme.getSize("stage_menu").height
source: UM.Controller.activeStage != null ? UM.Controller.activeStage.stageMenuComponent : ""
}
UM.MessageStack

View File

@ -11,32 +11,10 @@ Menu
{
title: catalog.i18nc("@title:menu menubar:toplevel", "&View")
id: base
enabled: !PrintInformation.preSliced
property var multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel()
// main views
Instantiator
{
model: UM.ViewModel{}
MenuItem
{
text: model.name
checkable: true
checked: model.active
exclusiveGroup: group
onTriggered: UM.Controller.setActiveView(model.id)
enabled: !PrintInformation.preSliced
}
onObjectAdded: base.insertItem(index, object)
onObjectRemoved: base.removeItem(object)
}
ExclusiveGroup
{
id: group
}
MenuSeparator {}
Menu
{
title: catalog.i18nc("@action:inmenu menubar:view","&Camera position");

View File

@ -460,8 +460,6 @@
"layerview_menu_size": [15, 20],
"layerview_menu_size_material_color_mode": [15, 16],
"layerview_menu_size_collapsed": [15, 6],
"layerview_menu_size_compatibility": [22, 22.0],
"layerview_menu_size_compatibility_collapsed": [15, 3.5],
"layerview_legend_size": [1.0, 1.0],
"layerview_row": [11.0, 1.5],
"layerview_row_spacing": [0.0, 0.5],