mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-13 01:37:51 -06:00
Merge branch 'STAR-322_cloud-connection' of github.com:Ultimaker/Cura into STAR-322_cloud-connection
This commit is contained in:
commit
2b8c9c17bb
191 changed files with 7411 additions and 5513 deletions
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, QUrl
|
from PyQt5.QtCore import QObject, QUrl
|
||||||
from PyQt5.QtGui import QDesktopServices
|
from PyQt5.QtGui import QDesktopServices
|
||||||
from typing import List, TYPE_CHECKING
|
from typing import List, TYPE_CHECKING, cast
|
||||||
|
|
||||||
from UM.Event import CallFunctionEvent
|
from UM.Event import CallFunctionEvent
|
||||||
from UM.FlameProfiler import pyqtSlot
|
from UM.FlameProfiler import pyqtSlot
|
||||||
|
@ -61,8 +61,10 @@ class CuraActions(QObject):
|
||||||
operation = GroupedOperation()
|
operation = GroupedOperation()
|
||||||
for node in Selection.getAllSelectedObjects():
|
for node in Selection.getAllSelectedObjects():
|
||||||
current_node = node
|
current_node = node
|
||||||
while current_node.getParent() and current_node.getParent().callDecoration("isGroup"):
|
parent_node = current_node.getParent()
|
||||||
current_node = current_node.getParent()
|
while parent_node and parent_node.callDecoration("isGroup"):
|
||||||
|
current_node = parent_node
|
||||||
|
parent_node = current_node.getParent()
|
||||||
|
|
||||||
# This was formerly done with SetTransformOperation but because of
|
# This was formerly done with SetTransformOperation but because of
|
||||||
# unpredictable matrix deconstruction it was possible that mirrors
|
# unpredictable matrix deconstruction it was possible that mirrors
|
||||||
|
@ -150,13 +152,13 @@ class CuraActions(QObject):
|
||||||
|
|
||||||
root = cura.CuraApplication.CuraApplication.getInstance().getController().getScene().getRoot()
|
root = cura.CuraApplication.CuraApplication.getInstance().getController().getScene().getRoot()
|
||||||
|
|
||||||
nodes_to_change = []
|
nodes_to_change = [] # type: List[SceneNode]
|
||||||
for node in Selection.getAllSelectedObjects():
|
for node in Selection.getAllSelectedObjects():
|
||||||
parent_node = node # Find the parent node to change instead
|
parent_node = node # Find the parent node to change instead
|
||||||
while parent_node.getParent() != root:
|
while parent_node.getParent() != root:
|
||||||
parent_node = parent_node.getParent()
|
parent_node = cast(SceneNode, parent_node.getParent())
|
||||||
|
|
||||||
for single_node in BreadthFirstIterator(parent_node): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
|
for single_node in BreadthFirstIterator(parent_node): # type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
|
||||||
nodes_to_change.append(single_node)
|
nodes_to_change.append(single_node)
|
||||||
|
|
||||||
if not nodes_to_change:
|
if not nodes_to_change:
|
||||||
|
|
|
@ -439,6 +439,7 @@ class CuraApplication(QtApplication):
|
||||||
"XmlMaterialProfile", #Cura crashes without this one.
|
"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.
|
"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.
|
"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.
|
"MonitorStage", #Major part of Cura's functionality.
|
||||||
"LocalFileOutputDevice", #Major part of Cura's functionality.
|
"LocalFileOutputDevice", #Major part of Cura's functionality.
|
||||||
"LocalContainerProvider", #Cura is useless without any profiles or setting definitions.
|
"LocalContainerProvider", #Cura is useless without any profiles or setting definitions.
|
||||||
|
@ -632,8 +633,6 @@ class CuraApplication(QtApplication):
|
||||||
self._message_box_callback = None
|
self._message_box_callback = None
|
||||||
self._message_box_callback_arguments = []
|
self._message_box_callback_arguments = []
|
||||||
|
|
||||||
showPrintMonitor = pyqtSignal(bool, arguments = ["show"])
|
|
||||||
|
|
||||||
def setSaveDataEnabled(self, enabled: bool) -> None:
|
def setSaveDataEnabled(self, enabled: bool) -> None:
|
||||||
self._save_data_enabled = enabled
|
self._save_data_enabled = enabled
|
||||||
|
|
||||||
|
@ -1664,7 +1663,9 @@ class CuraApplication(QtApplication):
|
||||||
is_non_sliceable = "." + file_extension in self._non_sliceable_extensions
|
is_non_sliceable = "." + file_extension in self._non_sliceable_extensions
|
||||||
|
|
||||||
if is_non_sliceable:
|
if is_non_sliceable:
|
||||||
self.callLater(lambda: self.getController().setActiveView("SimulationView"))
|
# Need to switch first to the preview stage and then to layer view
|
||||||
|
self.callLater(lambda: (self.getController().setActiveStage("PreviewStage"),
|
||||||
|
self.getController().setActiveView("SimulationView")))
|
||||||
|
|
||||||
block_slicing_decorator = BlockSlicingDecorator()
|
block_slicing_decorator = BlockSlicingDecorator()
|
||||||
node.addDecorator(block_slicing_decorator)
|
node.addDecorator(block_slicing_decorator)
|
||||||
|
|
24
cura/CuraView.py
Normal file
24
cura/CuraView.py
Normal 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")
|
|
@ -21,6 +21,7 @@ class QualityProfilesDropDownMenuModel(ListModel):
|
||||||
AvailableRole = Qt.UserRole + 5
|
AvailableRole = Qt.UserRole + 5
|
||||||
QualityGroupRole = Qt.UserRole + 6
|
QualityGroupRole = Qt.UserRole + 6
|
||||||
QualityChangesGroupRole = Qt.UserRole + 7
|
QualityChangesGroupRole = Qt.UserRole + 7
|
||||||
|
IsExperimentalRole = Qt.UserRole + 8
|
||||||
|
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
@ -32,6 +33,7 @@ class QualityProfilesDropDownMenuModel(ListModel):
|
||||||
self.addRoleName(self.AvailableRole, "available") #Whether the quality profile is available in our current nozzle + material.
|
self.addRoleName(self.AvailableRole, "available") #Whether the quality profile is available in our current nozzle + material.
|
||||||
self.addRoleName(self.QualityGroupRole, "quality_group")
|
self.addRoleName(self.QualityGroupRole, "quality_group")
|
||||||
self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group")
|
self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group")
|
||||||
|
self.addRoleName(self.IsExperimentalRole, "is_experimental")
|
||||||
|
|
||||||
self._application = Application.getInstance()
|
self._application = Application.getInstance()
|
||||||
self._machine_manager = self._application.getMachineManager()
|
self._machine_manager = self._application.getMachineManager()
|
||||||
|
@ -74,7 +76,8 @@ class QualityProfilesDropDownMenuModel(ListModel):
|
||||||
"layer_height": layer_height,
|
"layer_height": layer_height,
|
||||||
"layer_height_unit": self._layer_height_unit,
|
"layer_height_unit": self._layer_height_unit,
|
||||||
"available": quality_group.is_available,
|
"available": quality_group.is_available,
|
||||||
"quality_group": quality_group}
|
"quality_group": quality_group,
|
||||||
|
"is_experimental": quality_group.is_experimental}
|
||||||
|
|
||||||
item_list.append(item)
|
item_list.append(item)
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
from typing import Dict, Optional, List, Set
|
from typing import Dict, Optional, List, Set
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtSlot
|
from PyQt5.QtCore import QObject, pyqtSlot
|
||||||
|
|
||||||
|
from UM.Util import parseBool
|
||||||
|
|
||||||
from cura.Machines.ContainerNode import ContainerNode
|
from cura.Machines.ContainerNode import ContainerNode
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +32,7 @@ class QualityGroup(QObject):
|
||||||
self.nodes_for_extruders = {} # type: Dict[int, ContainerNode]
|
self.nodes_for_extruders = {} # type: Dict[int, ContainerNode]
|
||||||
self.quality_type = quality_type
|
self.quality_type = quality_type
|
||||||
self.is_available = False
|
self.is_available = False
|
||||||
|
self.is_experimental = False
|
||||||
|
|
||||||
@pyqtSlot(result = str)
|
@pyqtSlot(result = str)
|
||||||
def getName(self) -> str:
|
def getName(self) -> str:
|
||||||
|
@ -51,3 +55,17 @@ class QualityGroup(QObject):
|
||||||
for extruder_node in self.nodes_for_extruders.values():
|
for extruder_node in self.nodes_for_extruders.values():
|
||||||
result.append(extruder_node)
|
result.append(extruder_node)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def setGlobalNode(self, node: "ContainerNode") -> None:
|
||||||
|
self.node_for_global = node
|
||||||
|
|
||||||
|
# Update is_experimental flag
|
||||||
|
is_experimental = parseBool(node.getMetaDataEntry("is_experimental", False))
|
||||||
|
self.is_experimental |= is_experimental
|
||||||
|
|
||||||
|
def setExtruderNode(self, position: int, node: "ContainerNode") -> None:
|
||||||
|
self.nodes_for_extruders[position] = node
|
||||||
|
|
||||||
|
# Update is_experimental flag
|
||||||
|
is_experimental = parseBool(node.getMetaDataEntry("is_experimental", False))
|
||||||
|
self.is_experimental |= is_experimental
|
||||||
|
|
|
@ -235,7 +235,7 @@ class QualityManager(QObject):
|
||||||
|
|
||||||
for quality_type, quality_node in node.quality_type_map.items():
|
for quality_type, quality_node in node.quality_type_map.items():
|
||||||
quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type)
|
quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type)
|
||||||
quality_group.node_for_global = quality_node
|
quality_group.setGlobalNode(quality_node)
|
||||||
quality_group_dict[quality_type] = quality_group
|
quality_group_dict[quality_type] = quality_group
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ class QualityManager(QObject):
|
||||||
|
|
||||||
quality_group = quality_group_dict[quality_type]
|
quality_group = quality_group_dict[quality_type]
|
||||||
if position not in quality_group.nodes_for_extruders:
|
if position not in quality_group.nodes_for_extruders:
|
||||||
quality_group.nodes_for_extruders[position] = quality_node
|
quality_group.setExtruderNode(position, quality_node)
|
||||||
|
|
||||||
# If the machine has its own specific qualities, for extruders, it should skip the global qualities
|
# If the machine has its own specific qualities, for extruders, it should skip the global qualities
|
||||||
# and use the material/variant specific qualities.
|
# and use the material/variant specific qualities.
|
||||||
|
@ -367,7 +367,7 @@ class QualityManager(QObject):
|
||||||
if node and node.quality_type_map:
|
if node and node.quality_type_map:
|
||||||
for quality_type, quality_node in node.quality_type_map.items():
|
for quality_type, quality_node in node.quality_type_map.items():
|
||||||
quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type)
|
quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type)
|
||||||
quality_group.node_for_global = quality_node
|
quality_group.setGlobalNode(quality_node)
|
||||||
quality_group_dict[quality_type] = quality_group
|
quality_group_dict[quality_type] = quality_group
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ class VariantManager:
|
||||||
break
|
break
|
||||||
return variant_node
|
return variant_node
|
||||||
|
|
||||||
return self._machine_to_variant_dict_map[machine_definition_id].get(variant_type, {}).get(variant_name)
|
return self._machine_to_variant_dict_map.get(machine_definition_id, {}).get(variant_type, {}).get(variant_name)
|
||||||
|
|
||||||
def getVariantNodes(self, machine: "GlobalStack", variant_type: "VariantType") -> Dict[str, ContainerNode]:
|
def getVariantNodes(self, machine: "GlobalStack", variant_type: "VariantType") -> Dict[str, ContainerNode]:
|
||||||
machine_definition_id = machine.definition.getId()
|
machine_definition_id = machine.definition.getId()
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,7 @@ from UM.Logger import Logger
|
||||||
from UM.Qt.Duration import Duration
|
from UM.Qt.Duration import Duration
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
from UM.MimeTypeDatabase import MimeTypeDatabase
|
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
|
||||||
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
@ -361,7 +360,7 @@ class PrintInformation(QObject):
|
||||||
try:
|
try:
|
||||||
mime_type = MimeTypeDatabase.getMimeTypeForFile(name)
|
mime_type = MimeTypeDatabase.getMimeTypeForFile(name)
|
||||||
data = mime_type.stripExtension(name)
|
data = mime_type.stripExtension(name)
|
||||||
except:
|
except MimeTypeNotFoundError:
|
||||||
Logger.log("w", "Unsupported Mime Type Database file extension %s", name)
|
Logger.log("w", "Unsupported Mime Type Database file extension %s", name)
|
||||||
|
|
||||||
if data is not None and check_name is not None:
|
if data is not None and check_name is not None:
|
||||||
|
@ -395,28 +394,14 @@ class PrintInformation(QObject):
|
||||||
return
|
return
|
||||||
active_machine_type_name = global_container_stack.definition.getName()
|
active_machine_type_name = global_container_stack.definition.getName()
|
||||||
|
|
||||||
abbr_machine = ""
|
self._abbr_machine = self._application.getMachineManager().getAbbreviatedMachineName(active_machine_type_name)
|
||||||
for word in re.findall(r"[\w']+", active_machine_type_name):
|
|
||||||
if word.lower() == "ultimaker":
|
|
||||||
abbr_machine += "UM"
|
|
||||||
elif word.isdigit():
|
|
||||||
abbr_machine += word
|
|
||||||
else:
|
|
||||||
stripped_word = self._stripAccents(word.upper())
|
|
||||||
# - use only the first character if the word is too long (> 3 characters)
|
|
||||||
# - use the whole word if it's not too long (<= 3 characters)
|
|
||||||
if len(stripped_word) > 3:
|
|
||||||
stripped_word = stripped_word[0]
|
|
||||||
abbr_machine += stripped_word
|
|
||||||
|
|
||||||
self._abbr_machine = abbr_machine
|
|
||||||
|
|
||||||
## Utility method that strips accents from characters (eg: â -> a)
|
## Utility method that strips accents from characters (eg: â -> a)
|
||||||
def _stripAccents(self, to_strip: str) -> str:
|
def _stripAccents(self, to_strip: str) -> str:
|
||||||
return ''.join(char for char in unicodedata.normalize('NFD', to_strip) if unicodedata.category(char) != 'Mn')
|
return ''.join(char for char in unicodedata.normalize('NFD', to_strip) if unicodedata.category(char) != 'Mn')
|
||||||
|
|
||||||
@pyqtSlot(result = "QVariantMap")
|
@pyqtSlot(result = "QVariantMap")
|
||||||
def getFeaturePrintTimes(self):
|
def getFeaturePrintTimes(self) -> Dict[str, Duration]:
|
||||||
result = {}
|
result = {}
|
||||||
if self._active_build_plate not in self._print_times_per_feature:
|
if self._active_build_plate not in self._print_times_per_feature:
|
||||||
self._initPrintTimesPerFeature(self._active_build_plate)
|
self._initPrintTimesPerFeature(self._active_build_plate)
|
||||||
|
|
|
@ -211,6 +211,11 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||||
self._unique_configurations.sort(key = lambda k: k.printerType)
|
self._unique_configurations.sort(key = lambda k: k.printerType)
|
||||||
self.uniqueConfigurationsChanged.emit()
|
self.uniqueConfigurationsChanged.emit()
|
||||||
|
|
||||||
|
# Returns the unique configurations of the printers within this output device
|
||||||
|
@pyqtProperty("QStringList", notify = uniqueConfigurationsChanged)
|
||||||
|
def uniquePrinterTypes(self) -> List[str]:
|
||||||
|
return list(set([configuration.printerType for configuration in self._unique_configurations]))
|
||||||
|
|
||||||
def _onPrintersChanged(self) -> None:
|
def _onPrintersChanged(self) -> None:
|
||||||
for printer in self._printers:
|
for printer in self._printers:
|
||||||
printer.configurationChanged.connect(self._updateUniqueConfigurations)
|
printer.configurationChanged.connect(self._updateUniqueConfigurations)
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
# Copyright (c) 2015 Ultimaker B.V.
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
from UM.Math.Polygon import Polygon
|
||||||
|
from UM.Qt.QtApplication import QtApplication
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
from UM.Math.Color import Color
|
from UM.Math.Color import Color
|
||||||
|
@ -16,7 +19,7 @@ class ConvexHullNode(SceneNode):
|
||||||
# location an object uses on the buildplate. This area (or area's in case of one at a time printing) is
|
# location an object uses on the buildplate. This area (or area's in case of one at a time printing) is
|
||||||
# then displayed as a transparent shadow. If the adhesion type is set to raft, the area is extruded
|
# then displayed as a transparent shadow. If the adhesion type is set to raft, the area is extruded
|
||||||
# to represent the raft as well.
|
# to represent the raft as well.
|
||||||
def __init__(self, node, hull, thickness, parent = None):
|
def __init__(self, node: SceneNode, hull: Optional[Polygon], thickness: float, parent: Optional[SceneNode] = None) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.setCalculateBoundingBox(False)
|
self.setCalculateBoundingBox(False)
|
||||||
|
@ -25,7 +28,11 @@ class ConvexHullNode(SceneNode):
|
||||||
|
|
||||||
# Color of the drawn convex hull
|
# Color of the drawn convex hull
|
||||||
if not Application.getInstance().getIsHeadLess():
|
if not Application.getInstance().getIsHeadLess():
|
||||||
self._color = Color(*Application.getInstance().getTheme().getColor("convex_hull").getRgb())
|
theme = QtApplication.getInstance().getTheme()
|
||||||
|
if theme:
|
||||||
|
self._color = Color(*theme.getColor("convex_hull").getRgb())
|
||||||
|
else:
|
||||||
|
self._color = Color(0, 0, 0)
|
||||||
else:
|
else:
|
||||||
self._color = Color(0, 0, 0)
|
self._color = Color(0, 0, 0)
|
||||||
|
|
||||||
|
@ -75,7 +82,7 @@ class ConvexHullNode(SceneNode):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _onNodeDecoratorsChanged(self, node):
|
def _onNodeDecoratorsChanged(self, node: SceneNode) -> None:
|
||||||
convex_hull_head = self._node.callDecoration("getConvexHullHead")
|
convex_hull_head = self._node.callDecoration("getConvexHullHead")
|
||||||
if convex_hull_head:
|
if convex_hull_head:
|
||||||
convex_hull_head_builder = MeshBuilder()
|
convex_hull_head_builder = MeshBuilder()
|
||||||
|
|
|
@ -24,8 +24,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
|
|
||||||
## Human-readable name of the extruder.
|
## Human-readable name of the extruder.
|
||||||
NameRole = Qt.UserRole + 2
|
NameRole = Qt.UserRole + 2
|
||||||
## Is the extruder enabled?
|
|
||||||
EnabledRole = Qt.UserRole + 9
|
|
||||||
|
|
||||||
## Colour of the material loaded in the extruder.
|
## Colour of the material loaded in the extruder.
|
||||||
ColorRole = Qt.UserRole + 3
|
ColorRole = Qt.UserRole + 3
|
||||||
|
@ -47,6 +45,12 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
VariantRole = Qt.UserRole + 7
|
VariantRole = Qt.UserRole + 7
|
||||||
StackRole = Qt.UserRole + 8
|
StackRole = Qt.UserRole + 8
|
||||||
|
|
||||||
|
MaterialBrandRole = Qt.UserRole + 9
|
||||||
|
ColorNameRole = Qt.UserRole + 10
|
||||||
|
|
||||||
|
## Is the extruder enabled?
|
||||||
|
EnabledRole = Qt.UserRole + 11
|
||||||
|
|
||||||
## List of colours to display if there is no material or the material has no known
|
## List of colours to display if there is no material or the material has no known
|
||||||
# colour.
|
# colour.
|
||||||
defaultColors = ["#ffc924", "#86ec21", "#22eeee", "#245bff", "#9124ff", "#ff24c8"]
|
defaultColors = ["#ffc924", "#86ec21", "#22eeee", "#245bff", "#9124ff", "#ff24c8"]
|
||||||
|
@ -67,7 +71,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
self.addRoleName(self.MaterialRole, "material")
|
self.addRoleName(self.MaterialRole, "material")
|
||||||
self.addRoleName(self.VariantRole, "variant")
|
self.addRoleName(self.VariantRole, "variant")
|
||||||
self.addRoleName(self.StackRole, "stack")
|
self.addRoleName(self.StackRole, "stack")
|
||||||
|
self.addRoleName(self.MaterialBrandRole, "material_brand")
|
||||||
|
self.addRoleName(self.ColorNameRole, "color_name")
|
||||||
self._update_extruder_timer = QTimer()
|
self._update_extruder_timer = QTimer()
|
||||||
self._update_extruder_timer.setInterval(100)
|
self._update_extruder_timer.setInterval(100)
|
||||||
self._update_extruder_timer.setSingleShot(True)
|
self._update_extruder_timer.setSingleShot(True)
|
||||||
|
@ -183,7 +188,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
|
|
||||||
default_color = self.defaultColors[position] if 0 <= position < len(self.defaultColors) else self.defaultColors[0]
|
default_color = self.defaultColors[position] if 0 <= position < len(self.defaultColors) else self.defaultColors[0]
|
||||||
color = extruder.material.getMetaDataEntry("color_code", default = default_color) if extruder.material else default_color
|
color = extruder.material.getMetaDataEntry("color_code", default = default_color) if extruder.material else default_color
|
||||||
|
material_brand = extruder.material.getMetaDataEntry("brand", default = "generic")
|
||||||
|
color_name = extruder.material.getMetaDataEntry("color_name")
|
||||||
# construct an item with only the relevant information
|
# construct an item with only the relevant information
|
||||||
item = {
|
item = {
|
||||||
"id": extruder.getId(),
|
"id": extruder.getId(),
|
||||||
|
@ -195,6 +201,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
"material": extruder.material.getName() if extruder.material else "",
|
"material": extruder.material.getName() if extruder.material else "",
|
||||||
"variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core
|
"variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core
|
||||||
"stack": extruder,
|
"stack": extruder,
|
||||||
|
"material_brand": material_brand,
|
||||||
|
"color_name": color_name
|
||||||
}
|
}
|
||||||
|
|
||||||
items.append(item)
|
items.append(item)
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import time
|
import time
|
||||||
|
import re
|
||||||
|
import unicodedata
|
||||||
from typing import Any, Callable, List, Dict, TYPE_CHECKING, Optional, cast
|
from typing import Any, Callable, List, Dict, TYPE_CHECKING, Optional, cast
|
||||||
|
|
||||||
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
||||||
|
@ -616,6 +618,14 @@ class MachineManager(QObject):
|
||||||
is_supported = self._current_quality_group.is_available
|
is_supported = self._current_quality_group.is_available
|
||||||
return is_supported
|
return is_supported
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify = activeQualityGroupChanged)
|
||||||
|
def isActiveQualityExperimental(self) -> bool:
|
||||||
|
is_experimental = False
|
||||||
|
if self._global_container_stack:
|
||||||
|
if self._current_quality_group:
|
||||||
|
is_experimental = self._current_quality_group.is_experimental
|
||||||
|
return is_experimental
|
||||||
|
|
||||||
## Returns whether there is anything unsupported in the current set-up.
|
## Returns whether there is anything unsupported in the current set-up.
|
||||||
#
|
#
|
||||||
# The current set-up signifies the global stack and all extruder stacks,
|
# The current set-up signifies the global stack and all extruder stacks,
|
||||||
|
@ -1532,3 +1542,22 @@ class MachineManager(QObject):
|
||||||
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
||||||
self.updateMaterialWithVariant(None)
|
self.updateMaterialWithVariant(None)
|
||||||
self._updateQualityWithMaterial()
|
self._updateQualityWithMaterial()
|
||||||
|
|
||||||
|
## This function will translate any printer type name to an abbreviated printer type name
|
||||||
|
@pyqtSlot(str, result = str)
|
||||||
|
def getAbbreviatedMachineName(self, machine_type_name: str) -> str:
|
||||||
|
abbr_machine = ""
|
||||||
|
for word in re.findall(r"[\w']+", machine_type_name):
|
||||||
|
if word.lower() == "ultimaker":
|
||||||
|
abbr_machine += "UM"
|
||||||
|
elif word.isdigit():
|
||||||
|
abbr_machine += word
|
||||||
|
else:
|
||||||
|
stripped_word = ''.join(char for char in unicodedata.normalize('NFD', word.upper()) if unicodedata.category(char) != 'Mn')
|
||||||
|
# - use only the first character if the word is too long (> 3 characters)
|
||||||
|
# - use the whole word if it's not too long (<= 3 characters)
|
||||||
|
if len(stripped_word) > 3:
|
||||||
|
stripped_word = stripped_word[0]
|
||||||
|
abbr_machine += stripped_word
|
||||||
|
|
||||||
|
return abbr_machine
|
||||||
|
|
|
@ -1,23 +1,33 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtProperty, QUrl
|
from PyQt5.QtCore import pyqtProperty, QUrl
|
||||||
|
|
||||||
from UM.Stage import Stage
|
from UM.Stage import Stage
|
||||||
|
|
||||||
|
|
||||||
|
# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
|
||||||
|
# to indicate this.
|
||||||
|
# * The StageMenuComponent is the horizontal area below the stage bar. This should be used to show stage specific
|
||||||
|
# buttons and elements. This component will be drawn over the bar & main component.
|
||||||
|
# * The MainComponent is the component that will be drawn starting from the bottom of the stageBar and fills the rest
|
||||||
|
# of the screen.
|
||||||
class CuraStage(Stage):
|
class CuraStage(Stage):
|
||||||
|
def __init__(self, parent = None) -> None:
|
||||||
def __init__(self, parent = None):
|
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def stageId(self):
|
def stageId(self) -> str:
|
||||||
return self.getPluginId()
|
return self.getPluginId()
|
||||||
|
|
||||||
@pyqtProperty(QUrl, constant = True)
|
@pyqtProperty(QUrl, constant = True)
|
||||||
def mainComponent(self):
|
def mainComponent(self) -> QUrl:
|
||||||
return self.getDisplayComponent("main")
|
return self.getDisplayComponent("main")
|
||||||
|
|
||||||
@pyqtProperty(QUrl, constant = True)
|
@pyqtProperty(QUrl, constant = True)
|
||||||
def sidebarComponent(self):
|
def sidebarComponent(self) -> QUrl:
|
||||||
return self.getDisplayComponent("sidebar")
|
return self.getDisplayComponent("sidebar")
|
||||||
|
|
||||||
|
@pyqtProperty(QUrl, constant = True)
|
||||||
|
def stageMenuComponent(self) -> QUrl:
|
||||||
|
return self.getDisplayComponent("menu")
|
|
@ -72,7 +72,7 @@ class GcodeStartEndFormatter(Formatter):
|
||||||
# "-1" is global stack, and if the setting value exists in the global stack, use it as the fallback value.
|
# "-1" is global stack, and if the setting value exists in the global stack, use it as the fallback value.
|
||||||
if key in kwargs["-1"]:
|
if key in kwargs["-1"]:
|
||||||
value = kwargs["-1"]
|
value = kwargs["-1"]
|
||||||
if key in kwargs[str(extruder_nr)]:
|
if str(extruder_nr) in kwargs and key in kwargs[str(extruder_nr)]:
|
||||||
value = kwargs[str(extruder_nr)][key]
|
value = kwargs[str(extruder_nr)][key]
|
||||||
|
|
||||||
if value == default_value_str:
|
if value == default_value_str:
|
||||||
|
|
|
@ -22,7 +22,7 @@ Cura.MachineAction
|
||||||
{
|
{
|
||||||
id: firmwareUpdaterMachineAction
|
id: firmwareUpdaterMachineAction
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
UM.I18nCatalog { id: catalog; name:"cura"}
|
UM.I18nCatalog { id: catalog; name: "cura"}
|
||||||
spacing: UM.Theme.getSize("default_margin").height
|
spacing: UM.Theme.getSize("default_margin").height
|
||||||
|
|
||||||
Label
|
Label
|
||||||
|
|
|
@ -20,7 +20,7 @@ UM.Dialog
|
||||||
|
|
||||||
GridLayout
|
GridLayout
|
||||||
{
|
{
|
||||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
columnSpacing: 16 * screenScaleFactor
|
columnSpacing: 16 * screenScaleFactor
|
||||||
|
|
|
@ -16,7 +16,7 @@ Button
|
||||||
{
|
{
|
||||||
id: modelCheckerButton
|
id: modelCheckerButton
|
||||||
|
|
||||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||||
|
|
||||||
visible: manager.hasWarnings
|
visible: manager.hasWarnings
|
||||||
tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.")
|
tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.")
|
||||||
|
|
|
@ -1,26 +1,21 @@
|
||||||
// Copyright (c) 2017 Ultimaker B.V.
|
// Copyright (c) 2017 Ultimaker B.V.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.10
|
||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.4
|
||||||
|
|
||||||
import UM 1.3 as UM
|
import UM 1.3 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
// parent could be undefined as this component is not visible at all times
|
|
||||||
width: parent ? parent.width : 0
|
|
||||||
height: parent ? parent.height : 0
|
|
||||||
|
|
||||||
// We show a nice overlay on the 3D viewer when the current output device has no monitor view
|
// We show a nice overlay on the 3D viewer when the current output device has no monitor view
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
id: viewportOverlay
|
id: viewportOverlay
|
||||||
|
|
||||||
color: UM.Theme.getColor("viewport_overlay")
|
color: UM.Theme.getColor("viewport_overlay")
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
height: parent.height
|
|
||||||
|
|
||||||
MouseArea
|
MouseArea
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -33,13 +28,13 @@ Item
|
||||||
{
|
{
|
||||||
id: monitorViewComponent
|
id: monitorViewComponent
|
||||||
|
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
|
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
property real maximumWidth: parent.width
|
property real maximumWidth: parent.width
|
||||||
property real maximumHeight: parent.height
|
property real maximumHeight: parent.height
|
||||||
|
|
||||||
sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null
|
sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null
|
||||||
visible: sourceComponent != null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
23
plugins/MonitorStage/MonitorMenu.qml
Normal file
23
plugins/MonitorStage/MonitorMenu.qml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
|
import UM 1.3 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
signal showTooltip(Item item, point location, string text)
|
||||||
|
signal hideTooltip()
|
||||||
|
|
||||||
|
Cura.MachineSelector
|
||||||
|
{
|
||||||
|
id: machineSelection
|
||||||
|
headerCornerSide: Cura.RoundedRectangle.Direction.All
|
||||||
|
width: UM.Theme.getSize("machine_selector_widget").width
|
||||||
|
height: parent.height
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,15 +65,10 @@ class MonitorStage(CuraStage):
|
||||||
# We can only connect now, as we need to be sure that everything is loaded (plugins get created quite early)
|
# We can only connect now, as we need to be sure that everything is loaded (plugins get created quite early)
|
||||||
Application.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
|
Application.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
|
||||||
self._onOutputDevicesChanged()
|
self._onOutputDevicesChanged()
|
||||||
self._updateMainOverlay()
|
|
||||||
self._updateSidebar()
|
|
||||||
|
|
||||||
def _updateMainOverlay(self):
|
plugin_path = Application.getInstance().getPluginRegistry().getPluginPath(self.getPluginId())
|
||||||
main_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("MonitorStage"),
|
if plugin_path is not None:
|
||||||
"MonitorMainView.qml")
|
menu_component_path = os.path.join(plugin_path, "MonitorMenu.qml")
|
||||||
|
main_component_path = os.path.join(plugin_path, "MonitorMain.qml")
|
||||||
|
self.addDisplayComponent("menu", menu_component_path)
|
||||||
self.addDisplayComponent("main", main_component_path)
|
self.addDisplayComponent("main", main_component_path)
|
||||||
|
|
||||||
def _updateSidebar(self):
|
|
||||||
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
|
|
||||||
"MonitorSidebar.qml")
|
|
||||||
self.addDisplayComponent("sidebar", sidebar_component_path)
|
|
||||||
|
|
|
@ -7,14 +7,16 @@ from . import MonitorStage
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
i18n_catalog = i18nCatalog("cura")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
def getMetaData():
|
def getMetaData():
|
||||||
return {
|
return {
|
||||||
"stage": {
|
"stage": {
|
||||||
"name": i18n_catalog.i18nc("@item:inmenu", "Monitor"),
|
"name": i18n_catalog.i18nc("@item:inmenu", "Monitor"),
|
||||||
"weight": 1
|
"weight": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
return {
|
return {
|
||||||
"stage": MonitorStage.MonitorStage()
|
"stage": MonitorStage.MonitorStage()
|
||||||
|
|
|
@ -55,14 +55,14 @@ class PostProcessingPlugin(QObject, Extension):
|
||||||
def selectedScriptDefinitionId(self) -> Optional[str]:
|
def selectedScriptDefinitionId(self) -> Optional[str]:
|
||||||
try:
|
try:
|
||||||
return self._script_list[self._selected_script_index].getDefinitionId()
|
return self._script_list[self._selected_script_index].getDefinitionId()
|
||||||
except:
|
except IndexError:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify=selectedIndexChanged)
|
@pyqtProperty(str, notify=selectedIndexChanged)
|
||||||
def selectedScriptStackId(self) -> Optional[str]:
|
def selectedScriptStackId(self) -> Optional[str]:
|
||||||
try:
|
try:
|
||||||
return self._script_list[self._selected_script_index].getStackId()
|
return self._script_list[self._selected_script_index].getStackId()
|
||||||
except:
|
except IndexError:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
## Execute all post-processing scripts on the gcode.
|
## Execute all post-processing scripts on the gcode.
|
||||||
|
|
|
@ -31,7 +31,7 @@ UM.Dialog
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||||
id: base
|
id: base
|
||||||
property int columnWidth: Math.round((base.width / 2) - UM.Theme.getSize("default_margin").width)
|
property int columnWidth: Math.round((base.width / 2) - UM.Theme.getSize("default_margin").width)
|
||||||
property int textMargin: Math.round(UM.Theme.getSize("default_margin").width / 2)
|
property int textMargin: Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||||
|
@ -260,7 +260,7 @@ UM.Dialog
|
||||||
|
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
color: UM.Theme.getColor("sidebar")
|
color: UM.Theme.getColor("main_background")
|
||||||
anchors.left: activeScripts.right
|
anchors.left: activeScripts.right
|
||||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
3
plugins/PostProcessingPlugin/scripts/ExampleScript.md
Normal file
3
plugins/PostProcessingPlugin/scripts/ExampleScript.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
A good example script is SearchAndReplace.py.
|
||||||
|
If you have any questions please ask them at:
|
||||||
|
https://github.com/Ultimaker/Cura/issues
|
|
@ -1,43 +0,0 @@
|
||||||
# Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V.
|
|
||||||
# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
|
|
||||||
from ..Script import Script
|
|
||||||
|
|
||||||
class ExampleScript(Script):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
def getSettingDataString(self):
|
|
||||||
return """{
|
|
||||||
"name":"Example script",
|
|
||||||
"key": "ExampleScript",
|
|
||||||
"metadata": {},
|
|
||||||
"version": 2,
|
|
||||||
"settings":
|
|
||||||
{
|
|
||||||
"test":
|
|
||||||
{
|
|
||||||
"label": "Test",
|
|
||||||
"description": "None",
|
|
||||||
"unit": "mm",
|
|
||||||
"type": "float",
|
|
||||||
"default_value": 0.5,
|
|
||||||
"minimum_value": "0",
|
|
||||||
"minimum_value_warning": "0.1",
|
|
||||||
"maximum_value_warning": "1"
|
|
||||||
},
|
|
||||||
"derp":
|
|
||||||
{
|
|
||||||
"label": "zomg",
|
|
||||||
"description": "afgasgfgasfgasf",
|
|
||||||
"unit": "mm",
|
|
||||||
"type": "float",
|
|
||||||
"default_value": 0.5,
|
|
||||||
"minimum_value": "0",
|
|
||||||
"minimum_value_warning": "0.1",
|
|
||||||
"maximum_value_warning": "1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
|
|
||||||
def execute(self, data):
|
|
||||||
return data
|
|
140
plugins/PrepareStage/PrepareMenu.qml
Normal file
140
plugins/PrepareStage/PrepareMenu.qml
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
|
import UM 1.3 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
import QtGraphicalEffects 1.0 // For the dropshadow
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: prepareMenu
|
||||||
|
// 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"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item to ensure that all of the buttons are nicely centered.
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: openFileButton.width + itemRow.width + UM.Theme.getSize("default_margin").width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
id: itemRow
|
||||||
|
|
||||||
|
anchors.left: openFileButton.right
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
width: Math.round(0.9 * prepareMenu.width)
|
||||||
|
height: parent.height
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Cura.MachineSelector
|
||||||
|
{
|
||||||
|
id: machineSelection
|
||||||
|
z: openFileButton.z - 1 //Ensure that the tooltip of the open file button stays above the item row.
|
||||||
|
headerCornerSide: Cura.RoundedRectangle.Direction.Left
|
||||||
|
Layout.minimumWidth: UM.Theme.getSize("machine_selector_widget").width
|
||||||
|
Layout.maximumWidth: UM.Theme.getSize("machine_selector_widget").width
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: parent.height
|
||||||
|
width: UM.Theme.getSize("default_lining").width
|
||||||
|
color: UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.QuickConfigurationSelector
|
||||||
|
{
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredWidth: itemRow.width - machineSelection.width - printSetupSelectorItem.width - 2 * UM.Theme.getSize("default_lining").width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: parent.height
|
||||||
|
width: UM.Theme.getSize("default_lining").width
|
||||||
|
color: UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: printSetupSelectorItem
|
||||||
|
// This is a work around to prevent the printSetupSelector from having to be re-loaded every time
|
||||||
|
// a stage switch is done.
|
||||||
|
children: [printSetupSelector]
|
||||||
|
height: childrenRect.height
|
||||||
|
width: childrenRect.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: openFileButton
|
||||||
|
height: UM.Theme.getSize("stage_menu").height
|
||||||
|
width: UM.Theme.getSize("stage_menu").height
|
||||||
|
onClicked: Cura.Actions.open.trigger()
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
contentItem: Item
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: buttonIcon
|
||||||
|
anchors.centerIn: parent
|
||||||
|
source: UM.Theme.getIcon("load")
|
||||||
|
width: UM.Theme.getSize("button_icon").width
|
||||||
|
height: UM.Theme.getSize("button_icon").height
|
||||||
|
color: UM.Theme.getColor("toolbar_button_text")
|
||||||
|
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
id: background
|
||||||
|
height: UM.Theme.getSize("stage_menu").height
|
||||||
|
width: UM.Theme.getSize("stage_menu").height
|
||||||
|
|
||||||
|
radius: UM.Theme.getSize("default_radius").width
|
||||||
|
color: openFileButton.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
|
||||||
|
}
|
||||||
|
|
||||||
|
DropShadow
|
||||||
|
{
|
||||||
|
id: shadow
|
||||||
|
// Don't blur the shadow
|
||||||
|
radius: 0
|
||||||
|
anchors.fill: background
|
||||||
|
source: background
|
||||||
|
verticalOffset: 2
|
||||||
|
visible: true
|
||||||
|
color: UM.Theme.getColor("action_button_shadow")
|
||||||
|
// Should always be drawn behind the background.
|
||||||
|
z: background.z - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,13 +2,14 @@
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
import os.path
|
import os.path
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
from UM.PluginRegistry import PluginRegistry
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
from cura.Stages.CuraStage import CuraStage
|
from cura.Stages.CuraStage import CuraStage
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Stage for preparing model (slicing).
|
## Stage for preparing model (slicing).
|
||||||
class PrepareStage(CuraStage):
|
class PrepareStage(CuraStage):
|
||||||
|
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
Application.getInstance().engineCreatedSignal.connect(self._engineCreated)
|
Application.getInstance().engineCreatedSignal.connect(self._engineCreated)
|
||||||
|
@ -16,4 +17,7 @@ class PrepareStage(CuraStage):
|
||||||
def _engineCreated(self):
|
def _engineCreated(self):
|
||||||
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
|
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
|
||||||
"PrepareSidebar.qml")
|
"PrepareSidebar.qml")
|
||||||
|
|
||||||
|
menu_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMenu.qml")
|
||||||
|
self.addDisplayComponent("menu", menu_component_path)
|
||||||
self.addDisplayComponent("sidebar", sidebar_component_path)
|
self.addDisplayComponent("sidebar", sidebar_component_path)
|
||||||
|
|
18
plugins/PreviewStage/PreviewMain.qml
Normal file
18
plugins/PreviewStage/PreviewMain.qml
Normal 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 : ""
|
||||||
|
}
|
77
plugins/PreviewStage/PreviewMenu.qml
Normal file
77
plugins/PreviewStage/PreviewMenu.qml
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
property real itemHeight: height - 2 * UM.Theme.getSize("default_lining").width
|
||||||
|
|
||||||
|
UM.I18nCatalog
|
||||||
|
{
|
||||||
|
id: catalog
|
||||||
|
name: "cura"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: stageMenuRow
|
||||||
|
anchors.centerIn: parent
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
Cura.ViewsSelector
|
||||||
|
{
|
||||||
|
id: viewsSelector
|
||||||
|
height: parent.height
|
||||||
|
width: UM.Theme.getSize("views_selector").width
|
||||||
|
headerCornerSide: Cura.RoundedRectangle.Direction.Left
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: parent.height
|
||||||
|
// If there is no viewPanel, we only need a single spacer, so hide this one.
|
||||||
|
visible: viewPanel.source != ""
|
||||||
|
width: visible ? UM.Theme.getSize("default_lining").width : 0
|
||||||
|
|
||||||
|
color: UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader
|
||||||
|
{
|
||||||
|
id: viewPanel
|
||||||
|
height: parent.height
|
||||||
|
width: childrenRect.width
|
||||||
|
source: UM.Controller.activeView != null && UM.Controller.activeView.stageMenuComponent != null ? UM.Controller.activeView.stageMenuComponent : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: parent.height
|
||||||
|
width: UM.Theme.getSize("default_lining").width
|
||||||
|
color: UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: printSetupSelectorItem
|
||||||
|
// This is a work around to prevent the printSetupSelector from having to be re-loaded every time
|
||||||
|
// a stage switch is done.
|
||||||
|
children: [printSetupSelector]
|
||||||
|
height: childrenRect.height
|
||||||
|
width: childrenRect.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
plugins/PreviewStage/PreviewStage.py
Normal file
51
plugins/PreviewStage/PreviewStage.py
Normal 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)
|
22
plugins/PreviewStage/__init__.py
Normal file
22
plugins/PreviewStage/__init__.py
Normal 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)
|
||||||
|
}
|
8
plugins/PreviewStage/plugin.json
Normal file
8
plugins/PreviewStage/plugin.json
Normal 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"
|
||||||
|
}
|
|
@ -13,23 +13,20 @@ Item
|
||||||
{
|
{
|
||||||
id: sliderRoot
|
id: sliderRoot
|
||||||
|
|
||||||
// handle properties
|
// Handle properties
|
||||||
property real handleSize: 10
|
property real handleSize: UM.Theme.getSize("slider_handle").width
|
||||||
property real handleRadius: handleSize / 2
|
property real handleRadius: handleSize / 2
|
||||||
property real minimumRangeHandleSize: handleSize / 2
|
property real minimumRangeHandleSize: handleSize / 2
|
||||||
property color upperHandleColor: "black"
|
property color upperHandleColor: UM.Theme.getColor("slider_handle")
|
||||||
property color lowerHandleColor: "black"
|
property color lowerHandleColor: UM.Theme.getColor("slider_handle")
|
||||||
property color rangeHandleColor: "black"
|
property color rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
|
||||||
property color handleActiveColor: "white"
|
property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
||||||
property real handleLabelWidth: width
|
|
||||||
property var activeHandle: upperHandle
|
property var activeHandle: upperHandle
|
||||||
|
|
||||||
// track properties
|
// Track properties
|
||||||
property real trackThickness: 4 // width of the slider track
|
property real trackThickness: UM.Theme.getSize("slider_groove").width // width of the slider track
|
||||||
property real trackRadius: trackThickness / 2
|
property real trackRadius: UM.Theme.getSize("slider_groove_radius").width
|
||||||
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"
|
|
||||||
|
|
||||||
// value properties
|
// value properties
|
||||||
property real maximumValue: 100
|
property real maximumValue: 100
|
||||||
|
@ -80,7 +77,7 @@ Item
|
||||||
return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue)
|
return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// slider track
|
// Slider track
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
id: track
|
id: track
|
||||||
|
@ -90,8 +87,6 @@ Item
|
||||||
radius: sliderRoot.trackRadius
|
radius: sliderRoot.trackRadius
|
||||||
anchors.centerIn: sliderRoot
|
anchors.centerIn: sliderRoot
|
||||||
color: sliderRoot.trackColor
|
color: sliderRoot.trackColor
|
||||||
border.width: sliderRoot.trackBorderWidth
|
|
||||||
border.color: sliderRoot.trackBorderColor
|
|
||||||
visible: sliderRoot.layersVisible
|
visible: sliderRoot.layersVisible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +101,7 @@ Item
|
||||||
anchors.horizontalCenter: sliderRoot.horizontalCenter
|
anchors.horizontalCenter: sliderRoot.horizontalCenter
|
||||||
visible: sliderRoot.layersVisible
|
visible: sliderRoot.layersVisible
|
||||||
|
|
||||||
// set the new value when dragging
|
// Set the new value when dragging
|
||||||
function onHandleDragged()
|
function onHandleDragged()
|
||||||
{
|
{
|
||||||
sliderRoot.manuallyChanged = true
|
sliderRoot.manuallyChanged = true
|
||||||
|
@ -140,9 +135,10 @@ Item
|
||||||
|
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
width: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth
|
width: sliderRoot.trackThickness
|
||||||
height: parent.height + sliderRoot.handleSize
|
height: parent.height + sliderRoot.handleSize
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
radius: sliderRoot.trackRadius
|
||||||
color: sliderRoot.rangeHandleColor
|
color: sliderRoot.rangeHandleColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,9 +163,9 @@ Item
|
||||||
id: rangleHandleLabel
|
id: rangleHandleLabel
|
||||||
|
|
||||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
x: parent.x + parent.width + UM.Theme.getSize("default_margin").width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
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
|
visible: sliderRoot.activeHandle == parent
|
||||||
|
|
||||||
// custom properties
|
// custom properties
|
||||||
|
@ -275,7 +271,7 @@ Item
|
||||||
id: upperHandleLabel
|
id: upperHandleLabel
|
||||||
|
|
||||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
x: parent.x - parent.width - width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
target: Qt.point(sliderRoot.width, y + height / 2)
|
target: Qt.point(sliderRoot.width, y + height / 2)
|
||||||
visible: sliderRoot.activeHandle == parent
|
visible: sliderRoot.activeHandle == parent
|
||||||
|
@ -385,9 +381,9 @@ Item
|
||||||
id: lowerHandleLabel
|
id: lowerHandleLabel
|
||||||
|
|
||||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
x: parent.x - parent.width - width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
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
|
visible: sliderRoot.activeHandle == parent
|
||||||
|
|
||||||
// custom properties
|
// custom properties
|
||||||
|
|
|
@ -14,19 +14,17 @@ Item
|
||||||
id: sliderRoot
|
id: sliderRoot
|
||||||
|
|
||||||
// handle properties
|
// handle properties
|
||||||
property real handleSize: 10
|
property real handleSize: UM.Theme.getSize("slider_handle").width
|
||||||
property real handleRadius: handleSize / 2
|
property real handleRadius: handleSize / 2
|
||||||
property color handleColor: "black"
|
property color handleColor: UM.Theme.getColor("slider_handle")
|
||||||
property color handleActiveColor: "white"
|
property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
||||||
property color rangeColor: "black"
|
property color rangeColor: UM.Theme.getColor("slider_groove_fill")
|
||||||
property real handleLabelWidth: width
|
property real handleLabelWidth: width
|
||||||
|
|
||||||
// track properties
|
// 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 real trackRadius: UM.Theme.getSize("slider_groove_radius").width
|
||||||
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"
|
|
||||||
|
|
||||||
// value properties
|
// value properties
|
||||||
property real maximumValue: 100
|
property real maximumValue: 100
|
||||||
|
@ -68,8 +66,6 @@ Item
|
||||||
radius: sliderRoot.trackRadius
|
radius: sliderRoot.trackRadius
|
||||||
anchors.centerIn: sliderRoot
|
anchors.centerIn: sliderRoot
|
||||||
color: sliderRoot.trackColor
|
color: sliderRoot.trackColor
|
||||||
border.width: sliderRoot.trackBorderWidth
|
|
||||||
border.color: sliderRoot.trackBorderColor
|
|
||||||
visible: sliderRoot.pathsVisible
|
visible: sliderRoot.pathsVisible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,9 +82,10 @@ Item
|
||||||
|
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
height: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth
|
height: sliderRoot.trackThickness
|
||||||
width: parent.width + sliderRoot.handleSize
|
width: parent.width + sliderRoot.handleSize
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
radius: sliderRoot.trackRadius
|
||||||
color: sliderRoot.rangeColor
|
color: sliderRoot.rangeColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ from UM.Mesh.MeshBuilder import MeshBuilder
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from UM.Platform import Platform
|
from UM.Platform import Platform
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
from UM.Qt.QtApplication import QtApplication
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
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.OpenGLContext import OpenGLContext
|
||||||
from UM.View.GL.ShaderProgram import ShaderProgram
|
from UM.View.GL.ShaderProgram import ShaderProgram
|
||||||
|
|
||||||
from UM.View.View import View
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
from cura.CuraView import CuraView
|
||||||
from cura.Scene.ConvexHullNode import ConvexHullNode
|
from cura.Scene.ConvexHullNode import ConvexHullNode
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
|
|
||||||
|
@ -48,15 +49,15 @@ catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
## View used to display g-code paths.
|
## View used to display g-code paths.
|
||||||
class SimulationView(View):
|
class SimulationView(CuraView):
|
||||||
# Must match SimulationView.qml
|
# Must match SimulationView.qml
|
||||||
LAYER_VIEW_TYPE_MATERIAL_TYPE = 0
|
LAYER_VIEW_TYPE_MATERIAL_TYPE = 0
|
||||||
LAYER_VIEW_TYPE_LINE_TYPE = 1
|
LAYER_VIEW_TYPE_LINE_TYPE = 1
|
||||||
LAYER_VIEW_TYPE_FEEDRATE = 2
|
LAYER_VIEW_TYPE_FEEDRATE = 2
|
||||||
LAYER_VIEW_TYPE_THICKNESS = 3
|
LAYER_VIEW_TYPE_THICKNESS = 3
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self, parent = None) -> None:
|
||||||
super().__init__()
|
super().__init__(parent)
|
||||||
|
|
||||||
self._max_layers = 0
|
self._max_layers = 0
|
||||||
self._current_layer_num = 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"),
|
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"))
|
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:
|
def _evaluateCompatibilityMode(self) -> bool:
|
||||||
return OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode"))
|
return OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode"))
|
||||||
|
|
||||||
|
|
|
@ -1,808 +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
|
|
||||||
visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
|
|
||||||
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
top: parent.bottom
|
|
||||||
topMargin: UM.Theme.getSize("slider_layerview_margin").height
|
|
||||||
left: parent.left
|
|
||||||
}
|
|
||||||
|
|
||||||
PathSlider
|
|
||||||
{
|
|
||||||
id: pathSlider
|
|
||||||
|
|
||||||
height: UM.Theme.getSize("slider_handle").width
|
|
||||||
anchors.left: playButton.right
|
|
||||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
|
||||||
anchors.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
|
|
||||||
{
|
|
||||||
top: !UM.SimulationView.compatibilityMode ? pathSlider.bottom : parent.top
|
|
||||||
topMargin: !UM.SimulationView.compatibilityMode ? UM.Theme.getSize("default_margin").height : 0
|
|
||||||
right: parent.right
|
|
||||||
rightMargin: UM.Theme.getSize("slider_layerview_margin").width
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
{
|
|
||||||
verticalCenter: pathSlider.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
212
plugins/SimulationView/SimulationViewMainComponent.qml
Normal file
212
plugins/SimulationView/SimulationViewMainComponent.qml
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
// 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.4 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("slider_layerview_size").height
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.SimpleButton
|
||||||
|
{
|
||||||
|
id: playButton
|
||||||
|
iconSource: !is_simulation_playing ? "./resources/simulation_resume.svg": "./resources/simulation_pause.svg"
|
||||||
|
width: UM.Theme.getSize("small_button").width
|
||||||
|
height: UM.Theme.getSize("small_button").height
|
||||||
|
hoverBackgroundColor: UM.Theme.getColor("small_button_hover")
|
||||||
|
hoverColor: UM.Theme.getColor("small_button_text_hover")
|
||||||
|
color: UM.Theme.getColor("small_button_text")
|
||||||
|
iconMargin: 0.5 * UM.Theme.getSize("wide_lining").width
|
||||||
|
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("slider_layerview_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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
530
plugins/SimulationView/SimulationViewMenuComponent.qml
Normal file
530
plugins/SimulationView/SimulationViewMenuComponent.qml
Normal file
|
@ -0,0 +1,530 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
|
||||||
|
Cura.ExpandableComponent
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
|
||||||
|
width: UM.Theme.getSize("layerview_menu_size").width
|
||||||
|
iconSource: UM.Theme.getIcon("pencil")
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
headerItem: Label
|
||||||
|
{
|
||||||
|
id: layerViewTypesLabel
|
||||||
|
text: catalog.i18nc("@label", "Color scheme")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("setting_control_text")
|
||||||
|
height: base.height
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
popupItem: Column
|
||||||
|
{
|
||||||
|
id: viewSettings
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
width: UM.Theme.getSize("layerview_menu_size").width - 2 * UM.Theme.getSize("default_margin").width
|
||||||
|
height: implicitHeight
|
||||||
|
|
||||||
|
spacing: UM.Theme.getSize("layerview_row_spacing").height
|
||||||
|
|
||||||
|
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
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
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
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
width: parent.width
|
||||||
|
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")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
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")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,19 +8,21 @@ from . import SimulationViewProxy, SimulationView
|
||||||
|
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
def getMetaData():
|
def getMetaData():
|
||||||
return {
|
return {
|
||||||
"view": {
|
"view": {
|
||||||
"name": catalog.i18nc("@item:inlistbox", "Layer view"),
|
"name": catalog.i18nc("@item:inlistbox", "Layer view"),
|
||||||
"view_panel": "SimulationView.qml",
|
"weight": 0
|
||||||
"weight": 2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def createSimulationViewProxy(engine, script_engine):
|
def createSimulationViewProxy(engine, script_engine):
|
||||||
return SimulationViewProxy.SimulationViewProxy()
|
return SimulationViewProxy.SimulationViewProxy()
|
||||||
|
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
simulation_view = SimulationView.SimulationView()
|
simulation_view = SimulationView.SimulationView()
|
||||||
qmlRegisterSingletonType(SimulationViewProxy.SimulationViewProxy, "UM", 1, 0, "SimulationView", simulation_view.getProxy)
|
qmlRegisterSingletonType(SimulationViewProxy.SimulationViewProxy, "UM", 1, 0, "SimulationView", simulation_view.getProxy)
|
||||||
return { "view": SimulationView.SimulationView()}
|
return { "view": simulation_view}
|
||||||
|
|
|
@ -10,7 +10,8 @@ def getMetaData():
|
||||||
return {
|
return {
|
||||||
"view": {
|
"view": {
|
||||||
"name": i18n_catalog.i18nc("@item:inmenu", "Solid view"),
|
"name": i18n_catalog.i18nc("@item:inmenu", "Solid view"),
|
||||||
"weight": 0
|
"weight": 0,
|
||||||
|
"visible": False
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ Window
|
||||||
maximumWidth: minimumWidth
|
maximumWidth: minimumWidth
|
||||||
minimumHeight: height
|
minimumHeight: height
|
||||||
maximumHeight: minimumHeight
|
maximumHeight: minimumHeight
|
||||||
color: UM.Theme.getColor("sidebar")
|
color: UM.Theme.getColor("main_background")
|
||||||
UM.I18nCatalog
|
UM.I18nCatalog
|
||||||
{
|
{
|
||||||
id: catalog
|
id: catalog
|
||||||
name:"cura"
|
name: "cura"
|
||||||
}
|
}
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,12 +36,19 @@ Item
|
||||||
var pg_name = "printingGuidelines"
|
var pg_name = "printingGuidelines"
|
||||||
return (pg_name in packageData.links) ? packageData.links[pg_name] : undefined
|
return (pg_name in packageData.links) ? packageData.links[pg_name] : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property var materialWebsiteUrl:
|
||||||
|
{
|
||||||
|
var pg_name = "website"
|
||||||
|
return (pg_name in packageData.links) ? packageData.links[pg_name] : undefined
|
||||||
|
}
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
height: visible ? childrenRect.height : 0
|
height: visible ? childrenRect.height : 0
|
||||||
|
|
||||||
visible: packageData.type == "material" &&
|
visible: packageData.type == "material" &&
|
||||||
(packageData.has_configs || technicalDataSheetUrl !== undefined ||
|
(packageData.has_configs || technicalDataSheetUrl !== undefined ||
|
||||||
safetyDataSheetUrl !== undefined || printingGuidelinesUrl !== undefined)
|
safetyDataSheetUrl !== undefined || printingGuidelinesUrl !== undefined ||
|
||||||
|
materialWebsiteUrl !== undefined)
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
|
@ -83,7 +90,7 @@ Item
|
||||||
model: packageData.supported_configs
|
model: packageData.supported_configs
|
||||||
headerDelegate: Rectangle
|
headerDelegate: Rectangle
|
||||||
{
|
{
|
||||||
color: UM.Theme.getColor("sidebar")
|
color: UM.Theme.getColor("main_background")
|
||||||
height: UM.Theme.getSize("toolbox_chart_row").height
|
height: UM.Theme.getSize("toolbox_chart_row").height
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
@ -180,7 +187,8 @@ Item
|
||||||
anchors.top: combatibilityItem.bottom
|
anchors.top: combatibilityItem.bottom
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height / 2
|
anchors.topMargin: UM.Theme.getSize("default_margin").height / 2
|
||||||
visible: base.technicalDataSheetUrl !== undefined ||
|
visible: base.technicalDataSheetUrl !== undefined ||
|
||||||
base.safetyDataSheetUrl !== undefined || base.printingGuidelinesUrl !== undefined
|
base.safetyDataSheetUrl !== undefined || base.printingGuidelinesUrl !== undefined ||
|
||||||
|
base.materialWebsiteUrl !== undefined
|
||||||
height: visible ? contentHeight : 0
|
height: visible ? contentHeight : 0
|
||||||
text:
|
text:
|
||||||
{
|
{
|
||||||
|
@ -208,6 +216,16 @@ Item
|
||||||
var pg_name = catalog.i18nc("@action:label", "Printing Guidelines")
|
var pg_name = catalog.i18nc("@action:label", "Printing Guidelines")
|
||||||
result += "<a href='%1'>%2</a>".arg(base.printingGuidelinesUrl).arg(pg_name)
|
result += "<a href='%1'>%2</a>".arg(base.printingGuidelinesUrl).arg(pg_name)
|
||||||
}
|
}
|
||||||
|
if (base.materialWebsiteUrl !== undefined)
|
||||||
|
{
|
||||||
|
if (result.length > 0)
|
||||||
|
{
|
||||||
|
result += "<br/>"
|
||||||
|
}
|
||||||
|
var pg_name = catalog.i18nc("@action:label", "Website")
|
||||||
|
result += "<a href='%1'>%2</a>".arg(base.materialWebsiteUrl).arg(pg_name)
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
font: UM.Theme.getFont("very_small")
|
font: UM.Theme.getFont("very_small")
|
||||||
|
|
|
@ -37,7 +37,7 @@ Item
|
||||||
leftMargin: UM.Theme.getSize("wide_margin").width
|
leftMargin: UM.Theme.getSize("wide_margin").width
|
||||||
topMargin: UM.Theme.getSize("wide_margin").height
|
topMargin: UM.Theme.getSize("wide_margin").height
|
||||||
}
|
}
|
||||||
color: white //Always a white background for image (regardless of theme).
|
color: "white" //Always a white background for image (regardless of theme).
|
||||||
Image
|
Image
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -144,10 +144,6 @@ Item
|
||||||
{
|
{
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if (details.author_email)
|
|
||||||
{
|
|
||||||
return "<a href=\"mailto:" + details.author_email+"?Subject=Cura: " + details.name + "\">" + details.author_name + "</a>"
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return "<a href=\"" + details.website + "\">" + details.author_name + "</a>"
|
return "<a href=\"" + details.website + "\">" + details.author_name + "</a>"
|
||||||
|
|
|
@ -37,7 +37,7 @@ Item
|
||||||
anchors.top: packageName.bottom
|
anchors.top: packageName.bottom
|
||||||
width: parent.width
|
width: parent.width
|
||||||
text: model.description
|
text: model.description
|
||||||
maximumLineCount: 6
|
maximumLineCount: 25
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
|
|
|
@ -19,10 +19,10 @@ Button
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
visible: control.active
|
visible: control.active
|
||||||
color: UM.Theme.getColor("sidebar_header_highlight_hover")
|
color: UM.Theme.getColor("toolbox_header_highlight_hover")
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: UM.Theme.getSize("sidebar_header_highlight").height
|
height: UM.Theme.getSize("toolbox_header_highlight").height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
label: Label
|
label: Label
|
||||||
|
@ -32,15 +32,15 @@ Button
|
||||||
{
|
{
|
||||||
if(control.hovered)
|
if(control.hovered)
|
||||||
{
|
{
|
||||||
return UM.Theme.getColor("topbar_button_text_hovered");
|
return UM.Theme.getColor("toolbox_header_button_text_hovered");
|
||||||
}
|
}
|
||||||
if(control.active)
|
if(control.active)
|
||||||
{
|
{
|
||||||
return UM.Theme.getColor("topbar_button_text_active");
|
return UM.Theme.getColor("toolbox_header_button_text_active");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return UM.Theme.getColor("topbar_button_text_inactive");
|
return UM.Theme.getColor("toolbox_header_button_text_inactive");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic")
|
font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic")
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1,014 KiB |
BIN
plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png
Normal file
BIN
plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 774 KiB |
BIN
plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png
Normal file
BIN
plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
|
@ -9,10 +9,10 @@ import Cura 1.0 as Cura
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
property var iconSource: null;
|
property var iconSource: null;
|
||||||
color: clickArea.containsMouse ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary"); // "Cura Blue"
|
color: "#0a0850" // TODO: Theme!
|
||||||
height: width;
|
height: width;
|
||||||
radius: Math.round(0.5 * width);
|
radius: Math.round(0.5 * width);
|
||||||
width: 36 * screenScaleFactor;
|
width: 24 * screenScaleFactor;
|
||||||
|
|
||||||
UM.RecolorImage {
|
UM.RecolorImage {
|
||||||
id: icon;
|
id: icon;
|
||||||
|
|
|
@ -13,7 +13,7 @@ Component {
|
||||||
property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width;
|
property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width;
|
||||||
property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width;
|
property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
color: UM.Theme.getColor("sidebar");
|
color: UM.Theme.getColor("main_background");
|
||||||
visible: OutputDevice != null;
|
visible: OutputDevice != null;
|
||||||
|
|
||||||
UM.I18nCatalog {
|
UM.I18nCatalog {
|
||||||
|
|
|
@ -10,14 +10,13 @@ import QtGraphicalEffects 1.0
|
||||||
|
|
||||||
Component
|
Component
|
||||||
{
|
{
|
||||||
Rectangle
|
Item
|
||||||
{
|
{
|
||||||
id: monitorFrame
|
id: monitorFrame
|
||||||
|
|
||||||
property var emphasisColor: UM.Theme.getColor("setting_control_border_highlight")
|
property var emphasisColor: UM.Theme.getColor("setting_control_border_highlight")
|
||||||
property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width
|
property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width
|
||||||
|
|
||||||
color: "transparent"
|
|
||||||
height: maximumHeight
|
height: maximumHeight
|
||||||
onVisibleChanged:
|
onVisibleChanged:
|
||||||
{
|
{
|
||||||
|
@ -48,13 +47,45 @@ Component
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScrollView
|
||||||
|
{
|
||||||
|
id: printers
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: queue.left
|
||||||
|
right: queue.right
|
||||||
|
top: parent.top
|
||||||
|
topMargin: 48 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
height: 264 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
spacing: 60 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
model: OutputDevice.printers
|
||||||
|
|
||||||
|
MonitorPrinterCard
|
||||||
|
{
|
||||||
|
printer: modelData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
id: queue
|
id: queue
|
||||||
|
width: Math.min(834 * screenScaleFactor, maximumWidth)
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors {
|
||||||
anchors.top: parent.top
|
bottom: parent.bottom
|
||||||
anchors.topMargin: 400 * screenScaleFactor // TODO: Insert carousel here
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
top: printers.bottom
|
||||||
|
topMargin: 48 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
@ -105,7 +136,6 @@ Component
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MouseArea
|
MouseArea
|
||||||
{
|
{
|
||||||
anchors.fill: manageQueueLabel
|
anchors.fill: manageQueueLabel
|
||||||
|
@ -187,7 +217,7 @@ Component
|
||||||
}
|
}
|
||||||
style: UM.Theme.styles.scrollview
|
style: UM.Theme.styles.scrollview
|
||||||
visible: OutputDevice.receivedPrintJobs
|
visible: OutputDevice.receivedPrintJobs
|
||||||
width: Math.min(834 * screenScaleFactor, maximumWidth)
|
width: parent.width
|
||||||
|
|
||||||
ListView
|
ListView
|
||||||
{
|
{
|
||||||
|
@ -214,5 +244,4 @@ Component
|
||||||
visible: OutputDevice.activeCameraUrl != ""
|
visible: OutputDevice.activeCameraUrl != ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ Cura.MachineAction
|
||||||
spacing: UM.Theme.getSize("default_margin").height
|
spacing: UM.Theme.getSize("default_margin").height
|
||||||
|
|
||||||
SystemPalette { id: palette }
|
SystemPalette { id: palette }
|
||||||
UM.I18nCatalog { id: catalog; name:"cura" }
|
UM.I18nCatalog { id: catalog; name: "cura" }
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: pageTitle
|
id: pageTitle
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Controls.Styles 1.3
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import UM 1.3 as UM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: For most labels, a fixed height with vertical alignment is used to make
|
||||||
|
* layouts more deterministic (like the fixed-size textboxes used in original
|
||||||
|
* mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
|
||||||
|
* with '// FIXED-LINE-HEIGHT:'.
|
||||||
|
*/
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
property var printJob: null
|
||||||
|
property var progress:
|
||||||
|
{
|
||||||
|
if (!printJob)
|
||||||
|
{
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var result = printJob.timeElapsed / printJob.timeTotal
|
||||||
|
if (result > 1.0)
|
||||||
|
{
|
||||||
|
result = 1.0
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
property var remainingTime:
|
||||||
|
{
|
||||||
|
if (!printJob) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
/* Sometimes total minus elapsed is less than 0. Use Math.max() to prevent remaining
|
||||||
|
time from ever being less than 0. Negative durations cause strange behavior such
|
||||||
|
as displaying "-1h -1m". */
|
||||||
|
return Math.max(printer.activePrintJob.timeTotal - printer.activePrintJob.timeElapsed, 0)
|
||||||
|
}
|
||||||
|
property var progressText:
|
||||||
|
{
|
||||||
|
if (!printJob)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
switch (printJob.state)
|
||||||
|
{
|
||||||
|
case "wait_cleanup":
|
||||||
|
if (printJob.timeTotal > printJob.timeElapsed)
|
||||||
|
{
|
||||||
|
return catalog.i18nc("@label:status", "Aborted")
|
||||||
|
}
|
||||||
|
return catalog.i18nc("@label:status", "Finished")
|
||||||
|
case "pre_print":
|
||||||
|
case "sent_to_printer":
|
||||||
|
return catalog.i18nc("@label:status", "Preparing")
|
||||||
|
case "aborted":
|
||||||
|
return catalog.i18nc("@label:status", "Aborted")
|
||||||
|
case "wait_user_action":
|
||||||
|
return catalog.i18nc("@label:status", "Aborted")
|
||||||
|
case "pausing":
|
||||||
|
return catalog.i18nc("@label:status", "Pausing")
|
||||||
|
case "paused":
|
||||||
|
return OutputDevice.formatDuration( remainingTime )
|
||||||
|
case "resuming":
|
||||||
|
return catalog.i18nc("@label:status", "Resuming")
|
||||||
|
case "queued":
|
||||||
|
return catalog.i18nc("@label:status", "Action required")
|
||||||
|
default:
|
||||||
|
return OutputDevice.formatDuration( remainingTime )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
width: childrenRect.width
|
||||||
|
height: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
ProgressBar
|
||||||
|
{
|
||||||
|
id: progressBar
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
value: progress;
|
||||||
|
style: ProgressBarStyle
|
||||||
|
{
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
color: "#e4e4f2" // TODO: Theme!
|
||||||
|
implicitHeight: visible ? 8 * screenScaleFactor : 0 // TODO: Theme!
|
||||||
|
implicitWidth: 180 * screenScaleFactor // TODO: Theme!
|
||||||
|
radius: 4 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
progress: Rectangle
|
||||||
|
{
|
||||||
|
id: progressItem;
|
||||||
|
color:
|
||||||
|
{
|
||||||
|
if (printJob)
|
||||||
|
{
|
||||||
|
var state = printJob.state
|
||||||
|
var inactiveStates = [
|
||||||
|
"pausing",
|
||||||
|
"paused",
|
||||||
|
"resuming",
|
||||||
|
"wait_cleanup"
|
||||||
|
]
|
||||||
|
if (inactiveStates.indexOf(state) > -1 && remainingTime > 0)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("monitor_progress_fill_inactive")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "#0a0850" // TODO: Theme!
|
||||||
|
}
|
||||||
|
radius: 4 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: progressLabel
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: progressBar.right
|
||||||
|
leftMargin: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
text: progressText
|
||||||
|
color: "#374355" // TODO: Theme!
|
||||||
|
width: contentWidth
|
||||||
|
font: UM.Theme.getFont("medium") // 14pt, regular
|
||||||
|
|
||||||
|
// FIXED-LINE-HEIGHT:
|
||||||
|
height: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
242
plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml
Normal file
242
plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import UM 1.3 as UM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Printer Card is has two main components: the printer portion and the print
|
||||||
|
* job portion, the latter being paired in the UI when a print job is paired
|
||||||
|
* a printer in-cluster.
|
||||||
|
*
|
||||||
|
* NOTE: For most labels, a fixed height with vertical alignment is used to make
|
||||||
|
* layouts more deterministic (like the fixed-size textboxes used in original
|
||||||
|
* mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
|
||||||
|
* with '// FIXED-LINE-HEIGHT:'.
|
||||||
|
*/
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
|
||||||
|
// The printer which all printer data is derived from
|
||||||
|
property var printer: null
|
||||||
|
|
||||||
|
property var borderSize: 1 * screenScaleFactor // TODO: Theme, and remove from here
|
||||||
|
|
||||||
|
width: 834 * screenScaleFactor // TODO: Theme!
|
||||||
|
height: 216 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
// Printer portion
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: printerInfo
|
||||||
|
border
|
||||||
|
{
|
||||||
|
color: "#EAEAEC" // TODO: Theme!
|
||||||
|
width: borderSize // TODO: Remove once themed
|
||||||
|
}
|
||||||
|
color: "white" // TODO: Theme!
|
||||||
|
width: parent.width
|
||||||
|
height: 144 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: 36 * screenScaleFactor // TODO: Theme!
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
spacing: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
Image
|
||||||
|
{
|
||||||
|
id: printerImage
|
||||||
|
width: 108 * screenScaleFactor // TODO: Theme!
|
||||||
|
height: 108 * screenScaleFactor // TODO: Theme!
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: "../png/" + printer.type + ".png"
|
||||||
|
mipmap: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
width: 216 * screenScaleFactor // TODO: Theme!
|
||||||
|
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: printerNameLabel
|
||||||
|
text: printer && printer.name ? printer.name : ""
|
||||||
|
color: "#414054" // TODO: Theme!
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: UM.Theme.getFont("large") // 16pt, bold
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
// FIXED-LINE-HEIGHT:
|
||||||
|
height: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
MonitorPrinterPill
|
||||||
|
{
|
||||||
|
id: printerFamilyPill
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
top: printerNameLabel.bottom
|
||||||
|
topMargin: 6 * screenScaleFactor // TODO: Theme!
|
||||||
|
left: printerNameLabel.left
|
||||||
|
}
|
||||||
|
text: printer.type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MonitorPrinterConfiguration
|
||||||
|
{
|
||||||
|
id: printerConfiguration
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
buildplate: "Glass"
|
||||||
|
configurations:
|
||||||
|
[
|
||||||
|
base.printer.printerConfiguration.extruderConfigurations[0],
|
||||||
|
base.printer.printerConfiguration.extruderConfigurations[1]
|
||||||
|
]
|
||||||
|
height: 72 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintJobContextMenu
|
||||||
|
{
|
||||||
|
id: contextButton
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: 12 * screenScaleFactor // TODO: Theme!
|
||||||
|
top: parent.top
|
||||||
|
topMargin: 12 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
printJob: printer.activePrintJob
|
||||||
|
width: 36 * screenScaleFactor // TODO: Theme!
|
||||||
|
height: 36 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
CameraButton
|
||||||
|
{
|
||||||
|
id: cameraButton;
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: 20 * screenScaleFactor // TODO: Theme!
|
||||||
|
bottom: parent.bottom
|
||||||
|
bottomMargin: 20 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
iconSource: "../svg/icons/camera.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Print job portion
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: printJobInfo
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
top: printerInfo.bottom
|
||||||
|
topMargin: -borderSize * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
border
|
||||||
|
{
|
||||||
|
color: "#EAEAEC" // TODO: Theme!
|
||||||
|
width: borderSize // TODO: Remove once themed
|
||||||
|
}
|
||||||
|
color: "white" // TODO: Theme!
|
||||||
|
height: 84 * screenScaleFactor + borderSize // TODO: Remove once themed
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
fill: parent
|
||||||
|
topMargin: 12 * screenScaleFactor + borderSize // TODO: Theme!
|
||||||
|
bottomMargin: 12 * screenScaleFactor // TODO: Theme!
|
||||||
|
leftMargin: 36 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
height: childrenRect.height
|
||||||
|
spacing: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
width: printerImage.width
|
||||||
|
height: 60 * screenScaleFactor // TODO: Theme!
|
||||||
|
MonitorPrintJobPreview
|
||||||
|
{
|
||||||
|
anchors.centerIn: parent
|
||||||
|
printJob: base.printer.activePrintJob
|
||||||
|
size: parent.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
width: 216 * screenScaleFactor // TODO: Theme!
|
||||||
|
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: printerJobNameLabel
|
||||||
|
text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N
|
||||||
|
color: "#414054" // TODO: Theme!
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: UM.Theme.getFont("large") // 16pt, bold
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
// FIXED-LINE-HEIGHT:
|
||||||
|
height: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: printerJobOwnerLabel
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
top: printerJobNameLabel.bottom
|
||||||
|
topMargin: 6 * screenScaleFactor // TODO: Theme!
|
||||||
|
left: printerJobNameLabel.left
|
||||||
|
}
|
||||||
|
text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N
|
||||||
|
color: "#53657d" // TODO: Theme!
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: UM.Theme.getFont("very_small") // 12pt, regular
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
// FIXED-LINE-HEIGHT:
|
||||||
|
height: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MonitorPrintJobProgressBar
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
printJob: printer.activePrintJob
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ Item {
|
||||||
}
|
}
|
||||||
contentItem: Label {
|
contentItem: Label {
|
||||||
color: UM.Theme.getColor("monitor_context_menu_dots");
|
color: UM.Theme.getColor("monitor_context_menu_dots");
|
||||||
font.pixelSize: 25 * screenScaleFactor;
|
font.pixelSize: 32 * screenScaleFactor;
|
||||||
horizontalAlignment: Text.AlignHCenter;
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
text: button.text;
|
text: button.text;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
@ -41,7 +41,7 @@ Item {
|
||||||
var states = ["queued", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"];
|
var states = ["queued", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"];
|
||||||
return states.indexOf(printJob.state) !== -1;
|
return states.indexOf(printJob.state) !== -1;
|
||||||
}
|
}
|
||||||
width: 35 * screenScaleFactor; // TODO: Theme!
|
width: 36 * screenScaleFactor; // TODO: Theme!
|
||||||
}
|
}
|
||||||
|
|
||||||
Popup {
|
Popup {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<path d="M4.298828,0.998047 L7.7,0.998047 L8.7,3 L12,3 L12,10 L0,10 L0,3 L3.3,3 L4.298828,0.998047 Z M6,4 C4.625211,4 3.5,5.1252 3.5,6.5 C3.5,7.8748 4.625211,9 6,9 C7.37479,9 8.5,7.8748 8.5,6.5 C8.5,5.1252 7.37479,4 6,4 Z M6,5 C6.83435,5 7.5,5.6657 7.5,6.5 C7.5,7.3343 6.83435,8 6,8 C5.165651,8 4.5,7.3343 4.5,6.5 C4.5,5.6657 5.165651,5 6,5 Z" id="Combined-Shape" fill="#0A0850" fill-rule="nonzero"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 658 B |
|
@ -65,7 +65,6 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
self._received_print_jobs = False # type: bool
|
self._received_print_jobs = False # type: bool
|
||||||
|
|
||||||
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterMonitorItem.qml")
|
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterMonitorItem.qml")
|
||||||
self._control_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterControlItem.qml")
|
|
||||||
|
|
||||||
# See comments about this hack with the clusterPrintersChanged signal
|
# See comments about this hack with the clusterPrintersChanged signal
|
||||||
self.printersChanged.connect(self.clusterPrintersChanged)
|
self.printersChanged.connect(self.clusterPrintersChanged)
|
||||||
|
|
|
@ -344,7 +344,6 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
|
|
||||||
# Request more data if info is not complete
|
# Request more data if info is not complete
|
||||||
if not info.address:
|
if not info.address:
|
||||||
Logger.log("d", "Trying to get address of %s", name)
|
|
||||||
info = zero_conf.get_service_info(service_type, name)
|
info = zero_conf.get_service_info(service_type, name)
|
||||||
|
|
||||||
if info:
|
if info:
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
from UM.Job import Job
|
from UM.Job import Job
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
from plugins.USBPrinting.avr_isp import ispBase
|
||||||
|
|
||||||
from .avr_isp.stk500v2 import Stk500v2
|
from .avr_isp.stk500v2 import Stk500v2
|
||||||
|
|
||||||
|
@ -14,12 +15,12 @@ from serial import Serial, SerialException
|
||||||
# It tries a pre-set list of baud rates. All these baud rates are validated by requesting the temperature a few times
|
# It tries a pre-set list of baud rates. All these baud rates are validated by requesting the temperature a few times
|
||||||
# and checking if the results make sense. If getResult() is not None, it was able to find a correct baud rate.
|
# and checking if the results make sense. If getResult() is not None, it was able to find a correct baud rate.
|
||||||
class AutoDetectBaudJob(Job):
|
class AutoDetectBaudJob(Job):
|
||||||
def __init__(self, serial_port):
|
def __init__(self, serial_port: int) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._serial_port = serial_port
|
self._serial_port = serial_port
|
||||||
self._all_baud_rates = [115200, 250000, 230400, 57600, 38400, 19200, 9600]
|
self._all_baud_rates = [115200, 250000, 230400, 57600, 38400, 19200, 9600]
|
||||||
|
|
||||||
def run(self):
|
def run(self) -> None:
|
||||||
Logger.log("d", "Auto detect baud rate started.")
|
Logger.log("d", "Auto detect baud rate started.")
|
||||||
wait_response_timeouts = [3, 15, 30]
|
wait_response_timeouts = [3, 15, 30]
|
||||||
wait_bootloader_times = [1.5, 5, 15]
|
wait_bootloader_times = [1.5, 5, 15]
|
||||||
|
@ -32,7 +33,7 @@ class AutoDetectBaudJob(Job):
|
||||||
try:
|
try:
|
||||||
programmer.connect(self._serial_port)
|
programmer.connect(self._serial_port)
|
||||||
serial = programmer.leaveISP()
|
serial = programmer.leaveISP()
|
||||||
except:
|
except ispBase.IspError:
|
||||||
programmer.close()
|
programmer.close()
|
||||||
|
|
||||||
for retry in range(tries):
|
for retry in range(tries):
|
||||||
|
@ -58,7 +59,7 @@ class AutoDetectBaudJob(Job):
|
||||||
# We already have a serial connection, just change the baud rate.
|
# We already have a serial connection, just change the baud rate.
|
||||||
try:
|
try:
|
||||||
serial.baudrate = baud_rate
|
serial.baudrate = baud_rate
|
||||||
except:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
sleep(wait_bootloader) # Ensure that we are not talking to the boot loader. 1.5 seconds seems to be the magic number
|
sleep(wait_bootloader) # Ensure that we are not talking to the boot loader. 1.5 seconds seems to be the magic number
|
||||||
successful_responses = 0
|
successful_responses = 0
|
||||||
|
|
46
plugins/USBPrinting/MonitorItem.qml
Normal file
46
plugins/USBPrinting/MonitorItem.qml
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: parent.width * 0.3
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
Cura.PrintMonitor
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: footerSeparator
|
||||||
|
width: parent.width
|
||||||
|
height: UM.Theme.getSize("wide_lining").height
|
||||||
|
color: UM.Theme.getColor("wide_lining")
|
||||||
|
anchors.bottom: monitorButton.top
|
||||||
|
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
|
||||||
|
}
|
||||||
|
|
||||||
|
// MonitorButton is actually the bottom footer panel.
|
||||||
|
Cura.MonitorButton
|
||||||
|
{
|
||||||
|
id: monitorButton
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
import os
|
||||||
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
@ -64,7 +65,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._accepts_commands = True
|
self._accepts_commands = True
|
||||||
|
|
||||||
self._paused = False
|
self._paused = False
|
||||||
self._printer_busy = False # when printer is preheating and waiting (M190/M109), or when waiting for action on the printer
|
self._printer_busy = False # When printer is preheating and waiting (M190/M109), or when waiting for action on the printer
|
||||||
|
|
||||||
self.setConnectionText(catalog.i18nc("@info:status", "Connected via USB"))
|
self.setConnectionText(catalog.i18nc("@info:status", "Connected via USB"))
|
||||||
|
|
||||||
|
@ -77,6 +78,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._firmware_name_requested = False
|
self._firmware_name_requested = False
|
||||||
self._firmware_updater = AvrFirmwareUpdater(self)
|
self._firmware_updater = AvrFirmwareUpdater(self)
|
||||||
|
|
||||||
|
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "MonitorItem.qml")
|
||||||
|
|
||||||
CuraApplication.getInstance().getOnExitCallbackManager().addCallback(self._checkActivePrintingUponAppExit)
|
CuraApplication.getInstance().getOnExitCallbackManager().addCallback(self._checkActivePrintingUponAppExit)
|
||||||
|
|
||||||
# This is a callback function that checks if there is any printing in progress via USB when the application tries
|
# This is a callback function that checks if there is any printing in progress via USB when the application tries
|
||||||
|
|
|
@ -19,7 +19,7 @@ Cura.MachineAction
|
||||||
property bool heatupBedStarted: false
|
property bool heatupBedStarted: false
|
||||||
property bool printerConnected: Cura.MachineManager.printerConnected
|
property bool printerConnected: Cura.MachineManager.printerConnected
|
||||||
|
|
||||||
UM.I18nCatalog { id: catalog; name:"cura"}
|
UM.I18nCatalog { id: catalog; name: "cura"}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: pageTitle
|
id: pageTitle
|
||||||
|
|
|
@ -36,7 +36,7 @@ UM.Dialog
|
||||||
width: parent.width
|
width: parent.width
|
||||||
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
|
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
|
||||||
|
|
||||||
UM.I18nCatalog { id: catalog; name:"cura" }
|
UM.I18nCatalog { id: catalog; name: "cura" }
|
||||||
|
|
||||||
Button
|
Button
|
||||||
{
|
{
|
||||||
|
|
|
@ -356,6 +356,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"PreviewStage": {
|
||||||
|
"package_info": {
|
||||||
|
"package_id": "PreviewStage",
|
||||||
|
"package_type": "plugin",
|
||||||
|
"display_name": "Preview Stage",
|
||||||
|
"description": "Provides a preview stage in Cura.",
|
||||||
|
"package_version": "1.0.0",
|
||||||
|
"sdk_version": 5,
|
||||||
|
"website": "https://ultimaker.com",
|
||||||
|
"author": {
|
||||||
|
"author_id": "UltimakerPackages",
|
||||||
|
"display_name": "Ultimaker B.V.",
|
||||||
|
"email": "plugins@ultimaker.com",
|
||||||
|
"website": "https://ultimaker.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"RemovableDriveOutputDevice": {
|
"RemovableDriveOutputDevice": {
|
||||||
"package_info": {
|
"package_info": {
|
||||||
"package_id": "RemovableDriveOutputDevice",
|
"package_id": "RemovableDriveOutputDevice",
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "Cocoon Create ModelMaker & Wanhao Duplicator i3 Mini",
|
"name": "Cocoon Create ModelMaker",
|
||||||
"version": 2,
|
"version": 2,
|
||||||
"inherits": "fdmprinter",
|
"inherits": "fdmprinter",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"visible": true,
|
"visible": true,
|
||||||
"author": "Samuel Pinches",
|
"author": "Samuel Pinches",
|
||||||
"manufacturer": "Cocoon Create / Wanhao",
|
"manufacturer": "Cocoon Create",
|
||||||
"file_formats": "text/x-gcode",
|
"file_formats": "text/x-gcode",
|
||||||
"preferred_quality_type": "fine",
|
"preferred_quality_type": "fine",
|
||||||
"machine_extruder_trains":
|
"machine_extruder_trains":
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"machine_name": {
|
"machine_name": {
|
||||||
"default_value": "Cocoon Create ModelMaker & Wanhao Duplicator i3 Mini"
|
"default_value": "Cocoon Create ModelMaker"
|
||||||
},
|
},
|
||||||
"machine_start_gcode": {
|
"machine_start_gcode": {
|
||||||
"default_value": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 ;home all axis\nG92 E0 ;zero the extruded length\nG1 Z1 F1000 ;move up slightly\nG1 X60.0 Z0 E9.0 F1000.0;intro line\nG1 X100.0 E21.5 F1000.0 ;continue line\nG92 E0 ;zero the extruded length again\n; -- end of START GCODE --"
|
"default_value": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 ;home all axis\nG92 E0 ;zero the extruded length\nG1 Z1 F1000 ;move up slightly\nG1 X60.0 Z0 E9.0 F1000.0;intro line\nG1 X100.0 E21.5 F1000.0 ;continue line\nG92 E0 ;zero the extruded length again\n; -- end of START GCODE --"
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
"default_value": 220
|
"default_value": 220
|
||||||
},
|
},
|
||||||
"layer_height": {
|
"layer_height": {
|
||||||
"default_value": 0.15
|
"default_value": 0.10
|
||||||
},
|
},
|
||||||
"layer_height_0": {
|
"layer_height_0": {
|
||||||
"default_value": 0.2
|
"default_value": 0.2
|
||||||
|
|
|
@ -1,170 +0,0 @@
|
||||||
// Copyright (c) 2015 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
import UM 1.1 as UM
|
|
||||||
|
|
||||||
UM.Dialog
|
|
||||||
{
|
|
||||||
id: base
|
|
||||||
|
|
||||||
//: About dialog title
|
|
||||||
title: catalog.i18nc("@title:window","About Cura")
|
|
||||||
|
|
||||||
minimumWidth: 500 * screenScaleFactor
|
|
||||||
minimumHeight: 650 * screenScaleFactor
|
|
||||||
width: minimumWidth
|
|
||||||
height: minimumHeight
|
|
||||||
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
width: parent.width + 2 * margin // margin from Dialog.qml
|
|
||||||
height: version.y + version.height + margin
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: - margin
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
color: UM.Theme.getColor("viewport_background")
|
|
||||||
}
|
|
||||||
|
|
||||||
Image
|
|
||||||
{
|
|
||||||
id: logo
|
|
||||||
width: (base.minimumWidth * 0.85) | 0
|
|
||||||
height: (width * (1/4.25)) | 0
|
|
||||||
|
|
||||||
source: UM.Theme.getImage("logo")
|
|
||||||
|
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: height
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: ((base.minimumWidth - width) / 2) | 0
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: version
|
|
||||||
|
|
||||||
text: catalog.i18nc("@label","version: %1").arg(UM.Application.version)
|
|
||||||
font: UM.Theme.getFont("large")
|
|
||||||
color: UM.Theme.getColor("text")
|
|
||||||
anchors.right : logo.right
|
|
||||||
anchors.top: logo.bottom
|
|
||||||
anchors.topMargin: (UM.Theme.getSize("default_margin").height / 2) | 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: description
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
//: About dialog application description
|
|
||||||
text: catalog.i18nc("@label","End-to-end solution for fused filament 3D printing.")
|
|
||||||
font: UM.Theme.getFont("system")
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
anchors.top: version.bottom
|
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: creditsNotes
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
//: About dialog application author note
|
|
||||||
text: catalog.i18nc("@info:credit","Cura is developed by Ultimaker B.V. in cooperation with the community.\nCura proudly uses the following open source projects:")
|
|
||||||
font: UM.Theme.getFont("system")
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
anchors.top: description.bottom
|
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollView
|
|
||||||
{
|
|
||||||
id: credits
|
|
||||||
anchors.top: creditsNotes.bottom
|
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height)
|
|
||||||
|
|
||||||
ListView
|
|
||||||
{
|
|
||||||
id: projectsList
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
delegate: Row
|
|
||||||
{
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: "<a href='%1' title='%2'>%2</a>".arg(model.url).arg(model.name)
|
|
||||||
width: (projectsList.width * 0.25) | 0
|
|
||||||
elide: Text.ElideRight
|
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
|
||||||
}
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: model.description
|
|
||||||
elide: Text.ElideRight
|
|
||||||
width: (projectsList.width * 0.6) | 0
|
|
||||||
}
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: model.license
|
|
||||||
elide: Text.ElideRight
|
|
||||||
width: (projectsList.width * 0.15) | 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
model: ListModel
|
|
||||||
{
|
|
||||||
id: projectsModel
|
|
||||||
}
|
|
||||||
Component.onCompleted:
|
|
||||||
{
|
|
||||||
projectsModel.append({ name:"Cura", description: catalog.i18nc("@label", "Graphical user interface"), license: "LGPLv3", url: "https://github.com/Ultimaker/Cura" });
|
|
||||||
projectsModel.append({ name:"Uranium", description: catalog.i18nc("@label", "Application framework"), license: "LGPLv3", url: "https://github.com/Ultimaker/Uranium" });
|
|
||||||
projectsModel.append({ name:"CuraEngine", description: catalog.i18nc("@label", "G-code generator"), license: "AGPLv3", url: "https://github.com/Ultimaker/CuraEngine" });
|
|
||||||
projectsModel.append({ name:"libArcus", description: catalog.i18nc("@label", "Interprocess communication library"), license: "LGPLv3", url: "https://github.com/Ultimaker/libArcus" });
|
|
||||||
|
|
||||||
projectsModel.append({ name:"Python", description: catalog.i18nc("@label", "Programming language"), license: "Python", url: "http://python.org/" });
|
|
||||||
projectsModel.append({ name:"Qt5", description: catalog.i18nc("@label", "GUI framework"), license: "LGPLv3", url: "https://www.qt.io/" });
|
|
||||||
projectsModel.append({ name:"PyQt", description: catalog.i18nc("@label", "GUI framework bindings"), license: "GPL", url: "https://riverbankcomputing.com/software/pyqt" });
|
|
||||||
projectsModel.append({ name:"SIP", description: catalog.i18nc("@label", "C/C++ Binding library"), license: "GPL", url: "https://riverbankcomputing.com/software/sip" });
|
|
||||||
projectsModel.append({ name:"Protobuf", description: catalog.i18nc("@label", "Data interchange format"), license: "BSD", url: "https://developers.google.com/protocol-buffers" });
|
|
||||||
projectsModel.append({ name:"SciPy", description: catalog.i18nc("@label", "Support library for scientific computing"), license: "BSD-new", url: "https://www.scipy.org/" });
|
|
||||||
projectsModel.append({ name:"NumPy", description: catalog.i18nc("@label", "Support library for faster math"), license: "BSD", url: "http://www.numpy.org/" });
|
|
||||||
projectsModel.append({ name:"NumPy-STL", description: catalog.i18nc("@label", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" });
|
|
||||||
projectsModel.append({ name:"Shapely", description: catalog.i18nc("@label", "Support library for handling planar objects"), license: "BSD", url: "https://github.com/Toblerity/Shapely" });
|
|
||||||
projectsModel.append({ name:"Trimesh", description: catalog.i18nc("@label", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" });
|
|
||||||
projectsModel.append({ name:"NetworkX", description: catalog.i18nc("@label", "Support library for analysis of complex networks"), license: "3-clause BSD", url: "https://networkx.github.io/" });
|
|
||||||
projectsModel.append({ name:"libSavitar", description: catalog.i18nc("@label", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" });
|
|
||||||
projectsModel.append({ name:"libCharon", description: catalog.i18nc("@label", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" });
|
|
||||||
projectsModel.append({ name:"PySerial", description: catalog.i18nc("@label", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" });
|
|
||||||
projectsModel.append({ name:"python-zeroconf", description: catalog.i18nc("@label", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" });
|
|
||||||
projectsModel.append({ name:"Clipper", description: catalog.i18nc("@label", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" });
|
|
||||||
projectsModel.append({ name:"Requests", description: catalog.i18nc("@Label", "Python HTTP library"), license: "GPL", url: "http://docs.python-requests.org" });
|
|
||||||
|
|
||||||
projectsModel.append({ name:"Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" });
|
|
||||||
projectsModel.append({ name:"Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" });
|
|
||||||
projectsModel.append({ name:"AppImageKit", description: catalog.i18nc("@label", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rightButtons: Button
|
|
||||||
{
|
|
||||||
//: Close about dialog button
|
|
||||||
id: closeButton
|
|
||||||
text: catalog.i18nc("@action:button","Close");
|
|
||||||
|
|
||||||
onClicked: base.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
69
resources/qml/Account/AccountDetails.qml
Normal file
69
resources/qml/Account/AccountDetails.qml
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Column
|
||||||
|
{
|
||||||
|
property var profile: null
|
||||||
|
property var loggedIn: false
|
||||||
|
property var profileImage: ""
|
||||||
|
|
||||||
|
padding: 2 * UM.Theme.getSize("default_margin").height
|
||||||
|
spacing: 2 * UM.Theme.getSize("default_margin").height
|
||||||
|
|
||||||
|
AvatarImage
|
||||||
|
{
|
||||||
|
id: avatar
|
||||||
|
width: UM.Theme.getSize("avatar_image").width
|
||||||
|
height: UM.Theme.getSize("avatar_image").height
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
source:
|
||||||
|
{
|
||||||
|
if(loggedIn)
|
||||||
|
{
|
||||||
|
if(profileImage)
|
||||||
|
{
|
||||||
|
return profileImage
|
||||||
|
}
|
||||||
|
return UM.Theme.getImage("avatar_no_user")
|
||||||
|
}
|
||||||
|
return UM.Theme.getImage("avatar_no_user")
|
||||||
|
}
|
||||||
|
outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: information
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
text: loggedIn ? profile["username"] : catalog.i18nc("@label", "Please log in or create an account to\nenjoy all features of Ultimaker Cura.")
|
||||||
|
font: loggedIn ? UM.Theme.getFont("large") : UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader
|
||||||
|
{
|
||||||
|
id: accountOperations
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
sourceComponent: loggedIn ? userOperations : generalOperations
|
||||||
|
}
|
||||||
|
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
id: userOperations
|
||||||
|
UserOperations { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
id: generalOperations
|
||||||
|
GeneralOperations { }
|
||||||
|
}
|
||||||
|
}
|
76
resources/qml/Account/AccountWidget.qml
Normal file
76
resources/qml/Account/AccountWidget.qml
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: accountWidget
|
||||||
|
property var profile: Cura.API.account.userProfile
|
||||||
|
property var loggedIn: Cura.API.account.isLoggedIn
|
||||||
|
|
||||||
|
implicitHeight: UM.Theme.getSize("main_window_header").height
|
||||||
|
implicitWidth: UM.Theme.getSize("main_window_header").height
|
||||||
|
|
||||||
|
background: AvatarImage
|
||||||
|
{
|
||||||
|
id: avatar
|
||||||
|
|
||||||
|
width: Math.round(0.8 * accountWidget.width)
|
||||||
|
height: Math.round(0.8 * accountWidget.height)
|
||||||
|
anchors.verticalCenter: accountWidget.verticalCenter
|
||||||
|
anchors.horizontalCenter: accountWidget.horizontalCenter
|
||||||
|
|
||||||
|
source:
|
||||||
|
{
|
||||||
|
if(loggedIn)
|
||||||
|
{
|
||||||
|
if(profile["profile_image_url"])
|
||||||
|
{
|
||||||
|
return profile["profile_image_url"]
|
||||||
|
}
|
||||||
|
return UM.Theme.getImage("avatar_no_user")
|
||||||
|
}
|
||||||
|
return UM.Theme.getImage("avatar_no_user")
|
||||||
|
}
|
||||||
|
outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: popup.opened ? popup.close() : popup.open()
|
||||||
|
|
||||||
|
Popup
|
||||||
|
{
|
||||||
|
id: popup
|
||||||
|
|
||||||
|
y: parent.height + UM.Theme.getSize("default_arrow").height
|
||||||
|
x: parent.width - width
|
||||||
|
|
||||||
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||||
|
|
||||||
|
opacity: opened ? 1 : 0
|
||||||
|
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||||
|
|
||||||
|
contentItem: AccountDetails
|
||||||
|
{
|
||||||
|
id: panel
|
||||||
|
profile: Cura.API.account.userProfile
|
||||||
|
loggedIn: Cura.API.account.isLoggedIn
|
||||||
|
profileImage: Cura.API.account.profileImageUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
background: UM.PointingRectangle
|
||||||
|
{
|
||||||
|
color: UM.Theme.getColor("tool_panel_background")
|
||||||
|
borderColor: UM.Theme.getColor("lining")
|
||||||
|
borderWidth: UM.Theme.getSize("default_lining").width
|
||||||
|
|
||||||
|
target: Qt.point(width - (accountWidget.width / 2), -10)
|
||||||
|
|
||||||
|
arrowSize: UM.Theme.getSize("default_arrow").width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
resources/qml/Account/AvatarImage.qml
Normal file
56
resources/qml/Account/AvatarImage.qml
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
// This item shows the provided image while applying a round mask to it.
|
||||||
|
// It also shows a round border around it. The color is defined by the outlineColor property.
|
||||||
|
|
||||||
|
id: avatar
|
||||||
|
|
||||||
|
property alias source: profileImage.source
|
||||||
|
property alias outlineColor: profileImageOutline.color
|
||||||
|
|
||||||
|
Image
|
||||||
|
{
|
||||||
|
id: profileImage
|
||||||
|
anchors.fill: parent
|
||||||
|
source: UM.Theme.getImage("avatar_default")
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
visible: false
|
||||||
|
mipmap: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: profileImageMask
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: width
|
||||||
|
}
|
||||||
|
|
||||||
|
OpacityMask
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
source: profileImage
|
||||||
|
maskSource: profileImageMask
|
||||||
|
cached: true
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: profileImageOutline
|
||||||
|
anchors.centerIn: parent
|
||||||
|
// Make it a bit bigger than it has to, otherwise it sometimes shows a white border.
|
||||||
|
width: parent.width + 2
|
||||||
|
height: parent.height + 2
|
||||||
|
source: UM.Theme.getIcon("circle_outline")
|
||||||
|
sourceSize: Qt.size(parent.width, parent.height)
|
||||||
|
color: UM.Theme.getColor("account_widget_ouline_active")
|
||||||
|
}
|
||||||
|
}
|
31
resources/qml/Account/GeneralOperations.qml
Normal file
31
resources/qml/Account/GeneralOperations.qml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.2
|
||||||
|
import QtQuick.Controls 1.1
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
spacing: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
Cura.SecondaryButton
|
||||||
|
{
|
||||||
|
width: UM.Theme.getSize("account_button").width
|
||||||
|
height: UM.Theme.getSize("account_button").height
|
||||||
|
text: catalog.i18nc("@button", "Create account")
|
||||||
|
onClicked: Qt.openUrlExternally("https://account.ultimaker.com/app/create")
|
||||||
|
fixedWidthMode: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.PrimaryButton
|
||||||
|
{
|
||||||
|
width: UM.Theme.getSize("account_button").width
|
||||||
|
height: UM.Theme.getSize("account_button").height
|
||||||
|
text: catalog.i18nc("@button", "Login")
|
||||||
|
onClicked: Cura.API.account.login()
|
||||||
|
fixedWidthMode: true
|
||||||
|
}
|
||||||
|
}
|
31
resources/qml/Account/UserOperations.qml
Normal file
31
resources/qml/Account/UserOperations.qml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.2
|
||||||
|
import QtQuick.Controls 1.1
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
spacing: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
Cura.SecondaryButton
|
||||||
|
{
|
||||||
|
width: UM.Theme.getSize("account_button").width
|
||||||
|
height: UM.Theme.getSize("account_button").height
|
||||||
|
text: catalog.i18nc("@button", "Manage account")
|
||||||
|
onClicked: Qt.openUrlExternally("https://account.ultimaker.com")
|
||||||
|
fixedWidthMode: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.PrimaryButton
|
||||||
|
{
|
||||||
|
width: UM.Theme.getSize("account_button").width
|
||||||
|
height: UM.Theme.getSize("account_button").height
|
||||||
|
text: catalog.i18nc("@button", "Logout")
|
||||||
|
onClicked: Cura.API.account.logout()
|
||||||
|
fixedWidthMode: true
|
||||||
|
}
|
||||||
|
}
|
98
resources/qml/ActionButton.qml
Normal file
98
resources/qml/ActionButton.qml
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
|
||||||
|
import QtGraphicalEffects 1.0 // For the dropshadow
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: button
|
||||||
|
property alias iconSource: buttonIcon.source
|
||||||
|
property alias textFont: buttonText.font
|
||||||
|
property alias cornerRadius: backgroundRect.radius
|
||||||
|
property alias tooltip: tooltip.text
|
||||||
|
|
||||||
|
property color color: UM.Theme.getColor("primary")
|
||||||
|
property color hoverColor: UM.Theme.getColor("primary_hover")
|
||||||
|
property color disabledColor: color
|
||||||
|
property color textColor: UM.Theme.getColor("button_text")
|
||||||
|
property color textHoverColor: textColor
|
||||||
|
property color textDisabledColor: textColor
|
||||||
|
property color outlineColor: color
|
||||||
|
property color outlineHoverColor: hoverColor
|
||||||
|
property color outlineDisabledColor: outlineColor
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
property alias shadowColor: shadow.color
|
||||||
|
property alias shadowEnabled: shadow.visible
|
||||||
|
|
||||||
|
// This property is used to indicate whether the button has a fixed width or the width would depend on the contents
|
||||||
|
// Be careful when using fixedWidthMode, the translated texts can be too long that they won't fit. In any case,
|
||||||
|
// we elide the text to the right so the text will be cut off with the three dots at the end.
|
||||||
|
property var fixedWidthMode: false
|
||||||
|
|
||||||
|
contentItem: Row
|
||||||
|
{
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: buttonIcon
|
||||||
|
source: ""
|
||||||
|
height: Math.round(0.6 * parent.height)
|
||||||
|
width: height
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
color: button.hovered ? button.textHoverColor : button.textColor
|
||||||
|
visible: source != ""
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: buttonText
|
||||||
|
text: button.text
|
||||||
|
color: button.enabled ? (button.hovered ? button.textHoverColor : button.textColor): button.textDisabledColor
|
||||||
|
font: UM.Theme.getFont("action_button")
|
||||||
|
visible: text != ""
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: fixedWidthMode ? button.width - button.leftPadding - button.rightPadding : undefined
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
id: backgroundRect
|
||||||
|
color: button.enabled ? (button.hovered ? button.hoverColor : button.color) : button.disabledColor
|
||||||
|
radius: UM.Theme.getSize("action_button_radius").width
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: button.enabled ? (button.hovered ? button.outlineHoverColor : button.outlineColor) : button.outlineDisabledColor
|
||||||
|
}
|
||||||
|
|
||||||
|
DropShadow
|
||||||
|
{
|
||||||
|
id: shadow
|
||||||
|
// Don't blur the shadow
|
||||||
|
radius: 0
|
||||||
|
anchors.fill: backgroundRect
|
||||||
|
source: backgroundRect
|
||||||
|
verticalOffset: 2
|
||||||
|
visible: false
|
||||||
|
// Should always be drawn behind the background.
|
||||||
|
z: backgroundRect.z - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolTip
|
||||||
|
{
|
||||||
|
id: tooltip
|
||||||
|
text: ""
|
||||||
|
delay: 500
|
||||||
|
visible: text != "" && button.hovered
|
||||||
|
}
|
||||||
|
}
|
55
resources/qml/ActionPanel/ActionPanelWidget.qml
Normal file
55
resources/qml/ActionPanel/ActionPanelWidget.qml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
|
||||||
|
// This element hold all the elements needed for the user to trigger the slicing process, and later
|
||||||
|
// to get information about the printing times, material consumption and the output process (such as
|
||||||
|
// saving to a file, printing over network, ...
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: actionPanelWidget
|
||||||
|
|
||||||
|
width: UM.Theme.getSize("action_panel_widget").width
|
||||||
|
height: childrenRect.height + 2 * UM.Theme.getSize("thick_margin").height
|
||||||
|
|
||||||
|
color: UM.Theme.getColor("main_background")
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: UM.Theme.getColor("lining")
|
||||||
|
radius: UM.Theme.getSize("default_radius").width
|
||||||
|
|
||||||
|
property bool outputAvailable: UM.Backend.state == UM.Backend.Done || UM.Backend.state == UM.Backend.Disabled
|
||||||
|
|
||||||
|
Loader
|
||||||
|
{
|
||||||
|
id: loader
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
top: parent.top
|
||||||
|
topMargin: UM.Theme.getSize("thick_margin").height
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: UM.Theme.getSize("thick_margin").width
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: UM.Theme.getSize("thick_margin").width
|
||||||
|
}
|
||||||
|
sourceComponent: outputAvailable ? outputProcessWidget : sliceProcessWidget
|
||||||
|
}
|
||||||
|
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
id: sliceProcessWidget
|
||||||
|
SliceProcessWidget { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
id: outputProcessWidget
|
||||||
|
OutputProcessWidget { }
|
||||||
|
}
|
||||||
|
}
|
103
resources/qml/ActionPanel/OutputDevicesActionButton.qml
Normal file
103
resources/qml/ActionPanel/OutputDevicesActionButton.qml
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: widget
|
||||||
|
|
||||||
|
Cura.PrimaryButton
|
||||||
|
{
|
||||||
|
id: saveToButton
|
||||||
|
height: parent.height
|
||||||
|
fixedWidthMode: true
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: deviceSelectionMenu.visible ? deviceSelectionMenu.left : parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip: UM.OutputDeviceManager.activeDeviceDescription
|
||||||
|
|
||||||
|
text: UM.OutputDeviceManager.activeDeviceShortDescription
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
forceActiveFocus();
|
||||||
|
UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, PrintInformation.jobName,
|
||||||
|
{ "filter_by_machine": true, "preferred_mimetypes": Cura.MachineManager.activeMachine.preferred_output_file_formats });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.ActionButton
|
||||||
|
{
|
||||||
|
id: deviceSelectionMenu
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
shadowEnabled: true
|
||||||
|
shadowColor: UM.Theme.getColor("primary_shadow")
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
top: parent.top
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip: catalog.i18nc("@info:tooltip", "Select the active output device")
|
||||||
|
iconSource: popup.opened ? UM.Theme.getIcon("arrow_top") : UM.Theme.getIcon("arrow_bottom")
|
||||||
|
color: UM.Theme.getColor("action_panel_secondary")
|
||||||
|
visible: (devicesModel.deviceCount > 1)
|
||||||
|
|
||||||
|
onClicked: popup.opened ? popup.close() : popup.open()
|
||||||
|
|
||||||
|
Popup
|
||||||
|
{
|
||||||
|
id: popup
|
||||||
|
padding: 0
|
||||||
|
|
||||||
|
y: -height
|
||||||
|
x: parent.width - width
|
||||||
|
|
||||||
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||||
|
|
||||||
|
contentItem: ColumnLayout
|
||||||
|
{
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
model: devicesModel
|
||||||
|
|
||||||
|
delegate: Cura.ActionButton
|
||||||
|
{
|
||||||
|
text: model.description
|
||||||
|
color: "transparent"
|
||||||
|
cornerRadius: 0
|
||||||
|
hoverColor: UM.Theme.getColor("primary")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
UM.OutputDeviceManager.setActiveDevice(model.id)
|
||||||
|
popup.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
opacity: visible ? 1 : 0
|
||||||
|
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||||
|
color: UM.Theme.getColor("action_panel_secondary")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.OutputDevicesModel { id: devicesModel }
|
||||||
|
}
|
130
resources/qml/ActionPanel/OutputProcessWidget.qml
Normal file
130
resources/qml/ActionPanel/OutputProcessWidget.qml
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
|
||||||
|
// This element contains all the elements the user needs to visualize the data
|
||||||
|
// that is gather after the slicing process, such as printint time, material usage, ...
|
||||||
|
// There are also two buttons: one to previsualize the output layers, and the other to
|
||||||
|
// select what to do with it (such as print over network, save to file, ...)
|
||||||
|
Column
|
||||||
|
{
|
||||||
|
id: widget
|
||||||
|
|
||||||
|
spacing: UM.Theme.getSize("thin_margin").height
|
||||||
|
property bool preSlicedData: PrintInformation.preSliced
|
||||||
|
|
||||||
|
UM.I18nCatalog
|
||||||
|
{
|
||||||
|
id: catalog
|
||||||
|
name: "cura"
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: information
|
||||||
|
width: parent.width
|
||||||
|
height: childrenRect.height
|
||||||
|
|
||||||
|
Column
|
||||||
|
{
|
||||||
|
id: timeAndCostsInformation
|
||||||
|
spacing: UM.Theme.getSize("thin_margin").height
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
right: printInformationPanel.left
|
||||||
|
rightMargin: UM.Theme.getSize("thin_margin").height
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.IconLabel
|
||||||
|
{
|
||||||
|
id: estimatedTime
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
text: preSlicedData ? catalog.i18nc("@label", "No time estimation available") : PrintInformation.currentPrintTime.getDisplayString(UM.DurationFormat.Long)
|
||||||
|
source: UM.Theme.getIcon("clock")
|
||||||
|
font: UM.Theme.getFont("small")
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.IconLabel
|
||||||
|
{
|
||||||
|
id: estimatedCosts
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
property var printMaterialLengths: PrintInformation.materialLengths
|
||||||
|
property var printMaterialWeights: PrintInformation.materialWeights
|
||||||
|
|
||||||
|
text:
|
||||||
|
{
|
||||||
|
if (preSlicedData)
|
||||||
|
{
|
||||||
|
return catalog.i18nc("@label", "No cost estimation available")
|
||||||
|
}
|
||||||
|
var totalLengths = 0
|
||||||
|
var totalWeights = 0
|
||||||
|
if (printMaterialLengths)
|
||||||
|
{
|
||||||
|
for(var index = 0; index < printMaterialLengths.length; index++)
|
||||||
|
{
|
||||||
|
if(printMaterialLengths[index] > 0)
|
||||||
|
{
|
||||||
|
totalLengths += printMaterialLengths[index]
|
||||||
|
totalWeights += Math.round(printMaterialWeights[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalWeights + "g · " + totalLengths.toFixed(2) + "m"
|
||||||
|
}
|
||||||
|
source: UM.Theme.getIcon("spool")
|
||||||
|
font: UM.Theme.getFont("very_small")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintInformationWidget
|
||||||
|
{
|
||||||
|
id: printInformationPanel
|
||||||
|
visible: !preSlicedData
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: timeAndCostsInformation.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: buttonRow
|
||||||
|
spacing: UM.Theme.getSize("default_margin").width
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
Cura.SecondaryButton
|
||||||
|
{
|
||||||
|
id: previewStageShortcut
|
||||||
|
|
||||||
|
height: UM.Theme.getSize("action_panel_button").height
|
||||||
|
text: catalog.i18nc("@button", "Preview")
|
||||||
|
|
||||||
|
onClicked: UM.Controller.setActiveStage("PreviewStage")
|
||||||
|
visible: UM.Controller.activeStage != null && UM.Controller.activeStage.stageId != "PreviewStage"
|
||||||
|
|
||||||
|
shadowEnabled: true
|
||||||
|
shadowColor: UM.Theme.getColor("action_button_disabled_shadow")
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.OutputDevicesActionButton
|
||||||
|
{
|
||||||
|
width: previewStageShortcut.visible ? UM.Theme.getSize("action_panel_button").width : parent.width
|
||||||
|
height: UM.Theme.getSize("action_panel_button").height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
resources/qml/ActionPanel/PrintInformationWidget.qml
Normal file
64
resources/qml/ActionPanel/PrintInformationWidget.qml
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: widget
|
||||||
|
|
||||||
|
//implicitHeight: UM.Theme.getSize("section_icon").height
|
||||||
|
//implicitWidth: UM.Theme.getSize("section_icon").width
|
||||||
|
|
||||||
|
source: UM.Theme.getIcon("info")
|
||||||
|
width: UM.Theme.getSize("section_icon").width
|
||||||
|
height: UM.Theme.getSize("section_icon").height
|
||||||
|
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
|
||||||
|
color: popup.opened ? UM.Theme.getColor("primary") : UM.Theme.getColor("text_medium")
|
||||||
|
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
onEntered: popup.open()
|
||||||
|
onExited: popup.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
Popup
|
||||||
|
{
|
||||||
|
id: popup
|
||||||
|
|
||||||
|
y: -(height + UM.Theme.getSize("default_arrow").height + UM.Theme.getSize("thin_margin").height)
|
||||||
|
x: parent.width - width + UM.Theme.getSize("thin_margin").width
|
||||||
|
|
||||||
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||||
|
|
||||||
|
opacity: opened ? 1 : 0
|
||||||
|
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||||
|
|
||||||
|
contentItem: PrintJobInformation
|
||||||
|
{
|
||||||
|
id: printJobInformation
|
||||||
|
width: UM.Theme.getSize("action_panel_information_widget").width
|
||||||
|
}
|
||||||
|
|
||||||
|
background: UM.PointingRectangle
|
||||||
|
{
|
||||||
|
color: UM.Theme.getColor("tool_panel_background")
|
||||||
|
borderColor: UM.Theme.getColor("lining")
|
||||||
|
borderWidth: UM.Theme.getSize("default_lining").width
|
||||||
|
|
||||||
|
target: Qt.point(width - (widget.width / 2) - UM.Theme.getSize("thin_margin").width,
|
||||||
|
height + UM.Theme.getSize("default_arrow").height - UM.Theme.getSize("thin_margin").height)
|
||||||
|
|
||||||
|
arrowSize: UM.Theme.getSize("default_arrow").width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
159
resources/qml/ActionPanel/PrintJobInformation.qml
Normal file
159
resources/qml/ActionPanel/PrintJobInformation.qml
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
Column
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
spacing: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
UM.I18nCatalog
|
||||||
|
{
|
||||||
|
id: catalog
|
||||||
|
name: "cura"
|
||||||
|
}
|
||||||
|
|
||||||
|
Column
|
||||||
|
{
|
||||||
|
id: timeSpecification
|
||||||
|
width: parent.width
|
||||||
|
topPadding: UM.Theme.getSize("default_margin").height
|
||||||
|
leftPadding: UM.Theme.getSize("default_margin").width
|
||||||
|
rightPadding: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@label", "Time specification").toUpperCase()
|
||||||
|
color: UM.Theme.getColor("primary")
|
||||||
|
font: UM.Theme.getFont("small")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
property var printDuration: PrintInformation.currentPrintTime
|
||||||
|
|
||||||
|
text:
|
||||||
|
{
|
||||||
|
// All the time information for the different features is achieved
|
||||||
|
var printTime = PrintInformation.getFeaturePrintTimes()
|
||||||
|
var totalSeconds = parseInt(printDuration.getDisplayString(UM.DurationFormat.Seconds))
|
||||||
|
|
||||||
|
// A message is created and displayed when the user hover the time label
|
||||||
|
var text = "<table width=\"100%\">"
|
||||||
|
for(var feature in printTime)
|
||||||
|
{
|
||||||
|
if(!printTime[feature].isTotalDurationZero)
|
||||||
|
{
|
||||||
|
text += "<tr><td>" + feature + ":</td>" +
|
||||||
|
"<td align=\"right\" valign=\"bottom\"> %1</td>".arg(printTime[feature].getDisplayString(UM.DurationFormat.ISO8601).slice(0,-3)) +
|
||||||
|
"<td align=\"right\" valign=\"bottom\"> %1%</td>".arg(Math.round(100 * parseInt(printTime[feature].getDisplayString(UM.DurationFormat.Seconds)) / totalSeconds)) +
|
||||||
|
"</tr>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text += "</table>"
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
width: parent.width - 2 * UM.Theme.getSize("default_margin").width
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
font: UM.Theme.getFont("very_small")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
textFormat: Text.RichText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column
|
||||||
|
{
|
||||||
|
id: materialSpecification
|
||||||
|
width: parent.width
|
||||||
|
bottomPadding: UM.Theme.getSize("default_margin").height
|
||||||
|
leftPadding: UM.Theme.getSize("default_margin").width
|
||||||
|
rightPadding: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@label", "Material specification").toUpperCase()
|
||||||
|
color: UM.Theme.getColor("primary")
|
||||||
|
font: UM.Theme.getFont("small")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
property var printMaterialLengths: PrintInformation.materialLengths
|
||||||
|
property var printMaterialWeights: PrintInformation.materialWeights
|
||||||
|
property var printMaterialCosts: PrintInformation.materialCosts
|
||||||
|
property var printMaterialNames: PrintInformation.materialNames
|
||||||
|
|
||||||
|
function formatRow(items)
|
||||||
|
{
|
||||||
|
var rowHTML = "<tr>"
|
||||||
|
for(var item = 0; item < items.length; item++)
|
||||||
|
{
|
||||||
|
if (item == 0)
|
||||||
|
{
|
||||||
|
rowHTML += "<td valign=\"bottom\">%1</td>".arg(items[item])
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rowHTML += "<td align=\"right\" valign=\"bottom\"> %1</td>".arg(items[item])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rowHTML += "</tr>"
|
||||||
|
return rowHTML
|
||||||
|
}
|
||||||
|
|
||||||
|
text:
|
||||||
|
{
|
||||||
|
var lengths = []
|
||||||
|
var weights = []
|
||||||
|
var costs = []
|
||||||
|
var names = []
|
||||||
|
if(printMaterialLengths)
|
||||||
|
{
|
||||||
|
for(var index = 0; index < printMaterialLengths.length; index++)
|
||||||
|
{
|
||||||
|
if(printMaterialLengths[index] > 0)
|
||||||
|
{
|
||||||
|
names.push(printMaterialNames[index])
|
||||||
|
lengths.push(printMaterialLengths[index].toFixed(2))
|
||||||
|
weights.push(String(Math.round(printMaterialWeights[index])))
|
||||||
|
var cost = printMaterialCosts[index] == undefined ? 0 : printMaterialCosts[index].toFixed(2)
|
||||||
|
costs.push(cost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(lengths.length == 0)
|
||||||
|
{
|
||||||
|
lengths = ["0.00"]
|
||||||
|
weights = ["0"]
|
||||||
|
costs = ["0.00"]
|
||||||
|
}
|
||||||
|
|
||||||
|
var text = "<table width=\"100%\">"
|
||||||
|
for(var index = 0; index < lengths.length; index++)
|
||||||
|
{
|
||||||
|
text += formatRow([
|
||||||
|
"%1:".arg(names[index]),
|
||||||
|
catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]),
|
||||||
|
catalog.i18nc("@label g for grams", "%1g").arg(weights[index]),
|
||||||
|
"%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
text += "</table>"
|
||||||
|
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
width: parent.width - 2 * UM.Theme.getSize("default_margin").width
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
font: UM.Theme.getFont("very_small")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
textFormat: Text.RichText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
154
resources/qml/ActionPanel/SliceProcessWidget.qml
Normal file
154
resources/qml/ActionPanel/SliceProcessWidget.qml
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import QtQuick.Controls 1.4 as Controls1
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
|
||||||
|
// This element contains all the elements the user needs to create a printjob from the
|
||||||
|
// model(s) that is(are) on the buildplate. Mainly the button to start/stop the slicing
|
||||||
|
// process and a progress bar to see the progress of the process.
|
||||||
|
Column
|
||||||
|
{
|
||||||
|
id: widget
|
||||||
|
|
||||||
|
spacing: UM.Theme.getSize("thin_margin").height
|
||||||
|
|
||||||
|
UM.I18nCatalog
|
||||||
|
{
|
||||||
|
id: catalog
|
||||||
|
name: "cura"
|
||||||
|
}
|
||||||
|
|
||||||
|
property real progress: UM.Backend.progress
|
||||||
|
property int backendState: UM.Backend.state
|
||||||
|
|
||||||
|
function sliceOrStopSlicing()
|
||||||
|
{
|
||||||
|
if (widget.backendState == UM.Backend.NotStarted)
|
||||||
|
{
|
||||||
|
CuraApplication.backend.forceSlice()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CuraApplication.backend.stopSlicing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: autoSlicingLabel
|
||||||
|
width: parent.width
|
||||||
|
visible: prepareButtons.autoSlice && widget.backendState == UM.Backend.Processing
|
||||||
|
|
||||||
|
text: catalog.i18nc("@label:PrintjobStatus", "Auto slicing...")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
font: UM.Theme.getFont("very_small")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.IconLabel
|
||||||
|
{
|
||||||
|
id: unableToSliceMessage
|
||||||
|
width: parent.width
|
||||||
|
visible: widget.backendState == UM.Backend.Error
|
||||||
|
|
||||||
|
text: catalog.i18nc("@label:PrintjobStatus", "Unable to Slice")
|
||||||
|
source: UM.Theme.getIcon("warning")
|
||||||
|
color: UM.Theme.getColor("warning")
|
||||||
|
font: UM.Theme.getFont("very_small")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Progress bar, only visible when the backend is in the process of slice the printjob
|
||||||
|
ProgressBar
|
||||||
|
{
|
||||||
|
id: progressBar
|
||||||
|
width: parent.width
|
||||||
|
height: UM.Theme.getSize("progressbar").height
|
||||||
|
value: progress
|
||||||
|
visible: widget.backendState == UM.Backend.Processing
|
||||||
|
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: UM.Theme.getSize("progressbar_radius").width
|
||||||
|
color: UM.Theme.getColor("progressbar_background")
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Item
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
width: progressBar.visualPosition * parent.width
|
||||||
|
height: parent.height
|
||||||
|
radius: UM.Theme.getSize("progressbar_radius").width
|
||||||
|
color: UM.Theme.getColor("progressbar_control")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: prepareButtons
|
||||||
|
// Get the current value from the preferences
|
||||||
|
property bool autoSlice: UM.Preferences.getValue("general/auto_slice")
|
||||||
|
// Disable the slice process when
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
height: UM.Theme.getSize("action_panel_button").height
|
||||||
|
visible: !autoSlice
|
||||||
|
Cura.PrimaryButton
|
||||||
|
{
|
||||||
|
id: sliceButton
|
||||||
|
fixedWidthMode: true
|
||||||
|
anchors.fill: parent
|
||||||
|
text: catalog.i18nc("@button", "Slice")
|
||||||
|
enabled: widget.backendState != UM.Backend.Error
|
||||||
|
visible: widget.backendState == UM.Backend.NotStarted || widget.backendState == UM.Backend.Error
|
||||||
|
onClicked: sliceOrStopSlicing()
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.SecondaryButton
|
||||||
|
{
|
||||||
|
id: cancelButton
|
||||||
|
fixedWidthMode: true
|
||||||
|
anchors.fill: parent
|
||||||
|
text: catalog.i18nc("@button", "Cancel")
|
||||||
|
enabled: sliceButton.enabled
|
||||||
|
visible: !sliceButton.visible
|
||||||
|
onClicked: sliceOrStopSlicing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// React when the user changes the preference of having the auto slice enabled
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: UM.Preferences
|
||||||
|
onPreferenceChanged:
|
||||||
|
{
|
||||||
|
var autoSlice = UM.Preferences.getValue("general/auto_slice")
|
||||||
|
prepareButtons.autoSlice = autoSlice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shortcut for "slice/stop"
|
||||||
|
Controls1.Action
|
||||||
|
{
|
||||||
|
shortcut: "Ctrl+P"
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
if (prepareButton.enabled)
|
||||||
|
{
|
||||||
|
sliceOrStopSlicing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2015 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
@ -23,8 +23,6 @@ Item
|
||||||
property alias viewLeftSideCamera: viewLeftSideCameraAction;
|
property alias viewLeftSideCamera: viewLeftSideCameraAction;
|
||||||
property alias viewRightSideCamera: viewRightSideCameraAction;
|
property alias viewRightSideCamera: viewRightSideCameraAction;
|
||||||
|
|
||||||
property alias expandSidebar: expandSidebarAction;
|
|
||||||
|
|
||||||
property alias deleteSelection: deleteSelectionAction;
|
property alias deleteSelection: deleteSelectionAction;
|
||||||
property alias centerSelection: centerSelectionAction;
|
property alias centerSelection: centerSelectionAction;
|
||||||
property alias multiplySelection: multiplySelectionAction;
|
property alias multiplySelection: multiplySelectionAction;
|
||||||
|
@ -58,7 +56,6 @@ Item
|
||||||
|
|
||||||
property alias preferences: preferencesAction;
|
property alias preferences: preferencesAction;
|
||||||
|
|
||||||
property alias showEngineLog: showEngineLogAction;
|
|
||||||
property alias showProfileFolder: showProfileFolderAction;
|
property alias showProfileFolder: showProfileFolderAction;
|
||||||
property alias documentation: documentationAction;
|
property alias documentation: documentationAction;
|
||||||
property alias reportBug: reportBugAction;
|
property alias reportBug: reportBugAction;
|
||||||
|
@ -70,7 +67,7 @@ Item
|
||||||
|
|
||||||
property alias browsePackages: browsePackagesAction
|
property alias browsePackages: browsePackagesAction
|
||||||
|
|
||||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||||
|
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
|
@ -398,14 +395,6 @@ Item
|
||||||
shortcut: StandardKey.New
|
shortcut: StandardKey.New
|
||||||
}
|
}
|
||||||
|
|
||||||
Action
|
|
||||||
{
|
|
||||||
id: showEngineLogAction;
|
|
||||||
text: catalog.i18nc("@action:inmenu menubar:help","Show Engine &Log...");
|
|
||||||
iconName: "view-list-text";
|
|
||||||
shortcut: StandardKey.WhatsThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
id: showProfileFolderAction;
|
id: showProfileFolderAction;
|
||||||
|
@ -426,11 +415,4 @@ Item
|
||||||
text: catalog.i18nc("@action:menu", "&Marketplace")
|
text: catalog.i18nc("@action:menu", "&Marketplace")
|
||||||
iconName: "plugins_browse"
|
iconName: "plugins_browse"
|
||||||
}
|
}
|
||||||
|
|
||||||
Action
|
|
||||||
{
|
|
||||||
id: expandSidebarAction;
|
|
||||||
text: catalog.i18nc("@action:inmenu menubar:view","Expand/Collapse Sidebar");
|
|
||||||
shortcut: "Ctrl+E";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
10
resources/qml/BorderGroup.qml
Normal file
10
resources/qml/BorderGroup.qml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.0
|
||||||
|
|
||||||
|
QtObject
|
||||||
|
{
|
||||||
|
property real width: 0
|
||||||
|
property color color: "black"
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2017 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
|
@ -6,53 +6,42 @@ import QtQuick.Controls 1.4
|
||||||
import QtQuick.Controls.Styles 1.4
|
import QtQuick.Controls.Styles 1.4
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import QtQuick.Dialogs 1.2
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
|
||||||
import UM 1.3 as UM
|
import UM 1.3 as UM
|
||||||
import Cura 1.1 as Cura
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
import "Dialogs"
|
||||||
import "Menus"
|
import "Menus"
|
||||||
|
import "MainWindow"
|
||||||
|
|
||||||
UM.MainWindow
|
UM.MainWindow
|
||||||
{
|
{
|
||||||
id: base
|
id: base
|
||||||
//: Cura application window title
|
|
||||||
title: catalog.i18nc("@title:window","Ultimaker Cura");
|
|
||||||
viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0)
|
|
||||||
property bool showPrintMonitor: false
|
|
||||||
|
|
||||||
|
// Cura application window title
|
||||||
|
title: catalog.i18nc("@title:window", "Ultimaker Cura")
|
||||||
backgroundColor: UM.Theme.getColor("viewport_background")
|
backgroundColor: UM.Theme.getColor("viewport_background")
|
||||||
// This connection is here to support legacy printer output devices that use the showPrintMonitor signal on Application to switch to the monitor stage
|
|
||||||
// It should be phased out in newer plugin versions.
|
UM.I18nCatalog
|
||||||
Connections
|
|
||||||
{
|
{
|
||||||
target: CuraApplication
|
id: catalog
|
||||||
onShowPrintMonitor: {
|
name: "cura"
|
||||||
if (show) {
|
|
||||||
UM.Controller.setActiveStage("MonitorStage")
|
|
||||||
} else {
|
|
||||||
UM.Controller.setActiveStage("PrepareStage")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onWidthChanged:
|
function showTooltip(item, position, text)
|
||||||
{
|
{
|
||||||
// If slidebar is collapsed then it should be invisible
|
tooltip.text = text;
|
||||||
// otherwise after the main_window resize the sidebar will be fully re-drawn
|
position = item.mapToItem(backgroundItem, position.x - UM.Theme.getSize("default_arrow").width, position.y);
|
||||||
if (sidebar.collapsed){
|
tooltip.show(position);
|
||||||
if (sidebar.visible == true){
|
|
||||||
sidebar.visible = false
|
|
||||||
sidebar.initialWidth = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (sidebar.visible == false){
|
|
||||||
sidebar.visible = true
|
|
||||||
sidebar.initialWidth = UM.Theme.getSize("sidebar").width
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hideTooltip()
|
||||||
|
{
|
||||||
|
tooltip.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Component.onCompleted:
|
Component.onCompleted:
|
||||||
{
|
{
|
||||||
CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size"))
|
CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size"))
|
||||||
|
@ -72,12 +61,12 @@ UM.MainWindow
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
id: backgroundItem;
|
id: backgroundItem
|
||||||
anchors.fill: parent;
|
anchors.fill: parent
|
||||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
|
||||||
|
|
||||||
signal hasMesh(string name) //this signal sends the filebase name so it can be used for the JobSpecs.qml
|
signal hasMesh(string name) //this signal sends the filebase name so it can be used for the JobSpecs.qml
|
||||||
function getMeshName(path){
|
function getMeshName(path)
|
||||||
|
{
|
||||||
//takes the path the complete path of the meshname and returns only the filebase
|
//takes the path the complete path of the meshname and returns only the filebase
|
||||||
var fileName = path.slice(path.lastIndexOf("/") + 1)
|
var fileName = path.slice(path.lastIndexOf("/") + 1)
|
||||||
var fileBase = fileName.slice(0, fileName.indexOf("."))
|
var fileBase = fileName.slice(0, fileName.indexOf("."))
|
||||||
|
@ -85,253 +74,49 @@ UM.MainWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
//DeleteSelection on the keypress backspace event
|
//DeleteSelection on the keypress backspace event
|
||||||
Keys.onPressed: {
|
Keys.onPressed:
|
||||||
|
{
|
||||||
if (event.key == Qt.Key_Backspace)
|
if (event.key == Qt.Key_Backspace)
|
||||||
{
|
{
|
||||||
Cura.Actions.deleteSelection.trigger()
|
Cura.Actions.deleteSelection.trigger()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UM.ApplicationMenu
|
ApplicationMenu
|
||||||
{
|
{
|
||||||
id: menu
|
id: applicationMenu
|
||||||
window: base
|
window: base
|
||||||
|
}
|
||||||
|
|
||||||
Menu
|
MainWindowHeader
|
||||||
{
|
{
|
||||||
id: fileMenu
|
id: mainWindowHeader
|
||||||
title: catalog.i18nc("@title:menu menubar:toplevel","&File");
|
anchors
|
||||||
MenuItem
|
|
||||||
{
|
{
|
||||||
id: newProjectMenu
|
left: parent.left
|
||||||
action: Cura.Actions.newProject;
|
right: parent.right
|
||||||
|
top: applicationMenu.bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
id: openMenu
|
|
||||||
action: Cura.Actions.open;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecentFilesMenu { }
|
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
id: saveWorkspaceMenu
|
|
||||||
text: catalog.i18nc("@title:menu menubar:file","&Save...")
|
|
||||||
onTriggered:
|
|
||||||
{
|
|
||||||
var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml" };
|
|
||||||
if(UM.Preferences.getValue("cura/dialog_on_project_save"))
|
|
||||||
{
|
|
||||||
saveWorkspaceDialog.args = args;
|
|
||||||
saveWorkspaceDialog.open()
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuSeparator { }
|
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
id: saveAsMenu
|
|
||||||
text: catalog.i18nc("@title:menu menubar:file", "&Export...")
|
|
||||||
onTriggered:
|
|
||||||
{
|
|
||||||
var localDeviceId = "local_file";
|
|
||||||
UM.OutputDeviceManager.requestWriteToDevice(localDeviceId, PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
id: exportSelectionMenu
|
|
||||||
text: catalog.i18nc("@action:inmenu menubar:file", "Export Selection...");
|
|
||||||
enabled: UM.Selection.hasSelection;
|
|
||||||
iconName: "document-save-as";
|
|
||||||
onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file", PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"});
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuSeparator { }
|
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
id: reloadAllMenu
|
|
||||||
action: Cura.Actions.reloadAll;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuSeparator { }
|
|
||||||
|
|
||||||
MenuItem { action: Cura.Actions.quit; }
|
|
||||||
}
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Edit");
|
|
||||||
|
|
||||||
MenuItem { action: Cura.Actions.undo; }
|
|
||||||
MenuItem { action: Cura.Actions.redo; }
|
|
||||||
MenuSeparator { }
|
|
||||||
MenuItem { action: Cura.Actions.selectAll; }
|
|
||||||
MenuItem { action: Cura.Actions.arrangeAll; }
|
|
||||||
MenuItem { action: Cura.Actions.deleteSelection; }
|
|
||||||
MenuItem { action: Cura.Actions.deleteAll; }
|
|
||||||
MenuItem { action: Cura.Actions.resetAllTranslation; }
|
|
||||||
MenuItem { action: Cura.Actions.resetAll; }
|
|
||||||
MenuSeparator { }
|
|
||||||
MenuItem { action: Cura.Actions.groupObjects;}
|
|
||||||
MenuItem { action: Cura.Actions.mergeObjects;}
|
|
||||||
MenuItem { action: Cura.Actions.unGroupObjects;}
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewMenu { title: catalog.i18nc("@title:menu", "&View") }
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
id: settingsMenu
|
|
||||||
title: catalog.i18nc("@title:menu", "&Settings")
|
|
||||||
|
|
||||||
PrinterMenu { title: catalog.i18nc("@title:menu menubar:settings", "&Printer") }
|
|
||||||
|
|
||||||
Instantiator
|
|
||||||
{
|
|
||||||
model: Cura.ExtrudersModel { simpleNames: true }
|
|
||||||
Menu {
|
|
||||||
title: model.name
|
|
||||||
|
|
||||||
NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.hasVariants; extruderIndex: index }
|
|
||||||
MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.hasMaterials; extruderIndex: index }
|
|
||||||
|
|
||||||
MenuSeparator
|
|
||||||
{
|
|
||||||
visible: Cura.MachineManager.hasVariants || Cura.MachineManager.hasMaterials
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@action:inmenu", "Set as Active Extruder")
|
|
||||||
onTriggered: Cura.MachineManager.setExtruderIndex(model.index)
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@action:inmenu", "Enable Extruder")
|
|
||||||
onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, true)
|
|
||||||
visible: !Cura.MachineManager.getExtruder(model.index).isEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@action:inmenu", "Disable Extruder")
|
|
||||||
onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, false)
|
|
||||||
visible: Cura.MachineManager.getExtruder(model.index).isEnabled
|
|
||||||
enabled: Cura.MachineManager.numberExtrudersEnabled > 1
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
onObjectAdded: settingsMenu.insertItem(index, object)
|
|
||||||
onObjectRemoved: settingsMenu.removeItem(object)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Only show in dev mode. Remove check when feature ready
|
|
||||||
BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: CuraSDKVersion == "dev" ? Cura.MachineManager.hasVariantBuildplates : false }
|
|
||||||
ProfileMenu { title: catalog.i18nc("@title:settings", "&Profile"); }
|
|
||||||
|
|
||||||
MenuSeparator { }
|
|
||||||
|
|
||||||
MenuItem { action: Cura.Actions.configureSettingVisibility }
|
|
||||||
}
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
id: extension_menu
|
|
||||||
title: catalog.i18nc("@title:menu menubar:toplevel","E&xtensions");
|
|
||||||
|
|
||||||
Instantiator
|
|
||||||
{
|
|
||||||
id: extensions
|
|
||||||
model: UM.ExtensionModel { }
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
id: sub_menu
|
|
||||||
title: model.name;
|
|
||||||
visible: actions != null
|
|
||||||
enabled: actions != null
|
|
||||||
Instantiator
|
|
||||||
{
|
|
||||||
model: actions
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
text: model.text
|
|
||||||
onTriggered: extensions.model.subMenuTriggered(name, model.text)
|
|
||||||
}
|
|
||||||
onObjectAdded: sub_menu.insertItem(index, object)
|
|
||||||
onObjectRemoved: sub_menu.removeItem(object)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onObjectAdded: extension_menu.insertItem(index, object)
|
|
||||||
onObjectRemoved: extension_menu.removeItem(object)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
id: plugin_menu
|
|
||||||
title: catalog.i18nc("@title:menu menubar:toplevel", "&Marketplace")
|
|
||||||
|
|
||||||
MenuItem { action: Cura.Actions.browsePackages }
|
|
||||||
}
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
id: preferencesMenu
|
|
||||||
title: catalog.i18nc("@title:menu menubar:toplevel","P&references");
|
|
||||||
|
|
||||||
MenuItem { action: Cura.Actions.preferences; }
|
|
||||||
}
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
id: helpMenu
|
|
||||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Help");
|
|
||||||
|
|
||||||
MenuItem { action: Cura.Actions.showProfileFolder; }
|
|
||||||
MenuItem { action: Cura.Actions.documentation; }
|
|
||||||
MenuItem { action: Cura.Actions.reportBug; }
|
|
||||||
MenuSeparator { }
|
|
||||||
MenuItem { action: Cura.Actions.about; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UM.SettingPropertyProvider
|
|
||||||
{
|
|
||||||
id: machineExtruderCount
|
|
||||||
|
|
||||||
containerStack: Cura.MachineManager.activeMachine
|
|
||||||
key: "machine_extruder_count"
|
|
||||||
watchedProperties: [ "value" ]
|
|
||||||
storeIndex: 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
id: contentItem;
|
id: contentItem
|
||||||
|
|
||||||
y: menu.height
|
anchors
|
||||||
width: parent.width;
|
{
|
||||||
height: parent.height - menu.height;
|
top: mainWindowHeader.bottom
|
||||||
|
bottom: parent.bottom
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
Keys.forwardTo: menu
|
Keys.forwardTo: applicationMenu
|
||||||
|
|
||||||
DropArea
|
DropArea
|
||||||
{
|
{
|
||||||
anchors.fill: parent;
|
// The drop area is here to handle files being dropped onto Cura.
|
||||||
|
anchors.fill: parent
|
||||||
onDropped:
|
onDropped:
|
||||||
{
|
{
|
||||||
if (drop.urls.length > 0)
|
if (drop.urls.length > 0)
|
||||||
|
@ -359,156 +144,154 @@ UM.MainWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: stageMenuBackground
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
top: parent.top
|
||||||
|
}
|
||||||
|
visible: stageMenu.source != ""
|
||||||
|
height: visible ? Math.round(UM.Theme.getSize("stage_menu").height / 2) : 0
|
||||||
|
|
||||||
|
LinearGradient
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
start: Qt.point(0, 0)
|
||||||
|
end: Qt.point(parent.width, 0)
|
||||||
|
gradient: Gradient
|
||||||
|
{
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.0
|
||||||
|
color: UM.Theme.getColor("main_window_header_background")
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.5
|
||||||
|
color: UM.Theme.getColor("main_window_header_background_gradient")
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 1.0
|
||||||
|
color: UM.Theme.getColor("main_window_header_background")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: stageMenu.item
|
||||||
|
onShowTooltip: base.showTooltip(item, location, text)
|
||||||
|
onHideTooltip: base.hideTooltip()
|
||||||
|
}
|
||||||
|
|
||||||
JobSpecs
|
JobSpecs
|
||||||
{
|
{
|
||||||
id: jobSpecs
|
id: jobSpecs
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
bottom: parent.bottom;
|
bottom: parent.bottom
|
||||||
right: sidebar.left;
|
bottomMargin: UM.Theme.getSize("default_margin").height
|
||||||
bottomMargin: UM.Theme.getSize("default_margin").height;
|
|
||||||
rightMargin: UM.Theme.getSize("default_margin").width;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
id: openFileButton;
|
|
||||||
text: catalog.i18nc("@action:button","Open File");
|
|
||||||
iconSource: UM.Theme.getIcon("load")
|
|
||||||
style: UM.Theme.styles.tool_button
|
|
||||||
tooltip: ""
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
top: topbar.bottom;
|
|
||||||
topMargin: UM.Theme.getSize("default_margin").height;
|
|
||||||
left: parent.left;
|
|
||||||
}
|
|
||||||
action: Cura.Actions.open;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toolbar
|
Toolbar
|
||||||
{
|
{
|
||||||
id: toolbar;
|
// The toolbar is the left bar that is populated by all the tools (which are dynamicly populated by
|
||||||
|
// plugins)
|
||||||
|
id: toolbar
|
||||||
|
|
||||||
property int mouseX: base.mouseX
|
property int mouseX: base.mouseX
|
||||||
property int mouseY: base.mouseY
|
property int mouseY: base.mouseY
|
||||||
|
|
||||||
anchors {
|
anchors
|
||||||
top: openFileButton.bottom;
|
{
|
||||||
topMargin: UM.Theme.getSize("window_margin").height;
|
verticalCenter: parent.verticalCenter
|
||||||
left: parent.left;
|
left: parent.left
|
||||||
}
|
}
|
||||||
|
visible: CuraApplication.platformActivity && !PrintInformation.preSliced
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectsList
|
ObjectsList
|
||||||
{
|
{
|
||||||
id: objectsList;
|
id: objectsList
|
||||||
visible: UM.Preferences.getValue("cura/use_multi_build_plate");
|
visible: UM.Preferences.getValue("cura/use_multi_build_plate")
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
bottom: parent.bottom;
|
bottom: viewOrientationControls.top
|
||||||
left: parent.left;
|
left: toolbar.right
|
||||||
|
margins: UM.Theme.getSize("default_margin").width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
ViewOrientationControls
|
||||||
|
{
|
||||||
Topbar
|
id: viewOrientationControls
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
margins: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.ActionPanelWidget
|
||||||
{
|
{
|
||||||
id: topbar
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("thick_margin").width
|
||||||
|
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
|
||||||
|
visible: CuraApplication.platformActivity
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader
|
Loader
|
||||||
{
|
{
|
||||||
|
// A stage can control this area. If nothing is set, it will therefore show the 3D view.
|
||||||
id: main
|
id: main
|
||||||
|
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: topbar.bottom
|
top: stageMenuBackground.bottom
|
||||||
bottom: parent.bottom
|
|
||||||
left: parent.left
|
left: parent.left
|
||||||
right: sidebar.left
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea
|
source: UM.Controller.activeStage != null ? UM.Controller.activeStage.mainComponent : ""
|
||||||
{
|
|
||||||
visible: UM.Controller.activeStage.mainComponent != ""
|
|
||||||
anchors.fill: parent
|
|
||||||
acceptedButtons: Qt.AllButtons
|
|
||||||
onWheel: wheel.accepted = true
|
|
||||||
}
|
|
||||||
|
|
||||||
source: UM.Controller.activeStage.mainComponent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader
|
Loader
|
||||||
{
|
{
|
||||||
id: sidebar
|
// 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
|
||||||
property bool collapsed: false;
|
// without this menu!
|
||||||
property var initialWidth: UM.Theme.getSize("sidebar").width;
|
id: stageMenu
|
||||||
|
|
||||||
function callExpandOrCollapse() {
|
|
||||||
if (collapsed) {
|
|
||||||
sidebar.visible = true;
|
|
||||||
sidebar.initialWidth = UM.Theme.getSize("sidebar").width;
|
|
||||||
viewportRect = Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0);
|
|
||||||
expandSidebarAnimation.start();
|
|
||||||
} else {
|
|
||||||
viewportRect = Qt.rect(0, 0, 1, 1.0);
|
|
||||||
collapseSidebarAnimation.start();
|
|
||||||
}
|
|
||||||
collapsed = !collapsed;
|
|
||||||
UM.Preferences.setValue("cura/sidebar_collapsed", collapsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: topbar.top
|
left: parent.left
|
||||||
bottom: parent.bottom
|
right: parent.right
|
||||||
|
top: parent.top
|
||||||
}
|
}
|
||||||
|
|
||||||
width: initialWidth
|
height: UM.Theme.getSize("stage_menu").height
|
||||||
x: base.width - sidebar.width
|
source: UM.Controller.activeStage != null ? UM.Controller.activeStage.stageMenuComponent : ""
|
||||||
source: UM.Controller.activeStage.sidebarComponent
|
|
||||||
|
|
||||||
NumberAnimation {
|
// The printSetupSelector is defined here so that the setting list doesn't need to get re-instantiated
|
||||||
id: collapseSidebarAnimation
|
// Every time the stage is changed.
|
||||||
target: sidebar
|
property var printSetupSelector: Cura.PrintSetupSelector
|
||||||
properties: "x"
|
|
||||||
to: base.width
|
|
||||||
duration: 100
|
|
||||||
}
|
|
||||||
|
|
||||||
NumberAnimation {
|
|
||||||
id: expandSidebarAnimation
|
|
||||||
target: sidebar
|
|
||||||
properties: "x"
|
|
||||||
to: base.width - sidebar.width
|
|
||||||
duration: 100
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted:
|
|
||||||
{
|
{
|
||||||
var sidebar_collapsed = UM.Preferences.getValue("cura/sidebar_collapsed");
|
onShowTooltip: base.showTooltip(item, location, text)
|
||||||
|
onHideTooltip: base.hideTooltip()
|
||||||
if (sidebar_collapsed)
|
width: UM.Theme.getSize("print_setup_widget").width
|
||||||
{
|
height: UM.Theme.getSize("stage_menu").height
|
||||||
sidebar.collapsed = true;
|
headerCornerSide: RoundedRectangle.Direction.Right
|
||||||
viewportRect = Qt.rect(0, 0, 1, 1.0)
|
|
||||||
collapseSidebarAnimation.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea
|
|
||||||
{
|
|
||||||
visible: UM.Controller.activeStage.sidebarComponent != ""
|
|
||||||
anchors.fill: parent
|
|
||||||
acceptedButtons: Qt.AllButtons
|
|
||||||
onWheel: wheel.accepted = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,20 +300,17 @@ UM.MainWindow
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
horizontalCenterOffset: -(Math.round(UM.Theme.getSize("sidebar").width / 2))
|
top: parent.verticalCenter
|
||||||
top: parent.verticalCenter;
|
bottom: parent.bottom
|
||||||
bottom: parent.bottom;
|
|
||||||
bottomMargin: UM.Theme.getSize("default_margin").height
|
bottomMargin: UM.Theme.getSize("default_margin").height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Expand or collapse sidebar
|
SidebarTooltip
|
||||||
Connections
|
|
||||||
{
|
{
|
||||||
target: Cura.Actions.expandSidebar
|
id: tooltip
|
||||||
onTriggered: sidebar.callExpandOrCollapse()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UM.PreferencesDialog
|
UM.PreferencesDialog
|
||||||
|
@ -567,13 +347,6 @@ UM.MainWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkspaceSummaryDialog
|
|
||||||
{
|
|
||||||
id: saveWorkspaceDialog
|
|
||||||
property var args
|
|
||||||
onYes: UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections
|
Connections
|
||||||
{
|
{
|
||||||
target: Cura.Actions.preferences
|
target: Cura.Actions.preferences
|
||||||
|
@ -586,33 +359,6 @@ UM.MainWindow
|
||||||
onShowPreferencesWindow: preferences.visible = true
|
onShowPreferencesWindow: preferences.visible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageDialog
|
|
||||||
{
|
|
||||||
id: newProjectDialog
|
|
||||||
modality: Qt.ApplicationModal
|
|
||||||
title: catalog.i18nc("@title:window", "New project")
|
|
||||||
text: catalog.i18nc("@info:question", "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings.")
|
|
||||||
standardButtons: StandardButton.Yes | StandardButton.No
|
|
||||||
icon: StandardIcon.Question
|
|
||||||
onYes:
|
|
||||||
{
|
|
||||||
CuraApplication.deleteAll();
|
|
||||||
Cura.Actions.resetProfile.trigger();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections
|
|
||||||
{
|
|
||||||
target: Cura.Actions.newProject
|
|
||||||
onTriggered:
|
|
||||||
{
|
|
||||||
if(Printer.platformActivity || Cura.MachineManager.hasUserSettings)
|
|
||||||
{
|
|
||||||
newProjectDialog.visible = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections
|
Connections
|
||||||
{
|
{
|
||||||
target: Cura.Actions.addProfile
|
target: Cura.Actions.addProfile
|
||||||
|
@ -670,19 +416,6 @@ UM.MainWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UM.ExtensionModel {
|
|
||||||
id: curaExtensions
|
|
||||||
}
|
|
||||||
|
|
||||||
// show the plugin browser dialog
|
|
||||||
Connections
|
|
||||||
{
|
|
||||||
target: Cura.Actions.browsePackages
|
|
||||||
onTriggered: {
|
|
||||||
curaExtensions.callExtensionMethod("Toolbox", "browsePackages")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer
|
Timer
|
||||||
{
|
{
|
||||||
id: createProfileTimer
|
id: createProfileTimer
|
||||||
|
@ -703,7 +436,8 @@ UM.MainWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextMenu {
|
ContextMenu
|
||||||
|
{
|
||||||
id: contextMenu
|
id: contextMenu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -870,7 +604,8 @@ UM.MainWindow
|
||||||
modality: Qt.ApplicationModal
|
modality: Qt.ApplicationModal
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageDialog {
|
MessageDialog
|
||||||
|
{
|
||||||
id: infoMultipleFilesWithGcodeDialog
|
id: infoMultipleFilesWithGcodeDialog
|
||||||
title: catalog.i18nc("@title:window", "Open File(s)")
|
title: catalog.i18nc("@title:window", "Open File(s)")
|
||||||
icon: StandardIcon.Information
|
icon: StandardIcon.Information
|
||||||
|
@ -914,11 +649,6 @@ UM.MainWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineLog
|
|
||||||
{
|
|
||||||
id: engineLog;
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections
|
Connections
|
||||||
{
|
{
|
||||||
target: Cura.Actions.showProfileFolder
|
target: Cura.Actions.showProfileFolder
|
||||||
|
|
357
resources/qml/CustomConfigurationSelector.qml
Normal file
357
resources/qml/CustomConfigurationSelector.qml
Normal file
|
@ -0,0 +1,357 @@
|
||||||
|
// 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.1
|
||||||
|
import QtQuick.Controls.Styles 1.1
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
implicitWidth: parent.width
|
||||||
|
implicitHeight: parent.height
|
||||||
|
|
||||||
|
id: base
|
||||||
|
color: UM.Theme.getColor("main_background")
|
||||||
|
|
||||||
|
// Height has an extra 2x margin for the top & bottom margin.
|
||||||
|
height: childrenRect.height + 2 * UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
Cura.ExtrudersModel { id: extrudersModel }
|
||||||
|
|
||||||
|
ListView
|
||||||
|
{
|
||||||
|
// Horizontal list that shows the extruders
|
||||||
|
id: extrudersList
|
||||||
|
visible: extrudersModel.items.length > 1
|
||||||
|
property var index: 0
|
||||||
|
|
||||||
|
height: UM.Theme.getSize("configuration_selector_mode_tabs").height
|
||||||
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
top: parent.top
|
||||||
|
margins: UM.Theme.getSize("thick_margin").width
|
||||||
|
}
|
||||||
|
|
||||||
|
ExclusiveGroup { id: extruderMenuGroup }
|
||||||
|
|
||||||
|
orientation: ListView.Horizontal
|
||||||
|
|
||||||
|
model: extrudersModel
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: Cura.MachineManager
|
||||||
|
onGlobalContainerChanged: forceActiveFocus() // Changing focus applies the currently-being-typed values so it can change the displayed setting values.
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: Button
|
||||||
|
{
|
||||||
|
height: parent.height
|
||||||
|
width: Math.round(ListView.view.width / extrudersModel.rowCount())
|
||||||
|
|
||||||
|
text: model.name
|
||||||
|
tooltip: model.name
|
||||||
|
exclusiveGroup: extruderMenuGroup
|
||||||
|
checked: Cura.ExtruderManager.activeExtruderIndex == index
|
||||||
|
|
||||||
|
property bool extruder_enabled: true
|
||||||
|
|
||||||
|
MouseArea // TODO; This really should be fixed. It makes absolutely no sense to have a button AND a mouse area.
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
switch (mouse.button)
|
||||||
|
{
|
||||||
|
case Qt.LeftButton:
|
||||||
|
extruder_enabled = Cura.MachineManager.getExtruder(model.index).isEnabled
|
||||||
|
if (extruder_enabled)
|
||||||
|
{
|
||||||
|
forceActiveFocus() // Changing focus applies the currently-being-typed values so it can change the displayed setting values.
|
||||||
|
Cura.ExtruderManager.setActiveExtruderIndex(index)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case Qt.RightButton:
|
||||||
|
extruder_enabled = Cura.MachineManager.getExtruder(model.index).isEnabled
|
||||||
|
extruderMenu.popup()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
|
id: extruderMenu
|
||||||
|
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@action:inmenu", "Enable Extruder")
|
||||||
|
onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, true)
|
||||||
|
visible: !extruder_enabled // using an intermediate variable prevents an empty popup that occured now and then
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@action:inmenu", "Disable Extruder")
|
||||||
|
onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, false)
|
||||||
|
visible: extruder_enabled
|
||||||
|
enabled: Cura.MachineManager.numberExtrudersEnabled > 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
style: ButtonStyle
|
||||||
|
{
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width
|
||||||
|
border.color:
|
||||||
|
{
|
||||||
|
if (Cura.MachineManager.getExtruder(index).isEnabled)
|
||||||
|
{
|
||||||
|
if(control.checked || control.pressed)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("action_button_active_border")
|
||||||
|
}
|
||||||
|
else if (control.hovered)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("action_button_hovered_border")
|
||||||
|
}
|
||||||
|
return UM.Theme.getColor("action_button_border")
|
||||||
|
}
|
||||||
|
return UM.Theme.getColor("action_button_disabled_border")
|
||||||
|
}
|
||||||
|
color:
|
||||||
|
{
|
||||||
|
if (Cura.MachineManager.getExtruder(index).isEnabled)
|
||||||
|
{
|
||||||
|
if(control.checked || control.pressed)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("action_button_active");
|
||||||
|
}
|
||||||
|
else if (control.hovered)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("action_button_hovered")
|
||||||
|
}
|
||||||
|
return UM.Theme.getColor("action_button")
|
||||||
|
}
|
||||||
|
return UM.Theme.getColor("action_button_disabled")
|
||||||
|
}
|
||||||
|
Behavior on color { ColorAnimation { duration: 50; } }
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: extruderButtonFace
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: childrenRect.width
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
// Static text that holds the "Extruder" label
|
||||||
|
id: extruderStaticText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
|
color:
|
||||||
|
{
|
||||||
|
if (Cura.MachineManager.getExtruder(index).isEnabled)
|
||||||
|
{
|
||||||
|
if(control.checked || control.pressed)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("action_button_active_text");
|
||||||
|
}
|
||||||
|
else if (control.hovered)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("action_button_hovered_text")
|
||||||
|
}
|
||||||
|
return UM.Theme.getColor("action_button_text")
|
||||||
|
}
|
||||||
|
return UM.Theme.getColor("action_button_disabled_text")
|
||||||
|
}
|
||||||
|
|
||||||
|
font: UM.Theme.getFont("large_nonbold")
|
||||||
|
text: catalog.i18nc("@label", "Extruder")
|
||||||
|
visible: width < (control.width - extruderIcon.width - UM.Theme.getSize("default_margin").width)
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtruderIcon
|
||||||
|
{
|
||||||
|
// Round icon with the extruder number and material color indicator.
|
||||||
|
id: extruderIcon
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: extruderStaticText.right
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
width: control.height - Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||||
|
height: width
|
||||||
|
|
||||||
|
checked: control.checked
|
||||||
|
materialColor: model.color
|
||||||
|
textColor: extruderStaticText.color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label: Item {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: materialRow
|
||||||
|
height: UM.Theme.getSize("print_setup_item").height
|
||||||
|
visible: Cura.MachineManager.hasMaterials
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
top: extrudersList.bottom
|
||||||
|
margins: UM.Theme.getSize("thick_margin").width
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: materialLabel
|
||||||
|
text: catalog.i18nc("@label", "Material");
|
||||||
|
width: Math.round(parent.width * 0.45 - UM.Theme.getSize("default_margin").width)
|
||||||
|
height: parent.height
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
font: UM.Theme.getFont("default");
|
||||||
|
color: UM.Theme.getColor("text");
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolButton
|
||||||
|
{
|
||||||
|
id: materialSelection
|
||||||
|
|
||||||
|
property var activeExtruder: Cura.MachineManager.activeStack
|
||||||
|
property var hasActiveExtruder: activeExtruder != null
|
||||||
|
property var currentRootMaterialName: hasActiveExtruder ? activeExtruder.material.name : ""
|
||||||
|
|
||||||
|
text: currentRootMaterialName
|
||||||
|
tooltip: currentRootMaterialName
|
||||||
|
visible: Cura.MachineManager.hasMaterials
|
||||||
|
|
||||||
|
enabled: !extrudersList.visible || Cura.ExtruderManager.activeExtruderIndex > -1
|
||||||
|
|
||||||
|
height: UM.Theme.getSize("setting_control").height
|
||||||
|
width: Math.round(parent.width * 0.7) + UM.Theme.getSize("thick_margin").width
|
||||||
|
anchors.right: parent.right
|
||||||
|
style: UM.Theme.styles.sidebar_header_button
|
||||||
|
activeFocusOnPress: true;
|
||||||
|
menu: Cura.MaterialMenu
|
||||||
|
{
|
||||||
|
extruderIndex: Cura.ExtruderManager.activeExtruderIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
property var valueError: hasActiveExtruder ? Cura.ContainerManager.getContainerMetaDataEntry(activeExtruder.material.id, "compatible", "") != "True" : true
|
||||||
|
property var valueWarning: ! Cura.MachineManager.isActiveQualitySupported
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: variantRow
|
||||||
|
height: UM.Theme.getSize("print_setup_item").height
|
||||||
|
visible: Cura.MachineManager.hasVariants
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
top: materialRow.bottom
|
||||||
|
margins: UM.Theme.getSize("thick_margin").width
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: variantLabel
|
||||||
|
text: Cura.MachineManager.activeDefinitionVariantsName;
|
||||||
|
width: Math.round(parent.width * 0.45 - UM.Theme.getSize("default_margin").width)
|
||||||
|
height: parent.height
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
font: UM.Theme.getFont("default");
|
||||||
|
color: UM.Theme.getColor("text");
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolButton
|
||||||
|
{
|
||||||
|
id: variantSelection
|
||||||
|
text: Cura.MachineManager.activeVariantName
|
||||||
|
tooltip: Cura.MachineManager.activeVariantName;
|
||||||
|
visible: Cura.MachineManager.hasVariants
|
||||||
|
|
||||||
|
height: UM.Theme.getSize("setting_control").height
|
||||||
|
width: Math.round(parent.width * 0.7 + UM.Theme.getSize("thick_margin").width)
|
||||||
|
anchors.right: parent.right
|
||||||
|
style: UM.Theme.styles.sidebar_header_button
|
||||||
|
activeFocusOnPress: true;
|
||||||
|
|
||||||
|
menu: Cura.NozzleMenu { extruderIndex: Cura.ExtruderManager.activeExtruderIndex }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: materialCompatibilityLink
|
||||||
|
height: UM.Theme.getSize("print_setup_item").height
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: variantRow.bottom
|
||||||
|
anchors.margins: UM.Theme.getSize("thick_margin").width
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: warningImage
|
||||||
|
|
||||||
|
anchors.right: materialInfoLabel.left
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
source: UM.Theme.getIcon("warning")
|
||||||
|
width: UM.Theme.getSize("section_icon").width
|
||||||
|
height: UM.Theme.getSize("section_icon").height
|
||||||
|
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
|
||||||
|
color: UM.Theme.getColor("material_compatibility_warning")
|
||||||
|
|
||||||
|
visible: !Cura.MachineManager.isCurrentSetupSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: materialInfoLabel
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: "<a href='%1'>" + catalog.i18nc("@label", "Check compatibility") + "</a>"
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
linkColor: UM.Theme.getColor("text_link")
|
||||||
|
|
||||||
|
verticalAlignment: Text.AlignTop
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
// open the material URL with web browser
|
||||||
|
Qt.openUrlExternally("https://ultimaker.com/incoming-links/cura/material-compatibilty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
170
resources/qml/Dialogs/AboutDialog.qml
Normal file
170
resources/qml/Dialogs/AboutDialog.qml
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.2
|
||||||
|
import QtQuick.Controls 1.1
|
||||||
|
import QtQuick.Window 2.1
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
|
||||||
|
UM.Dialog
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
|
||||||
|
//: About dialog title
|
||||||
|
title: catalog.i18nc("@title:window","About Cura")
|
||||||
|
|
||||||
|
minimumWidth: 500 * screenScaleFactor
|
||||||
|
minimumHeight: 650 * screenScaleFactor
|
||||||
|
width: minimumWidth
|
||||||
|
height: minimumHeight
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
width: parent.width + 2 * margin // margin from Dialog.qml
|
||||||
|
height: version.y + version.height + margin
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: - margin
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
color: UM.Theme.getColor("viewport_background")
|
||||||
|
}
|
||||||
|
|
||||||
|
Image
|
||||||
|
{
|
||||||
|
id: logo
|
||||||
|
width: (base.minimumWidth * 0.85) | 0
|
||||||
|
height: (width * (1/4.25)) | 0
|
||||||
|
|
||||||
|
source: UM.Theme.getImage("logo")
|
||||||
|
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: ((base.minimumWidth - width) / 2) | 0
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: version
|
||||||
|
|
||||||
|
text: catalog.i18nc("@label","version: %1").arg(UM.Application.version)
|
||||||
|
font: UM.Theme.getFont("large")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
anchors.right : logo.right
|
||||||
|
anchors.top: logo.bottom
|
||||||
|
anchors.topMargin: (UM.Theme.getSize("default_margin").height / 2) | 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: description
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
//: About dialog application description
|
||||||
|
text: catalog.i18nc("@label","End-to-end solution for fused filament 3D printing.")
|
||||||
|
font: UM.Theme.getFont("system")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
anchors.top: version.bottom
|
||||||
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: creditsNotes
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
//: About dialog application author note
|
||||||
|
text: catalog.i18nc("@info:credit","Cura is developed by Ultimaker B.V. in cooperation with the community.\nCura proudly uses the following open source projects:")
|
||||||
|
font: UM.Theme.getFont("system")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
anchors.top: description.bottom
|
||||||
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollView
|
||||||
|
{
|
||||||
|
id: credits
|
||||||
|
anchors.top: creditsNotes.bottom
|
||||||
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height)
|
||||||
|
|
||||||
|
ListView
|
||||||
|
{
|
||||||
|
id: projectsList
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
delegate: Row
|
||||||
|
{
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: "<a href='%1' title='%2'>%2</a>".arg(model.url).arg(model.name)
|
||||||
|
width: (projectsList.width * 0.25) | 0
|
||||||
|
elide: Text.ElideRight
|
||||||
|
onLinkActivated: Qt.openUrlExternally(link)
|
||||||
|
}
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: model.description
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: (projectsList.width * 0.6) | 0
|
||||||
|
}
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: model.license
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: (projectsList.width * 0.15) | 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model: ListModel
|
||||||
|
{
|
||||||
|
id: projectsModel
|
||||||
|
}
|
||||||
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
projectsModel.append({ name: "Cura", description: catalog.i18nc("@label", "Graphical user interface"), license: "LGPLv3", url: "https://github.com/Ultimaker/Cura" });
|
||||||
|
projectsModel.append({ name: "Uranium", description: catalog.i18nc("@label", "Application framework"), license: "LGPLv3", url: "https://github.com/Ultimaker/Uranium" });
|
||||||
|
projectsModel.append({ name: "CuraEngine", description: catalog.i18nc("@label", "G-code generator"), license: "AGPLv3", url: "https://github.com/Ultimaker/CuraEngine" });
|
||||||
|
projectsModel.append({ name: "libArcus", description: catalog.i18nc("@label", "Interprocess communication library"), license: "LGPLv3", url: "https://github.com/Ultimaker/libArcus" });
|
||||||
|
|
||||||
|
projectsModel.append({ name: "Python", description: catalog.i18nc("@label", "Programming language"), license: "Python", url: "http://python.org/" });
|
||||||
|
projectsModel.append({ name: "Qt5", description: catalog.i18nc("@label", "GUI framework"), license: "LGPLv3", url: "https://www.qt.io/" });
|
||||||
|
projectsModel.append({ name: "PyQt", description: catalog.i18nc("@label", "GUI framework bindings"), license: "GPL", url: "https://riverbankcomputing.com/software/pyqt" });
|
||||||
|
projectsModel.append({ name: "SIP", description: catalog.i18nc("@label", "C/C++ Binding library"), license: "GPL", url: "https://riverbankcomputing.com/software/sip" });
|
||||||
|
projectsModel.append({ name: "Protobuf", description: catalog.i18nc("@label", "Data interchange format"), license: "BSD", url: "https://developers.google.com/protocol-buffers" });
|
||||||
|
projectsModel.append({ name: "SciPy", description: catalog.i18nc("@label", "Support library for scientific computing"), license: "BSD-new", url: "https://www.scipy.org/" });
|
||||||
|
projectsModel.append({ name: "NumPy", description: catalog.i18nc("@label", "Support library for faster math"), license: "BSD", url: "http://www.numpy.org/" });
|
||||||
|
projectsModel.append({ name: "NumPy-STL", description: catalog.i18nc("@label", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" });
|
||||||
|
projectsModel.append({ name: "Shapely", description: catalog.i18nc("@label", "Support library for handling planar objects"), license: "BSD", url: "https://github.com/Toblerity/Shapely" });
|
||||||
|
projectsModel.append({ name: "Trimesh", description: catalog.i18nc("@label", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" });
|
||||||
|
projectsModel.append({ name: "NetworkX", description: catalog.i18nc("@label", "Support library for analysis of complex networks"), license: "3-clause BSD", url: "https://networkx.github.io/" });
|
||||||
|
projectsModel.append({ name: "libSavitar", description: catalog.i18nc("@label", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" });
|
||||||
|
projectsModel.append({ name: "libCharon", description: catalog.i18nc("@label", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" });
|
||||||
|
projectsModel.append({ name: "PySerial", description: catalog.i18nc("@label", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" });
|
||||||
|
projectsModel.append({ name: "python-zeroconf", description: catalog.i18nc("@label", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" });
|
||||||
|
projectsModel.append({ name: "Clipper", description: catalog.i18nc("@label", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" });
|
||||||
|
projectsModel.append({ name: "Requests", description: catalog.i18nc("@Label", "Python HTTP library"), license: "GPL", url: "http://docs.python-requests.org" });
|
||||||
|
|
||||||
|
projectsModel.append({ name: "Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" });
|
||||||
|
projectsModel.append({ name: "Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" });
|
||||||
|
projectsModel.append({ name: "AppImageKit", description: catalog.i18nc("@label", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rightButtons: Button
|
||||||
|
{
|
||||||
|
//: Close about dialog button
|
||||||
|
id: closeButton
|
||||||
|
text: catalog.i18nc("@action:button","Close");
|
||||||
|
|
||||||
|
onClicked: base.visible = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -213,28 +213,6 @@ UM.Dialog
|
||||||
|
|
||||||
PropertyChanges { target: machineButton; opacity: 0; height: 0; }
|
PropertyChanges { target: machineButton; opacity: 0; height: 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
transitions:
|
|
||||||
[
|
|
||||||
Transition
|
|
||||||
{
|
|
||||||
to: "collapsed";
|
|
||||||
SequentialAnimation
|
|
||||||
{
|
|
||||||
NumberAnimation { property: "opacity"; duration: 75; }
|
|
||||||
NumberAnimation { property: "height"; duration: 75; }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Transition
|
|
||||||
{
|
|
||||||
from: "collapsed";
|
|
||||||
SequentialAnimation
|
|
||||||
{
|
|
||||||
NumberAnimation { property: "height"; duration: 75; }
|
|
||||||
NumberAnimation { property: "opacity"; duration: 75; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,7 +276,6 @@ UM.Dialog
|
||||||
id: machineName
|
id: machineName
|
||||||
text: getMachineName()
|
text: getMachineName()
|
||||||
width: Math.floor(parent.width * 0.75)
|
width: Math.floor(parent.width * 0.75)
|
||||||
implicitWidth: UM.Theme.getSize("standard_list_input").width
|
|
||||||
maximumLength: 40
|
maximumLength: 40
|
||||||
//validator: Cura.MachineNameValidator { } //TODO: Gives a segfault in PyQt5.6. For now, we must use a signal on text changed.
|
//validator: Cura.MachineNameValidator { } //TODO: Gives a segfault in PyQt5.6. For now, we must use a signal on text changed.
|
||||||
validator: RegExpValidator
|
validator: RegExpValidator
|
|
@ -1,53 +0,0 @@
|
||||||
// Copyright (c) 2015 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.1
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
|
|
||||||
import UM 1.1 as UM
|
|
||||||
|
|
||||||
UM.Dialog
|
|
||||||
{
|
|
||||||
id: dialog;
|
|
||||||
|
|
||||||
//: Engine Log dialog title
|
|
||||||
title: catalog.i18nc("@title:window","Engine Log");
|
|
||||||
|
|
||||||
modality: Qt.NonModal;
|
|
||||||
|
|
||||||
TextArea
|
|
||||||
{
|
|
||||||
id: textArea
|
|
||||||
anchors.fill: parent;
|
|
||||||
|
|
||||||
Timer
|
|
||||||
{
|
|
||||||
id: updateTimer;
|
|
||||||
interval: 1000;
|
|
||||||
running: false;
|
|
||||||
repeat: true;
|
|
||||||
onTriggered: textArea.text = CuraApplication.getEngineLog();
|
|
||||||
}
|
|
||||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
|
||||||
}
|
|
||||||
|
|
||||||
rightButtons: Button
|
|
||||||
{
|
|
||||||
//: Close engine log button
|
|
||||||
text: catalog.i18nc("@action:button","Close");
|
|
||||||
onClicked: dialog.visible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
onVisibleChanged:
|
|
||||||
{
|
|
||||||
if(visible)
|
|
||||||
{
|
|
||||||
textArea.text = CuraApplication.getEngineLog();
|
|
||||||
updateTimer.start();
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
updateTimer.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
196
resources/qml/ExpandableComponent.qml
Normal file
196
resources/qml/ExpandableComponent.qml
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
import QtGraphicalEffects 1.0 // For the dropshadow
|
||||||
|
|
||||||
|
// The expandable component has 3 major sub components:
|
||||||
|
// * The headerItem; Always visible and should hold some info about what happens if the component is expanded
|
||||||
|
// * The popupItem; The content that needs to be shown if the component is expanded.
|
||||||
|
// * The icon; An icon that is displayed on the right of the drawer.
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
|
||||||
|
// Enumeration with the different possible alignments of the popup with respect of the headerItem
|
||||||
|
enum PopupAlignment
|
||||||
|
{
|
||||||
|
AlignLeft,
|
||||||
|
AlignRight
|
||||||
|
}
|
||||||
|
|
||||||
|
// The headerItem holds the QML item that is always displayed.
|
||||||
|
property alias headerItem: headerItemLoader.sourceComponent
|
||||||
|
|
||||||
|
// The popupItem holds the QML item that is shown when the "open" button is pressed
|
||||||
|
property var popupItem
|
||||||
|
|
||||||
|
property color popupBackgroundColor: UM.Theme.getColor("action_button")
|
||||||
|
|
||||||
|
property color headerBackgroundColor: UM.Theme.getColor("action_button")
|
||||||
|
property color headerHoverColor: UM.Theme.getColor("action_button_hovered")
|
||||||
|
|
||||||
|
// Defines the alignment of the popup with respect of the headerItem, by default to the right
|
||||||
|
property int popupAlignment: ExpandableComponent.PopupAlignment.AlignRight
|
||||||
|
|
||||||
|
// How much spacing is needed around the popupItem
|
||||||
|
property alias popupPadding: popup.padding
|
||||||
|
|
||||||
|
// How much padding is needed around the header & button
|
||||||
|
property alias headerPadding: background.padding
|
||||||
|
|
||||||
|
// What icon should be displayed on the right.
|
||||||
|
property alias iconSource: collapseButton.source
|
||||||
|
|
||||||
|
property alias iconColor: collapseButton.color
|
||||||
|
|
||||||
|
// The icon size (it's always drawn as a square)
|
||||||
|
property alias iconSize: collapseButton.height
|
||||||
|
|
||||||
|
// Is the "drawer" open?
|
||||||
|
readonly property alias expanded: popup.visible
|
||||||
|
|
||||||
|
property alias expandedHighlightColor: expandedHighlight.color
|
||||||
|
|
||||||
|
// What should the radius of the header be. This is also influenced by the headerCornerSide
|
||||||
|
property alias headerRadius: background.radius
|
||||||
|
|
||||||
|
// On what side should the header corners be shown? 1 is down, 2 is left, 3 is up and 4 is right.
|
||||||
|
property alias headerCornerSide: background.cornerSide
|
||||||
|
|
||||||
|
property alias headerShadowColor: shadow.color
|
||||||
|
|
||||||
|
property alias enableHeaderShadow: shadow.visible
|
||||||
|
|
||||||
|
property int shadowOffset: 2
|
||||||
|
|
||||||
|
function togglePopup()
|
||||||
|
{
|
||||||
|
if(popup.visible)
|
||||||
|
{
|
||||||
|
popup.close()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
popup.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPopupItemChanged:
|
||||||
|
{
|
||||||
|
// Since we want the size of the popup to be set by the size of the content,
|
||||||
|
// we need to do it like this.
|
||||||
|
popup.width = popupItem.width + 2 * popup.padding
|
||||||
|
popup.height = popupItem.height + 2 * popup.padding
|
||||||
|
popup.contentItem = popupItem
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
// Since it could be that the popup is dynamically populated, we should also take these changes into account.
|
||||||
|
target: popupItem
|
||||||
|
onWidthChanged: popup.width = popupItem.width + 2 * popup.padding
|
||||||
|
onHeightChanged: popup.height = popupItem.height + 2 * popup.padding
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitHeight: 100 * screenScaleFactor
|
||||||
|
implicitWidth: 400 * screenScaleFactor
|
||||||
|
|
||||||
|
RoundedRectangle
|
||||||
|
{
|
||||||
|
id: background
|
||||||
|
property real padding: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
color: headerBackgroundColor
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Loader
|
||||||
|
{
|
||||||
|
id: headerItemLoader
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
right: collapseButton.visible ? collapseButton.left : parent.right
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
margins: background.padding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A highlight that is shown when the popup is expanded
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: expandedHighlight
|
||||||
|
width: parent.width
|
||||||
|
height: UM.Theme.getSize("thick_lining").height
|
||||||
|
color: UM.Theme.getColor("primary")
|
||||||
|
visible: expanded
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: collapseButton
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
margins: background.padding
|
||||||
|
}
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
visible: source != ""
|
||||||
|
width: height
|
||||||
|
height: Math.round(0.2 * base.height)
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: togglePopup()
|
||||||
|
hoverEnabled: true
|
||||||
|
onEntered: background.color = headerHoverColor
|
||||||
|
onExited: background.color = headerBackgroundColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DropShadow
|
||||||
|
{
|
||||||
|
id: shadow
|
||||||
|
// Don't blur the shadow
|
||||||
|
radius: 0
|
||||||
|
anchors.fill: background
|
||||||
|
source: background
|
||||||
|
verticalOffset: base.shadowOffset
|
||||||
|
visible: true
|
||||||
|
color: UM.Theme.getColor("action_button_shadow")
|
||||||
|
// Should always be drawn behind the background.
|
||||||
|
z: background.z - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Popup
|
||||||
|
{
|
||||||
|
id: popup
|
||||||
|
|
||||||
|
// Ensure that the popup is located directly below the headerItem
|
||||||
|
y: headerItemLoader.height + 2 * background.padding + base.shadowOffset
|
||||||
|
|
||||||
|
// Make the popup aligned with the rest, using the property popupAlignment to decide whether is right or left.
|
||||||
|
// In case of right alignment, the 3x padding is due to left, right and padding between the button & text.
|
||||||
|
x: popupAlignment == ExpandableComponent.PopupAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0
|
||||||
|
padding: UM.Theme.getSize("default_margin").width
|
||||||
|
closePolicy: Popup.CloseOnPressOutsideParent
|
||||||
|
|
||||||
|
background: Cura.RoundedRectangle
|
||||||
|
{
|
||||||
|
cornerSide: Cura.RoundedRectangle.Direction.Down
|
||||||
|
color: popupBackgroundColor
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: UM.Theme.getColor("lining")
|
||||||
|
radius: UM.Theme.getSize("default_radius").width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,80 +2,32 @@
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 2.0
|
||||||
|
|
||||||
import UM 1.2 as UM
|
import UM 1.2 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
Button
|
Cura.ToolbarButton
|
||||||
{
|
{
|
||||||
id: base
|
id: base
|
||||||
|
|
||||||
property var extruder;
|
property var extruder
|
||||||
|
|
||||||
text: catalog.i18ncp("@label %1 is filled in with the name of an extruder", "Print Selected Model with %1", "Print Selected Models with %1", UM.Selection.selectionCount).arg(extruder.name)
|
text: catalog.i18ncp("@label %1 is filled in with the name of an extruder", "Print Selected Model with %1", "Print Selected Models with %1", UM.Selection.selectionCount).arg(extruder.name)
|
||||||
|
|
||||||
style: UM.Theme.styles.tool_button;
|
|
||||||
iconSource: UM.Theme.getIcon("extruder_button")
|
|
||||||
|
|
||||||
checked: Cura.ExtruderManager.selectedObjectExtruders.indexOf(extruder.id) != -1
|
checked: Cura.ExtruderManager.selectedObjectExtruders.indexOf(extruder.id) != -1
|
||||||
enabled: UM.Selection.hasSelection && extruder.stack.isEnabled
|
enabled: UM.Selection.hasSelection && extruder.stack.isEnabled
|
||||||
|
|
||||||
property color customColor: base.hovered ? UM.Theme.getColor("button_hover") : UM.Theme.getColor("button");
|
toolItem: ExtruderIcon
|
||||||
|
|
||||||
Rectangle
|
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
materialColor: extruder.color
|
||||||
anchors.margins: UM.Theme.getSize("default_lining").width;
|
extruderEnabled: extruder.stack.isEnabled
|
||||||
|
property int index: extruder.index
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
border.width: base.checked ? UM.Theme.getSize("default_lining").width : 0;
|
|
||||||
border.color: UM.Theme.getColor("button_text")
|
|
||||||
}
|
|
||||||
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: UM.Theme.getSize("default_margin").width
|
|
||||||
height: UM.Theme.getSize("default_margin").height
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
anchors.centerIn: parent;
|
|
||||||
text: index + 1;
|
|
||||||
color: parent.enabled ? UM.Theme.getColor("button_text") : UM.Theme.getColor("button_disabled_text")
|
|
||||||
font: UM.Theme.getFont("default_bold");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Material colour circle
|
|
||||||
// Only draw the filling colour of the material inside the SVG border.
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
right: parent.right
|
|
||||||
top: parent.top
|
|
||||||
rightMargin: UM.Theme.getSize("extruder_button_material_margin").width
|
|
||||||
topMargin: UM.Theme.getSize("extruder_button_material_margin").height
|
|
||||||
}
|
|
||||||
|
|
||||||
color: model.color
|
|
||||||
|
|
||||||
width: UM.Theme.getSize("extruder_button_material").width
|
|
||||||
height: UM.Theme.getSize("extruder_button_material").height
|
|
||||||
radius: Math.round(width / 2)
|
|
||||||
|
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
|
||||||
border.color: UM.Theme.getColor("extruder_button_material_border")
|
|
||||||
|
|
||||||
opacity: !base.enabled ? 0.2 : 1.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
forceActiveFocus() //First grab focus, so all the text fields are updated
|
forceActiveFocus() //First grab focus, so all the text fields are updated
|
||||||
CuraActions.setExtruderForSelection(extruder.id);
|
CuraActions.setExtruderForSelection(extruder.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
72
resources/qml/ExtruderIcon.qml
Normal file
72
resources/qml/ExtruderIcon.qml
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// 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.1
|
||||||
|
import UM 1.2 as UM
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: extruderIconItem
|
||||||
|
|
||||||
|
implicitWidth: UM.Theme.getSize("extruder_icon").width
|
||||||
|
implicitHeight: UM.Theme.getSize("extruder_icon").height
|
||||||
|
|
||||||
|
property bool checked: true
|
||||||
|
property color materialColor
|
||||||
|
property alias textColor: extruderNumberText.color
|
||||||
|
property bool extruderEnabled: true
|
||||||
|
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: mainIcon
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
sourceSize.width: parent.width
|
||||||
|
sourceSize.height: parent.height
|
||||||
|
source: UM.Theme.getIcon("extruder_button")
|
||||||
|
color: extruderEnabled ? materialColor: "gray"
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: extruderNumberCircle
|
||||||
|
|
||||||
|
width: height
|
||||||
|
height: Math.round(parent.height / 2)
|
||||||
|
radius: Math.round(width / 2)
|
||||||
|
color: UM.Theme.getColor("toolbar_background")
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
top: parent.top
|
||||||
|
// The circle needs to be slightly off center (so it sits in the middle of the square bit of the icon)
|
||||||
|
topMargin: (parent.height - height) / 2 - 0.1 * parent.height
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: extruderNumberText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: index + 1
|
||||||
|
font: UM.Theme.getFont("extruder_icon")
|
||||||
|
visible: extruderEnabled
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: disabledIcon
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: UM.Theme.getSize("thick_lining").width
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: width
|
||||||
|
source: UM.Theme.getIcon("cross1")
|
||||||
|
visible: !extruderEnabled
|
||||||
|
color: "black"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
resources/qml/IconLabel.qml
Normal file
54
resources/qml/IconLabel.qml
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
|
||||||
|
// This item will show a label with a squared icon in the left
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: container
|
||||||
|
|
||||||
|
property alias text: label.text
|
||||||
|
property alias source: icon.source
|
||||||
|
property alias color: label.color
|
||||||
|
property alias font: label.font
|
||||||
|
property alias iconSize: icon.width
|
||||||
|
|
||||||
|
implicitHeight: icon.height
|
||||||
|
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: icon
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
source: ""
|
||||||
|
width: UM.Theme.getSize("section_icon").width
|
||||||
|
height: width
|
||||||
|
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
|
||||||
|
color: label.color
|
||||||
|
visible: source != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: label
|
||||||
|
anchors.left: icon.visible ? icon.right : parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("thin_margin").width
|
||||||
|
anchors.verticalCenter: icon.verticalCenter
|
||||||
|
text: "Empty label"
|
||||||
|
elide: Text.ElideRight
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
font: UM.Theme.getFont("very_small")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
}
|
70
resources/qml/IconWithText.qml
Normal file
70
resources/qml/IconWithText.qml
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
// Reusable component that holds an (re-colorable) icon on the left with some text on the right.
|
||||||
|
// This component is also designed to be used with layouts. It will use the width of the text + icon as preferred width
|
||||||
|
// It sets the icon size + half of the content as its minium width (in which case it will elide the text)
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
property alias iconColor: icon.color
|
||||||
|
property alias source: icon.source
|
||||||
|
property alias text: label.text
|
||||||
|
|
||||||
|
property real margin: UM.Theme.getSize("narrow_margin").width
|
||||||
|
|
||||||
|
// These properties can be used in combination with layouts.
|
||||||
|
readonly property real contentWidth: icon.width + margin + label.contentWidth
|
||||||
|
readonly property real minContentWidth: Math.round(icon.width + margin + 0.5 * label.contentWidth)
|
||||||
|
|
||||||
|
Layout.minimumWidth: minContentWidth
|
||||||
|
Layout.preferredWidth: contentWidth
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
implicitWidth: icon.width + 100
|
||||||
|
implicitHeight: icon.height
|
||||||
|
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: icon
|
||||||
|
width: UM.Theme.getSize("section_icon").width
|
||||||
|
height: UM.Theme.getSize("section_icon").height
|
||||||
|
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
color: "black"
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: label
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
elide: Text.ElideRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: icon.right
|
||||||
|
right: parent.right
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
rightMargin: 0
|
||||||
|
margins: margin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2017 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
|
@ -15,7 +15,7 @@ Item {
|
||||||
property bool activity: CuraApplication.platformActivity
|
property bool activity: CuraApplication.platformActivity
|
||||||
property string fileBaseName: PrintInformation.baseName
|
property string fileBaseName: PrintInformation.baseName
|
||||||
|
|
||||||
UM.I18nCatalog { id: catalog; name:"cura"}
|
UM.I18nCatalog { id: catalog; name: "cura"}
|
||||||
|
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
// Copyright (c) 2017 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 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
|
|
||||||
import "Menus"
|
|
||||||
|
|
||||||
ToolButton
|
|
||||||
{
|
|
||||||
id: base
|
|
||||||
property bool isNetworkPrinter: Cura.MachineManager.activeMachineNetworkKey != ""
|
|
||||||
property bool printerConnected: Cura.MachineManager.printerConnected
|
|
||||||
property var printerStatus: Cura.MachineManager.printerConnected ? "connected" : "disconnected"
|
|
||||||
text: isNetworkPrinter ? Cura.MachineManager.activeMachineNetworkGroupName : Cura.MachineManager.activeMachineName
|
|
||||||
|
|
||||||
tooltip: Cura.MachineManager.activeMachineName
|
|
||||||
|
|
||||||
style: ButtonStyle
|
|
||||||
{
|
|
||||||
background: Rectangle
|
|
||||||
{
|
|
||||||
color:
|
|
||||||
{
|
|
||||||
if (control.pressed) {
|
|
||||||
return UM.Theme.getColor("sidebar_header_active");
|
|
||||||
}
|
|
||||||
else if (control.hovered) {
|
|
||||||
return UM.Theme.getColor("sidebar_header_hover");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return UM.Theme.getColor("sidebar_header_bar");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on color { ColorAnimation { duration: 50; } }
|
|
||||||
|
|
||||||
UM.RecolorImage
|
|
||||||
{
|
|
||||||
id: downArrow
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
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
|
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: width
|
|
||||||
color: UM.Theme.getColor("text_emphasis")
|
|
||||||
source: UM.Theme.getIcon("arrow_bottom")
|
|
||||||
}
|
|
||||||
|
|
||||||
PrinterStatusIcon
|
|
||||||
{
|
|
||||||
id: printerStatusIcon
|
|
||||||
visible: printerConnected || isNetworkPrinter
|
|
||||||
status: printerStatus
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
left: parent.left
|
|
||||||
leftMargin: UM.Theme.getSize("sidebar_margin").width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: sidebarComboBoxLabel
|
|
||||||
color: UM.Theme.getColor("sidebar_header_text_active")
|
|
||||||
text: control.text;
|
|
||||||
elide: Text.ElideRight;
|
|
||||||
anchors.left: printerStatusIcon.visible ? printerStatusIcon.right : parent.left;
|
|
||||||
anchors.leftMargin: printerStatusIcon.visible ? UM.Theme.getSize("sidebar_lining").width : UM.Theme.getSize("sidebar_margin").width
|
|
||||||
anchors.right: downArrow.left;
|
|
||||||
anchors.rightMargin: control.rightMargin;
|
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
|
||||||
font: UM.Theme.getFont("medium_bold")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
label: Label {}
|
|
||||||
}
|
|
||||||
|
|
||||||
menu: PrinterMenu { }
|
|
||||||
}
|
|
171
resources/qml/MainWindow/ApplicationMenu.qml
Normal file
171
resources/qml/MainWindow/ApplicationMenu.qml
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
// 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 QtQuick.Controls.Styles 1.4
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
|
||||||
|
import UM 1.3 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
import "../Menus"
|
||||||
|
import "../Dialogs"
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: menu
|
||||||
|
width: applicationMenu.width
|
||||||
|
height: applicationMenu.height
|
||||||
|
property alias window: applicationMenu.window
|
||||||
|
|
||||||
|
UM.ApplicationMenu
|
||||||
|
{
|
||||||
|
id: applicationMenu
|
||||||
|
|
||||||
|
FileMenu { title: catalog.i18nc("@title:menu menubar:toplevel", "&File") }
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
|
title: catalog.i18nc("@title:menu menubar:toplevel", "&Edit")
|
||||||
|
|
||||||
|
MenuItem { action: Cura.Actions.undo }
|
||||||
|
MenuItem { action: Cura.Actions.redo }
|
||||||
|
MenuSeparator { }
|
||||||
|
MenuItem { action: Cura.Actions.selectAll }
|
||||||
|
MenuItem { action: Cura.Actions.arrangeAll }
|
||||||
|
MenuItem { action: Cura.Actions.deleteSelection }
|
||||||
|
MenuItem { action: Cura.Actions.deleteAll }
|
||||||
|
MenuItem { action: Cura.Actions.resetAllTranslation }
|
||||||
|
MenuItem { action: Cura.Actions.resetAll }
|
||||||
|
MenuSeparator { }
|
||||||
|
MenuItem { action: Cura.Actions.groupObjects }
|
||||||
|
MenuItem { action: Cura.Actions.mergeObjects }
|
||||||
|
MenuItem { action: Cura.Actions.unGroupObjects }
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewMenu { title: catalog.i18nc("@title:menu menubar:toplevel", "&View") }
|
||||||
|
|
||||||
|
SettingsMenu { title: catalog.i18nc("@title:menu menubar:toplevel", "&Settings") }
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
|
id: extensionMenu
|
||||||
|
title: catalog.i18nc("@title:menu menubar:toplevel", "E&xtensions")
|
||||||
|
|
||||||
|
Instantiator
|
||||||
|
{
|
||||||
|
id: extensions
|
||||||
|
model: UM.ExtensionModel { }
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
|
id: sub_menu
|
||||||
|
title: model.name;
|
||||||
|
visible: actions != null
|
||||||
|
enabled: actions != null
|
||||||
|
Instantiator
|
||||||
|
{
|
||||||
|
model: actions
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
text: model.text
|
||||||
|
onTriggered: extensions.model.subMenuTriggered(name, model.text)
|
||||||
|
}
|
||||||
|
onObjectAdded: sub_menu.insertItem(index, object)
|
||||||
|
onObjectRemoved: sub_menu.removeItem(object)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onObjectAdded: extensionMenu.insertItem(index, object)
|
||||||
|
onObjectRemoved: extensionMenu.removeItem(object)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
|
id: plugin_menu
|
||||||
|
title: catalog.i18nc("@title:menu menubar:toplevel", "&Marketplace")
|
||||||
|
|
||||||
|
MenuItem { action: Cura.Actions.browsePackages }
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
|
id: preferencesMenu
|
||||||
|
title: catalog.i18nc("@title:menu menubar:toplevel", "P&references")
|
||||||
|
|
||||||
|
MenuItem { action: Cura.Actions.preferences }
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
|
id: helpMenu
|
||||||
|
title: catalog.i18nc("@title:menu menubar:toplevel", "&Help")
|
||||||
|
|
||||||
|
MenuItem { action: Cura.Actions.showProfileFolder }
|
||||||
|
MenuItem { action: Cura.Actions.documentation }
|
||||||
|
MenuItem { action: Cura.Actions.reportBug }
|
||||||
|
MenuSeparator { }
|
||||||
|
MenuItem { action: Cura.Actions.about }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ###############################################################################################
|
||||||
|
// Definition of other components that are linked to the menus
|
||||||
|
// ###############################################################################################
|
||||||
|
|
||||||
|
WorkspaceSummaryDialog
|
||||||
|
{
|
||||||
|
id: saveWorkspaceDialog
|
||||||
|
property var args
|
||||||
|
onYes: UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageDialog
|
||||||
|
{
|
||||||
|
id: newProjectDialog
|
||||||
|
modality: Qt.ApplicationModal
|
||||||
|
title: catalog.i18nc("@title:window", "New project")
|
||||||
|
text: catalog.i18nc("@info:question", "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings.")
|
||||||
|
standardButtons: StandardButton.Yes | StandardButton.No
|
||||||
|
icon: StandardIcon.Question
|
||||||
|
onYes:
|
||||||
|
{
|
||||||
|
CuraApplication.deleteAll();
|
||||||
|
Cura.Actions.resetProfile.trigger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.ExtensionModel
|
||||||
|
{
|
||||||
|
id: curaExtensions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ###############################################################################################
|
||||||
|
// Definition of all the connections
|
||||||
|
// ###############################################################################################
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: Cura.Actions.newProject
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
if(Printer.platformActivity || Cura.MachineManager.hasUserSettings)
|
||||||
|
{
|
||||||
|
newProjectDialog.visible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// show the plugin browser dialog
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: Cura.Actions.browsePackages
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
curaExtensions.callExtensionMethod("Toolbox", "browsePackages")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
146
resources/qml/MainWindow/MainWindowHeader.qml
Normal file
146
resources/qml/MainWindow/MainWindowHeader.qml
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.0 as Controls2
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls.Styles 1.1
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
|
||||||
|
import "../Account"
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
|
||||||
|
implicitHeight: UM.Theme.getSize("main_window_header").height
|
||||||
|
implicitWidth: UM.Theme.getSize("main_window_header").width
|
||||||
|
|
||||||
|
LinearGradient
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
start: Qt.point(0, 0)
|
||||||
|
end: Qt.point(parent.width, 0)
|
||||||
|
gradient: Gradient
|
||||||
|
{
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.0
|
||||||
|
color: UM.Theme.getColor("main_window_header_background")
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.5
|
||||||
|
color: UM.Theme.getColor("main_window_header_background_gradient")
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 1.0
|
||||||
|
color: UM.Theme.getColor("main_window_header_background")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image
|
||||||
|
{
|
||||||
|
id: logo
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
source: UM.Theme.getImage("logo")
|
||||||
|
width: UM.Theme.getSize("logo").width
|
||||||
|
height: UM.Theme.getSize("logo").height
|
||||||
|
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
}
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: stagesListContainer
|
||||||
|
spacing: Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main window header is dynamically filled with all available stages
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
id: stagesHeader
|
||||||
|
|
||||||
|
model: UM.StageModel { }
|
||||||
|
|
||||||
|
delegate: Button
|
||||||
|
{
|
||||||
|
text: model.name.toUpperCase()
|
||||||
|
checkable: true
|
||||||
|
checked: model.active
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
exclusiveGroup: mainWindowHeaderMenuGroup
|
||||||
|
style: UM.Theme.styles.main_window_header_tab
|
||||||
|
height: UM.Theme.getSize("main_window_header_button").height
|
||||||
|
onClicked: UM.Controller.setActiveStage(model.id)
|
||||||
|
iconSource: model.stage.iconSource
|
||||||
|
|
||||||
|
property color overlayColor: "transparent"
|
||||||
|
property string overlayIconSource: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExclusiveGroup { id: mainWindowHeaderMenuGroup }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shortcut button to quick access the Toolbox
|
||||||
|
Controls2.Button
|
||||||
|
{
|
||||||
|
id: marketplaceButton
|
||||||
|
text: catalog.i18nc("@action:button", "Marketplace")
|
||||||
|
height: Math.round(0.5 * UM.Theme.getSize("main_window_header").height)
|
||||||
|
onClicked: Cura.Actions.browsePackages.trigger()
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
radius: UM.Theme.getSize("action_button_radius").width
|
||||||
|
color: marketplaceButton.hovered ? UM.Theme.getColor("primary_text") : UM.Theme.getColor("main_window_header_background")
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: UM.Theme.getColor("primary_text")
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Label
|
||||||
|
{
|
||||||
|
id: label
|
||||||
|
text: marketplaceButton.text
|
||||||
|
color: marketplaceButton.hovered ? UM.Theme.getColor("main_window_header_background") : UM.Theme.getColor("primary_text")
|
||||||
|
width: contentWidth
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: accountWidget.left
|
||||||
|
rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountWidget
|
||||||
|
{
|
||||||
|
id: accountWidget
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,7 +63,7 @@ Rectangle
|
||||||
|
|
||||||
visible: buildplateInformation.visible
|
visible: buildplateInformation.visible
|
||||||
width: parent.width - 2 * parent.padding
|
width: parent.width - 2 * parent.padding
|
||||||
height: visible ? Math.round(UM.Theme.getSize("sidebar_lining_thin").height / 2) : 0
|
height: visible ? Math.round(UM.Theme.getSize("thick_lining").height / 2) : 0
|
||||||
color: textColor
|
color: textColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +77,8 @@ Rectangle
|
||||||
UM.RecolorImage {
|
UM.RecolorImage {
|
||||||
id: buildplateIcon
|
id: buildplateIcon
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
width: UM.Theme.getSize("topbar_button_icon").width
|
width: UM.Theme.getSize("main_window_header_button_icon").width
|
||||||
height: UM.Theme.getSize("topbar_button_icon").height
|
height: UM.Theme.getSize("main_window_header_button_icon").height
|
||||||
sourceSize.width: width
|
sourceSize.width: width
|
||||||
sourceSize.height: height
|
sourceSize.height: height
|
||||||
source: UM.Theme.getIcon("buildplate")
|
source: UM.Theme.getIcon("buildplate")
|
||||||
|
@ -110,7 +110,7 @@ Rectangle
|
||||||
parent.border.color = UM.Theme.getColor("configuration_item_border_hover")
|
parent.border.color = UM.Theme.getColor("configuration_item_border_hover")
|
||||||
if (configurationItem.selected == false)
|
if (configurationItem.selected == false)
|
||||||
{
|
{
|
||||||
configurationItem.color = UM.Theme.getColor("sidebar_lining")
|
configurationItem.color = UM.Theme.getColor("wide_lining")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onExited:
|
onExited:
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue