Merge branch '4.0' of github.com:Ultimaker/Cura into CURA-6013-rate-packages

This commit is contained in:
Jaime van Kessel 2018-12-12 11:50:26 +01:00
commit e30ca20c54
156 changed files with 3195 additions and 3884 deletions

View file

@ -83,7 +83,14 @@ class BuildVolume(SceneNode):
" with printed models."), title = catalog.i18nc("@info:title", "Build Volume"))
self._global_container_stack = None
self._stack_change_timer = QTimer()
self._stack_change_timer.setInterval(100)
self._stack_change_timer.setSingleShot(True)
self._stack_change_timer.timeout.connect(self._onStackChangeTimerFinished)
self._application.globalContainerStackChanged.connect(self._onStackChanged)
self._onStackChanged()
self._engine_ready = False
@ -105,6 +112,8 @@ class BuildVolume(SceneNode):
self._setting_change_timer.setSingleShot(True)
self._setting_change_timer.timeout.connect(self._onSettingChangeTimerFinished)
# Must be after setting _build_volume_message, apparently that is used in getMachineManager.
# activeQualityChanged is always emitted after setActiveVariant, setActiveMaterial and setActiveQuality.
# Therefore this works.
@ -479,6 +488,8 @@ class BuildVolume(SceneNode):
maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - disallowed_area_size + bed_adhesion_size - 1)
)
self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds
self.updateNodeBoundaryCheck()
def getBoundingBox(self) -> AxisAlignedBox:
@ -524,8 +535,11 @@ class BuildVolume(SceneNode):
if extra_z != self._extra_z_clearance:
self._extra_z_clearance = extra_z
## Update the build volume visualization
def _onStackChanged(self):
self._stack_change_timer.start()
## Update the build volume visualization
def _onStackChangeTimerFinished(self):
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
extruders = ExtruderManager.getInstance().getActiveExtruderStacks()

View file

@ -36,18 +36,14 @@ else:
except ImportError:
CuraDebugMode = False # [CodeStyle: Reflecting imported value]
# List of exceptions that should be considered "fatal" and abort the program.
# These are primarily some exception types that we simply cannot really recover from
# (MemoryError and SystemError) and exceptions that indicate grave errors in the
# code that cause the Python interpreter to fail (SyntaxError, ImportError).
fatal_exception_types = [
MemoryError,
SyntaxError,
ImportError,
SystemError,
# List of exceptions that should not be considered "fatal" and abort the program.
# These are primarily some exception types that we simply skip
skip_exception_types = [
SystemExit,
KeyboardInterrupt,
GeneratorExit
]
class CrashHandler:
crash_url = "https://stats.ultimaker.com/api/cura"
@ -70,7 +66,7 @@ class CrashHandler:
# If Cura has fully started, we only show fatal errors.
# If Cura has not fully started yet, we always show the early crash dialog. Otherwise, Cura will just crash
# without any information.
if has_started and exception_type not in fatal_exception_types:
if has_started and exception_type in skip_exception_types:
return
if not has_started:
@ -387,7 +383,7 @@ class CrashHandler:
Application.getInstance().callLater(self._show)
def _show(self):
# When the exception is not in the fatal_exception_types list, the dialog is not created, so we don't need to show it
# When the exception is in the skip_exception_types list, the dialog is not created, so we don't need to show it
if self.dialog:
self.dialog.exec_()
os._exit(1)

View file

@ -181,7 +181,6 @@ class CuraApplication(QtApplication):
# Variables set from CLI
self._files_to_open = []
self._use_single_instance = False
self._trigger_early_crash = False # For debug only
self._single_instance = None
@ -292,7 +291,10 @@ class CuraApplication(QtApplication):
sys.exit(0)
self._use_single_instance = self._cli_args.single_instance
self._trigger_early_crash = self._cli_args.trigger_early_crash
# FOR TESTING ONLY
if self._cli_args.trigger_early_crash:
assert not "This crash is triggered by the trigger_early_crash command line argument."
for filename in self._cli_args.file:
self._files_to_open.append(os.path.abspath(filename))

View file

@ -64,21 +64,21 @@ class MachineErrorChecker(QObject):
def _onMachineChanged(self) -> None:
if self._global_stack:
self._global_stack.propertyChanged.disconnect(self.startErrorCheck)
self._global_stack.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
self._global_stack.containersChanged.disconnect(self.startErrorCheck)
for extruder in self._global_stack.extruders.values():
extruder.propertyChanged.disconnect(self.startErrorCheck)
extruder.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.disconnect(self.startErrorCheck)
self._global_stack = self._machine_manager.activeMachine
if self._global_stack:
self._global_stack.propertyChanged.connect(self.startErrorCheck)
self._global_stack.propertyChanged.connect(self.startErrorCheckPropertyChanged)
self._global_stack.containersChanged.connect(self.startErrorCheck)
for extruder in self._global_stack.extruders.values():
extruder.propertyChanged.connect(self.startErrorCheck)
extruder.propertyChanged.connect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.connect(self.startErrorCheck)
hasErrorUpdated = pyqtSignal()
@ -93,6 +93,13 @@ class MachineErrorChecker(QObject):
def needToWaitForResult(self) -> bool:
return self._need_to_check or self._check_in_progress
# Start the error check for property changed
# this is seperate from the startErrorCheck because it ignores a number property types
def startErrorCheckPropertyChanged(self, key, property_name):
if property_name != "value":
return
self.startErrorCheck()
# Starts the error check timer to schedule a new error check.
def startErrorCheck(self, *args) -> None:
if not self._check_in_progress:

View file

@ -1,5 +1,6 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional, Dict, Set
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
from UM.Qt.ListModel import ListModel
@ -9,6 +10,9 @@ from UM.Qt.ListModel import ListModel
# Those 2 models are used by the material drop down menu to show generic materials and branded materials separately.
# The extruder position defined here is being used to bound a menu to the correct extruder. This is used in the top
# bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu
from cura.Machines.MaterialNode import MaterialNode
class BaseMaterialsModel(ListModel):
extruderPositionChanged = pyqtSignal()
@ -54,8 +58,8 @@ class BaseMaterialsModel(ListModel):
self._extruder_position = 0
self._extruder_stack = None
self._available_materials = None
self._favorite_ids = None
self._available_materials = None # type: Optional[Dict[str, MaterialNode]]
self._favorite_ids = set() # type: Set[str]
def _updateExtruderStack(self):
global_stack = self._machine_manager.activeMachine
@ -102,8 +106,10 @@ class BaseMaterialsModel(ListModel):
return False
extruder_stack = global_stack.extruders[extruder_position]
self._available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack)
available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack)
if available_materials == self._available_materials:
return False
self._available_materials = available_materials
if self._available_materials is None:
return False

View file

@ -4,17 +4,14 @@
from UM.Logger import Logger
from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
class FavoriteMaterialsModel(BaseMaterialsModel):
class FavoriteMaterialsModel(BaseMaterialsModel):
def __init__(self, parent = None):
super().__init__(parent)
self._update()
def _update(self):
# Perform standard check and reset if the check fails
if not self._canUpdate():
self.setItems([])
return
# Get updated list of favorites

View file

@ -11,10 +11,7 @@ class GenericMaterialsModel(BaseMaterialsModel):
self._update()
def _update(self):
# Perform standard check and reset if the check fails
if not self._canUpdate():
self.setItems([])
return
# Get updated list of favorites

View file

@ -28,12 +28,8 @@ class MaterialBrandsModel(BaseMaterialsModel):
self._update()
def _update(self):
# Perform standard check and reset if the check fails
if not self._canUpdate():
self.setItems([])
return
# Get updated list of favorites
self._favorite_ids = self._material_manager.getFavorites()

View file

@ -187,7 +187,10 @@ class ConvexHullDecorator(SceneNodeDecorator):
for child in self._node.getChildren():
child_hull = child.callDecoration("_compute2DConvexHull")
if child_hull:
try:
points = numpy.append(points, child_hull.getPoints(), axis = 0)
except ValueError:
pass
if points.size < 3:
return None

View file

@ -83,6 +83,7 @@ class ExtruderManager(QObject):
# \param index The index of the new active extruder.
@pyqtSlot(int)
def setActiveExtruderIndex(self, index: int) -> None:
if self._active_extruder_index != index:
self._active_extruder_index = index
self.activeExtruderChanged.emit()
@ -344,6 +345,7 @@ class ExtruderManager(QObject):
if extruders_changed:
self.extrudersChanged.emit(global_stack_id)
self.setActiveExtruderIndex(0)
self.activeExtruderChanged.emit()
# After 3.4, all single-extrusion machines have their own extruder definition files instead of reusing
# "fdmextruder". We need to check a machine here so its extruder definition is correct according to this.

View file

@ -52,8 +52,8 @@ class ExtruderStack(CuraContainerStack):
return super().getNextStack()
def setEnabled(self, enabled: bool) -> None:
if self.getMetaDataEntry("enabled", True) == enabled: #No change.
return #Don't emit a signal then.
if self.getMetaDataEntry("enabled", True) == enabled: # No change.
return # Don't emit a signal then.
self.setMetaDataEntry("enabled", str(enabled))
self.enabledChanged.emit()

View file

@ -224,6 +224,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
"definition": ""
}
items.append(item)
if self._items != items:
self.setItems(items)
self.modelChanged.emit()

View file

@ -3,8 +3,8 @@
from collections import defaultdict
import threading
from typing import Any, Dict, Optional, Set, TYPE_CHECKING
from PyQt5.QtCore import pyqtProperty, pyqtSlot
from typing import Any, Dict, Optional, Set, TYPE_CHECKING, List
from PyQt5.QtCore import pyqtProperty, pyqtSlot, pyqtSignal
from UM.Decorators import override
from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
@ -42,13 +42,23 @@ class GlobalStack(CuraContainerStack):
# Per thread we have our own resolving_settings, or strange things sometimes occur.
self._resolving_settings = defaultdict(set) #type: Dict[str, Set[str]] # keys are thread names
extrudersChanged = pyqtSignal()
## Get the list of extruders of this stack.
#
# \return The extruders registered with this stack.
@pyqtProperty("QVariantMap")
@pyqtProperty("QVariantMap", notify = extrudersChanged)
def extruders(self) -> Dict[str, "ExtruderStack"]:
return self._extruders
@pyqtProperty("QVariantList", notify = extrudersChanged)
def extruderList(self) -> List["ExtruderStack"]:
result_tuple_list = sorted(list(self.extruders.items()), key=lambda x: int(x[0]))
result_list = [item[1] for item in result_tuple_list]
machine_extruder_count = self.getProperty("machine_extruder_count", "value")
return result_list[:machine_extruder_count]
@classmethod
def getLoadingPriority(cls) -> int:
return 2

View file

@ -1536,6 +1536,10 @@ class MachineManager(QObject):
name = self._current_quality_group.name
return name
@pyqtProperty(bool, notify = activeQualityGroupChanged)
def hasNotSupportedQuality(self) -> bool:
return self._current_quality_group is None and self._current_quality_changes_group is None
def _updateUponMaterialMetadataChange(self) -> None:
if self._global_container_stack is None:
return

View file

@ -17,12 +17,6 @@ parser.add_argument("--debug",
default = False,
help = "Turn on the debug mode by setting this option."
)
parser.add_argument("--trigger-early-crash",
dest = "trigger_early_crash",
action = "store_true",
default = False,
help = "FOR TESTING ONLY. Trigger an early crash to show the crash dialog."
)
known_args = vars(parser.parse_known_args()[0])
if not known_args["debug"]:

View file

@ -203,7 +203,7 @@ class CuraEngineBackend(QObject, Backend):
@pyqtSlot()
def stopSlicing(self) -> None:
self.backendStateChange.emit(BackendState.NotStarted)
self.setState(BackendState.NotStarted)
if self._slicing: # We were already slicing. Stop the old job.
self._terminate()
self._createSocket()
@ -322,7 +322,7 @@ class CuraEngineBackend(QObject, Backend):
self._start_slice_job = None
if job.isCancelled() or job.getError() or job.getResult() == StartJobResult.Error:
self.backendStateChange.emit(BackendState.Error)
self.setState(BackendState.Error)
self.backendError.emit(job)
return
@ -331,10 +331,10 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status",
"Unable to slice with the current material as it is incompatible with the selected machine or configuration."), title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
self.setState(BackendState.Error)
self.backendError.emit(job)
else:
self.backendStateChange.emit(BackendState.NotStarted)
self.setState(BackendState.NotStarted)
return
if job.getResult() == StartJobResult.SettingError:
@ -362,10 +362,10 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. The following settings have errors: {0}").format(", ".join(error_labels)),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
self.setState(BackendState.Error)
self.backendError.emit(job)
else:
self.backendStateChange.emit(BackendState.NotStarted)
self.setState(BackendState.NotStarted)
return
elif job.getResult() == StartJobResult.ObjectSettingError:
@ -386,7 +386,7 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}").format(error_labels = ", ".join(errors.values())),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
self.setState(BackendState.Error)
self.backendError.emit(job)
return
@ -395,16 +395,16 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because the prime tower or prime position(s) are invalid."),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
self.setState(BackendState.Error)
self.backendError.emit(job)
else:
self.backendStateChange.emit(BackendState.NotStarted)
self.setState(BackendState.NotStarted)
if job.getResult() == StartJobResult.ObjectsWithDisabledExtruder:
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because there are objects associated with disabled Extruder %s." % job.getMessage()),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
self.setState(BackendState.Error)
self.backendError.emit(job)
return
@ -413,10 +413,10 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status", "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
self.setState(BackendState.Error)
self.backendError.emit(job)
else:
self.backendStateChange.emit(BackendState.NotStarted)
self.setState(BackendState.NotStarted)
self._invokeSlice()
return
@ -424,7 +424,7 @@ class CuraEngineBackend(QObject, Backend):
self._socket.sendMessage(job.getSliceMessage())
# Notify the user that it's now up to the backend to do it's job
self.backendStateChange.emit(BackendState.Processing)
self.setState(BackendState.Processing)
if self._slice_start_time:
Logger.log("d", "Sending slice message took %s seconds", time() - self._slice_start_time )
@ -442,7 +442,7 @@ class CuraEngineBackend(QObject, Backend):
for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
if node.callDecoration("isBlockSlicing"):
enable_timer = False
self.backendStateChange.emit(BackendState.Disabled)
self.setState(BackendState.Disabled)
self._is_disabled = True
gcode_list = node.callDecoration("getGCodeList")
if gcode_list is not None:
@ -451,7 +451,7 @@ class CuraEngineBackend(QObject, Backend):
if self._use_timer == enable_timer:
return self._use_timer
if enable_timer:
self.backendStateChange.emit(BackendState.NotStarted)
self.setState(BackendState.NotStarted)
self.enableTimer()
return True
else:
@ -518,7 +518,7 @@ class CuraEngineBackend(QObject, Backend):
self._build_plates_to_be_sliced.append(build_plate_number)
self.printDurationMessage.emit(source_build_plate_number, {}, [])
self.processingProgress.emit(0.0)
self.backendStateChange.emit(BackendState.NotStarted)
self.setState(BackendState.NotStarted)
# if not self._use_timer:
# With manually having to slice, we want to clear the old invalid layer data.
self._clearLayerData(build_plate_changed)
@ -567,7 +567,7 @@ class CuraEngineBackend(QObject, Backend):
self.stopSlicing()
self.markSliceAll()
self.processingProgress.emit(0.0)
self.backendStateChange.emit(BackendState.NotStarted)
self.setState(BackendState.NotStarted)
if not self._use_timer:
# With manually having to slice, we want to clear the old invalid layer data.
self._clearLayerData()
@ -613,7 +613,7 @@ class CuraEngineBackend(QObject, Backend):
# \param message The protobuf message containing the slicing progress.
def _onProgressMessage(self, message: Arcus.PythonMessage) -> None:
self.processingProgress.emit(message.amount)
self.backendStateChange.emit(BackendState.Processing)
self.setState(BackendState.Processing)
def _invokeSlice(self) -> None:
if self._use_timer:
@ -632,7 +632,7 @@ class CuraEngineBackend(QObject, Backend):
#
# \param message The protobuf message signalling that slicing is finished.
def _onSlicingFinishedMessage(self, message: Arcus.PythonMessage) -> None:
self.backendStateChange.emit(BackendState.Done)
self.setState(BackendState.Done)
self.processingProgress.emit(1.0)
gcode_list = self._scene.gcode_dict[self._start_slice_job_build_plate] #type: ignore #Because we generate this attribute dynamically.

View file

@ -4,19 +4,19 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Window 2.2
import UM 1.2 as UM
import Cura 1.0 as Cura
Button
{
id: modelCheckerButton
UM.I18nCatalog{id: catalog; name: "cura"}
UM.I18nCatalog
{
id: catalog
name: "cura"
}
visible: manager.hasWarnings
tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.")
@ -25,6 +25,8 @@ Button
width: UM.Theme.getSize("save_button_specs_icons").width
height: UM.Theme.getSize("save_button_specs_icons").height
anchors.verticalCenter: parent ? parent.verticalCenter : undefined
style: ButtonStyle
{
background: Item

View file

@ -412,7 +412,7 @@ UM.Dialog
}
}
Cura.SidebarTooltip
Cura.PrintSetupTooltip
{
id: tooltip
}

View file

@ -13,10 +13,6 @@ 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
{
@ -45,7 +41,6 @@ Item
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

View file

@ -10,9 +10,6 @@ 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

View file

@ -16,7 +16,7 @@ Cura.ExpandableComponent
id: base
width: UM.Theme.getSize("layerview_menu_size").width
iconSource: UM.Theme.getIcon("pencil")
contentHeaderTitle: catalog.i18nc("@label", "Color scheme")
Connections
{
@ -45,7 +45,7 @@ Cura.ExpandableComponent
verticalAlignment: Text.AlignVCenter
}
popupItem: Column
contentItem: Column
{
id: viewSettings

View file

@ -14,8 +14,8 @@ Window
modality: Qt.ApplicationModal
flags: Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
width: 720 * screenScaleFactor
height: 640 * screenScaleFactor
width: Math.floor(720 * screenScaleFactor)
height: Math.floor(640 * screenScaleFactor)
minimumWidth: width
maximumWidth: minimumWidth
minimumHeight: height

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -59,6 +59,7 @@ Item
wrapMode: Text.WordWrap
width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height
renderType: Text.NativeRendering
}
Label
{
@ -70,6 +71,7 @@ Item
left: title.left
topMargin: UM.Theme.getSize("default_margin").height
}
renderType: Text.NativeRendering
}
Column
{
@ -88,12 +90,14 @@ Item
text: catalog.i18nc("@label", "Website") + ":"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering
}
Label
{
text: catalog.i18nc("@label", "Email") + ":"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering
}
}
Column
@ -122,6 +126,7 @@ Item
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
renderType: Text.NativeRendering
}
Label
@ -138,6 +143,7 @@ Item
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
renderType: Text.NativeRendering
}
}
Rectangle

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -64,6 +64,7 @@ Item
font: UM.Theme.getFont("default_bold")
horizontalAlignment: Text.AlignRight
width: control.width
renderType: Text.NativeRendering
}
}
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -67,6 +67,7 @@ Item
wrapMode: Text.WordWrap
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering
}
TableView
@ -99,6 +100,7 @@ Item
text: styleData.value || ""
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default_bold")
renderType: Text.NativeRendering
}
Rectangle
{
@ -118,6 +120,7 @@ Item
text: styleData.value || ""
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
}
itemDelegate: Item
@ -130,6 +133,7 @@ Item
text: styleData.value || ""
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
}
@ -144,6 +148,7 @@ Item
elide: Text.ElideRight
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
}
@ -232,5 +237,6 @@ Item
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
renderType: Text.NativeRendering
}
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick 2.10
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Layouts 1.1
@ -66,6 +66,7 @@ UM.Dialog
anchors.right: parent.right
font: UM.Theme.getFont("default")
wrapMode: Text.WordWrap
renderType: Text.NativeRendering
}
// Buttons

View file

@ -32,7 +32,11 @@ Item
model: toolbox.packagesModel
delegate: Loader
{
asynchronous: true
// FIXME: When using asynchronous loading, on Mac and Windows, the tile may fail to load complete,
// leaving an empty space below the title part. We turn it off for now to make it work on Mac and
// Windows.
// Can be related to this QT bug: https://bugreports.qt.io/browse/QTBUG-50992
asynchronous: false
source: "ToolboxDetailTile.qml"
}
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -64,6 +64,7 @@ Item
color: UM.Theme.getColor("text")
width: contentWidth
height: contentHeight
renderType: Text.NativeRendering
}
SmallRatingWidget
@ -91,30 +92,35 @@ Item
text: catalog.i18nc("@label", "Rating") + ":"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering
}
Label
{
text: catalog.i18nc("@label", "Version") + ":"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering
}
Label
{
text: catalog.i18nc("@label", "Last updated") + ":"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering
}
Label
{
text: catalog.i18nc("@label", "Author") + ":"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering
}
Label
{
text: catalog.i18nc("@label", "Downloads") + ":"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering
}
}
Column
@ -176,6 +182,7 @@ Item
text: details === null ? "" : (details.version || catalog.i18nc("@label", "Unknown"))
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
Label
{
@ -190,6 +197,7 @@ Item
}
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
Label
{
@ -208,12 +216,14 @@ Item
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
renderType: Text.NativeRendering
}
Label
{
text: details === null ? "" : (details.download_count || catalog.i18nc("@label", "Unknown"))
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
}
Rectangle

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -31,6 +31,7 @@ Item
wrapMode: Text.WordWrap
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("medium_bold")
renderType: Text.NativeRendering
}
Label
{
@ -42,6 +43,7 @@ Item
wrapMode: Text.WordWrap
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -57,6 +57,8 @@ Column
linkColor: UM.Theme.getColor("text_link")
visible: loginRequired
width: installButton.width
renderType: Text.NativeRendering
MouseArea
{
anchors.fill: parent

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
@ -23,6 +23,7 @@ Column
width: parent.width
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering
}
Grid
{
@ -37,7 +38,7 @@ Column
delegate: Loader
{
asynchronous: true
width: (grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns
width: Math.round((grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns)
height: UM.Theme.getSize("toolbox_thumbnail_small").height
source: "ToolboxDownloadsGridTile.qml"
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
@ -13,7 +13,7 @@ Item
id: toolboxDownloadsGridTile
property int packageCount: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getTotalNumberOfMaterialPackagesByAuthor(model.id) : 1
property int installedPackages: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
height: UM.Theme.getSize("toolbox_thumbnail_small").height
height: childrenRect.height
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
MouseArea

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -24,6 +24,7 @@ Rectangle
width: parent.width
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering
}
Grid
{

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
@ -43,6 +43,7 @@ Rectangle
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
height: UM.Theme.getSize("toolbox_heading_label").height
width: parent.width - UM.Theme.getSize("default_margin").width
wrapMode: Text.WordWrap

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
@ -18,5 +18,6 @@ Rectangle
{
centerIn: parent
}
renderType: Text.NativeRendering
}
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -26,7 +26,7 @@ Item
right: restartButton.right
rightMargin: UM.Theme.getSize("default_margin").width
}
renderType: Text.NativeRendering
}
Button
{
@ -56,6 +56,7 @@ Item
text: control.text
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
}
}
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Dialogs 1.1
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
@ -38,6 +38,7 @@ ScrollView
text: catalog.i18nc("@title:tab", "Plugins")
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering
}
Rectangle
{
@ -68,6 +69,7 @@ ScrollView
text: catalog.i18nc("@title:tab", "Materials")
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering
}
Rectangle

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -51,6 +51,7 @@ Item
wrapMode: Text.WordWrap
font: UM.Theme.getFont("default_bold")
color: pluginInfo.color
renderType: Text.NativeRendering
}
Label
{
@ -60,6 +61,7 @@ Item
width: parent.width
wrapMode: Text.WordWrap
color: pluginInfo.color
renderType: Text.NativeRendering
}
}
Column
@ -88,6 +90,7 @@ Item
onLinkActivated: Qt.openUrlExternally("mailto:" + model.author_email + "?Subject=Cura: " + model.name + " Plugin")
color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining")
linkColor: UM.Theme.getColor("text_link")
renderType: Text.NativeRendering
}
Label
@ -98,6 +101,7 @@ Item
color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
renderType: Text.NativeRendering
}
}
ToolboxInstalledTileActions

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@ -24,6 +24,7 @@ Column
font: UM.Theme.getFont("default")
wrapMode: Text.WordWrap
width: parent.width
renderType: Text.NativeRendering
}
ToolboxProgressButton
@ -55,6 +56,8 @@ Column
linkColor: UM.Theme.getColor("text_link")
visible: loginRequired
width: updateButton.width
renderType: Text.NativeRendering
MouseArea
{
anchors.fill: parent

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick 2.10
import QtQuick.Dialogs 1.1
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
@ -32,6 +32,7 @@ UM.Dialog
anchors.right: parent.right
text: licenseDialog.pluginName + catalog.i18nc("@label", "This plugin contains a license.\nYou need to accept this license to install this plugin.\nDo you agree with the terms below?")
wrapMode: Text.Wrap
renderType: Text.NativeRendering
}
TextArea
{

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
@ -18,5 +18,6 @@ Rectangle
{
centerIn: parent
}
renderType: Text.NativeRendering
}
}

View file

@ -7,7 +7,7 @@ import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
import Cura 1.0 as Cura
// TODO; This is in quite some need for refactoring.
Item
{
id: base

View file

@ -1,8 +1,8 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 2.0
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.1 as UM
Button
@ -46,5 +46,6 @@ Button
font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
}
}

View file

@ -691,7 +691,8 @@ class Toolbox(QObject, Extension):
self.setDownloadProgress(new_progress)
if bytes_sent == bytes_total:
self.setIsDownloading(False)
cast(QNetworkReply, self._download_reply).downloadProgress.disconnect(self._onDownloadProgress)
self._download_reply = cast(QNetworkReply, self._download_reply)
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
# Check if the download was sucessfull
if self._download_reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:

View file

@ -1,110 +0,0 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.3
import UM 1.3 as UM
import Cura 1.0 as Cura
Component {
Rectangle {
id: base;
property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width;
property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width;
anchors.fill: parent;
color: UM.Theme.getColor("main_background");
visible: OutputDevice != null;
UM.I18nCatalog {
id: catalog;
name: "cura";
}
Label {
id: printingLabel;
anchors {
left: parent.left;
leftMargin: 4 * UM.Theme.getSize("default_margin").width;
margins: 2 * UM.Theme.getSize("default_margin").width;
right: parent.right;
top: parent.top;
}
color: UM.Theme.getColor("text");
elide: Text.ElideRight;
font: UM.Theme.getFont("large");
text: catalog.i18nc("@label", "Printing");
}
Label {
id: managePrintersLabel;
anchors {
bottom: printingLabel.bottom;
right: printerScrollView.right;
rightMargin: 4 * UM.Theme.getSize("default_margin").width;
}
color: UM.Theme.getColor("primary"); // "Cura Blue"
font: UM.Theme.getFont("default");
linkColor: UM.Theme.getColor("primary"); // "Cura Blue"
text: catalog.i18nc("@label link to connect manager", "Manage printers");
}
MouseArea {
anchors.fill: managePrintersLabel;
hoverEnabled: true;
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrinterControlPanel();
onEntered: managePrintersLabel.font.underline = true;
onExited: managePrintersLabel.font.underline = false;
}
// Skeleton loading
Column {
id: skeletonLoader;
anchors {
left: parent.left;
leftMargin: UM.Theme.getSize("wide_margin").width;
right: parent.right;
rightMargin: UM.Theme.getSize("wide_margin").width;
top: printingLabel.bottom;
topMargin: UM.Theme.getSize("default_margin").height;
}
spacing: UM.Theme.getSize("default_margin").height - 10;
visible: printerList.count === 0;
PrinterCard {
printer: null;
}
PrinterCard {
printer: null;
}
}
// Actual content
ScrollView {
id: printerScrollView;
anchors {
bottom: parent.bottom;
left: parent.left;
right: parent.right;
top: printingLabel.bottom;
topMargin: UM.Theme.getSize("default_margin").height;
}
style: UM.Theme.styles.scrollview;
ListView {
id: printerList;
property var currentIndex: -1;
anchors {
fill: parent;
leftMargin: UM.Theme.getSize("wide_margin").width;
rightMargin: UM.Theme.getSize("wide_margin").width;
}
delegate: PrinterCard {
printer: modelData;
}
model: OutputDevice.printers;
spacing: UM.Theme.getSize("default_margin").height - 10;
}
}
}
}

View file

@ -57,7 +57,7 @@ Cura.MachineAction
spacing: UM.Theme.getSize("default_margin").height
SystemPalette { id: palette }
UM.I18nCatalog { id: catalog; name: "cura" }
UM.I18nCatalog { id: catalog; name:"cura" }
Label
{
id: pageTitle

View file

@ -1,12 +0,0 @@
// 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
Rectangle {
color: UM.Theme.getColor("monitor_lining_light"); // TODO: Maybe theme separately? Maybe not.
height: UM.Theme.getSize("default_lining").height;
width: parent.width;
}

View file

@ -27,7 +27,7 @@ Item
Row
{
height: parent.height
spacing: 12 * screenScaleFactor // TODO: Theme! (Should be same as extruder spacing)
spacing: UM.Theme.getSize("print_setup_slider_handle").width // TODO: Theme! (Should be same as extruder spacing)
// This wrapper ensures that the buildplate icon is located centered
// below an extruder icon.

View file

@ -0,0 +1,142 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import UM 1.3 as UM
UM.Dialog
{
id: overrideConfirmationDialog
property var printer: null
minimumWidth: screenScaleFactor * 640;
minimumHeight: screenScaleFactor * 320;
width: minimumWidth
height: minimumHeight
title: catalog.i18nc("@title:window", "Configuration Changes")
rightButtons:
[
Button
{
id: overrideButton
anchors.margins: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@action:button", "Override")
onClicked:
{
OutputDevice.forceSendJob(printer.activePrintJob.key)
overrideConfirmationDialog.close()
}
},
Button
{
id: cancelButton
anchors.margins: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@action:button", "Cancel")
onClicked:
{
overrideConfirmationDialog.reject()
}
}
]
Label
{
anchors
{
fill: parent
margins: 36 * screenScaleFactor // TODO: Theme!
bottomMargin: 56 * screenScaleFactor // TODO: Theme!
}
wrapMode: Text.WordWrap
text:
{
if (!printer.activePrintJob)
{
return ""
}
var topLine
if (materialsAreKnown(printer.activePrintJob))
{
topLine = catalog.i18ncp("@label", "The assigned printer, %1, requires the following configuration change:", "The assigned printer, %1, requires the following configuration changes:", printer.activePrintJob.configurationChanges.length).arg(printer.name)
}
else
{
topLine = catalog.i18nc("@label", "The printer %1 is assigned, but the job contains an unknown material configuration.").arg(printer.name)
}
var result = "<p>" + topLine +"</p>\n\n"
for (var i = 0; i < printer.activePrintJob.configurationChanges.length; i++)
{
var change = printer.activePrintJob.configurationChanges[i]
var text
switch (change.typeOfChange)
{
case "material_change":
text = catalog.i18nc("@label", "Change material %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName)
break
case "material_insert":
text = catalog.i18nc("@label", "Load %3 as material %1 (This cannot be overridden).").arg(change.index + 1).arg(change.targetName)
break
case "print_core_change":
text = catalog.i18nc("@label", "Change print core %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName)
break
case "buildplate_change":
text = catalog.i18nc("@label", "Change build plate to %1 (This cannot be overridden).").arg(formatBuildPlateType(change.target_name))
break
default:
text = "unknown"
}
result += "<p><b>" + text + "</b></p>\n\n"
}
var bottomLine = catalog.i18nc("@label", "Override will use the specified settings with the existing printer configuration. This may result in a failed print.")
result += "<p>" + bottomLine + "</p>\n\n"
return result
}
}
// Utils
function formatPrintJobName(name)
{
var extensions = [ ".gcode.gz", ".gz", ".gcode", ".ufp" ]
for (var i = 0; i < extensions.length; i++)
{
var extension = extensions[i]
if (name.slice(-extension.length) === extension)
{
name = name.substring(0, name.length - extension.length)
}
}
return name;
}
function materialsAreKnown(job)
{
var conf0 = job.configuration[0]
if (conf0 && !conf0.material.material)
{
return false
}
var conf1 = job.configuration[1]
if (conf1 && !conf1.material.material)
{
return false
}
return true
}
function formatBuildPlateType(buildPlateType)
{
var translationText = ""
switch (buildPlateType) {
case "glass":
translationText = catalog.i18nc("@label", "Glass")
break
case "aluminum":
translationText = catalog.i18nc("@label", "Aluminum")
break
default:
translationText = null
}
return translationText
}
}

View file

@ -26,6 +26,7 @@ Item
ExpandableCard
{
borderColor: printJob.configurationChanges.length !== 0 ? "#f5a623" : "#EAEAEC" // TODO: Theme!
headerItem: Row
{
height: 48 * screenScaleFactor // TODO: Theme!

View file

@ -23,7 +23,7 @@ Item
anchors.fill: parent
opacity:
{
if (printJob && (printJob.state == "error" || !printJob.isActive))
if (printJob && (printJob.state == "error" || printJob.configurationChanges.length > 0 || !printJob.isActive))
{
return 0.5
}
@ -60,6 +60,14 @@ Item
height: 0.5 * printJobPreview.height
source:
{
if (!printJob)
{
return ""
}
if (printJob.configurationChanges.length > 0)
{
return "../svg/warning-icon.svg"
}
switch(printJob.state)
{
case "error":
@ -75,6 +83,7 @@ Item
default:
return ""
}
return ""
}
sourceSize
{

View file

@ -55,7 +55,7 @@ Item
left: progressBar.right
leftMargin: 18 * screenScaleFactor // TODO: Theme!
}
text: Math.round(printJob.progress * 100) + "%"
text: printJob ? Math.round(printJob.progress * 100) + "%" : "0%"
color: printJob && printJob.isActive ? "#374355" : "#babac1" // TODO: Theme!
width: contentWidth
font: UM.Theme.getFont("medium") // 14pt, regular
@ -88,6 +88,8 @@ Item
return catalog.i18nc("@label:status", "Aborted")
}
return catalog.i18nc("@label:status", "Finished")
case "finished":
return catalog.i18nc("@label:status", "Finished")
case "sent_to_printer":
return catalog.i18nc("@label:status", "Preparing...")
case "pre_print":

View file

@ -3,6 +3,7 @@
import QtQuick 2.3
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.1
import UM 1.3 as UM
/**
@ -66,7 +67,7 @@ Item
{
verticalCenter: parent.verticalCenter
}
width: 216 * screenScaleFactor // TODO: Theme!
width: 180 * screenScaleFactor // TODO: Theme!
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
Label
@ -150,7 +151,7 @@ Item
}
border
{
color: "#EAEAEC" // TODO: Theme!
color: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? "#f5a623" : "#EAEAEC" // TODO: Theme!
width: borderSize // TODO: Remove once themed
}
color: "white" // TODO: Theme!
@ -185,14 +186,15 @@ Item
}
if (printer && printer.state == "unreachable")
{
return catalog.i18nc("@label:status", "Unreachable")
return catalog.i18nc("@label:status", "Unavailable")
}
if (printer && printer.state == "idle")
if (printer && !printer.activePrintJob && printer.state == "idle")
{
return catalog.i18nc("@label:status", "Idle")
}
return ""
}
visible: text !== ""
}
Item
@ -218,7 +220,7 @@ Item
{
verticalCenter: parent.verticalCenter
}
width: 216 * screenScaleFactor // TODO: Theme!
width: 180 * screenScaleFactor // TODO: Theme!
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
visible: printer.activePrintJob
@ -247,7 +249,7 @@ Item
}
color: printer.activePrintJob && printer.activePrintJob.isActive ? "#53657d" : "#babac1" // TODO: Theme!
elide: Text.ElideRight
font: UM.Theme.getFont("very_small") // 12pt, regular
font: UM.Theme.getFont("default") // 12pt, regular
text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N
width: parent.width
@ -264,8 +266,67 @@ Item
verticalCenter: parent.verticalCenter
}
printJob: printer.activePrintJob
visible: printer.activePrintJob
visible: printer.activePrintJob && printer.activePrintJob.configurationChanges.length === 0
}
Label
{
anchors
{
verticalCenter: parent.verticalCenter
}
font: UM.Theme.getFont("default")
text: "Requires configuration changes"
visible: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
}
}
Button
{
id: detailsButton
anchors
{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 18 * screenScaleFactor // TODO: Theme!
}
background: Rectangle
{
color: "#d8d8d8" // TODO: Theme!
radius: 2 * screenScaleFactor // Todo: Theme!
Rectangle
{
anchors.fill: parent
anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
color: detailsButton.hovered ? "#e4e4e4" : "#f0f0f0" // TODO: Theme!
radius: 2 * screenScaleFactor // Todo: Theme!
}
}
contentItem: Label
{
anchors.fill: parent
anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
color: "#1e66d7" // TODO: Theme!
font: UM.Theme.getFont("medium") // 14pt, regular
text: "Details" // TODO: I18NC!
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
height: 18 * screenScaleFactor // TODO: Theme!
}
implicitHeight: 32 * screenScaleFactor // TODO: Theme!
implicitWidth: 96 * screenScaleFactor // TODO: Theme!
visible: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0
onClicked: overrideConfirmationDialog.open()
}
}
MonitorConfigOverrideDialog
{
id: overrideConfirmationDialog
printer: base.printer
}
}

View file

@ -8,6 +8,7 @@ import UM 1.3 as UM
import Cura 1.0 as Cura
import QtGraphicalEffects 1.0
// Root component for the monitor tab (stage)
Component
{
Item
@ -130,7 +131,7 @@ Component
verticalCenter: externalLinkIcon.verticalCenter
}
color: UM.Theme.getColor("primary")
font: UM.Theme.getFont("default")
font: UM.Theme.getFont("default") // 12pt, regular
linkColor: UM.Theme.getColor("primary")
text: catalog.i18nc("@label link to connect manager", "Manage queue in Cura Connect")
}

View file

@ -1,121 +0,0 @@
// 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.4
import QtQuick.Controls.Styles 1.4
import UM 1.2 as UM
Item {
id: extruderInfo;
property var printCoreConfiguration: null;
height: childrenRect.height;
width: Math.round(parent.width / 2);
// Extruder circle
Item {
id: extruderCircle;
height: UM.Theme.getSize("monitor_extruder_circle").height;
width: UM.Theme.getSize("monitor_extruder_circle").width;
// Loading skeleton
Rectangle {
anchors.fill: parent;
color: UM.Theme.getColor("monitor_skeleton_fill");
radius: Math.round(width / 2);
visible: !printCoreConfiguration;
}
// Actual content
Rectangle {
anchors.fill: parent;
border.width: UM.Theme.getSize("monitor_thick_lining").width;
border.color: UM.Theme.getColor("monitor_lining_heavy");
color: "transparent";
opacity: {
if (printCoreConfiguration == null || printCoreConfiguration.activeMaterial == null || printCoreConfiguration.hotendID == null) {
return 0.5;
}
return 1;
}
radius: Math.round(width / 2);
visible: printCoreConfiguration;
Label {
anchors.centerIn: parent;
color: UM.Theme.getColor("text");
font: UM.Theme.getFont("default_bold");
text: printCoreConfiguration ? printCoreConfiguration.position + 1 : 0;
}
}
}
// Print core and material labels
Item {
id: materialLabel
anchors {
left: extruderCircle.right;
leftMargin: UM.Theme.getSize("default_margin").width;
right: parent.right;
top: parent.top;
}
height: UM.Theme.getSize("monitor_text_line").height;
// Loading skeleton
Rectangle {
anchors.fill: parent;
color: UM.Theme.getColor("monitor_skeleton_fill");
visible: !extruderInfo.printCoreConfiguration;
}
// Actual content
Label {
anchors.fill: parent;
elide: Text.ElideRight;
color: UM.Theme.getColor("text");
font: UM.Theme.getFont("default");
text: {
if (printCoreConfiguration && printCoreConfiguration.activeMaterial != undefined) {
return printCoreConfiguration.activeMaterial.name;
}
return "";
}
visible: extruderInfo.printCoreConfiguration;
}
}
Item {
id: printCoreLabel;
anchors {
left: extruderCircle.right;
leftMargin: UM.Theme.getSize("default_margin").width;
right: parent.right;
top: materialLabel.bottom;
topMargin: Math.floor(UM.Theme.getSize("default_margin").height/4);
}
height: UM.Theme.getSize("monitor_text_line").height;
// Loading skeleton
Rectangle {
color: UM.Theme.getColor("monitor_skeleton_fill");
height: parent.height;
visible: !extruderInfo.printCoreConfiguration;
width: Math.round(parent.width / 3);
}
// Actual content
Label {
color: UM.Theme.getColor("text");
elide: Text.ElideRight;
font: UM.Theme.getFont("default");
opacity: 0.6;
text: {
if (printCoreConfiguration != undefined && printCoreConfiguration.hotendID != undefined) {
return printCoreConfiguration.hotendID;
}
return "";
}
visible: extruderInfo.printCoreConfiguration;
}
}
}

View file

@ -182,7 +182,7 @@ Item {
abortConfirmationDialog.visible = true;
popup.close();
}
text: printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort");
text: printJob && printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort");
visible: {
if (!printJob) {
return false;

View file

@ -1,505 +0,0 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Dialogs 1.1
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.1
import UM 1.3 as UM
Item {
id: root;
property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width;
property var shadowOffset: 2 * screenScaleFactor;
property var debug: false;
property var printJob: null;
width: parent.width; // Bubbles downward
height: childrenRect.height + shadowRadius * 2; // Bubbles upward
UM.I18nCatalog {
id: catalog;
name: "cura";
}
// The actual card (white block)
Rectangle {
// 5px margin, but shifted 2px vertically because of the shadow
anchors {
bottomMargin: root.shadowRadius + root.shadowOffset;
leftMargin: root.shadowRadius;
rightMargin: root.shadowRadius;
topMargin: root.shadowRadius - root.shadowOffset;
}
color: UM.Theme.getColor("monitor_card_background");
height: childrenRect.height;
layer.enabled: true
layer.effect: DropShadow {
radius: root.shadowRadius
verticalOffset: 2 * screenScaleFactor
color: "#3F000000" // 25% shadow
}
width: parent.width - shadowRadius * 2;
Column {
height: childrenRect.height;
width: parent.width;
// Main content
Item {
id: mainContent;
height: 200 * screenScaleFactor; // TODO: Theme!
width: parent.width;
// Left content
Item {
anchors {
bottom: parent.bottom;
left: parent.left;
margins: UM.Theme.getSize("wide_margin").width;
right: parent.horizontalCenter;
top: parent.top;
}
Item {
id: printJobName;
width: parent.width;
height: UM.Theme.getSize("monitor_text_line").height;
Rectangle {
color: UM.Theme.getColor("monitor_skeleton_fill");
height: parent.height;
visible: !printJob;
width: Math.round(parent.width / 3);
}
Label {
anchors.fill: parent;
color: UM.Theme.getColor("text");
elide: Text.ElideRight;
font: UM.Theme.getFont("default_bold");
text: printJob && printJob.name ? printJob.name : ""; // Supress QML warnings
visible: printJob;
}
}
Item {
id: printJobOwnerName;
anchors {
top: printJobName.bottom;
topMargin: Math.floor(UM.Theme.getSize("default_margin").height / 2);
}
height: UM.Theme.getSize("monitor_text_line").height;
width: parent.width;
Rectangle {
color: UM.Theme.getColor("monitor_skeleton_fill");
height: parent.height;
visible: !printJob;
width: Math.round(parent.width / 2);
}
Label {
anchors.fill: parent;
color: UM.Theme.getColor("text");
elide: Text.ElideRight;
font: UM.Theme.getFont("default");
text: printJob ? printJob.owner : ""; // Supress QML warnings
visible: printJob;
}
}
Item {
id: printJobPreview;
property var useUltibot: false;
anchors {
bottom: parent.bottom;
horizontalCenter: parent.horizontalCenter;
top: printJobOwnerName.bottom;
topMargin: UM.Theme.getSize("default_margin").height;
}
width: height;
// Skeleton
Rectangle {
anchors.fill: parent;
color: UM.Theme.getColor("monitor_skeleton_fill");
radius: UM.Theme.getSize("default_margin").width;
visible: !printJob;
}
// Actual content
Image {
id: previewImage;
anchors.fill: parent;
opacity: printJob && printJob.state == "error" ? 0.5 : 1.0;
source: printJob ? printJob.previewImageUrl : "";
visible: printJob;
}
UM.RecolorImage {
id: ultiBotImage;
anchors.centerIn: printJobPreview;
color: UM.Theme.getColor("monitor_placeholder_image");
height: printJobPreview.height;
source: "../svg/ultibot.svg";
sourceSize {
height: height;
width: width;
}
/* Since print jobs ALWAYS have an image url, we have to check if that image URL errors or
not in order to determine if we show the placeholder (ultibot) image instead. */
visible: printJob && previewImage.status == Image.Error;
width: printJobPreview.width;
}
UM.RecolorImage {
id: statusImage;
anchors.centerIn: printJobPreview;
color: UM.Theme.getColor("monitor_image_overlay");
height: 0.5 * printJobPreview.height;
source: printJob && printJob.state == "error" ? "../svg/aborted-icon.svg" : "";
sourceSize {
height: height;
width: width;
}
visible: source != "";
width: 0.5 * printJobPreview.width;
}
}
Label {
id: totalTimeLabel;
anchors {
bottom: parent.bottom;
right: parent.right;
}
color: UM.Theme.getColor("text");
elide: Text.ElideRight;
font: UM.Theme.getFont("default");
text: printJob ? OutputDevice.formatDuration(printJob.timeTotal) : "";
}
}
// Divider
Rectangle {
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter;
}
color: !printJob ? UM.Theme.getColor("monitor_skeleton_fill") : UM.Theme.getColor("monitor_lining_light");
height: parent.height - 2 * UM.Theme.getSize("default_margin").height;
width: UM.Theme.getSize("default_lining").width;
}
// Right content
Item {
anchors {
bottom: parent.bottom;
left: parent.horizontalCenter;
margins: UM.Theme.getSize("wide_margin").width;
right: parent.right;
top: parent.top;
}
Item {
id: targetPrinterLabel;
height: UM.Theme.getSize("monitor_text_line").height;
width: parent.width;
Rectangle {
visible: !printJob;
color: UM.Theme.getColor("monitor_skeleton_fill");
anchors.fill: parent;
}
Label {
color: UM.Theme.getColor("text");
elide: Text.ElideRight;
font: UM.Theme.getFont("default_bold");
text: {
if (printJob !== null) {
if (printJob.assignedPrinter == null) {
if (printJob.state == "error") {
return catalog.i18nc("@label", "Waiting for: Unavailable printer");
}
return catalog.i18nc("@label", "Waiting for: First available");
} else {
return catalog.i18nc("@label", "Waiting for: ") + printJob.assignedPrinter.name;
}
}
return "";
}
visible: printJob;
}
}
PrinterInfoBlock {
anchors.bottom: parent.bottom;
printer: root.printJon && root.printJob.assignedPrinter;
printJob: root.printJob;
}
}
PrintJobContextMenu {
id: contextButton;
anchors {
right: mainContent.right;
rightMargin: UM.Theme.getSize("default_margin").width * 3 + root.shadowRadius;
top: mainContent.top;
topMargin: UM.Theme.getSize("default_margin").height;
}
printJob: root.printJob;
visible: root.printJob;
}
}
Item {
id: configChangesBox;
height: childrenRect.height;
visible: printJob && printJob.configurationChanges.length !== 0;
width: parent.width;
// Config change toggle
Rectangle {
id: configChangeToggle;
color: {
if (configChangeToggleArea.containsMouse) {
return UM.Theme.getColor("viewport_background"); // TODO: Theme!
} else {
return "transparent";
}
}
width: parent.width;
height: UM.Theme.getSize("default_margin").height * 4; // TODO: Theme!
anchors {
left: parent.left;
right: parent.right;
top: parent.top;
}
Rectangle {
color: !printJob ? UM.Theme.getColor("monitor_skeleton_fill") : UM.Theme.getColor("monitor_lining_light");
height: UM.Theme.getSize("default_lining").height;
width: parent.width;
}
UM.RecolorImage {
anchors {
right: configChangeToggleLabel.left;
rightMargin: UM.Theme.getSize("default_margin").width;
verticalCenter: parent.verticalCenter;
}
color: UM.Theme.getColor("text");
height: 23 * screenScaleFactor; // TODO: Theme!
source: "../svg/warning-icon.svg";
sourceSize {
height: height;
width: width;
}
width: 23 * screenScaleFactor; // TODO: Theme!
}
Label {
id: configChangeToggleLabel;
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter;
}
color: UM.Theme.getColor("text");
font: UM.Theme.getFont("default");
text: catalog.i18nc("@label", "Configuration change");
}
UM.RecolorImage {
anchors {
left: configChangeToggleLabel.right;
leftMargin: UM.Theme.getSize("default_margin").width;
verticalCenter: parent.verticalCenter;
}
color: UM.Theme.getColor("text");
height: 15 * screenScaleFactor; // TODO: Theme!
source: {
if (configChangeDetails.visible) {
return UM.Theme.getIcon("arrow_top");
} else {
return UM.Theme.getIcon("arrow_bottom");
}
}
sourceSize {
width: width;
height: height;
}
width: 15 * screenScaleFactor; // TODO: Theme!
}
MouseArea {
id: configChangeToggleArea;
anchors.fill: parent;
hoverEnabled: true;
onClicked: {
configChangeDetails.visible = !configChangeDetails.visible;
}
}
}
// Config change details
Item {
id: configChangeDetails;
anchors.top: configChangeToggle.bottom;
Behavior on height { NumberAnimation { duration: 100 } }
// In case of really massive multi-line configuration changes
height: visible ? Math.max(UM.Theme.getSize("monitor_config_override_box").height, childrenRect.height) : 0;
visible: false;
width: parent.width;
Item {
anchors {
bottomMargin: UM.Theme.getSize("wide_margin").height;
fill: parent;
leftMargin: UM.Theme.getSize("wide_margin").height * 4;
rightMargin: UM.Theme.getSize("wide_margin").height * 4;
topMargin: UM.Theme.getSize("wide_margin").height;
}
clip: true;
Label {
anchors.fill: parent;
elide: Text.ElideRight;
color: UM.Theme.getColor("text");
font: UM.Theme.getFont("default");
text: {
if (!printJob || printJob.configurationChanges.length === 0) {
return "";
}
var topLine;
if (materialsAreKnown(printJob)) {
topLine = catalog.i18nc("@label", "The assigned printer, %1, requires the following configuration change(s):").arg(printJob.assignedPrinter.name);
} else {
topLine = catalog.i18nc("@label", "The printer %1 is assigned, but the job contains an unknown material configuration.").arg(printJob.assignedPrinter.name);
}
var result = "<p>" + topLine +"</p>";
for (var i = 0; i < printJob.configurationChanges.length; i++) {
var change = printJob.configurationChanges[i];
var text;
switch (change.typeOfChange) {
case "material_change":
text = catalog.i18nc("@label", "Change material %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName);
break;
case "material_insert":
text = catalog.i18nc("@label", "Load %3 as material %1 (This cannot be overridden).").arg(change.index + 1).arg(change.targetName);
break;
case "print_core_change":
text = catalog.i18nc("@label", "Change print core %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName);
break;
case "buildplate_change":
text = catalog.i18nc("@label", "Change build plate to %1 (This cannot be overridden).").arg(formatBuildPlateType(change.target_name));
break;
default:
text = "";
}
result += "<p><b>" + text + "</b></p>";
}
return result;
}
wrapMode: Text.WordWrap;
}
Button {
anchors {
bottom: parent.bottom;
left: parent.left;
}
background: Rectangle {
border {
color: UM.Theme.getColor("monitor_lining_heavy");
width: UM.Theme.getSize("default_lining").width;
}
color: parent.hovered ? UM.Theme.getColor("monitor_card_background_inactive") : UM.Theme.getColor("monitor_card_background");
implicitHeight: UM.Theme.getSize("default_margin").height * 3;
implicitWidth: UM.Theme.getSize("default_margin").height * 8;
}
contentItem: Label {
color: UM.Theme.getColor("text");
font: UM.Theme.getFont("medium");
horizontalAlignment: Text.AlignHCenter;
text: parent.text;
verticalAlignment: Text.AlignVCenter;
}
onClicked: {
overrideConfirmationDialog.visible = true;
}
text: catalog.i18nc("@label", "Override");
visible: {
if (printJob && printJob.configurationChanges) {
var length = printJob.configurationChanges.length;
for (var i = 0; i < length; i++) {
var typeOfChange = printJob.configurationChanges[i].typeOfChange;
if (typeOfChange === "material_insert" || typeOfChange === "buildplate_change") {
return false;
}
}
}
return true;
}
}
}
}
MessageDialog {
id: overrideConfirmationDialog;
Component.onCompleted: visible = false;
icon: StandardIcon.Warning;
onYes: OutputDevice.forceSendJob(printJob.key);
standardButtons: StandardButton.Yes | StandardButton.No;
text: {
if (!printJob) {
return "";
}
var printJobName = formatPrintJobName(printJob.name);
var confirmText = catalog.i18nc("@label", "Starting a print job with an incompatible configuration could damage your 3D printer. Are you sure you want to override the configuration and print %1?").arg(printJobName);
return confirmText;
}
title: catalog.i18nc("@window:title", "Override configuration configuration and start print");
}
}
}
}
// Utils
function formatPrintJobName(name) {
var extensions = [ ".gz", ".gcode", ".ufp" ];
for (var i = 0; i < extensions.length; i++) {
var extension = extensions[i];
if (name.slice(-extension.length) === extension) {
name = name.substring(0, name.length - extension.length);
}
}
return name;
}
function materialsAreKnown(job) {
var conf0 = job.configuration[0];
if (conf0 && !conf0.material.material) {
return false;
}
var conf1 = job.configuration[1];
if (conf1 && !conf1.material.material) {
return false;
}
return true;
}
function formatBuildPlateType(buildPlateType) {
var translationText = "";
switch (buildPlateType) {
case "glass":
translationText = catalog.i18nc("@label", "Glass");
break;
case "aluminum":
translationText = catalog.i18nc("@label", "Aluminum");
break;
default:
translationText = null;
}
return translationText;
}
}

View file

@ -1,75 +0,0 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick.Dialogs 1.1
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.3
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.4 as LegacyControls
import UM 1.3 as UM
// Includes print job name, owner, and preview
Item {
property var job: null;
property var useUltibot: false;
height: 100 * screenScaleFactor;
width: height;
// Skeleton
Rectangle {
anchors.fill: parent;
color: UM.Theme.getColor("monitor_skeleton_fill");
radius: UM.Theme.getSize("default_margin").width;
visible: !job;
}
// Actual content
Image {
id: previewImage;
visible: job;
source: job ? job.previewImageUrl : "";
opacity: {
if (job == null) {
return 1.0;
}
var states = ["wait_cleanup", "wait_user_action", "error", "paused"];
if (states.indexOf(job.state) !== -1) {
return 0.5;
}
return 1.0;
}
anchors.fill: parent;
}
UM.RecolorImage {
id: ultibotImage;
anchors.centerIn: parent;
color: UM.Theme.getColor("monitor_placeholder_image"); // TODO: Theme!
height: parent.height;
source: "../svg/ultibot.svg";
sourceSize {
height: height;
width: width;
}
/* Since print jobs ALWAYS have an image url, we have to check if that image URL errors or
not in order to determine if we show the placeholder (ultibot) image instead. */
visible: job && previewImage.status == Image.Error;
width: parent.width;
}
UM.RecolorImage {
id: statusImage;
anchors.centerIn: parent;
color: "black"; // TODO: Theme!
height: Math.round(0.5 * parent.height);
source: job && job.state == "error" ? "../svg/aborted-icon.svg" : "";
sourceSize {
height: height;
width: width;
}
visible: source != "";
width: Math.round(0.5 * parent.width);
}
}

View file

@ -1,59 +0,0 @@
// 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
Column {
property var job: null;
height: childrenRect.height;
spacing: Math.floor( UM.Theme.getSize("default_margin").height / 2); // TODO: Use explicit theme size
width: parent.width;
Item {
id: jobName;
height: UM.Theme.getSize("monitor_text_line").height;
width: parent.width;
// Skeleton loading
Rectangle {
color: UM.Theme.getColor("monitor_skeleton_fill");
height: parent.height;
visible: !job;
width: Math.round(parent.width / 3);
}
Label {
anchors.fill: parent;
color: UM.Theme.getColor("text");
elide: Text.ElideRight;
font: UM.Theme.getFont("default_bold");
text: job && job.name ? job.name : "";
visible: job;
}
}
Item {
id: ownerName;
height: UM.Theme.getSize("monitor_text_line").height;
width: parent.width;
// Skeleton loading
Rectangle {
color: UM.Theme.getColor("monitor_skeleton_fill");
height: parent.height;
visible: !job;
width: Math.round(parent.width / 2);
}
Label {
anchors.fill: parent;
color: UM.Theme.getColor("text")
elide: Text.ElideRight;
font: UM.Theme.getFont("default");
text: job ? job.owner : "";
visible: job;
}
}
}

View file

@ -1,241 +0,0 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick.Dialogs 1.1
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.3
import QtGraphicalEffects 1.0
import UM 1.3 as UM
Item {
id: root;
property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width;
property var shadowOffset: UM.Theme.getSize("monitor_shadow_offset").width;
property var printer: null;
property var collapsed: true;
height: childrenRect.height + shadowRadius * 2; // Bubbles upward
width: parent.width; // Bubbles downward
// The actual card (white block)
Rectangle {
// 5px margin, but shifted 2px vertically because of the shadow
anchors {
bottomMargin: root.shadowRadius + root.shadowOffset;
leftMargin: root.shadowRadius;
rightMargin: root.shadowRadius;
topMargin: root.shadowRadius - root.shadowOffset;
}
color: {
if (!printer) {
return UM.Theme.getColor("monitor_card_background_inactive");
}
if (printer.state == "disabled") {
return UM.Theme.getColor("monitor_card_background_inactive");
} else {
return UM.Theme.getColor("monitor_card_background");
}
}
height: childrenRect.height;
layer.effect: DropShadow {
radius: root.shadowRadius;
verticalOffset: root.shadowOffset;
color: "#3F000000"; // 25% shadow
}
layer.enabled: true
width: parent.width - 2 * shadowRadius;
Column {
id: cardContents;
height: childrenRect.height;
width: parent.width;
// Main card
Item {
id: mainCard;
anchors {
left: parent.left;
leftMargin: UM.Theme.getSize("default_margin").width;
right: parent.right;
rightMargin: UM.Theme.getSize("default_margin").width;
}
height: 60 * screenScaleFactor + 2 * UM.Theme.getSize("default_margin").height;
width: parent.width;
// Machine icon
Item {
id: machineIcon;
anchors.verticalCenter: parent.verticalCenter;
height: parent.height - 2 * UM.Theme.getSize("default_margin").width;
width: height;
// Skeleton
Rectangle {
anchors.fill: parent;
color: UM.Theme.getColor("monitor_skeleton_fill_dark");
radius: UM.Theme.getSize("default_margin").width;
visible: !printer;
}
// Content
UM.RecolorImage {
anchors.centerIn: parent;
color: {
if (printer && printer.activePrintJob != undefined) {
return UM.Theme.getColor("monitor_printer_icon");
}
return UM.Theme.getColor("monitor_printer_icon_inactive");
}
height: sourceSize.height;
source: {
if (!printer) {
return "";
}
switch(printer.type) {
case "Ultimaker 3":
return "../svg/UM3-icon.svg";
case "Ultimaker 3 Extended":
return "../svg/UM3x-icon.svg";
case "Ultimaker S5":
return "../svg/UMs5-icon.svg";
}
}
visible: printer;
width: sourceSize.width;
}
}
// Printer info
Item {
id: printerInfo;
anchors {
left: machineIcon.right;
leftMargin: UM.Theme.getSize("wide_margin").width;
right: collapseIcon.left;
verticalCenter: machineIcon.verticalCenter;
}
height: childrenRect.height;
// Machine name
Item {
id: machineNameLabel;
height: UM.Theme.getSize("monitor_text_line").height;
width: {
var percent = printer ? 0.75 : 0.3;
return Math.round(parent.width * percent);
}
// Skeleton
Rectangle {
anchors.fill: parent;
color: UM.Theme.getColor("monitor_skeleton_fill_dark");
visible: !printer;
}
// Actual content
Label {
anchors.fill: parent;
color: UM.Theme.getColor("text");
elide: Text.ElideRight;
font: UM.Theme.getFont("default_bold");
text: printer ? printer.name : "";
visible: printer;
width: parent.width;
}
}
// Job name
Item {
id: activeJobLabel;
anchors {
top: machineNameLabel.bottom;
topMargin: Math.round(UM.Theme.getSize("default_margin").height / 2);
}
height: UM.Theme.getSize("monitor_text_line").height;
width: Math.round(parent.width * 0.75);
// Skeleton
Rectangle {
anchors.fill: parent;
color: UM.Theme.getColor("monitor_skeleton_fill_dark");
visible: !printer;
}
// Actual content
Label {
anchors.fill: parent;
color: UM.Theme.getColor("monitor_text_inactive");
elide: Text.ElideRight;
font: UM.Theme.getFont("default");
text: {
if (!printer) {
return "";
}
if (printer.state == "disabled") {
return catalog.i18nc("@label", "Not available");
} else if (printer.state == "unreachable") {
return catalog.i18nc("@label", "Unreachable");
}
if (printer.activePrintJob != null && printer.activePrintJob.name) {
return printer.activePrintJob.name;
}
return catalog.i18nc("@label", "Available");
}
visible: printer;
}
}
}
// Collapse icon
UM.RecolorImage {
id: collapseIcon;
anchors {
right: parent.right;
rightMargin: UM.Theme.getSize("default_margin").width;
verticalCenter: parent.verticalCenter;
}
color: UM.Theme.getColor("text");
height: 15 * screenScaleFactor; // TODO: Theme!
source: root.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom");
sourceSize {
height: height;
width: width;
}
visible: printer;
width: 15 * screenScaleFactor; // TODO: Theme!
}
MouseArea {
anchors.fill: parent;
enabled: printer;
onClicked: {
if (model && root.collapsed) {
printerList.currentIndex = model.index;
} else {
printerList.currentIndex = -1;
}
}
}
Connections {
target: printerList;
onCurrentIndexChanged: {
root.collapsed = printerList.currentIndex != model.index;
}
}
}
// Detailed card
PrinterCardDetails {
collapsed: root.collapsed;
printer: root.printer;
visible: root.printer;
}
// Progress bar
PrinterCardProgressBar {
visible: printer && printer.activePrintJob != null;
width: parent.width;
}
}
}
}

View file

@ -1,75 +0,0 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick.Dialogs 1.1
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.3
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.4 as LegacyControls
import UM 1.3 as UM
Item {
id: root;
property var printer: null;
property var printJob: printer ? printer.activePrintJob : null;
property var collapsed: true;
Behavior on height { NumberAnimation { duration: 100 } }
Behavior on opacity { NumberAnimation { duration: 100 } }
height: collapsed ? 0 : childrenRect.height;
opacity: collapsed ? 0 : 1;
width: parent.width;
Column {
id: contentColumn;
anchors {
left: parent.left;
leftMargin: UM.Theme.getSize("default_margin").width;
right: parent.right;
rightMargin: UM.Theme.getSize("default_margin").width;
}
height: childrenRect.height + UM.Theme.getSize("default_margin").height;
spacing: UM.Theme.getSize("default_margin").height;
width: parent.width;
HorizontalLine {}
PrinterInfoBlock {
printer: root.printer;
printJob: root.printer ? root.printer.activePrintJob : null;
}
HorizontalLine {}
Row {
height: childrenRect.height;
visible: root.printJob;
width: parent.width;
PrintJobTitle {
job: root.printer ? root.printer.activePrintJob : null;
}
PrintJobContextMenu {
id: contextButton;
anchors {
right: parent.right;
rightMargin: UM.Theme.getSize("wide_margin").width;
}
printJob: root.printer ? root.printer.activePrintJob : null;
visible: printJob;
}
}
PrintJobPreview {
anchors.horizontalCenter: parent.horizontalCenter;
job: root.printer && root.printer.activePrintJob ? root.printer.activePrintJob : null;
visible: root.printJob;
}
CameraButton {
id: showCameraButton;
iconSource: "../svg/camera-icon.svg";
visible: root.printer;
}
}
}

View file

@ -1,108 +0,0 @@
// 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
ProgressBar {
property var progress: {
if (!printer || printer.activePrintJob == null) {
return 0;
}
var result = printer.activePrintJob.timeElapsed / printer.activePrintJob.timeTotal;
if (result > 1.0) {
result = 1.0;
}
return result;
}
style: ProgressBarStyle {
property var remainingTime: {
if (!printer || printer.activePrintJob == null) {
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 (printer === null ) {
return "";
}
switch (printer.activePrintJob.state) {
case "wait_cleanup":
if (printer.activePrintJob.timeTotal > printer.activePrintJob.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 );
}
}
background: Rectangle {
color: UM.Theme.getColor("monitor_progress_background");
implicitHeight: visible ? 24 : 0;
implicitWidth: 100;
}
progress: Rectangle {
id: progressItem;
color: {
if (! printer || !printer.activePrintJob) {
return "black";
}
var state = printer.activePrintJob.state
var inactiveStates = [
"pausing",
"paused",
"resuming",
"wait_cleanup"
];
if (inactiveStates.indexOf(state) > -1 && remainingTime > 0) {
return UM.Theme.getColor("monitor_progress_fill_inactive");
} else {
return UM.Theme.getColor("monitor_progress_fill");
}
}
Label {
id: progressLabel;
anchors {
left: parent.left;
leftMargin: getTextOffset();
}
text: progressText;
anchors.verticalCenter: parent.verticalCenter;
color: progressItem.width + progressLabel.width < control.width ? UM.Theme.getColor("text") : UM.Theme.getColor("monitor_progress_fill_text");
width: contentWidth;
font: UM.Theme.getFont("default");
}
function getTextOffset() {
if (progressItem.width + progressLabel.width + 16 < control.width) {
return progressItem.width + UM.Theme.getSize("default_margin").width;
} else {
return progressItem.width - progressLabel.width - UM.Theme.getSize("default_margin").width;
}
}
}
}
value: progress;
width: parent.width;
}

View file

@ -1,32 +0,0 @@
// 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.4
import UM 1.2 as UM
Item {
property alias text: familyNameLabel.text;
property var padding: 3 * screenScaleFactor; // TODO: Theme!
implicitHeight: familyNameLabel.contentHeight + 2 * padding; // Apply the padding to top and bottom.
implicitWidth: Math.max(48 * screenScaleFactor, familyNameLabel.contentWidth + implicitHeight); // The extra height is added to ensure the radius doesn't cut something off.
Rectangle {
id: background;
anchors {
horizontalCenter: parent.horizontalCenter;
right: parent.right;
}
color: familyNameLabel.text.length < 1 ? UM.Theme.getColor("monitor_skeleton_fill") : UM.Theme.getColor("monitor_pill_background");
height: parent.height;
radius: 0.5 * height;
width: parent.width;
}
Label {
id: familyNameLabel;
anchors.centerIn: parent;
color: UM.Theme.getColor("text");
text: "";
}
}

View file

@ -1,83 +0,0 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick.Dialogs 1.1
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.3
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.4 as LegacyControls
import UM 1.3 as UM
// Includes printer type pill and extuder configurations
Item {
id: root;
property var printer: null;
property var printJob: null;
width: parent.width;
height: childrenRect.height;
// Printer family pills
Row {
id: printerFamilyPills;
anchors {
left: parent.left;
right: parent.right;
}
height: childrenRect.height;
spacing: Math.round(0.5 * UM.Theme.getSize("default_margin").width);
width: parent.width;
Repeater {
id: compatiblePills;
delegate: PrinterFamilyPill {
text: modelData;
}
model: printJob ? printJob.compatibleMachineFamilies : [];
visible: printJob;
}
PrinterFamilyPill {
text: printer ? printer.type : "";
visible: !compatiblePills.visible && printer;
}
}
// Extruder info
Row {
id: extrudersInfo;
anchors {
left: parent.left;
right: parent.right;
rightMargin: UM.Theme.getSize("default_margin").width;
top: printerFamilyPills.bottom;
topMargin: UM.Theme.getSize("default_margin").height;
}
height: childrenRect.height;
spacing: UM.Theme.getSize("default_margin").width;
width: parent.width;
PrintCoreConfiguration {
width: Math.round(parent.width / 2) * screenScaleFactor;
printCoreConfiguration: getExtruderConfig(0);
}
PrintCoreConfiguration {
width: Math.round(parent.width / 2) * screenScaleFactor;
printCoreConfiguration: getExtruderConfig(1);
}
}
function getExtruderConfig( i ) {
if (root.printJob) {
// Use more-specific print job if possible
return root.printJob.configuration.extruderConfigurations[i];
}
if (root.printer) {
return root.printer.printerConfiguration.extruderConfigurations[i];
}
return null;
}
}

View file

@ -29,7 +29,7 @@ Item {
Button {
height: UM.Theme.getSize("save_button_save_to_button").height;
onClicked: Cura.MachineManager.printerOutputDevices[0].requestAuthentication();
style: UM.Theme.styles.sidebar_action_button;
style: UM.Theme.styles.print_setup_action_button;
text: catalog.i18nc("@action:button", "Request Access");
tooltip: catalog.i18nc("@info:tooltip", "Send access request to the printer");
visible: printerConnected && !printerAcceptsCommands && !authenticationRequested;
@ -38,7 +38,7 @@ Item {
Button {
height: UM.Theme.getSize("save_button_save_to_button").height;
onClicked: connectActionDialog.show();
style: UM.Theme.styles.sidebar_action_button;
style: UM.Theme.styles.print_setup_action_button;
text: catalog.i18nc("@action:button", "Connect");
tooltip: catalog.i18nc("@info:tooltip", "Connect to a printer");
visible: !printerConnected;

View file

@ -64,7 +64,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
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/MonitorStage.qml")
# See comments about this hack with the clusterPrintersChanged signal
self.printersChanged.connect(self.clusterPrintersChanged)
@ -607,12 +607,19 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
def _createMaterialOutputModel(self, material_data: Dict[str, Any]) -> "MaterialOutputModel":
material_manager = CuraApplication.getInstance().getMaterialManager()
material_group_list = material_manager.getMaterialGroupListByGUID(material_data["guid"])
material_group_list = None
# Avoid crashing if there is no "guid" field in the metadata
material_guid = material_data.get("guid")
if material_guid:
material_group_list = material_manager.getMaterialGroupListByGUID(material_guid)
# This can happen if the connected machine has no material in one or more extruders (if GUID is empty), or the
# material is unknown to Cura, so we should return an "empty" or "unknown" material model.
if material_group_list is None:
material_name = "Empty" if len(material_data["guid"]) == 0 else "Unknown"
return MaterialOutputModel(guid = material_data["guid"],
material_name = i18n_catalog.i18nc("@label:material", "Empty") if len(material_data.get("guid", "")) == 0 \
else i18n_catalog.i18nc("@label:material", "Unknown")
return MaterialOutputModel(guid = material_data.get("guid", ""),
type = material_data.get("type", ""),
color = material_data.get("color", ""),
brand = material_data.get("brand", ""),
@ -643,9 +650,10 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
color = material_data["color"]
brand = material_data["brand"]
material_type = material_data["material"]
name = "Empty" if material_data["material"] == "empty" else "Unknown"
return MaterialOutputModel(guid=material_data["guid"], type=material_type,
brand=brand, color=color, name=name)
name = i18n_catalog.i18nc("@label:material", "Empty") if material_data["material"] == "empty" \
else i18n_catalog.i18nc("@label:material", "Unknown")
return MaterialOutputModel(guid = material_data["guid"], type = material_type,
brand = brand, color = color, name = name)
def _updatePrinter(self, printer: PrinterOutputModel, data: Dict[str, Any]) -> None:
# For some unknown reason the cluster wants UUID for everything, except for sending a job directly to a printer.

View file

@ -13,8 +13,8 @@ Column
property var loggedIn: false
property var profileImage: ""
padding: 2 * UM.Theme.getSize("default_margin").height
spacing: 2 * UM.Theme.getSize("default_margin").height
padding: UM.Theme.getSize("wide_margin").height
spacing: UM.Theme.getSize("wide_margin").height
AvatarImage
{

View file

@ -3,17 +3,17 @@
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtGraphicalEffects 1.0 // For the dropshadow
import UM 1.1 as UM
import Cura 1.0 as Cura
Button
{
id: button
property alias iconSource: buttonIconLeft.source
property bool isIconOnRightSide: false
property alias iconSource: buttonIconLeft.source
property alias textFont: buttonText.font
property alias cornerRadius: backgroundRect.radius
property alias tooltip: tooltip.text
@ -28,9 +28,6 @@ Button
property color outlineColor: color
property color outlineHoverColor: hoverColor
property color outlineDisabledColor: outlineColor
hoverEnabled: true
property alias shadowColor: shadow.color
property alias shadowEnabled: shadow.visible
@ -42,6 +39,7 @@ Button
leftPadding: UM.Theme.getSize("default_margin").width
rightPadding: UM.Theme.getSize("default_margin").width
height: UM.Theme.getSize("action_button").height
hoverEnabled: true
contentItem: Row
{
@ -52,6 +50,8 @@ Button
source: ""
height: buttonText.height
width: visible ? height : 0
sourceSize.width: width
sourceSize.height: height
color: button.hovered ? button.textHoverColor : button.textColor
visible: source != "" && !button.isIconOnRightSide
anchors.verticalCenter: parent.verticalCenter
@ -78,6 +78,8 @@ Button
source: buttonIconLeft.source
height: buttonText.height
width: visible ? height : 0
sourceSize.width: width
sourceSize.height: height
color: buttonIconLeft.color
visible: source != "" && button.isIconOnRightSide
anchors.verticalCenter: buttonIconLeft.verticalCenter

View file

@ -55,7 +55,7 @@ Item
leftPadding: UM.Theme.getSize("narrow_margin").width //Need more space than usual here for wide text.
rightPadding: UM.Theme.getSize("narrow_margin").width
tooltip: catalog.i18nc("@info:tooltip", "Select the active output device")
tooltip: popup.opened ? "" : 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)

View file

@ -44,7 +44,7 @@ Column
rightMargin: UM.Theme.getSize("thin_margin").height
}
Cura.IconLabel
Cura.IconWithText
{
id: estimatedTime
width: parent.width
@ -54,7 +54,7 @@ Column
font: UM.Theme.getFont("default_bold")
}
Cura.IconLabel
Cura.IconWithText
{
id: estimatedCosts
width: parent.width
@ -84,7 +84,6 @@ Column
return totalWeights + "g · " + totalLengths.toFixed(2) + "m"
}
source: UM.Theme.getIcon("spool")
font: UM.Theme.getFont("default")
}
}

View file

@ -52,7 +52,7 @@ Column
renderType: Text.NativeRendering
}
Cura.IconLabel
Cura.IconWithText
{
id: unableToSliceMessage
width: parent.width
@ -61,7 +61,6 @@ Column
text: catalog.i18nc("@label:PrintjobStatus", "Unable to Slice")
source: UM.Theme.getIcon("warning")
color: UM.Theme.getColor("warning")
font: UM.Theme.getFont("default")
}
// Progress bar, only visible when the backend is in the process of slice the printjob

View file

@ -88,7 +88,7 @@ UM.MainWindow
window: base
}
Rectangle
Item
{
id: headerBackground
anchors
@ -123,17 +123,6 @@ UM.MainWindow
}
}
}
// This is the new fancy pattern
Image
{
id: backgroundPattern
anchors.fill: parent
fillMode: Image.Tile
source: UM.Theme.getImage("header_pattern")
horizontalAlignment: Image.AlignLeft
verticalAlignment: Image.AlignTop
}
}
MainWindowHeader
@ -192,23 +181,6 @@ UM.MainWindow
}
}
Connections
{
target: stageMenu.item
onShowTooltip: base.showTooltip(item, location, text)
onHideTooltip: base.hideTooltip()
}
JobSpecs
{
id: jobSpecs
anchors
{
bottom: parent.bottom
bottomMargin: UM.Theme.getSize("default_margin").height
}
}
Toolbar
{
// The toolbar is the left bar that is populated by all the tools (which are dynamicly populated by
@ -238,6 +210,19 @@ UM.MainWindow
}
}
JobSpecs
{
id: jobSpecs
visible: CuraApplication.platformActivity
anchors
{
left: parent.left
bottom: viewOrientationControls.top
margins: UM.Theme.getSize("default_margin").width
bottomMargin: UM.Theme.getSize("thin_margin").width
}
}
ViewOrientationControls
{
id: viewOrientationControls
@ -245,9 +230,8 @@ UM.MainWindow
anchors
{
left: parent.left
margins: UM.Theme.getSize("default_margin").width
bottom: parent.bottom
margins: UM.Theme.getSize("default_margin").width
}
}
@ -298,8 +282,6 @@ UM.MainWindow
// Every time the stage is changed.
property var printSetupSelector: Cura.PrintSetupSelector
{
onShowTooltip: base.showTooltip(item, location, text)
onHideTooltip: base.hideTooltip()
width: UM.Theme.getSize("print_setup_widget").width
height: UM.Theme.getSize("stage_menu").height
headerCornerSide: RoundedRectangle.Direction.Right
@ -318,7 +300,7 @@ UM.MainWindow
}
}
SidebarTooltip
PrintSetupTooltip
{
id: tooltip
}

View file

@ -11,6 +11,7 @@ import Cura 1.0 as Cura
UM.Dialog
{
id: base
title: catalog.i18nc("@title:window", "Save Project")
minimumWidth: 500 * screenScaleFactor
@ -49,7 +50,7 @@ UM.Dialog
UM.SettingDefinitionsModel
{
id: definitionsModel
containerId: Cura.MachineManager.activeDefinitionId
containerId: base.visible ? Cura.MachineManager.activeDefinitionId: ""
showAll: true
exclude: ["command_line_settings"]
showAncestors: true

View file

@ -1,3 +1,6 @@
// 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
@ -6,16 +9,15 @@ import Cura 1.0 as Cura
import QtGraphicalEffects 1.0 // For the dropshadow
// The expandable component has 3 major sub components:
// The expandable component has 2 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.
// * The contentItem; The content that needs to be shown if the component is expanded.
Item
{
id: base
// Enumeration with the different possible alignments of the popup with respect of the headerItem
enum PopupAlignment
// Enumeration with the different possible alignments of the content with respect of the headerItem
enum ContentAlignment
{
AlignLeft,
AlignRight
@ -24,21 +26,31 @@ Item
// 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
// The contentItem holds the QML item that is shown when the "open" button is pressed
property alias contentItem: content.contentItem
property color popupBackgroundColor: UM.Theme.getColor("action_button")
property color contentBackgroundColor: UM.Theme.getColor("action_button")
property color headerBackgroundColor: UM.Theme.getColor("action_button")
property color headerActiveColor: UM.Theme.getColor("secondary")
property color headerHoverColor: UM.Theme.getColor("action_button_hovered")
property alias enabled: mouseArea.enabled
// Defines the alignment of the popup with respect of the headerItem, by default to the right
property int popupAlignment: ExpandableComponent.PopupAlignment.AlignRight
// Text to show when this component is disabled
property alias disabledText: disabledLabel.text
// How much spacing is needed around the popupItem
property alias popupPadding: popup.padding
// Defines the alignment of the content with respect of the headerItem, by default to the right
property int contentAlignment: ExpandableComponent.ContentAlignment.AlignRight
// How much spacing is needed around the contentItem
property alias contentPadding: content.padding
// Adds a title to the content item
property alias contentHeaderTitle: contentHeader.headerTitle
// How much spacing is needed for the contentItem by Y coordinate
property var contentSpacingY: UM.Theme.getSize("narrow_margin").width
// How much padding is needed around the header & button
property alias headerPadding: background.padding
@ -52,9 +64,7 @@ Item
property alias iconSize: collapseButton.height
// Is the "drawer" open?
readonly property alias expanded: popup.visible
property alias expandedHighlightColor: expandedHighlight.color
readonly property alias expanded: contentContainer.visible
// What should the radius of the header be. This is also influenced by the headerCornerSide
property alias headerRadius: background.radius
@ -68,33 +78,33 @@ Item
property int shadowOffset: 2
function togglePopup()
function toggleContent()
{
if(popup.visible)
{
popup.close()
contentContainer.visible = !expanded
}
else
// Add this binding since the background color is not updated otherwise
Binding
{
popup.open()
target: background
property: "color"
value:
{
return base.enabled ? (expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled")
}
}
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
}
// The panel needs to close when it becomes disabled
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
target: base
onEnabledChanged:
{
if (!base.enabled && expanded)
{
toggleContent()
}
}
}
implicitHeight: 100 * screenScaleFactor
@ -105,9 +115,29 @@ Item
id: background
property real padding: UM.Theme.getSize("default_margin").width
color: headerBackgroundColor
color: base.enabled ? (base.expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled")
anchors.fill: parent
Label
{
id: disabledLabel
visible: !base.enabled
anchors.fill: parent
leftPadding: background.padding
rightPadding: background.padding
text: ""
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter
color: UM.Theme.getColor("text")
wrapMode: Text.WordWrap
}
Item
{
anchors.fill: parent
visible: base.enabled
Loader
{
id: headerItemLoader
@ -121,17 +151,6 @@ Item
}
}
// 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
@ -141,22 +160,25 @@ Item
verticalCenter: parent.verticalCenter
margins: background.padding
}
visible: source != "" && base.enabled
width: height
height: Math.round(0.2 * base.height)
color: UM.Theme.getColor("text")
source: UM.Theme.getIcon("pencil")
visible: source != ""
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
color: UM.Theme.getColor("small_button_text")
}
}
MouseArea
{
id: mouseArea
anchors.fill: parent
onClicked: togglePopup()
onClicked: toggleContent()
hoverEnabled: true
onEntered: background.color = headerHoverColor
onExited: background.color = headerBackgroundColor
onExited: background.color = base.enabled ? (base.expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled")
}
}
DropShadow
{
id: shadow
@ -171,26 +193,70 @@ Item
z: background.z - 1
}
Popup
Cura.RoundedRectangle
{
id: popup
id: contentContainer
// Ensure that the popup is located directly below the headerItem
y: headerItemLoader.height + 2 * background.padding + base.shadowOffset
visible: false
width: childrenRect.width
height: childrenRect.height
// Make the popup aligned with the rest, using the property popupAlignment to decide whether is right or left.
// Ensure that the content is located directly below the headerItem
y: background.height + base.shadowOffset + base.contentSpacingY
// Make the content aligned with the rest, using the property contentAlignment 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
x: contentAlignment == ExpandableComponent.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0
background: Cura.RoundedRectangle
{
cornerSide: Cura.RoundedRectangle.Direction.Down
color: popupBackgroundColor
cornerSide: Cura.RoundedRectangle.Direction.All
color: contentBackgroundColor
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
radius: UM.Theme.getSize("default_radius").width
ExpandableComponentHeader
{
id: contentHeader
headerTitle: ""
anchors
{
top: parent.top
right: parent.right
left: parent.left
}
}
Control
{
id: content
anchors.top: contentHeader.bottom
padding: UM.Theme.getSize("default_margin").width
contentItem: Item {}
onContentItemChanged:
{
// Since we want the size of the content to be set by the size of the content,
// we need to do it like this.
content.width = contentItem.width + 2 * content.padding
content.height = contentItem.height + 2 * content.padding
}
}
}
// DO NOT MOVE UP IN THE CODE: This connection has to be here, after the definition of the content item.
// Apparently the order in which these are handled matters and so the height is correctly updated if this is here.
Connections
{
// Since it could be that the content is dynamically populated, we should also take these changes into account.
target: content.contentItem
onWidthChanged: content.width = content.contentItem.width + 2 * content.padding
onHeightChanged:
{
content.height = content.contentItem.height + 2 * content.padding
contentContainer.height = contentHeader.height + content.height
}
}
}

View file

@ -0,0 +1,68 @@
// 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.2 as UM
import Cura 1.0 as Cura
// Header of the popup
Cura.RoundedRectangle
{
id: header
property alias headerTitle: headerLabel.text
height: UM.Theme.getSize("expandable_component_content_header").height
color: UM.Theme.getColor("secondary")
cornerSide: Cura.RoundedRectangle.Direction.Up
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
radius: UM.Theme.getSize("default_radius").width
Label
{
id: headerLabel
text: ""
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter
color: UM.Theme.getColor("small_button_text")
height: parent.height
anchors
{
topMargin: UM.Theme.getSize("default_margin").height
left: parent.left
leftMargin: UM.Theme.getSize("default_margin").height
}
}
Button
{
id: closeButton
width: UM.Theme.getSize("message_close").width
height: UM.Theme.getSize("message_close").height
hoverEnabled: true
anchors
{
right: parent.right
rightMargin: UM.Theme.getSize("default_margin").width
verticalCenter: parent.verticalCenter
}
contentItem: UM.RecolorImage
{
anchors.fill: parent
sourceSize.width: width
color: closeButton.hovered ? UM.Theme.getColor("small_button_text_hover") : UM.Theme.getColor("small_button_text")
source: UM.Theme.getIcon("cross1")
}
background: Item {}
onClicked: toggleContent() // Will hide the popup item
}
}

View file

@ -0,0 +1,250 @@
// 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.2 as UM
import Cura 1.0 as Cura
import QtGraphicalEffects 1.0 // For the dropshadow
// The expandable component has 2 major sub components:
// * The headerItem; Always visible and should hold some info about what happens if the component is expanded
// * The contentItem; The content that needs to be shown if the component is expanded.
Item
{
id: base
// Enumeration with the different possible alignments of the content with respect of the headerItem
enum ContentAlignment
{
AlignLeft,
AlignRight
}
// The headerItem holds the QML item that is always displayed.
property alias headerItem: headerItemLoader.sourceComponent
// The contentItem holds the QML item that is shown when the "open" button is pressed
property alias contentItem: content.contentItem
property color contentBackgroundColor: UM.Theme.getColor("action_button")
property color headerBackgroundColor: UM.Theme.getColor("action_button")
property color headerActiveColor: UM.Theme.getColor("secondary")
property color headerHoverColor: UM.Theme.getColor("action_button_hovered")
property alias enabled: mouseArea.enabled
// Text to show when this component is disabled
property alias disabledText: disabledLabel.text
// Defines the alignment of the content with respect of the headerItem, by default to the right
property int contentAlignment: ExpandablePopup.ContentAlignment.AlignRight
// How much spacing is needed around the contentItem
property alias contentPadding: content.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: content.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
// Change the contentItem close behaviour
property alias contentClosePolicy : content.closePolicy
property alias headerShadowColor: shadow.color
property alias enableHeaderShadow: shadow.visible
property int shadowOffset: 2
function toggleContent()
{
if (content.visible)
{
content.close()
}
else
{
content.open()
}
}
// Add this binding since the background color is not updated otherwise
Binding
{
target: background
property: "color"
value: base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
}
// The panel needs to close when it becomes disabled
Connections
{
target: base
onEnabledChanged:
{
if (!base.enabled && expanded)
{
toggleContent()
}
}
}
implicitHeight: 100 * screenScaleFactor
implicitWidth: 400 * screenScaleFactor
RoundedRectangle
{
id: background
property real padding: UM.Theme.getSize("default_margin").width
color: base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
anchors.fill: parent
Label
{
id: disabledLabel
visible: !base.enabled
leftPadding: background.padding
text: ""
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter
color: UM.Theme.getColor("text")
height: parent.height
}
Item
{
anchors.fill: parent
visible: base.enabled
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 content 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
}
source: expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left")
visible: source != ""
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
color: UM.Theme.getColor("small_button_text")
}
}
MouseArea
{
id: mouseArea
anchors.fill: parent
onClicked: toggleContent()
hoverEnabled: true
onEntered: background.color = headerHoverColor
onExited: background.color = base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
}
}
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: content
// Ensure that the content is located directly below the headerItem
y: background.height + base.shadowOffset
// Make the content aligned with the rest, using the property contentAlignment 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: contentAlignment == ExpandablePopup.ContentAlignment.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: contentBackgroundColor
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
radius: UM.Theme.getSize("default_radius").width
}
contentItem: Item {}
onContentItemChanged:
{
// Since we want the size of the content to be set by the size of the content,
// we need to do it like this.
content.width = contentItem.width + 2 * content.padding
content.height = contentItem.height + 2 * content.padding
}
}
// DO NOT MOVE UP IN THE CODE: This connection has to be here, after the definition of the content item.
// Apparently the order in which these are handled matters and so the height is correctly updated if this is here.
Connections
{
// Since it could be that the content is dynamically populated, we should also take these changes into account.
target: content.contentItem
onWidthChanged: content.width = content.contentItem.width + 2 * content.padding
onHeightChanged: content.height = content.contentItem.height + 2 * content.padding
}
}

View file

@ -23,7 +23,7 @@ Item
anchors.fill: parent
source: UM.Theme.getIcon("extruder_button")
color: extruderEnabled ? materialColor: "gray"
color: extruderEnabled ? materialColor: UM.Theme.getColor("disabled")
}
Rectangle

View file

@ -1,51 +0,0 @@
// 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
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("default")
renderType: Text.NativeRendering
}
}

View file

@ -13,9 +13,11 @@ import Cura 1.0 as Cura
// 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 iconSize: icon.width
property alias color: label.color
property alias text: label.text
property alias font: label.font
property real margin: UM.Theme.getSize("narrow_margin").width
@ -37,7 +39,7 @@ Item
width: UM.Theme.getSize("section_icon").width
height: UM.Theme.getSize("section_icon").height
color: "black"
color: label.color
anchors
{

View file

@ -9,60 +9,64 @@ import QtQuick.Layouts 1.1
import UM 1.1 as UM
import Cura 1.0 as Cura
Item {
Item
{
id: base
property bool activity: CuraApplication.platformActivity
property string fileBaseName: PrintInformation.baseName
UM.I18nCatalog { id: catalog; name: "cura"}
UM.I18nCatalog
{
id: catalog
name: "cura"
}
width: childrenRect.width
height: childrenRect.height
onActivityChanged: {
if (activity == false) {
//When there is no mesh in the buildplate; the printJobTextField is set to an empty string so it doesn't set an empty string as a jobName (which is later used for saving the file)
PrintInformation.baseName = ''
}
}
Rectangle
onActivityChanged:
{
id: jobNameRow
anchors.top: parent.top
anchors.right: parent.right
height: UM.Theme.getSize("jobspecs_line").height
visible: base.activity
if (!activity)
{
//When there is no mesh in the buildplate; the printJobTextField is set to an empty string so it doesn't set an empty string as a jobName (which is later used for saving the file)
PrintInformation.baseName = ""
}
}
Item
{
width: parent.width
height: parent.height
id: jobNameRow
anchors.top: parent.top
anchors.left: parent.left
height: UM.Theme.getSize("jobspecs_line").height
Button
{
id: printJobPencilIcon
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: UM.Theme.getSize("save_button_specs_icons").width
height: UM.Theme.getSize("save_button_specs_icons").height
onClicked:
{
printJobTextfield.selectAll();
printJobTextfield.focus = true;
printJobTextfield.selectAll()
printJobTextfield.focus = true
}
style: ButtonStyle
{
background: Item
{
UM.RecolorImage
{
width: UM.Theme.getSize("save_button_specs_icons").width;
height: UM.Theme.getSize("save_button_specs_icons").height;
sourceSize.height: width;
color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene");
source: UM.Theme.getIcon("pencil");
width: UM.Theme.getSize("save_button_specs_icons").width
height: UM.Theme.getSize("save_button_specs_icons").height
sourceSize.width: width
sourceSize.height: width
color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene")
source: UM.Theme.getIcon("pencil")
}
}
}
@ -71,56 +75,44 @@ Item {
TextField
{
id: printJobTextfield
anchors.right: printJobPencilIcon.left
anchors.rightMargin: Math.round(UM.Theme.getSize("default_margin").width / 2)
anchors.left: printJobPencilIcon.right
anchors.leftMargin: UM.Theme.getSize("narrow_margin").width
height: UM.Theme.getSize("jobspecs_line").height
width: Math.max(__contentWidth + UM.Theme.getSize("default_margin").width, 50)
maximumLength: 120
property int unremovableSpacing: 5
text: PrintInformation.jobName
horizontalAlignment: TextInput.AlignRight
onEditingFinished: {
var new_name = text == "" ? catalog.i18nc("@text Print job name", "Untitled") : text;
PrintInformation.setJobName(new_name, true);
printJobTextfield.focus = false;
horizontalAlignment: TextInput.AlignLeft
onEditingFinished:
{
var new_name = text == "" ? catalog.i18nc("@text Print job name", "Untitled") : text
PrintInformation.setJobName(new_name, true)
printJobTextfield.focus = false
}
validator: RegExpValidator {
regExp: /^[^\\\/\*\?\|\[\]]*$/
}
style: TextFieldStyle{
textColor: UM.Theme.getColor("text_scene");
font: UM.Theme.getFont("default_bold");
background: Rectangle {
style: TextFieldStyle
{
textColor: UM.Theme.getColor("text_scene")
font: UM.Theme.getFont("default_bold")
background: Rectangle
{
opacity: 0
border.width: 0
}
}
}
}
}
Row {
id: additionalComponentsRow
anchors.top: jobNameRow.bottom
anchors.right: parent.right
}
Label
{
id: boundingSpec
anchors.top: jobNameRow.bottom
anchors.right: additionalComponentsRow.left
anchors.rightMargin:
{
if (additionalComponentsRow.width > 0)
{
return UM.Theme.getSize("default_margin").width
}
else
{
return 0;
}
}
anchors.left: parent.left
height: UM.Theme.getSize("jobspecs_line").height
verticalAlignment: Text.AlignVCenter
font: UM.Theme.getFont("default_bold")
@ -128,21 +120,34 @@ Item {
text: CuraApplication.getSceneBoundingBoxString
}
Component.onCompleted: {
Row
{
id: additionalComponentsRow
anchors.top: boundingSpec.top
anchors.bottom: boundingSpec.bottom
anchors.left: boundingSpec.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width
}
Component.onCompleted:
{
base.addAdditionalComponents("jobSpecsButton")
}
Connections {
Connections
{
target: CuraApplication
onAdditionalComponentsChanged: base.addAdditionalComponents("jobSpecsButton")
}
function addAdditionalComponents (areaId) {
if(areaId == "jobSpecsButton") {
for (var component in CuraApplication.additionalComponents["jobSpecsButton"]) {
function addAdditionalComponents(areaId)
{
if (areaId == "jobSpecsButton")
{
for (var component in CuraApplication.additionalComponents["jobSpecsButton"])
{
CuraApplication.additionalComponents["jobSpecsButton"][component].parent = additionalComponentsRow
}
}
}
}

View file

@ -29,7 +29,7 @@ Button
id: contentColumn
width: parent.width
padding: UM.Theme.getSize("wide_margin").width
spacing: Math.round(UM.Theme.getSize("default_margin").height / 2)
spacing: UM.Theme.getSize("narrow_margin").height
Row
{
@ -72,8 +72,8 @@ Button
right: parent.right
rightMargin: parent.padding
}
height: visible ? Math.round(UM.Theme.getSize("thick_lining").height / 2) : 0
color: UM.Theme.getColor("text")
height: visible ? Math.round(UM.Theme.getSize("default_lining").height / 2) : 0
color: UM.Theme.getColor("lining")
}
Item

View file

@ -12,7 +12,7 @@ Column
id: base
property var outputDevice: null
height: childrenRect.height + 2 * padding
spacing: Math.round(UM.Theme.getSize("default_margin").height / 2)
spacing: UM.Theme.getSize("narrow_margin").height
function forceModelUpdate()
{
@ -55,7 +55,7 @@ Column
ListView
{
id: configurationList
spacing: Math.round(UM.Theme.getSize("default_margin").height / 2)
spacing: UM.Theme.getSize("narrow_margin").height
width: container.width - ((height > container.maximumHeight) ? container.ScrollBar.vertical.background.width : 0) //Make room for scroll bar if there is any.
contentHeight: childrenRect.height
height: childrenRect.height
@ -64,11 +64,12 @@ Column
section.criteria: ViewSection.FullString
section.delegate: Item
{
height: printerTypeLabel.height + UM.Theme.getSize("default_margin").height
height: printerTypeLabel.height + UM.Theme.getSize("wide_margin").height //Causes a default margin above the label and a default margin below the label.
Cura.PrinterTypeLabel
{
id: printerTypeLabel
text: Cura.MachineManager.getAbbreviatedMachineName(section)
anchors.verticalCenter: parent.verticalCenter //One default margin above and one below.
}
}

View file

@ -13,7 +13,7 @@ import Cura 1.0 as Cura
* Menu that allows you to select the configuration of the current printer, such
* as the nozzle sizes and materials in each extruder.
*/
Cura.ExpandableComponent
Cura.ExpandablePopup
{
id: base
@ -30,14 +30,15 @@ Cura.ExpandableComponent
enum ConfigurationMethod
{
AUTO,
CUSTOM
Auto,
Custom
}
iconSource: expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left")
enabled: Cura.MachineManager.hasMaterials || Cura.MachineManager.hasVariants || Cura.MachineManager.hasVariantBuildplates; //Only let it drop down if there is any configuration that you could change.
headerItem: Item
{
// Horizontal list that shows the extruders
// Horizontal list that shows the extruders and their materials
ListView
{
id: extrudersList
@ -45,7 +46,7 @@ Cura.ExpandableComponent
orientation: ListView.Horizontal
anchors.fill: parent
model: extrudersModel
visible: base.enabled
visible: Cura.MachineManager.hasMaterials
delegate: Item
{
@ -102,26 +103,28 @@ Cura.ExpandableComponent
}
}
}
}
//Disable the menu if there are no materials, variants or build plates to change.
function updateEnabled()
//Placeholder text if there is a configuration to select but no materials (so we can't show the materials per extruder).
Label
{
var active_definition_id = Cura.MachineManager.activeMachine.definition.id;
var has_materials = Cura.ContainerManager.getContainerMetaDataEntry(active_definition_id, "has_materials");
var has_variants = Cura.ContainerManager.getContainerMetaDataEntry(active_definition_id, "has_variants");
var has_buildplates = Cura.ContainerManager.getContainerMetaDataEntry(active_definition_id, "has_variant_buildplates");
base.enabled = has_materials || has_variants || has_buildplates; //Only let it drop down if there is any configuration that you could change.
}
text: catalog.i18nc("@label", "Select configuration")
elide: Text.ElideRight
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
Connections
visible: !Cura.MachineManager.hasMaterials && (Cura.MachineManager.hasVariants || Cura.MachineManager.hasVariantBuildplates)
anchors
{
target: Cura.MachineManager
onGlobalContainerChanged: base.updateEnabled();
left: parent.left
leftMargin: UM.Theme.getSize("default_margin").width
verticalCenter: parent.verticalCenter
}
}
}
Component.onCompleted: updateEnabled();
popupItem: Column
contentItem: Column
{
id: popupItem
width: base.width - 2 * UM.Theme.getSize("default_margin").width
@ -134,22 +137,34 @@ Cura.ExpandableComponent
is_connected = Cura.MachineManager.activeMachineNetworkKey !== "" && Cura.MachineManager.printerConnected //Re-evaluate.
}
property int configuration_method: is_connected ? ConfigurationMenu.ConfigurationMethod.AUTO : ConfigurationMenu.ConfigurationMethod.CUSTOM //Auto if connected to a printer at start-up, or Custom if not.
property int configuration_method: is_connected ? ConfigurationMenu.ConfigurationMethod.Auto : ConfigurationMenu.ConfigurationMethod.Custom //Auto if connected to a printer at start-up, or Custom if not.
Item
{
width: parent.width
height: childrenRect.height
height:
{
var height = 0;
if(autoConfiguration.visible)
{
height += autoConfiguration.height;
}
if(customConfiguration.visible)
{
height += customConfiguration.height;
}
return height;
}
AutoConfiguration
{
id: autoConfiguration
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.AUTO
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto
}
CustomConfiguration
{
id: customConfiguration
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.CUSTOM
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Custom
}
}
@ -157,7 +172,7 @@ Cura.ExpandableComponent
{
id: separator
visible: buttonBar.visible
x: -popupPadding
x: -contentPadding
width: base.width
height: UM.Theme.getSize("default_lining").height
@ -177,7 +192,7 @@ Cura.ExpandableComponent
Cura.SecondaryButton
{
id: goToCustom
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.AUTO
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto
text: catalog.i18nc("@label", "Custom")
anchors.right: parent.right
@ -185,18 +200,18 @@ Cura.ExpandableComponent
iconSource: UM.Theme.getIcon("arrow_right")
isIconOnRightSide: true
onClicked: popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.CUSTOM
onClicked: popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.Custom
}
Cura.SecondaryButton
{
id: goToAuto
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.CUSTOM
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Custom
text: catalog.i18nc("@label", "Configurations")
iconSource: UM.Theme.getIcon("arrow_left")
onClicked: popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.AUTO
onClicked: popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.Auto
}
}
}

View file

@ -36,10 +36,57 @@ Item
}
}
//Printer type selector.
Item
{
id: printerTypeSelectorRow
visible:
{
return Cura.MachineManager.printerOutputDevices.length >= 1 //If connected...
&& Cura.MachineManager.printerOutputDevices[0].connectedPrintersTypeCount != null //...and we have configuration information...
&& Cura.MachineManager.printerOutputDevices[0].connectedPrintersTypeCount.length > 1; //...and there is more than one type of printer in the configuration list.
}
height: visible ? childrenRect.height : 0
anchors
{
left: parent.left
leftMargin: UM.Theme.getSize("default_margin").width
right: parent.right
rightMargin: UM.Theme.getSize("default_margin").width
top: header.bottom
topMargin: visible ? UM.Theme.getSize("default_margin").height : 0
}
Label
{
text: catalog.i18nc("@label", "Printer")
width: Math.round(parent.width * 0.3) - UM.Theme.getSize("default_margin").width
height: contentHeight
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
anchors.verticalCenter: printerTypeSelector.verticalCenter
anchors.left: parent.left
}
OldControls.ToolButton
{
id: printerTypeSelector
text: Cura.MachineManager.activeMachineDefinitionName
tooltip: Cura.MachineManager.activeMachineDefinitionName
height: UM.Theme.getSize("setting_control").height
width: Math.round(parent.width * 0.7) + UM.Theme.getSize("default_margin").width
anchors.right: parent.right
style: UM.Theme.styles.print_setup_header_button
menu: Cura.PrinterTypeMenu { }
}
}
UM.TabRow
{
id: tabBar
anchors.top: header.bottom
anchors.top: printerTypeSelectorRow.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
visible: extrudersModel.count > 1
@ -141,6 +188,7 @@ Item
Row
{
height: UM.Theme.getSize("print_setup_item").height
visible: extrudersModel.count > 1 // If there is only one extruder, there is no point to enable/disable that.
Label
{
@ -150,7 +198,6 @@ Item
color: UM.Theme.getColor("text")
height: parent.height
width: selectors.textWidth
visible: extrudersModel.count > 1
renderType: Text.NativeRendering
}
@ -160,7 +207,6 @@ Item
enabled: !checked || Cura.MachineManager.numberExtrudersEnabled > 1 //Disable if it's the last enabled extruder.
height: UM.Theme.getSize("setting_control").height
style: UM.Theme.styles.checkbox
visible: extrudersModel.count > 1
/* Use a MouseArea to process the click on this checkbox.
This is necessary because actually clicking the checkbox
@ -179,6 +225,8 @@ Item
Row
{
height: UM.Theme.getSize("print_setup_item").height
visible: Cura.MachineManager.hasMaterials
Label
{
text: catalog.i18nc("@label", "Material")
@ -187,7 +235,6 @@ Item
color: UM.Theme.getColor("text")
height: parent.height
width: selectors.textWidth
visible: materialSelection.visible
renderType: Text.NativeRendering
}
@ -200,12 +247,11 @@ Item
text: Cura.MachineManager.activeStack != null ? Cura.MachineManager.activeStack.material.name : ""
tooltip: text
visible: Cura.MachineManager.hasMaterials
height: UM.Theme.getSize("setting_control").height
width: selectors.controlWidth
style: UM.Theme.styles.sidebar_header_button
style: UM.Theme.styles.print_setup_header_button
activeFocusOnPress: true
menu: Cura.MaterialMenu
{
@ -217,6 +263,7 @@ Item
Row
{
height: UM.Theme.getSize("print_setup_item").height
visible: Cura.MachineManager.hasVariants
Label
{
@ -226,7 +273,6 @@ Item
color: UM.Theme.getColor("text")
height: parent.height
width: selectors.textWidth
visible: variantSelection.visible
renderType: Text.NativeRendering
}
@ -234,12 +280,11 @@ Item
{
id: variantSelection
text: Cura.MachineManager.activeVariantName
tooltip: Cura.MachineManager.activeVariantName;
visible: Cura.MachineManager.hasVariants
tooltip: Cura.MachineManager.activeVariantName
height: UM.Theme.getSize("setting_control").height
width: selectors.controlWidth
style: UM.Theme.styles.sidebar_header_button
style: UM.Theme.styles.print_setup_header_button
activeFocusOnPress: true;
menu: Cura.NozzleMenu { extruderIndex: Cura.ExtruderManager.activeExtruderIndex }

View file

@ -20,7 +20,7 @@ Row
{
materialColor: printCoreConfiguration.material.color
anchors.verticalCenter: parent.verticalCenter
extruderEnabled: printCoreConfiguration.material.name !== "" && printCoreConfiguration.hotendID !== ""
extruderEnabled: printCoreConfiguration.material.brand !== "" && printCoreConfiguration.hotendID !== ""
}
Column
@ -36,7 +36,7 @@ Row
}
Label
{
text: printCoreConfiguration.material.name ? printCoreConfiguration.material.name : " " //Use space so that the height is still correct.
text: printCoreConfiguration.material.brand ? printCoreConfiguration.material.name : " " //Use space so that the height is still correct.
renderType: Text.NativeRendering
elide: Text.ElideRight
font: UM.Theme.getFont("default")

View file

@ -16,10 +16,11 @@ Menu
Instantiator
{
model: Cura.ExtrudersModel { simpleNames: true }
model: Cura.MachineManager.activeMachine.extruderList
Menu
{
title: model.name
title: modelData.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 }

View file

@ -309,7 +309,7 @@ Item
}
}
style: UM.Theme.styles.sidebar_action_button
style: UM.Theme.styles.print_setup_action_button
}
Button
@ -325,7 +325,7 @@ Item
text: catalog.i18nc("@label", "Abort Print")
onClicked: confirmationDialog.visible = true
style: UM.Theme.styles.sidebar_action_button
style: UM.Theme.styles.print_setup_action_button
}
MessageDialog

View file

@ -173,7 +173,7 @@ Rectangle
anchors.bottom: parent.bottom
}
SidebarTooltip
PrintSetupTooltip
{
id: tooltip
}

View file

@ -224,7 +224,7 @@ Rectangle
{
id: arrangeAllBuildPlatesButton;
text: catalog.i18nc("@action:button","Arrange to all build plates");
style: UM.Theme.styles.sidebar_action_button
style: UM.Theme.styles.print_setup_action_button
height: UM.Theme.getSize("objects_menu_button").height;
tooltip: '';
anchors
@ -244,7 +244,7 @@ Rectangle
{
id: arrangeBuildPlateButton;
text: catalog.i18nc("@action:button","Arrange current build plate");
style: UM.Theme.styles.sidebar_action_button
style: UM.Theme.styles.print_setup_action_button
height: UM.Theme.getSize("objects_menu_button").height;
tooltip: '';
anchors

View file

@ -49,7 +49,7 @@ Rectangle
property var activePrinter: connectedDevice != null ? connectedDevice.activePrinter : null
property var activePrintJob: activePrinter != null ? activePrinter.activePrintJob: null
SidebarTooltip
PrintSetupTooltip
{
id: tooltip
}

View file

@ -1,261 +0,0 @@
// 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
import "Menus"
import "Menus/ConfigurationMenu"
Cura.ExpandableComponent
{
id: base
property int currentModeIndex: -1
property bool hideSettings: PrintInformation.preSliced
property string enabledText: catalog.i18nc("@label:Should be short", "On")
property string disabledText: catalog.i18nc("@label:Should be short", "Off")
// 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()
implicitWidth: 200 * screenScaleFactor
height: childrenRect.height
iconSource: UM.Theme.getIcon("pencil")
onCurrentModeIndexChanged: UM.Preferences.setValue("cura/active_mode", currentModeIndex)
UM.I18nCatalog
{
id: catalog
name: "cura"
}
Timer
{
id: tooltipDelayTimer
interval: 500
repeat: false
property var item
property string text
onTriggered: base.showTooltip(base, {x: 0, y: item.y}, text)
}
headerItem: RowLayout
{
anchors.fill: parent
IconWithText
{
source: UM.Theme.getIcon("category_layer_height")
text: Cura.MachineManager.activeStack ? Cura.MachineManager.activeQualityOrQualityChangesName + " " + layerHeight.properties.value + "mm" : ""
UM.SettingPropertyProvider
{
id: layerHeight
containerStack: Cura.MachineManager.activeStack
key: "layer_height"
watchedProperties: ["value"]
}
}
IconWithText
{
source: UM.Theme.getIcon("category_infill")
text: Cura.MachineManager.activeStack ? parseInt(infillDensity.properties.value) + "%" : "0%"
UM.SettingPropertyProvider
{
id: infillDensity
containerStack: Cura.MachineManager.activeStack
key: "infill_sparse_density"
watchedProperties: ["value"]
}
}
IconWithText
{
source: UM.Theme.getIcon("category_support")
text: supportEnabled.properties.value == "True" ? enabledText : disabledText
UM.SettingPropertyProvider
{
id: supportEnabled
containerStack: Cura.MachineManager.activeMachine
key: "support_enable"
watchedProperties: ["value"]
}
}
IconWithText
{
source: UM.Theme.getIcon("category_adhesion")
text: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none" ? enabledText : disabledText
UM.SettingPropertyProvider
{
id: platformAdhesionType
containerStack: Cura.MachineManager.activeMachine
key: "adhesion_type"
watchedProperties: [ "value"]
}
}
}
popupItem: Item
{
height: settingsModeSelection.height + sidebarContents.height + 2 * UM.Theme.getSize("default_margin").height
width: UM.Theme.getSize("print_setup_widget").width
ListView
{
// Settings mode selection toggle
id: settingsModeSelection
model: modesListModel
height: UM.Theme.getSize("print_setup_mode_toggle").height
visible: !hideSettings
anchors
{
right: parent.right
left: parent.left
margins: UM.Theme.getSize("thick_margin").width
}
ButtonGroup
{
id: modeMenuGroup
}
delegate: Button
{
id: control
height: settingsModeSelection.height
width: Math.round(parent.width / 2)
anchors.left: parent.left
anchors.leftMargin: model.index * Math.round(settingsModeSelection.width / 2)
anchors.verticalCenter: parent.verticalCenter
ButtonGroup.group: modeMenuGroup
checkable: true
checked: base.currentModeIndex == index
onClicked: base.currentModeIndex = index
onHoveredChanged:
{
if (hovered)
{
tooltipDelayTimer.item = settingsModeSelection
tooltipDelayTimer.text = model.tooltipText
tooltipDelayTimer.start()
}
else
{
tooltipDelayTimer.stop()
base.hideTooltip()
}
}
background: Rectangle
{
border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width
border.color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active_border") : control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
// For some reason, QtQuick decided to use the color of the background property as text color for the contentItem, so here it is
color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active") : control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
}
contentItem: Label
{
text: model.text
font: UM.Theme.getFont("default")
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering
elide: Text.ElideRight
color:
{
if(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")
}
}
}
}
Item
{
id: sidebarContents
anchors.top: settingsModeSelection.bottom
anchors.topMargin: UM.Theme.getSize("thick_margin").height
anchors.left: parent.left
anchors.right: parent.right
height: UM.Theme.getSize("print_setup_widget").height
visible: !hideSettings
// We load both of them at once (instead of using a loader) because the advanced sidebar can take
// quite some time to load. So in this case we sacrifice memory for speed.
SidebarAdvanced
{
anchors.fill: parent
visible: currentModeIndex == 1
onShowTooltip: base.showTooltip(item, location, text)
onHideTooltip: base.hideTooltip()
}
SidebarSimple
{
anchors.fill: parent
visible: currentModeIndex != 1
onShowTooltip: base.showTooltip(item, location, text)
onHideTooltip: base.hideTooltip()
}
}
// Setting mode: Recommended or Custom
ListModel
{
id: modesListModel
}
Component.onCompleted:
{
modesListModel.append({
text: catalog.i18nc("@title:tab", "Recommended"),
tooltipText: "<b>%1</b><br/><br/>%2".arg(catalog.i18nc("@tooltip:title", "Recommended Print Setup")).arg(catalog.i18nc("@tooltip", "Print with the recommended settings for the selected printer, material and quality."))
})
modesListModel.append({
text: catalog.i18nc("@title:tab", "Custom"),
tooltipText: "<b>%1</b><br/><br/>%2".arg(catalog.i18nc("@tooltip:title", "Custom Print Setup")).arg(catalog.i18nc("@tooltip", "Print with finegrained control over every last bit of the slicing process."))
})
var index = Math.round(UM.Preferences.getValue("cura/active_mode"))
if(index != null && !isNaN(index))
{
currentModeIndex = index
}
else
{
currentModeIndex = 0
}
}
}
}

View file

@ -0,0 +1,133 @@
// 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 UM 1.3 as UM
import Cura 1.0 as Cura
Item
{
id: customPrintSetup
height: childrenRect.height + padding
property real padding: UM.Theme.getSize("default_margin").width
property bool multipleExtruders: extrudersModel.count > 1
Cura.ExtrudersModel
{
id: extrudersModel
}
// Profile selector row
GlobalProfileSelector
{
id: globalProfileRow
anchors
{
top: parent.top
topMargin: parent.padding
left: parent.left
leftMargin: parent.padding
right: parent.right
rightMargin: parent.padding
}
}
UM.TabRow
{
id: tabBar
visible: multipleExtruders // The tab row is only visible when there are more than 1 extruder
anchors
{
top: globalProfileRow.bottom
topMargin: UM.Theme.getSize("default_margin").height
left: parent.left
leftMargin: parent.padding
right: parent.right
rightMargin: parent.padding
}
Repeater
{
id: repeater
model: extrudersModel
delegate: UM.TabRowButton
{
contentItem: Item
{
Cura.ExtruderIcon
{
anchors.horizontalCenter: parent.horizontalCenter
materialColor: model.color
extruderEnabled: model.enabled
}
}
onClicked:
{
Cura.ExtruderManager.setActiveExtruderIndex(tabBar.currentIndex)
}
}
}
//When active extruder changes for some other reason, switch tabs.
//Don't directly link currentIndex to Cura.ExtruderManager.activeExtruderIndex!
//This causes a segfault in Qt 5.11. Something with VisualItemModel removing index -1. We have to use setCurrentIndex instead.
Connections
{
target: Cura.ExtruderManager
onActiveExtruderChanged:
{
tabBar.setCurrentIndex(Cura.ExtruderManager.activeExtruderIndex);
}
}
//When the model of the extruders is rebuilt, the list of extruders is briefly emptied and rebuilt.
//This causes the currentIndex of the tab to be in an invalid position which resets it to 0.
//Therefore we need to change it back to what it was: The active extruder index.
Connections
{
target: repeater.model
onModelChanged:
{
tabBar.setCurrentIndex(Cura.ExtruderManager.activeExtruderIndex)
}
}
}
Rectangle
{
height: UM.Theme.getSize("print_setup_widget").height
anchors
{
top: tabBar.visible ? tabBar.bottom : globalProfileRow.bottom
left: parent.left
leftMargin: parent.padding
right: parent.right
rightMargin: parent.padding
topMargin: -UM.Theme.getSize("default_lining").width
}
z: tabBar.z - 1
// Don't show the border when only one extruder
border.color: tabBar.visible ? UM.Theme.getColor("lining") : "transparent"
border.width: UM.Theme.getSize("default_lining").width
Cura.SettingView
{
anchors
{
fill: parent
topMargin: UM.Theme.getSize("default_margin").height
leftMargin: UM.Theme.getSize("default_margin").width
// Small space for the scrollbar
rightMargin: UM.Theme.getSize("narrow_margin").width
// Compensate for the negative margin in the parent
bottomMargin: UM.Theme.getSize("default_lining").width
}
}
}
}

View file

@ -0,0 +1,100 @@
// 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 QtQuick.Layouts 1.2
import UM 1.2 as UM
import Cura 1.0 as Cura
Item
{
id: globalProfileRow
height: childrenRect.height
Label
{
id: globalProfileLabel
anchors
{
top: parent.top
bottom: parent.bottom
left: parent.left
right: globalProfileSelection.left
}
text: catalog.i18nc("@label", "Profile")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter
}
ToolButton
{
id: globalProfileSelection
text: generateActiveQualityText()
width: UM.Theme.getSize("print_setup_big_item").width
height: UM.Theme.getSize("print_setup_big_item").height
anchors
{
top: parent.top
right: parent.right
}
tooltip: Cura.MachineManager.activeQualityOrQualityChangesName
style: UM.Theme.styles.print_setup_header_button
activeFocusOnPress: true
menu: Cura.ProfileMenu { }
function generateActiveQualityText()
{
var result = Cura.MachineManager.activeQualityOrQualityChangesName
if (Cura.MachineManager.isActiveQualityExperimental)
{
result += " (Experimental)"
}
if (Cura.MachineManager.isActiveQualitySupported)
{
if (Cura.MachineManager.activeQualityLayerHeight > 0)
{
result += " <font color=\"" + UM.Theme.getColor("text_detail") + "\">"
result += " - "
result += Cura.MachineManager.activeQualityLayerHeight + "mm"
result += "</font>"
}
}
return result
}
UM.SimpleButton
{
id: customisedSettings
visible: Cura.MachineManager.hasUserSettings
width: UM.Theme.getSize("print_setup_icon").width
height: UM.Theme.getSize("print_setup_icon").height
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: Math.round(UM.Theme.getSize("setting_preferences_button_margin").width - UM.Theme.getSize("thick_margin").width)
color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button");
iconSource: UM.Theme.getIcon("star")
onClicked:
{
forceActiveFocus();
Cura.Actions.manageProfiles.trigger()
}
onEntered:
{
var content = catalog.i18nc("@tooltip","Some setting/override values are different from the values stored in the profile.\n\nClick to open the profile manager.")
base.showTooltip(globalProfileRow, Qt.point(-UM.Theme.getSize("default_margin").width, 0), content)
}
onExited: base.hideTooltip()
}
}
}

View file

@ -0,0 +1,35 @@
// 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 UM 1.3 as UM
import Cura 1.0 as Cura
Cura.ExpandableComponent
{
id: printSetupSelector
property bool preSlicedData: PrintInformation.preSliced
contentPadding: UM.Theme.getSize("default_lining").width
contentHeaderTitle: catalog.i18nc("@label", "Print settings")
enabled: !preSlicedData
disabledText: catalog.i18nc("@label shown when we load a Gcode file", "Print setup disabled. G code file can not be modified.")
UM.I18nCatalog
{
id: catalog
name: "cura"
}
headerItem: PrintSetupSelectorHeader {}
Cura.ExtrudersModel
{
id: extrudersModel
}
contentItem: PrintSetupSelectorContents {}
}

View file

@ -0,0 +1,129 @@
// 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.0 as Cura
import "Recommended"
import "Custom"
Item
{
id: content
width: UM.Theme.getSize("print_setup_widget").width - 2 * UM.Theme.getSize("default_margin").width
height: childrenRect.height
enum Mode
{
Recommended = 0,
Custom = 1
}
// Set the current mode index to the value that is stored in the preferences or Recommended mode otherwise.
property int currentModeIndex:
{
var index = Math.round(UM.Preferences.getValue("cura/active_mode"))
if (index != null && !isNaN(index))
{
return index
}
return PrintSetupSelectorContents.Mode.Recommended
}
onCurrentModeIndexChanged: UM.Preferences.setValue("cura/active_mode", currentModeIndex)
Item
{
id: contents
// Use the visible property instead of checking the currentModeIndex. That creates a binding that
// evaluates the new height every time the visible property changes.
height: recommendedPrintSetup.visible ? recommendedPrintSetup.height : customPrintSetup.height
anchors
{
top: parent.top
left: parent.left
right: parent.right
}
RecommendedPrintSetup
{
id: recommendedPrintSetup
anchors
{
left: parent.left
right: parent.right
top: parent.top
}
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Recommended
}
CustomPrintSetup
{
id: customPrintSetup
anchors
{
left: parent.left
right: parent.right
top: parent.top
}
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom
}
}
Rectangle
{
id: buttonsSeparator
// The buttonsSeparator is inside the contents. This is to avoid a double line in the bottom
anchors.bottom: contents.bottom
width: parent.width
height: UM.Theme.getSize("default_lining").height
color: UM.Theme.getColor("lining")
}
Item
{
id: buttonRow
property real padding: UM.Theme.getSize("default_margin").width
height: childrenRect.height + 2 * padding
anchors
{
top: buttonsSeparator.bottom
left: parent.left
right: parent.right
}
Cura.SecondaryButton
{
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: parent.padding
leftPadding: UM.Theme.getSize("default_margin").width
rightPadding: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@button", "Recommended")
iconSource: UM.Theme.getIcon("arrow_left")
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom
onClicked: currentModeIndex = PrintSetupSelectorContents.Mode.Recommended
}
Cura.SecondaryButton
{
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: UM.Theme.getSize("default_margin").width
leftPadding: UM.Theme.getSize("default_margin").width
rightPadding: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@button", "Custom")
iconSource: UM.Theme.getIcon("arrow_right")
isIconOnRightSide: true
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Recommended
onClicked: currentModeIndex = PrintSetupSelectorContents.Mode.Custom
}
}
}

View file

@ -0,0 +1,83 @@
// 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 QtQuick.Layouts 1.3
import UM 1.3 as UM
import Cura 1.0 as Cura
RowLayout
{
property string enabledText: catalog.i18nc("@label:Should be short", "On")
property string disabledText: catalog.i18nc("@label:Should be short", "Off")
Cura.IconWithText
{
source: UM.Theme.getIcon("category_layer_height")
text:
{
if (Cura.MachineManager.activeStack)
{
var text = Cura.MachineManager.activeQualityOrQualityChangesName
if (!Cura.MachineManager.hasNotSupportedQuality)
{
text += " " + layerHeight.properties.value + "mm"
}
return text
}
return ""
}
UM.SettingPropertyProvider
{
id: layerHeight
containerStack: Cura.MachineManager.activeStack
key: "layer_height"
watchedProperties: ["value"]
}
}
Cura.IconWithText
{
source: UM.Theme.getIcon("category_infill")
text: Cura.MachineManager.activeStack ? parseInt(infillDensity.properties.value) + "%" : "0%"
UM.SettingPropertyProvider
{
id: infillDensity
containerStack: Cura.MachineManager.activeStack
key: "infill_sparse_density"
watchedProperties: ["value"]
}
}
Cura.IconWithText
{
source: UM.Theme.getIcon("category_support")
text: supportEnabled.properties.value == "True" ? enabledText : disabledText
UM.SettingPropertyProvider
{
id: supportEnabled
containerStack: Cura.MachineManager.activeMachine
key: "support_enable"
watchedProperties: ["value"]
}
}
Cura.IconWithText
{
source: UM.Theme.getIcon("category_adhesion")
text: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none" ? enabledText : disabledText
UM.SettingPropertyProvider
{
id: platformAdhesionType
containerStack: Cura.MachineManager.activeMachine
key: "adhesion_type"
watchedProperties: [ "value"]
}
}
}

View file

@ -0,0 +1,100 @@
// 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 UM 1.2 as UM
import Cura 1.0 as Cura
//
// Adhesion
//
Item
{
id: enableAdhesionRow
height: childrenRect.height
property real labelColumnWidth: Math.round(width / 3)
Cura.IconWithText
{
id: enableAdhesionRowTitle
anchors.top: parent.top
anchors.left: parent.left
source: UM.Theme.getIcon("category_adhesion")
text: catalog.i18nc("@label", "Adhesion")
width: labelColumnWidth
}
Item
{
id: enableAdhesionContainer
height: enableAdhesionCheckBox.height
anchors
{
left: enableAdhesionRowTitle.right
right: parent.right
verticalCenter: enableAdhesionRowTitle.verticalCenter
}
CheckBox
{
id: enableAdhesionCheckBox
anchors.verticalCenter: parent.verticalCenter
property alias _hovered: adhesionMouseArea.containsMouse
//: Setting enable printing build-plate adhesion helper checkbox
style: UM.Theme.styles.checkbox
enabled: recommendedPrintSetup.settingsEnabled
visible: platformAdhesionType.properties.enabled == "True"
checked: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none"
MouseArea
{
id: adhesionMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked:
{
var adhesionType = "skirt"
if (!parent.checked)
{
// Remove the "user" setting to see if the rest of the stack prescribes a brim or a raft
platformAdhesionType.removeFromContainer(0)
adhesionType = platformAdhesionType.properties.value
if(adhesionType == "skirt" || adhesionType == "none")
{
// If the rest of the stack doesn't prescribe an adhesion-type, default to a brim
adhesionType = "brim"
}
}
platformAdhesionType.setPropertyValue("value", adhesionType)
}
onEntered:
{
base.showTooltip(enableAdhesionCheckBox, Qt.point(-enableAdhesionContainer.x - UM.Theme.getSize("thick_margin").width, 0),
catalog.i18nc("@label", "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards."));
}
onExited: base.hideTooltip()
}
}
}
UM.SettingPropertyProvider
{
id: platformAdhesionType
containerStack: Cura.MachineManager.activeMachine
removeUnusedValue: false //Doesn't work with settings that are resolved.
key: "adhesion_type"
watchedProperties: [ "value", "enabled" ]
storeIndex: 0
}
}

View file

@ -0,0 +1,252 @@
// 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 UM 1.2 as UM
import Cura 1.0 as Cura
//
// Infill
//
Item
{
id: infillRow
height: childrenRect.height
property real labelColumnWidth: Math.round(width / 3)
// Create a binding to update the icon when the infill density changes
Binding
{
target: infillRowTitle
property: "source"
value:
{
var density = parseInt(infillDensity.properties.value)
if (parseInt(infillSteps.properties.value) != 0)
{
return UM.Theme.getIcon("gradual")
}
if (density <= 0)
{
return UM.Theme.getIcon("hollow")
}
if (density < 40)
{
return UM.Theme.getIcon("sparse")
}
if (density < 90)
{
return UM.Theme.getIcon("dense")
}
return UM.Theme.getIcon("solid")
}
}
// We use a binding to make sure that after manually setting infillSlider.value it is still bound to the property provider
Binding
{
target: infillSlider
property: "value"
value: parseInt(infillDensity.properties.value)
}
// Here are the elements that are shown in the left column
Cura.IconWithText
{
id: infillRowTitle
anchors.top: parent.top
anchors.left: parent.left
source: UM.Theme.getIcon("category_infill")
text: catalog.i18nc("@label", "Infill") + " (%)"
width: labelColumnWidth
}
Item
{
id: infillSliderContainer
height: childrenRect.height
anchors
{
left: infillRowTitle.right
right: parent.right
verticalCenter: infillRowTitle.verticalCenter
}
Slider
{
id: infillSlider
width: parent.width
height: UM.Theme.getSize("print_setup_slider_handle").height // The handle is the widest element of the slider
minimumValue: 0
maximumValue: 100
stepSize: 1
tickmarksEnabled: true
// disable slider when gradual support is enabled
enabled: parseInt(infillSteps.properties.value) == 0
// set initial value from stack
value: parseInt(infillDensity.properties.value)
style: SliderStyle
{
//Draw line
groove: Item
{
Rectangle
{
height: UM.Theme.getSize("print_setup_slider_groove").height
width: control.width - UM.Theme.getSize("print_setup_slider_handle").width
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
}
}
handle: Rectangle
{
id: handleButton
color: control.enabled ? UM.Theme.getColor("primary") : UM.Theme.getColor("quality_slider_unavailable")
implicitWidth: UM.Theme.getSize("print_setup_slider_handle").width
implicitHeight: implicitWidth
radius: Math.round(implicitWidth / 2)
}
tickmarks: Repeater
{
id: repeater
model: control.maximumValue / control.stepSize + 1
Rectangle
{
color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
implicitWidth: UM.Theme.getSize("print_setup_slider_tickmarks").width
implicitHeight: UM.Theme.getSize("print_setup_slider_tickmarks").height
anchors.verticalCenter: parent.verticalCenter
// Do not use Math.round otherwise the tickmarks won't be aligned
x: ((styleData.handleWidth / 2) - (implicitWidth / 2) + (index * ((repeater.width - styleData.handleWidth) / (repeater.count-1))))
radius: Math.round(implicitWidth / 2)
visible: (index % 10) == 0 // Only show steps of 10%
Label
{
text: index
visible: (index % 20) == 0 // Only show steps of 20%
anchors.horizontalCenter: parent.horizontalCenter
y: UM.Theme.getSize("thin_margin").height
renderType: Text.NativeRendering
}
}
}
}
onValueChanged:
{
// Don't round the value if it's already the same
if (parseInt(infillDensity.properties.value) == infillSlider.value)
{
return
}
// Round the slider value to the nearest multiple of 10 (simulate step size of 10)
var roundedSliderValue = Math.round(infillSlider.value / 10) * 10
// Update the slider value to represent the rounded value
infillSlider.value = roundedSliderValue
// Update value only if the Recomended mode is Active,
// Otherwise if I change the value in the Custom mode the Recomended view will try to repeat
// same operation
var active_mode = UM.Preferences.getValue("cura/active_mode")
if (active_mode == 0 || active_mode == "simple")
{
Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", roundedSliderValue)
Cura.MachineManager.resetSettingForAllExtruders("infill_line_distance")
}
}
}
}
// Gradual Support Infill Checkbox
CheckBox
{
id: enableGradualInfillCheckBox
property alias _hovered: enableGradualInfillMouseArea.containsMouse
anchors.top: infillSliderContainer.bottom
anchors.topMargin: UM.Theme.getSize("wide_margin").height
anchors.left: infillSliderContainer.left
text: catalog.i18nc("@label", "Gradual infill")
style: UM.Theme.styles.checkbox
enabled: recommendedPrintSetup.settingsEnabled
visible: infillSteps.properties.enabled == "True"
checked: parseInt(infillSteps.properties.value) > 0
MouseArea
{
id: enableGradualInfillMouseArea
anchors.fill: parent
hoverEnabled: true
enabled: true
property var previousInfillDensity: parseInt(infillDensity.properties.value)
onClicked:
{
// Set to 90% only when enabling gradual infill
var newInfillDensity;
if (parseInt(infillSteps.properties.value) == 0)
{
previousInfillDensity = parseInt(infillDensity.properties.value)
newInfillDensity = 90
} else {
newInfillDensity = previousInfillDensity
}
Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", String(newInfillDensity))
var infill_steps_value = 0
if (parseInt(infillSteps.properties.value) == 0)
{
infill_steps_value = 5
}
Cura.MachineManager.setSettingForAllExtruders("gradual_infill_steps", "value", infill_steps_value)
}
onEntered: base.showTooltip(enableGradualInfillCheckBox, Qt.point(-infillSliderContainer.x - UM.Theme.getSize("thick_margin").width, 0),
catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top."))
onExited: base.hideTooltip()
}
}
UM.SettingPropertyProvider
{
id: infillDensity
containerStackId: Cura.MachineManager.activeStackId
key: "infill_sparse_density"
watchedProperties: [ "value" ]
storeIndex: 0
}
UM.SettingPropertyProvider
{
id: infillSteps
containerStackId: Cura.MachineManager.activeStackId
key: "gradual_infill_steps"
watchedProperties: ["value", "enabled"]
storeIndex: 0
}
}

View file

@ -0,0 +1,81 @@
// 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 UM 1.2 as UM
import Cura 1.0 as Cura
Item
{
id: recommendedPrintSetup
height: childrenRect.height + 2 * padding
property Action configureSettings
property bool settingsEnabled: Cura.ExtruderManager.activeExtruderStackId || extrudersEnabledCount.properties.value == 1
property real padding: UM.Theme.getSize("thick_margin").width
UM.I18nCatalog
{
id: catalog
name: "cura"
}
Column
{
width: parent.width - 2 * parent.padding
spacing: UM.Theme.getSize("wide_margin").height
anchors
{
left: parent.left
right: parent.right
top: parent.top
margins: parent.padding
}
// TODO
property real firstColumnWidth: Math.round(width / 3)
RecommendedQualityProfileSelector
{
width: parent.width
// TODO Create a reusable component with these properties to not define them separately for each component
labelColumnWidth: parent.firstColumnWidth
}
RecommendedInfillDensitySelector
{
width: parent.width
// TODO Create a reusable component with these properties to not define them separately for each component
labelColumnWidth: parent.firstColumnWidth
}
RecommendedSupportSelector
{
width: parent.width
// TODO Create a reusable component with these properties to not define them separately for each component
labelColumnWidth: parent.firstColumnWidth
}
RecommendedAdhesionSelector
{
width: parent.width
// TODO Create a reusable component with these properties to not define them separately for each component
labelColumnWidth: parent.firstColumnWidth
}
}
UM.SettingPropertyProvider
{
id: extrudersEnabledCount
containerStack: Cura.MachineManager.activeMachine
key: "extruders_enabled_count"
watchedProperties: [ "value" ]
storeIndex: 0
}
}

View file

@ -0,0 +1,453 @@
// 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 UM 1.2 as UM
import Cura 1.0 as Cura
//
// Quality profile
//
Item
{
id: qualityRow
height: childrenRect.height
property real labelColumnWidth: Math.round(width / 3)
property real settingsColumnWidth: width - labelColumnWidth
Timer
{
id: qualitySliderChangeTimer
interval: 50
running: false
repeat: false
onTriggered:
{
var item = Cura.QualityProfilesDropDownMenuModel.getItem(qualitySlider.value);
Cura.MachineManager.activeQualityGroup = item.quality_group;
}
}
Component.onCompleted: qualityModel.update()
Connections
{
target: Cura.QualityProfilesDropDownMenuModel
onItemsChanged: qualityModel.update()
}
Connections {
target: base
onVisibleChanged:
{
// update needs to be called when the widgets are visible, otherwise the step width calculation
// will fail because the width of an invisible item is 0.
if (visible)
{
qualityModel.update();
}
}
}
ListModel
{
id: qualityModel
property var totalTicks: 0
property var availableTotalTicks: 0
property var existingQualityProfile: 0
property var qualitySliderActiveIndex: 0
property var qualitySliderStepWidth: 0
property var qualitySliderAvailableMin: 0
property var qualitySliderAvailableMax: 0
property var qualitySliderMarginRight: 0
function update ()
{
reset()
var availableMin = -1
var availableMax = -1
for (var i = 0; i < Cura.QualityProfilesDropDownMenuModel.rowCount(); i++)
{
var qualityItem = Cura.QualityProfilesDropDownMenuModel.getItem(i)
// Add each quality item to the UI quality model
qualityModel.append(qualityItem)
// Set selected value
if (Cura.MachineManager.activeQualityType == qualityItem.quality_type)
{
// set to -1 when switching to user created profile so all ticks are clickable
if (Cura.SimpleModeSettingsManager.isProfileUserCreated)
{
qualityModel.qualitySliderActiveIndex = -1
}
else
{
qualityModel.qualitySliderActiveIndex = i
}
qualityModel.existingQualityProfile = 1
}
// Set min available
if (qualityItem.available && availableMin == -1)
{
availableMin = i
}
// Set max available
if (qualityItem.available)
{
availableMax = i
}
}
// Set total available ticks for active slider part
if (availableMin != -1)
{
qualityModel.availableTotalTicks = availableMax - availableMin + 1
}
// Calculate slider values
calculateSliderStepWidth(qualityModel.totalTicks)
calculateSliderMargins(availableMin, availableMax, qualityModel.totalTicks)
qualityModel.qualitySliderAvailableMin = availableMin
qualityModel.qualitySliderAvailableMax = availableMax
}
function calculateSliderStepWidth (totalTicks)
{
// Do not use Math.round otherwise the tickmarks won't be aligned
qualityModel.qualitySliderStepWidth = totalTicks != 0 ?
((settingsColumnWidth - UM.Theme.getSize("print_setup_slider_handle").width) / (totalTicks)) : 0
}
function calculateSliderMargins (availableMin, availableMax, totalTicks)
{
if (availableMin == -1 || (availableMin == 0 && availableMax == 0))
{
// Do not use Math.round otherwise the tickmarks won't be aligned
qualityModel.qualitySliderMarginRight = settingsColumnWidth
}
else if (availableMin == availableMax)
{
// Do not use Math.round otherwise the tickmarks won't be aligned
qualityModel.qualitySliderMarginRight = (totalTicks - availableMin) * qualitySliderStepWidth
}
else
{
// Do not use Math.round otherwise the tickmarks won't be aligned
qualityModel.qualitySliderMarginRight = (totalTicks - availableMax) * qualitySliderStepWidth
}
}
function reset () {
qualityModel.clear()
qualityModel.availableTotalTicks = 0
qualityModel.existingQualityProfile = 0
// check, the ticks count cannot be less than zero
qualityModel.totalTicks = Math.max(0, Cura.QualityProfilesDropDownMenuModel.rowCount() - 1)
}
}
// Here are the elements that are shown in the left column
Item
{
id: titleRow
width: labelColumnWidth
height: childrenRect.height
Cura.IconWithText
{
id: qualityRowTitle
source: UM.Theme.getIcon("category_layer_height")
text: catalog.i18nc("@label", "Layer Height")
anchors.left: parent.left
anchors.right: customisedSettings.left
}
UM.SimpleButton
{
id: customisedSettings
visible: Cura.SimpleModeSettingsManager.isProfileCustomized || Cura.SimpleModeSettingsManager.isProfileUserCreated
height: visible ? UM.Theme.getSize("print_setup_icon").height : 0
width: height
anchors
{
right: parent.right
rightMargin: UM.Theme.getSize("default_margin").width
leftMargin: UM.Theme.getSize("default_margin").width
verticalCenter: parent.verticalCenter
}
color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
iconSource: UM.Theme.getIcon("reset")
onClicked:
{
// if the current profile is user-created, switch to a built-in quality
Cura.MachineManager.resetToUseDefaultQuality()
}
onEntered:
{
var tooltipContent = catalog.i18nc("@tooltip","You have modified some profile settings. If you want to change these go to custom mode.")
base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, 0), tooltipContent)
}
onExited: base.hideTooltip()
}
}
// Show titles for the each quality slider ticks
Item
{
anchors.left: speedSlider.left
anchors.top: speedSlider.bottom
height: childrenRect.height
Repeater
{
model: qualityModel
Label
{
anchors.verticalCenter: parent.verticalCenter
anchors.top: parent.top
// The height has to be set manually, otherwise it's not automatically calculated in the repeater
height: UM.Theme.getSize("default_margin").height
color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesDropDownMenuModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
text:
{
var result = ""
if(Cura.MachineManager.activeMachine != null)
{
result = Cura.QualityProfilesDropDownMenuModel.getItem(index).layer_height
if(result == undefined)
{
result = "";
}
else
{
result = Number(Math.round(result + "e+2") + "e-2"); //Round to 2 decimals. Javascript makes this difficult...
if (result == undefined || result != result) //Parse failure.
{
result = "";
}
}
}
return result
}
x:
{
// Make sure the text aligns correctly with each tick
if (qualityModel.totalTicks == 0)
{
// If there is only one tick, align it centrally
return Math.round(((settingsColumnWidth) - width) / 2)
}
else if (index == 0)
{
return Math.round(settingsColumnWidth / qualityModel.totalTicks) * index
}
else if (index == qualityModel.totalTicks)
{
return Math.round(settingsColumnWidth / qualityModel.totalTicks) * index - width
}
else
{
return Math.round((settingsColumnWidth / qualityModel.totalTicks) * index - (width / 2))
}
}
}
}
}
// Print speed slider
// Two sliders are created, one at the bottom with the unavailable qualities
// and the other at the top with the available quality profiles and so the handle to select them.
Item
{
id: speedSlider
height: childrenRect.height
anchors
{
left: titleRow.right
right: parent.right
verticalCenter: titleRow.verticalCenter
}
// Draw unavailable slider
Slider
{
id: unavailableSlider
width: parent.width
height: qualitySlider.height // Same height as the slider that is on top
updateValueWhileDragging : false
tickmarksEnabled: true
minimumValue: 0
// maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly
// speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available)
maximumValue: qualityModel.totalTicks
stepSize: 1
style: SliderStyle
{
//Draw Unvailable line
groove: Item
{
Rectangle
{
height: UM.Theme.getSize("print_setup_slider_groove").height
width: control.width - UM.Theme.getSize("print_setup_slider_handle").width
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: UM.Theme.getColor("quality_slider_unavailable")
}
}
handle: Item {}
tickmarks: Repeater
{
id: qualityRepeater
model: qualityModel.totalTicks > 0 ? qualityModel : 0
Rectangle
{
color: Cura.QualityProfilesDropDownMenuModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
implicitWidth: UM.Theme.getSize("print_setup_slider_tickmarks").width
implicitHeight: UM.Theme.getSize("print_setup_slider_tickmarks").height
anchors.verticalCenter: parent.verticalCenter
// Do not use Math.round otherwise the tickmarks won't be aligned
x: ((UM.Theme.getSize("print_setup_slider_handle").width / 2) - (implicitWidth / 2) + (qualityModel.qualitySliderStepWidth * index))
radius: Math.round(implicitWidth / 2)
}
}
}
// Create a mouse area on top of the unavailable profiles to show a specific tooltip
MouseArea
{
anchors.fill: parent
hoverEnabled: true
enabled: !Cura.SimpleModeSettingsManager.isProfileUserCreated
onEntered:
{
var tooltipContent = catalog.i18nc("@tooltip", "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile")
base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, customisedSettings.height), tooltipContent)
}
onExited: base.hideTooltip()
}
}
// Draw available slider
Slider
{
id: qualitySlider
width: qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks - 1) + UM.Theme.getSize("print_setup_slider_handle").width
height: UM.Theme.getSize("print_setup_slider_handle").height // The handle is the widest element of the slider
enabled: qualityModel.totalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized
visible: qualityModel.availableTotalTicks > 0
updateValueWhileDragging : false
anchors
{
right: parent.right
rightMargin: qualityModel.qualitySliderMarginRight
}
minimumValue: qualityModel.qualitySliderAvailableMin >= 0 ? qualityModel.qualitySliderAvailableMin : 0
// maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly
// speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available)
maximumValue: qualityModel.qualitySliderAvailableMax >= 1 ? qualityModel.qualitySliderAvailableMax : 1
stepSize: 1
value: qualityModel.qualitySliderActiveIndex
style: SliderStyle
{
// Draw Available line
groove: Item
{
Rectangle
{
height: UM.Theme.getSize("print_setup_slider_groove").height
width: control.width - UM.Theme.getSize("print_setup_slider_handle").width
anchors.verticalCenter: parent.verticalCenter
// Do not use Math.round otherwise the tickmarks won't be aligned
x: UM.Theme.getSize("print_setup_slider_handle").width / 2
color: UM.Theme.getColor("quality_slider_available")
}
}
handle: Rectangle
{
id: qualityhandleButton
color: UM.Theme.getColor("primary")
implicitWidth: UM.Theme.getSize("print_setup_slider_handle").width
implicitHeight: implicitWidth
radius: Math.round(implicitWidth / 2)
visible: !Cura.SimpleModeSettingsManager.isProfileCustomized && !Cura.SimpleModeSettingsManager.isProfileUserCreated && qualityModel.existingQualityProfile
}
}
onValueChanged:
{
// only change if an active machine is set and the slider is visible at all.
if (Cura.MachineManager.activeMachine != null && visible)
{
// prevent updating during view initializing. Trigger only if the value changed by user
if (qualitySlider.value != qualityModel.qualitySliderActiveIndex && qualityModel.qualitySliderActiveIndex != -1)
{
// start updating with short delay
qualitySliderChangeTimer.start()
}
}
}
// This mouse area is only used to capture the onHover state and don't propagate it to the unavailable mouse area
MouseArea
{
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
enabled: !Cura.SimpleModeSettingsManager.isProfileUserCreated
}
}
// This mouse area will only take the mouse events and show a tooltip when the profile in use is
// a user created profile
MouseArea
{
anchors.fill: parent
hoverEnabled: true
visible: Cura.SimpleModeSettingsManager.isProfileUserCreated
onEntered:
{
var tooltipContent = catalog.i18nc("@tooltip", "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab")
base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, customisedSettings.height), tooltipContent)
}
onExited: base.hideTooltip()
}
}
}

Some files were not shown because too many files have changed in this diff Show more