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")) " with printed models."), title = catalog.i18nc("@info:title", "Build Volume"))
self._global_container_stack = None 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._application.globalContainerStackChanged.connect(self._onStackChanged)
self._onStackChanged() self._onStackChanged()
self._engine_ready = False self._engine_ready = False
@ -105,6 +112,8 @@ class BuildVolume(SceneNode):
self._setting_change_timer.setSingleShot(True) self._setting_change_timer.setSingleShot(True)
self._setting_change_timer.timeout.connect(self._onSettingChangeTimerFinished) self._setting_change_timer.timeout.connect(self._onSettingChangeTimerFinished)
# Must be after setting _build_volume_message, apparently that is used in getMachineManager. # Must be after setting _build_volume_message, apparently that is used in getMachineManager.
# activeQualityChanged is always emitted after setActiveVariant, setActiveMaterial and setActiveQuality. # activeQualityChanged is always emitted after setActiveVariant, setActiveMaterial and setActiveQuality.
# Therefore this works. # 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) 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() self.updateNodeBoundaryCheck()
def getBoundingBox(self) -> AxisAlignedBox: def getBoundingBox(self) -> AxisAlignedBox:
@ -524,8 +535,11 @@ class BuildVolume(SceneNode):
if extra_z != self._extra_z_clearance: if extra_z != self._extra_z_clearance:
self._extra_z_clearance = extra_z self._extra_z_clearance = extra_z
## Update the build volume visualization
def _onStackChanged(self): def _onStackChanged(self):
self._stack_change_timer.start()
## Update the build volume visualization
def _onStackChangeTimerFinished(self):
if self._global_container_stack: if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged) self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
extruders = ExtruderManager.getInstance().getActiveExtruderStacks() extruders = ExtruderManager.getInstance().getActiveExtruderStacks()

View file

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

View file

@ -181,7 +181,6 @@ class CuraApplication(QtApplication):
# Variables set from CLI # Variables set from CLI
self._files_to_open = [] self._files_to_open = []
self._use_single_instance = False self._use_single_instance = False
self._trigger_early_crash = False # For debug only
self._single_instance = None self._single_instance = None
@ -292,7 +291,10 @@ class CuraApplication(QtApplication):
sys.exit(0) sys.exit(0)
self._use_single_instance = self._cli_args.single_instance 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: for filename in self._cli_args.file:
self._files_to_open.append(os.path.abspath(filename)) self._files_to_open.append(os.path.abspath(filename))

View file

@ -64,21 +64,21 @@ class MachineErrorChecker(QObject):
def _onMachineChanged(self) -> None: def _onMachineChanged(self) -> None:
if self._global_stack: 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) self._global_stack.containersChanged.disconnect(self.startErrorCheck)
for extruder in self._global_stack.extruders.values(): for extruder in self._global_stack.extruders.values():
extruder.propertyChanged.disconnect(self.startErrorCheck) extruder.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.disconnect(self.startErrorCheck) extruder.containersChanged.disconnect(self.startErrorCheck)
self._global_stack = self._machine_manager.activeMachine self._global_stack = self._machine_manager.activeMachine
if self._global_stack: 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) self._global_stack.containersChanged.connect(self.startErrorCheck)
for extruder in self._global_stack.extruders.values(): for extruder in self._global_stack.extruders.values():
extruder.propertyChanged.connect(self.startErrorCheck) extruder.propertyChanged.connect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.connect(self.startErrorCheck) extruder.containersChanged.connect(self.startErrorCheck)
hasErrorUpdated = pyqtSignal() hasErrorUpdated = pyqtSignal()
@ -93,6 +93,13 @@ class MachineErrorChecker(QObject):
def needToWaitForResult(self) -> bool: def needToWaitForResult(self) -> bool:
return self._need_to_check or self._check_in_progress 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. # Starts the error check timer to schedule a new error check.
def startErrorCheck(self, *args) -> None: def startErrorCheck(self, *args) -> None:
if not self._check_in_progress: if not self._check_in_progress:

View file

@ -1,5 +1,6 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional, Dict, Set
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
from UM.Qt.ListModel import ListModel 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. # 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 # 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 # bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu
from cura.Machines.MaterialNode import MaterialNode
class BaseMaterialsModel(ListModel): class BaseMaterialsModel(ListModel):
extruderPositionChanged = pyqtSignal() extruderPositionChanged = pyqtSignal()
@ -54,8 +58,8 @@ class BaseMaterialsModel(ListModel):
self._extruder_position = 0 self._extruder_position = 0
self._extruder_stack = None self._extruder_stack = None
self._available_materials = None self._available_materials = None # type: Optional[Dict[str, MaterialNode]]
self._favorite_ids = None self._favorite_ids = set() # type: Set[str]
def _updateExtruderStack(self): def _updateExtruderStack(self):
global_stack = self._machine_manager.activeMachine global_stack = self._machine_manager.activeMachine
@ -102,8 +106,10 @@ class BaseMaterialsModel(ListModel):
return False return False
extruder_stack = global_stack.extruders[extruder_position] extruder_stack = global_stack.extruders[extruder_position]
available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack)
self._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: if self._available_materials is None:
return False return False

View file

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

View file

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

View file

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

View file

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

View file

@ -83,6 +83,7 @@ class ExtruderManager(QObject):
# \param index The index of the new active extruder. # \param index The index of the new active extruder.
@pyqtSlot(int) @pyqtSlot(int)
def setActiveExtruderIndex(self, index: int) -> None: def setActiveExtruderIndex(self, index: int) -> None:
if self._active_extruder_index != index:
self._active_extruder_index = index self._active_extruder_index = index
self.activeExtruderChanged.emit() self.activeExtruderChanged.emit()
@ -344,6 +345,7 @@ class ExtruderManager(QObject):
if extruders_changed: if extruders_changed:
self.extrudersChanged.emit(global_stack_id) self.extrudersChanged.emit(global_stack_id)
self.setActiveExtruderIndex(0) self.setActiveExtruderIndex(0)
self.activeExtruderChanged.emit()
# After 3.4, all single-extrusion machines have their own extruder definition files instead of reusing # 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. # "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() return super().getNextStack()
def setEnabled(self, enabled: bool) -> None: def setEnabled(self, enabled: bool) -> None:
if self.getMetaDataEntry("enabled", True) == enabled: #No change. if self.getMetaDataEntry("enabled", True) == enabled: # No change.
return #Don't emit a signal then. return # Don't emit a signal then.
self.setMetaDataEntry("enabled", str(enabled)) self.setMetaDataEntry("enabled", str(enabled))
self.enabledChanged.emit() self.enabledChanged.emit()

View file

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

View file

@ -3,8 +3,8 @@
from collections import defaultdict from collections import defaultdict
import threading import threading
from typing import Any, Dict, Optional, Set, TYPE_CHECKING from typing import Any, Dict, Optional, Set, TYPE_CHECKING, List
from PyQt5.QtCore import pyqtProperty, pyqtSlot from PyQt5.QtCore import pyqtProperty, pyqtSlot, pyqtSignal
from UM.Decorators import override from UM.Decorators import override
from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase 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. # 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 self._resolving_settings = defaultdict(set) #type: Dict[str, Set[str]] # keys are thread names
extrudersChanged = pyqtSignal()
## Get the list of extruders of this stack. ## Get the list of extruders of this stack.
# #
# \return The extruders registered with this stack. # \return The extruders registered with this stack.
@pyqtProperty("QVariantMap") @pyqtProperty("QVariantMap", notify = extrudersChanged)
def extruders(self) -> Dict[str, "ExtruderStack"]: def extruders(self) -> Dict[str, "ExtruderStack"]:
return self._extruders 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 @classmethod
def getLoadingPriority(cls) -> int: def getLoadingPriority(cls) -> int:
return 2 return 2

View file

@ -1536,6 +1536,10 @@ class MachineManager(QObject):
name = self._current_quality_group.name name = self._current_quality_group.name
return 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: def _updateUponMaterialMetadataChange(self) -> None:
if self._global_container_stack is None: if self._global_container_stack is None:
return return

View file

@ -17,12 +17,6 @@ parser.add_argument("--debug",
default = False, default = False,
help = "Turn on the debug mode by setting this option." 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]) known_args = vars(parser.parse_known_args()[0])
if not known_args["debug"]: if not known_args["debug"]:

View file

@ -203,7 +203,7 @@ class CuraEngineBackend(QObject, Backend):
@pyqtSlot() @pyqtSlot()
def stopSlicing(self) -> None: def stopSlicing(self) -> None:
self.backendStateChange.emit(BackendState.NotStarted) self.setState(BackendState.NotStarted)
if self._slicing: # We were already slicing. Stop the old job. if self._slicing: # We were already slicing. Stop the old job.
self._terminate() self._terminate()
self._createSocket() self._createSocket()
@ -322,7 +322,7 @@ class CuraEngineBackend(QObject, Backend):
self._start_slice_job = None self._start_slice_job = None
if job.isCancelled() or job.getError() or job.getResult() == StartJobResult.Error: if job.isCancelled() or job.getError() or job.getResult() == StartJobResult.Error:
self.backendStateChange.emit(BackendState.Error) self.setState(BackendState.Error)
self.backendError.emit(job) self.backendError.emit(job)
return return
@ -331,10 +331,10 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status", 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")) "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._error_message.show()
self.backendStateChange.emit(BackendState.Error) self.setState(BackendState.Error)
self.backendError.emit(job) self.backendError.emit(job)
else: else:
self.backendStateChange.emit(BackendState.NotStarted) self.setState(BackendState.NotStarted)
return return
if job.getResult() == StartJobResult.SettingError: 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)), 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")) title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show() self._error_message.show()
self.backendStateChange.emit(BackendState.Error) self.setState(BackendState.Error)
self.backendError.emit(job) self.backendError.emit(job)
else: else:
self.backendStateChange.emit(BackendState.NotStarted) self.setState(BackendState.NotStarted)
return return
elif job.getResult() == StartJobResult.ObjectSettingError: 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())), 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")) title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show() self._error_message.show()
self.backendStateChange.emit(BackendState.Error) self.setState(BackendState.Error)
self.backendError.emit(job) self.backendError.emit(job)
return 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."), 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")) title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show() self._error_message.show()
self.backendStateChange.emit(BackendState.Error) self.setState(BackendState.Error)
self.backendError.emit(job) self.backendError.emit(job)
else: else:
self.backendStateChange.emit(BackendState.NotStarted) self.setState(BackendState.NotStarted)
if job.getResult() == StartJobResult.ObjectsWithDisabledExtruder: 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()), 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")) title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show() self._error_message.show()
self.backendStateChange.emit(BackendState.Error) self.setState(BackendState.Error)
self.backendError.emit(job) self.backendError.emit(job)
return 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."), 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")) title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show() self._error_message.show()
self.backendStateChange.emit(BackendState.Error) self.setState(BackendState.Error)
self.backendError.emit(job) self.backendError.emit(job)
else: else:
self.backendStateChange.emit(BackendState.NotStarted) self.setState(BackendState.NotStarted)
self._invokeSlice() self._invokeSlice()
return return
@ -424,7 +424,7 @@ class CuraEngineBackend(QObject, Backend):
self._socket.sendMessage(job.getSliceMessage()) self._socket.sendMessage(job.getSliceMessage())
# Notify the user that it's now up to the backend to do it's job # 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: if self._slice_start_time:
Logger.log("d", "Sending slice message took %s seconds", time() - 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. 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"): if node.callDecoration("isBlockSlicing"):
enable_timer = False enable_timer = False
self.backendStateChange.emit(BackendState.Disabled) self.setState(BackendState.Disabled)
self._is_disabled = True self._is_disabled = True
gcode_list = node.callDecoration("getGCodeList") gcode_list = node.callDecoration("getGCodeList")
if gcode_list is not None: if gcode_list is not None:
@ -451,7 +451,7 @@ class CuraEngineBackend(QObject, Backend):
if self._use_timer == enable_timer: if self._use_timer == enable_timer:
return self._use_timer return self._use_timer
if enable_timer: if enable_timer:
self.backendStateChange.emit(BackendState.NotStarted) self.setState(BackendState.NotStarted)
self.enableTimer() self.enableTimer()
return True return True
else: else:
@ -518,7 +518,7 @@ class CuraEngineBackend(QObject, Backend):
self._build_plates_to_be_sliced.append(build_plate_number) self._build_plates_to_be_sliced.append(build_plate_number)
self.printDurationMessage.emit(source_build_plate_number, {}, []) self.printDurationMessage.emit(source_build_plate_number, {}, [])
self.processingProgress.emit(0.0) self.processingProgress.emit(0.0)
self.backendStateChange.emit(BackendState.NotStarted) self.setState(BackendState.NotStarted)
# if not self._use_timer: # if not self._use_timer:
# With manually having to slice, we want to clear the old invalid layer data. # With manually having to slice, we want to clear the old invalid layer data.
self._clearLayerData(build_plate_changed) self._clearLayerData(build_plate_changed)
@ -567,7 +567,7 @@ class CuraEngineBackend(QObject, Backend):
self.stopSlicing() self.stopSlicing()
self.markSliceAll() self.markSliceAll()
self.processingProgress.emit(0.0) self.processingProgress.emit(0.0)
self.backendStateChange.emit(BackendState.NotStarted) self.setState(BackendState.NotStarted)
if not self._use_timer: if not self._use_timer:
# With manually having to slice, we want to clear the old invalid layer data. # With manually having to slice, we want to clear the old invalid layer data.
self._clearLayerData() self._clearLayerData()
@ -613,7 +613,7 @@ class CuraEngineBackend(QObject, Backend):
# \param message The protobuf message containing the slicing progress. # \param message The protobuf message containing the slicing progress.
def _onProgressMessage(self, message: Arcus.PythonMessage) -> None: def _onProgressMessage(self, message: Arcus.PythonMessage) -> None:
self.processingProgress.emit(message.amount) self.processingProgress.emit(message.amount)
self.backendStateChange.emit(BackendState.Processing) self.setState(BackendState.Processing)
def _invokeSlice(self) -> None: def _invokeSlice(self) -> None:
if self._use_timer: if self._use_timer:
@ -632,7 +632,7 @@ class CuraEngineBackend(QObject, Backend):
# #
# \param message The protobuf message signalling that slicing is finished. # \param message The protobuf message signalling that slicing is finished.
def _onSlicingFinishedMessage(self, message: Arcus.PythonMessage) -> None: def _onSlicingFinishedMessage(self, message: Arcus.PythonMessage) -> None:
self.backendStateChange.emit(BackendState.Done) self.setState(BackendState.Done)
self.processingProgress.emit(1.0) 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. 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 2.2
import QtQuick.Controls 1.1 import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 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 UM 1.2 as UM
import Cura 1.0 as Cura
Button Button
{ {
id: modelCheckerButton id: modelCheckerButton
UM.I18nCatalog{id: catalog; name: "cura"} UM.I18nCatalog
{
id: catalog
name: "cura"
}
visible: manager.hasWarnings visible: manager.hasWarnings
tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.") tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.")
@ -25,6 +25,8 @@ Button
width: UM.Theme.getSize("save_button_specs_icons").width width: UM.Theme.getSize("save_button_specs_icons").width
height: UM.Theme.getSize("save_button_specs_icons").height height: UM.Theme.getSize("save_button_specs_icons").height
anchors.verticalCenter: parent ? parent.verticalCenter : undefined
style: ButtonStyle style: ButtonStyle
{ {
background: Item background: Item

View file

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

View file

@ -13,10 +13,6 @@ import QtGraphicalEffects 1.0 // For the dropshadow
Item Item
{ {
id: prepareMenu 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 UM.I18nCatalog
{ {
@ -45,7 +41,6 @@ Item
Cura.MachineSelector Cura.MachineSelector
{ {
id: machineSelection 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 headerCornerSide: Cura.RoundedRectangle.Direction.Left
Layout.minimumWidth: UM.Theme.getSize("machine_selector_widget").width Layout.minimumWidth: UM.Theme.getSize("machine_selector_widget").width
Layout.maximumWidth: 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 Item
{ {
id: previewMenu 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 property real itemHeight: height - 2 * UM.Theme.getSize("default_lining").width

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -32,7 +32,11 @@ Item
model: toolbox.packagesModel model: toolbox.packagesModel
delegate: Loader 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" source: "ToolboxDetailTile.qml"
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher. // 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 1.4
import QtQuick.Controls.Styles 1.4 import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
@ -13,7 +13,7 @@ Item
id: toolboxDownloadsGridTile id: toolboxDownloadsGridTile
property int packageCount: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getTotalNumberOfMaterialPackagesByAuthor(model.id) : 1 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) 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 Layout.alignment: Qt.AlignTop | Qt.AlignLeft
MouseArea MouseArea

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher. // 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.Dialogs 1.1
import QtQuick.Window 2.2 import QtQuick.Window 2.2
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
@ -32,6 +32,7 @@ UM.Dialog
anchors.right: parent.right 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?") 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 wrapMode: Text.Wrap
renderType: Text.NativeRendering
} }
TextArea TextArea
{ {

View file

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

View file

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

View file

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

View file

@ -691,7 +691,8 @@ class Toolbox(QObject, Extension):
self.setDownloadProgress(new_progress) self.setDownloadProgress(new_progress)
if bytes_sent == bytes_total: if bytes_sent == bytes_total:
self.setIsDownloading(False) 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 # Check if the download was sucessfull
if self._download_reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200: 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 spacing: UM.Theme.getSize("default_margin").height
SystemPalette { id: palette } SystemPalette { id: palette }
UM.I18nCatalog { id: catalog; name: "cura" } UM.I18nCatalog { id: catalog; name:"cura" }
Label Label
{ {
id: pageTitle id: pageTitle

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 Row
{ {
height: parent.height 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 // This wrapper ensures that the buildplate icon is located centered
// below an extruder icon. // 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 ExpandableCard
{ {
borderColor: printJob.configurationChanges.length !== 0 ? "#f5a623" : "#EAEAEC" // TODO: Theme!
headerItem: Row headerItem: Row
{ {
height: 48 * screenScaleFactor // TODO: Theme! height: 48 * screenScaleFactor // TODO: Theme!

View file

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

View file

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

View file

@ -3,6 +3,7 @@
import QtQuick 2.3 import QtQuick 2.3
import QtQuick.Controls 2.0 import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.1
import UM 1.3 as UM import UM 1.3 as UM
/** /**
@ -66,7 +67,7 @@ Item
{ {
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
} }
width: 216 * screenScaleFactor // TODO: Theme! width: 180 * screenScaleFactor // TODO: Theme!
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme! height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
Label Label
@ -150,7 +151,7 @@ Item
} }
border border
{ {
color: "#EAEAEC" // TODO: Theme! color: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? "#f5a623" : "#EAEAEC" // TODO: Theme!
width: borderSize // TODO: Remove once themed width: borderSize // TODO: Remove once themed
} }
color: "white" // TODO: Theme! color: "white" // TODO: Theme!
@ -185,14 +186,15 @@ Item
} }
if (printer && printer.state == "unreachable") 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 catalog.i18nc("@label:status", "Idle")
} }
return "" return ""
} }
visible: text !== ""
} }
Item Item
@ -218,7 +220,7 @@ Item
{ {
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
} }
width: 216 * screenScaleFactor // TODO: Theme! width: 180 * screenScaleFactor // TODO: Theme!
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme! height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
visible: printer.activePrintJob visible: printer.activePrintJob
@ -247,7 +249,7 @@ Item
} }
color: printer.activePrintJob && printer.activePrintJob.isActive ? "#53657d" : "#babac1" // TODO: Theme! color: printer.activePrintJob && printer.activePrintJob.isActive ? "#53657d" : "#babac1" // TODO: Theme!
elide: Text.ElideRight 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 text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N
width: parent.width width: parent.width
@ -264,8 +266,67 @@ Item
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
} }
printJob: printer.activePrintJob 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 Cura 1.0 as Cura
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
// Root component for the monitor tab (stage)
Component Component
{ {
Item Item
@ -130,7 +131,7 @@ Component
verticalCenter: externalLinkIcon.verticalCenter verticalCenter: externalLinkIcon.verticalCenter
} }
color: UM.Theme.getColor("primary") color: UM.Theme.getColor("primary")
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default") // 12pt, regular
linkColor: UM.Theme.getColor("primary") linkColor: UM.Theme.getColor("primary")
text: catalog.i18nc("@label link to connect manager", "Manage queue in Cura Connect") 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; abortConfirmationDialog.visible = true;
popup.close(); 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: { visible: {
if (!printJob) { if (!printJob) {
return false; 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 { Button {
height: UM.Theme.getSize("save_button_save_to_button").height; height: UM.Theme.getSize("save_button_save_to_button").height;
onClicked: Cura.MachineManager.printerOutputDevices[0].requestAuthentication(); 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"); text: catalog.i18nc("@action:button", "Request Access");
tooltip: catalog.i18nc("@info:tooltip", "Send access request to the printer"); tooltip: catalog.i18nc("@info:tooltip", "Send access request to the printer");
visible: printerConnected && !printerAcceptsCommands && !authenticationRequested; visible: printerConnected && !printerAcceptsCommands && !authenticationRequested;
@ -38,7 +38,7 @@ Item {
Button { Button {
height: UM.Theme.getSize("save_button_save_to_button").height; height: UM.Theme.getSize("save_button_save_to_button").height;
onClicked: connectActionDialog.show(); onClicked: connectActionDialog.show();
style: UM.Theme.styles.sidebar_action_button; style: UM.Theme.styles.print_setup_action_button;
text: catalog.i18nc("@action:button", "Connect"); text: catalog.i18nc("@action:button", "Connect");
tooltip: catalog.i18nc("@info:tooltip", "Connect to a printer"); tooltip: catalog.i18nc("@info:tooltip", "Connect to a printer");
visible: !printerConnected; visible: !printerConnected;

View file

@ -64,7 +64,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._print_jobs = [] # type: List[UM3PrintJobOutputModel] self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
self._received_print_jobs = False # type: bool self._received_print_jobs = False # type: bool
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterMonitorItem.qml") self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/MonitorStage.qml")
# See comments about this hack with the clusterPrintersChanged signal # See comments about this hack with the clusterPrintersChanged signal
self.printersChanged.connect(self.clusterPrintersChanged) self.printersChanged.connect(self.clusterPrintersChanged)
@ -607,12 +607,19 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
def _createMaterialOutputModel(self, material_data: Dict[str, Any]) -> "MaterialOutputModel": def _createMaterialOutputModel(self, material_data: Dict[str, Any]) -> "MaterialOutputModel":
material_manager = CuraApplication.getInstance().getMaterialManager() 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 # 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. # material is unknown to Cura, so we should return an "empty" or "unknown" material model.
if material_group_list is None: if material_group_list is None:
material_name = "Empty" if len(material_data["guid"]) == 0 else "Unknown" material_name = i18n_catalog.i18nc("@label:material", "Empty") if len(material_data.get("guid", "")) == 0 \
return MaterialOutputModel(guid = material_data["guid"], else i18n_catalog.i18nc("@label:material", "Unknown")
return MaterialOutputModel(guid = material_data.get("guid", ""),
type = material_data.get("type", ""), type = material_data.get("type", ""),
color = material_data.get("color", ""), color = material_data.get("color", ""),
brand = material_data.get("brand", ""), brand = material_data.get("brand", ""),
@ -643,9 +650,10 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
color = material_data["color"] color = material_data["color"]
brand = material_data["brand"] brand = material_data["brand"]
material_type = material_data["material"] material_type = material_data["material"]
name = "Empty" if material_data["material"] == "empty" else "Unknown" name = i18n_catalog.i18nc("@label:material", "Empty") if material_data["material"] == "empty" \
return MaterialOutputModel(guid=material_data["guid"], type=material_type, else i18n_catalog.i18nc("@label:material", "Unknown")
brand=brand, color=color, name=name) 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: 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. # 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 loggedIn: false
property var profileImage: "" property var profileImage: ""
padding: 2 * UM.Theme.getSize("default_margin").height padding: UM.Theme.getSize("wide_margin").height
spacing: 2 * UM.Theme.getSize("default_margin").height spacing: UM.Theme.getSize("wide_margin").height
AvatarImage AvatarImage
{ {

View file

@ -3,17 +3,17 @@
import QtQuick 2.7 import QtQuick 2.7
import QtQuick.Controls 2.1 import QtQuick.Controls 2.1
import QtGraphicalEffects 1.0 // For the dropshadow import QtGraphicalEffects 1.0 // For the dropshadow
import UM 1.1 as UM import UM 1.1 as UM
import Cura 1.0 as Cura import Cura 1.0 as Cura
Button Button
{ {
id: button id: button
property alias iconSource: buttonIconLeft.source
property bool isIconOnRightSide: false property bool isIconOnRightSide: false
property alias iconSource: buttonIconLeft.source
property alias textFont: buttonText.font property alias textFont: buttonText.font
property alias cornerRadius: backgroundRect.radius property alias cornerRadius: backgroundRect.radius
property alias tooltip: tooltip.text property alias tooltip: tooltip.text
@ -28,9 +28,6 @@ Button
property color outlineColor: color property color outlineColor: color
property color outlineHoverColor: hoverColor property color outlineHoverColor: hoverColor
property color outlineDisabledColor: outlineColor property color outlineDisabledColor: outlineColor
hoverEnabled: true
property alias shadowColor: shadow.color property alias shadowColor: shadow.color
property alias shadowEnabled: shadow.visible property alias shadowEnabled: shadow.visible
@ -42,6 +39,7 @@ Button
leftPadding: UM.Theme.getSize("default_margin").width leftPadding: UM.Theme.getSize("default_margin").width
rightPadding: UM.Theme.getSize("default_margin").width rightPadding: UM.Theme.getSize("default_margin").width
height: UM.Theme.getSize("action_button").height height: UM.Theme.getSize("action_button").height
hoverEnabled: true
contentItem: Row contentItem: Row
{ {
@ -52,6 +50,8 @@ Button
source: "" source: ""
height: buttonText.height height: buttonText.height
width: visible ? height : 0 width: visible ? height : 0
sourceSize.width: width
sourceSize.height: height
color: button.hovered ? button.textHoverColor : button.textColor color: button.hovered ? button.textHoverColor : button.textColor
visible: source != "" && !button.isIconOnRightSide visible: source != "" && !button.isIconOnRightSide
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -78,6 +78,8 @@ Button
source: buttonIconLeft.source source: buttonIconLeft.source
height: buttonText.height height: buttonText.height
width: visible ? height : 0 width: visible ? height : 0
sourceSize.width: width
sourceSize.height: height
color: buttonIconLeft.color color: buttonIconLeft.color
visible: source != "" && button.isIconOnRightSide visible: source != "" && button.isIconOnRightSide
anchors.verticalCenter: buttonIconLeft.verticalCenter 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. leftPadding: UM.Theme.getSize("narrow_margin").width //Need more space than usual here for wide text.
rightPadding: UM.Theme.getSize("narrow_margin").width 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") iconSource: popup.opened ? UM.Theme.getIcon("arrow_top") : UM.Theme.getIcon("arrow_bottom")
color: UM.Theme.getColor("action_panel_secondary") color: UM.Theme.getColor("action_panel_secondary")
visible: (devicesModel.deviceCount > 1) visible: (devicesModel.deviceCount > 1)

View file

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

View file

@ -52,7 +52,7 @@ Column
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
Cura.IconLabel Cura.IconWithText
{ {
id: unableToSliceMessage id: unableToSliceMessage
width: parent.width width: parent.width
@ -61,7 +61,6 @@ Column
text: catalog.i18nc("@label:PrintjobStatus", "Unable to Slice") text: catalog.i18nc("@label:PrintjobStatus", "Unable to Slice")
source: UM.Theme.getIcon("warning") source: UM.Theme.getIcon("warning")
color: UM.Theme.getColor("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 // 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 window: base
} }
Rectangle Item
{ {
id: headerBackground id: headerBackground
anchors 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 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 Toolbar
{ {
// The toolbar is the left bar that is populated by all the tools (which are dynamicly populated by // 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 ViewOrientationControls
{ {
id: viewOrientationControls id: viewOrientationControls
@ -245,9 +230,8 @@ UM.MainWindow
anchors anchors
{ {
left: parent.left left: parent.left
margins: UM.Theme.getSize("default_margin").width
bottom: parent.bottom bottom: parent.bottom
margins: UM.Theme.getSize("default_margin").width
} }
} }
@ -298,8 +282,6 @@ UM.MainWindow
// Every time the stage is changed. // Every time the stage is changed.
property var printSetupSelector: Cura.PrintSetupSelector property var printSetupSelector: Cura.PrintSetupSelector
{ {
onShowTooltip: base.showTooltip(item, location, text)
onHideTooltip: base.hideTooltip()
width: UM.Theme.getSize("print_setup_widget").width width: UM.Theme.getSize("print_setup_widget").width
height: UM.Theme.getSize("stage_menu").height height: UM.Theme.getSize("stage_menu").height
headerCornerSide: RoundedRectangle.Direction.Right headerCornerSide: RoundedRectangle.Direction.Right
@ -318,7 +300,7 @@ UM.MainWindow
} }
} }
SidebarTooltip PrintSetupTooltip
{ {
id: tooltip id: tooltip
} }

View file

@ -11,6 +11,7 @@ import Cura 1.0 as Cura
UM.Dialog UM.Dialog
{ {
id: base
title: catalog.i18nc("@title:window", "Save Project") title: catalog.i18nc("@title:window", "Save Project")
minimumWidth: 500 * screenScaleFactor minimumWidth: 500 * screenScaleFactor
@ -49,7 +50,7 @@ UM.Dialog
UM.SettingDefinitionsModel UM.SettingDefinitionsModel
{ {
id: definitionsModel id: definitionsModel
containerId: Cura.MachineManager.activeDefinitionId containerId: base.visible ? Cura.MachineManager.activeDefinitionId: ""
showAll: true showAll: true
exclude: ["command_line_settings"] exclude: ["command_line_settings"]
showAncestors: true 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 2.7
import QtQuick.Controls 2.3 import QtQuick.Controls 2.3
@ -6,16 +9,15 @@ import Cura 1.0 as Cura
import QtGraphicalEffects 1.0 // For the dropshadow 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 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 contentItem; The content that needs to be shown if the component is expanded.
// * The icon; An icon that is displayed on the right of the drawer.
Item Item
{ {
id: base id: base
// Enumeration with the different possible alignments of the popup with respect of the headerItem // Enumeration with the different possible alignments of the content with respect of the headerItem
enum PopupAlignment enum ContentAlignment
{ {
AlignLeft, AlignLeft,
AlignRight AlignRight
@ -24,21 +26,31 @@ Item
// The headerItem holds the QML item that is always displayed. // The headerItem holds the QML item that is always displayed.
property alias headerItem: headerItemLoader.sourceComponent property alias headerItem: headerItemLoader.sourceComponent
// The popupItem holds the QML item that is shown when the "open" button is pressed // The contentItem holds the QML item that is shown when the "open" button is pressed
property var popupItem 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 headerBackgroundColor: UM.Theme.getColor("action_button")
property color headerActiveColor: UM.Theme.getColor("secondary")
property color headerHoverColor: UM.Theme.getColor("action_button_hovered") property color headerHoverColor: UM.Theme.getColor("action_button_hovered")
property alias enabled: mouseArea.enabled property alias enabled: mouseArea.enabled
// Defines the alignment of the popup with respect of the headerItem, by default to the right // Text to show when this component is disabled
property int popupAlignment: ExpandableComponent.PopupAlignment.AlignRight property alias disabledText: disabledLabel.text
// How much spacing is needed around the popupItem // Defines the alignment of the content with respect of the headerItem, by default to the right
property alias popupPadding: popup.padding 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 // How much padding is needed around the header & button
property alias headerPadding: background.padding property alias headerPadding: background.padding
@ -52,9 +64,7 @@ Item
property alias iconSize: collapseButton.height property alias iconSize: collapseButton.height
// Is the "drawer" open? // Is the "drawer" open?
readonly property alias expanded: popup.visible readonly property alias expanded: contentContainer.visible
property alias expandedHighlightColor: expandedHighlight.color
// What should the radius of the header be. This is also influenced by the headerCornerSide // What should the radius of the header be. This is also influenced by the headerCornerSide
property alias headerRadius: background.radius property alias headerRadius: background.radius
@ -68,33 +78,33 @@ Item
property int shadowOffset: 2 property int shadowOffset: 2
function togglePopup() function toggleContent()
{ {
if(popup.visible) contentContainer.visible = !expanded
{
popup.close()
} }
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: // The panel needs to close when it becomes disabled
{
// Since we want the size of the popup to be set by the size of the content,
// we need to do it like this.
popup.width = popupItem.width + 2 * popup.padding
popup.height = popupItem.height + 2 * popup.padding
popup.contentItem = popupItem
}
Connections Connections
{ {
// Since it could be that the popup is dynamically populated, we should also take these changes into account. target: base
target: popupItem onEnabledChanged:
onWidthChanged: popup.width = popupItem.width + 2 * popup.padding {
onHeightChanged: popup.height = popupItem.height + 2 * popup.padding if (!base.enabled && expanded)
{
toggleContent()
}
}
} }
implicitHeight: 100 * screenScaleFactor implicitHeight: 100 * screenScaleFactor
@ -105,9 +115,29 @@ Item
id: background id: background
property real padding: UM.Theme.getSize("default_margin").width 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 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 Loader
{ {
id: headerItemLoader 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 UM.RecolorImage
{ {
id: collapseButton id: collapseButton
@ -141,22 +160,25 @@ Item
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
margins: background.padding margins: background.padding
} }
visible: source != "" && base.enabled source: UM.Theme.getIcon("pencil")
width: height visible: source != ""
height: Math.round(0.2 * base.height) width: UM.Theme.getSize("standard_arrow").width
color: UM.Theme.getColor("text") height: UM.Theme.getSize("standard_arrow").height
color: UM.Theme.getColor("small_button_text")
}
} }
MouseArea MouseArea
{ {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
onClicked: togglePopup() onClicked: toggleContent()
hoverEnabled: true hoverEnabled: true
onEntered: background.color = headerHoverColor onEntered: background.color = headerHoverColor
onExited: background.color = headerBackgroundColor onExited: background.color = base.enabled ? (base.expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled")
} }
} }
DropShadow DropShadow
{ {
id: shadow id: shadow
@ -171,26 +193,70 @@ Item
z: background.z - 1 z: background.z - 1
} }
Popup Cura.RoundedRectangle
{ {
id: popup id: contentContainer
// Ensure that the popup is located directly below the headerItem visible: false
y: headerItemLoader.height + 2 * background.padding + base.shadowOffset 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. // 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 x: contentAlignment == ExpandableComponent.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.All
{ color: contentBackgroundColor
cornerSide: Cura.RoundedRectangle.Direction.Down
color: popupBackgroundColor
border.width: UM.Theme.getSize("default_lining").width border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining") border.color: UM.Theme.getColor("lining")
radius: UM.Theme.getSize("default_radius").width 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 anchors.fill: parent
source: UM.Theme.getIcon("extruder_button") source: UM.Theme.getIcon("extruder_button")
color: extruderEnabled ? materialColor: "gray" color: extruderEnabled ? materialColor: UM.Theme.getColor("disabled")
} }
Rectangle 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) // It sets the icon size + half of the content as its minium width (in which case it will elide the text)
Item Item
{ {
property alias iconColor: icon.color
property alias source: icon.source property alias source: icon.source
property alias iconSize: icon.width
property alias color: label.color
property alias text: label.text property alias text: label.text
property alias font: label.font
property real margin: UM.Theme.getSize("narrow_margin").width property real margin: UM.Theme.getSize("narrow_margin").width
@ -37,7 +39,7 @@ Item
width: UM.Theme.getSize("section_icon").width width: UM.Theme.getSize("section_icon").width
height: UM.Theme.getSize("section_icon").height height: UM.Theme.getSize("section_icon").height
color: "black" color: label.color
anchors anchors
{ {

View file

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

View file

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

View file

@ -12,7 +12,7 @@ Column
id: base id: base
property var outputDevice: null property var outputDevice: null
height: childrenRect.height + 2 * padding height: childrenRect.height + 2 * padding
spacing: Math.round(UM.Theme.getSize("default_margin").height / 2) spacing: UM.Theme.getSize("narrow_margin").height
function forceModelUpdate() function forceModelUpdate()
{ {
@ -55,7 +55,7 @@ Column
ListView ListView
{ {
id: configurationList 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. width: container.width - ((height > container.maximumHeight) ? container.ScrollBar.vertical.background.width : 0) //Make room for scroll bar if there is any.
contentHeight: childrenRect.height contentHeight: childrenRect.height
height: childrenRect.height height: childrenRect.height
@ -64,11 +64,12 @@ Column
section.criteria: ViewSection.FullString section.criteria: ViewSection.FullString
section.delegate: Item 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 Cura.PrinterTypeLabel
{ {
id: printerTypeLabel id: printerTypeLabel
text: Cura.MachineManager.getAbbreviatedMachineName(section) 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 * Menu that allows you to select the configuration of the current printer, such
* as the nozzle sizes and materials in each extruder. * as the nozzle sizes and materials in each extruder.
*/ */
Cura.ExpandableComponent Cura.ExpandablePopup
{ {
id: base id: base
@ -30,14 +30,15 @@ Cura.ExpandableComponent
enum ConfigurationMethod enum ConfigurationMethod
{ {
AUTO, Auto,
CUSTOM 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 headerItem: Item
{ {
// Horizontal list that shows the extruders // Horizontal list that shows the extruders and their materials
ListView ListView
{ {
id: extrudersList id: extrudersList
@ -45,7 +46,7 @@ Cura.ExpandableComponent
orientation: ListView.Horizontal orientation: ListView.Horizontal
anchors.fill: parent anchors.fill: parent
model: extrudersModel model: extrudersModel
visible: base.enabled visible: Cura.MachineManager.hasMaterials
delegate: Item delegate: Item
{ {
@ -102,26 +103,28 @@ Cura.ExpandableComponent
} }
} }
} }
}
//Disable the menu if there are no materials, variants or build plates to change. //Placeholder text if there is a configuration to select but no materials (so we can't show the materials per extruder).
function updateEnabled() Label
{ {
var active_definition_id = Cura.MachineManager.activeMachine.definition.id; text: catalog.i18nc("@label", "Select configuration")
var has_materials = Cura.ContainerManager.getContainerMetaDataEntry(active_definition_id, "has_materials"); elide: Text.ElideRight
var has_variants = Cura.ContainerManager.getContainerMetaDataEntry(active_definition_id, "has_variants"); font: UM.Theme.getFont("default")
var has_buildplates = Cura.ContainerManager.getContainerMetaDataEntry(active_definition_id, "has_variant_buildplates"); color: UM.Theme.getColor("text")
base.enabled = has_materials || has_variants || has_buildplates; //Only let it drop down if there is any configuration that you could change. renderType: Text.NativeRendering
}
Connections visible: !Cura.MachineManager.hasMaterials && (Cura.MachineManager.hasVariants || Cura.MachineManager.hasVariantBuildplates)
anchors
{ {
target: Cura.MachineManager left: parent.left
onGlobalContainerChanged: base.updateEnabled(); leftMargin: UM.Theme.getSize("default_margin").width
verticalCenter: parent.verticalCenter
}
}
} }
Component.onCompleted: updateEnabled();
popupItem: Column contentItem: Column
{ {
id: popupItem id: popupItem
width: base.width - 2 * UM.Theme.getSize("default_margin").width 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. 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 Item
{ {
width: parent.width 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 AutoConfiguration
{ {
id: autoConfiguration id: autoConfiguration
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.AUTO visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto
} }
CustomConfiguration CustomConfiguration
{ {
id: 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 id: separator
visible: buttonBar.visible visible: buttonBar.visible
x: -popupPadding x: -contentPadding
width: base.width width: base.width
height: UM.Theme.getSize("default_lining").height height: UM.Theme.getSize("default_lining").height
@ -177,7 +192,7 @@ Cura.ExpandableComponent
Cura.SecondaryButton Cura.SecondaryButton
{ {
id: goToCustom id: goToCustom
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.AUTO visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto
text: catalog.i18nc("@label", "Custom") text: catalog.i18nc("@label", "Custom")
anchors.right: parent.right anchors.right: parent.right
@ -185,18 +200,18 @@ Cura.ExpandableComponent
iconSource: UM.Theme.getIcon("arrow_right") iconSource: UM.Theme.getIcon("arrow_right")
isIconOnRightSide: true isIconOnRightSide: true
onClicked: popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.CUSTOM onClicked: popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.Custom
} }
Cura.SecondaryButton Cura.SecondaryButton
{ {
id: goToAuto id: goToAuto
visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.CUSTOM visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Custom
text: catalog.i18nc("@label", "Configurations") text: catalog.i18nc("@label", "Configurations")
iconSource: UM.Theme.getIcon("arrow_left") 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 UM.TabRow
{ {
id: tabBar id: tabBar
anchors.top: header.bottom anchors.top: printerTypeSelectorRow.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.topMargin: UM.Theme.getSize("default_margin").height
visible: extrudersModel.count > 1 visible: extrudersModel.count > 1
@ -141,6 +188,7 @@ Item
Row Row
{ {
height: UM.Theme.getSize("print_setup_item").height 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 Label
{ {
@ -150,7 +198,6 @@ Item
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
height: parent.height height: parent.height
width: selectors.textWidth width: selectors.textWidth
visible: extrudersModel.count > 1
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -160,7 +207,6 @@ Item
enabled: !checked || Cura.MachineManager.numberExtrudersEnabled > 1 //Disable if it's the last enabled extruder. enabled: !checked || Cura.MachineManager.numberExtrudersEnabled > 1 //Disable if it's the last enabled extruder.
height: UM.Theme.getSize("setting_control").height height: UM.Theme.getSize("setting_control").height
style: UM.Theme.styles.checkbox style: UM.Theme.styles.checkbox
visible: extrudersModel.count > 1
/* Use a MouseArea to process the click on this checkbox. /* Use a MouseArea to process the click on this checkbox.
This is necessary because actually clicking the checkbox This is necessary because actually clicking the checkbox
@ -179,6 +225,8 @@ Item
Row Row
{ {
height: UM.Theme.getSize("print_setup_item").height height: UM.Theme.getSize("print_setup_item").height
visible: Cura.MachineManager.hasMaterials
Label Label
{ {
text: catalog.i18nc("@label", "Material") text: catalog.i18nc("@label", "Material")
@ -187,7 +235,6 @@ Item
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
height: parent.height height: parent.height
width: selectors.textWidth width: selectors.textWidth
visible: materialSelection.visible
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -200,12 +247,11 @@ Item
text: Cura.MachineManager.activeStack != null ? Cura.MachineManager.activeStack.material.name : "" text: Cura.MachineManager.activeStack != null ? Cura.MachineManager.activeStack.material.name : ""
tooltip: text tooltip: text
visible: Cura.MachineManager.hasMaterials
height: UM.Theme.getSize("setting_control").height height: UM.Theme.getSize("setting_control").height
width: selectors.controlWidth width: selectors.controlWidth
style: UM.Theme.styles.sidebar_header_button style: UM.Theme.styles.print_setup_header_button
activeFocusOnPress: true activeFocusOnPress: true
menu: Cura.MaterialMenu menu: Cura.MaterialMenu
{ {
@ -217,6 +263,7 @@ Item
Row Row
{ {
height: UM.Theme.getSize("print_setup_item").height height: UM.Theme.getSize("print_setup_item").height
visible: Cura.MachineManager.hasVariants
Label Label
{ {
@ -226,7 +273,6 @@ Item
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
height: parent.height height: parent.height
width: selectors.textWidth width: selectors.textWidth
visible: variantSelection.visible
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -234,12 +280,11 @@ Item
{ {
id: variantSelection id: variantSelection
text: Cura.MachineManager.activeVariantName text: Cura.MachineManager.activeVariantName
tooltip: Cura.MachineManager.activeVariantName; tooltip: Cura.MachineManager.activeVariantName
visible: Cura.MachineManager.hasVariants
height: UM.Theme.getSize("setting_control").height height: UM.Theme.getSize("setting_control").height
width: selectors.controlWidth width: selectors.controlWidth
style: UM.Theme.styles.sidebar_header_button style: UM.Theme.styles.print_setup_header_button
activeFocusOnPress: true; activeFocusOnPress: true;
menu: Cura.NozzleMenu { extruderIndex: Cura.ExtruderManager.activeExtruderIndex } menu: Cura.NozzleMenu { extruderIndex: Cura.ExtruderManager.activeExtruderIndex }

View file

@ -20,7 +20,7 @@ Row
{ {
materialColor: printCoreConfiguration.material.color materialColor: printCoreConfiguration.material.color
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
extruderEnabled: printCoreConfiguration.material.name !== "" && printCoreConfiguration.hotendID !== "" extruderEnabled: printCoreConfiguration.material.brand !== "" && printCoreConfiguration.hotendID !== ""
} }
Column Column
@ -36,7 +36,7 @@ Row
} }
Label 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 renderType: Text.NativeRendering
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")

View file

@ -16,10 +16,11 @@ Menu
Instantiator Instantiator
{ {
model: Cura.ExtrudersModel { simpleNames: true } model: Cura.MachineManager.activeMachine.extruderList
Menu Menu
{ {
title: model.name title: modelData.name
NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.hasVariants; extruderIndex: index } NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.hasVariants; extruderIndex: index }
MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.hasMaterials; 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 Button
@ -325,7 +325,7 @@ Item
text: catalog.i18nc("@label", "Abort Print") text: catalog.i18nc("@label", "Abort Print")
onClicked: confirmationDialog.visible = true onClicked: confirmationDialog.visible = true
style: UM.Theme.styles.sidebar_action_button style: UM.Theme.styles.print_setup_action_button
} }
MessageDialog MessageDialog

View file

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

View file

@ -224,7 +224,7 @@ Rectangle
{ {
id: arrangeAllBuildPlatesButton; id: arrangeAllBuildPlatesButton;
text: catalog.i18nc("@action:button","Arrange to all build plates"); 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; height: UM.Theme.getSize("objects_menu_button").height;
tooltip: ''; tooltip: '';
anchors anchors
@ -244,7 +244,7 @@ Rectangle
{ {
id: arrangeBuildPlateButton; id: arrangeBuildPlateButton;
text: catalog.i18nc("@action:button","Arrange current build plate"); 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; height: UM.Theme.getSize("objects_menu_button").height;
tooltip: ''; tooltip: '';
anchors anchors

View file

@ -49,7 +49,7 @@ Rectangle
property var activePrinter: connectedDevice != null ? connectedDevice.activePrinter : null property var activePrinter: connectedDevice != null ? connectedDevice.activePrinter : null
property var activePrintJob: activePrinter != null ? activePrinter.activePrintJob: null property var activePrintJob: activePrinter != null ? activePrinter.activePrintJob: null
SidebarTooltip PrintSetupTooltip
{ {
id: tooltip 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