mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-12 09:17:50 -06:00
Fix merge conflicts
This commit is contained in:
commit
b6ea61612e
265 changed files with 11829 additions and 9342 deletions
|
@ -38,12 +38,13 @@ class Account(QObject):
|
||||||
|
|
||||||
self._callback_port = 32118
|
self._callback_port = 32118
|
||||||
self._oauth_root = "https://account.ultimaker.com"
|
self._oauth_root = "https://account.ultimaker.com"
|
||||||
|
self._cloud_api_root = "https://api.ultimaker.com"
|
||||||
|
|
||||||
self._oauth_settings = OAuth2Settings(
|
self._oauth_settings = OAuth2Settings(
|
||||||
OAUTH_SERVER_URL= self._oauth_root,
|
OAUTH_SERVER_URL= self._oauth_root,
|
||||||
CALLBACK_PORT=self._callback_port,
|
CALLBACK_PORT=self._callback_port,
|
||||||
CALLBACK_URL="http://localhost:{}/callback".format(self._callback_port),
|
CALLBACK_URL="http://localhost:{}/callback".format(self._callback_port),
|
||||||
CLIENT_ID="um----------------------------ultimaker_cura",
|
CLIENT_ID="um---------------ultimaker_cura_drive_plugin",
|
||||||
CLIENT_SCOPES="account.user.read drive.backup.read drive.backup.write packages.download packages.rating.read packages.rating.write",
|
CLIENT_SCOPES="account.user.read drive.backup.read drive.backup.write packages.download packages.rating.read packages.rating.write",
|
||||||
AUTH_DATA_PREFERENCE_KEY="general/ultimaker_auth_data",
|
AUTH_DATA_PREFERENCE_KEY="general/ultimaker_auth_data",
|
||||||
AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(self._oauth_root),
|
AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(self._oauth_root),
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -526,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()
|
||||||
|
|
|
@ -434,6 +434,7 @@ class CuraApplication(QtApplication):
|
||||||
"XmlMaterialProfile", #Cura crashes without this one.
|
"XmlMaterialProfile", #Cura crashes without this one.
|
||||||
"Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back.
|
"Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back.
|
||||||
"PrepareStage", #Cura is useless without this one since you can't load models.
|
"PrepareStage", #Cura is useless without this one since you can't load models.
|
||||||
|
"PreviewStage", #This shows the list of the plugin views that are installed in Cura.
|
||||||
"MonitorStage", #Major part of Cura's functionality.
|
"MonitorStage", #Major part of Cura's functionality.
|
||||||
"LocalFileOutputDevice", #Major part of Cura's functionality.
|
"LocalFileOutputDevice", #Major part of Cura's functionality.
|
||||||
"LocalContainerProvider", #Cura is useless without any profiles or setting definitions.
|
"LocalContainerProvider", #Cura is useless without any profiles or setting definitions.
|
||||||
|
@ -627,8 +628,6 @@ class CuraApplication(QtApplication):
|
||||||
self._message_box_callback = None
|
self._message_box_callback = None
|
||||||
self._message_box_callback_arguments = []
|
self._message_box_callback_arguments = []
|
||||||
|
|
||||||
showPrintMonitor = pyqtSignal(bool, arguments = ["show"])
|
|
||||||
|
|
||||||
def setSaveDataEnabled(self, enabled: bool) -> None:
|
def setSaveDataEnabled(self, enabled: bool) -> None:
|
||||||
self._save_data_enabled = enabled
|
self._save_data_enabled = enabled
|
||||||
|
|
||||||
|
@ -1659,7 +1658,9 @@ class CuraApplication(QtApplication):
|
||||||
is_non_sliceable = "." + file_extension in self._non_sliceable_extensions
|
is_non_sliceable = "." + file_extension in self._non_sliceable_extensions
|
||||||
|
|
||||||
if is_non_sliceable:
|
if is_non_sliceable:
|
||||||
self.callLater(lambda: self.getController().setActiveView("SimulationView"))
|
# Need to switch first to the preview stage and then to layer view
|
||||||
|
self.callLater(lambda: (self.getController().setActiveStage("PreviewStage"),
|
||||||
|
self.getController().setActiveView("SimulationView")))
|
||||||
|
|
||||||
block_slicing_decorator = BlockSlicingDecorator()
|
block_slicing_decorator = BlockSlicingDecorator()
|
||||||
node.addDecorator(block_slicing_decorator)
|
node.addDecorator(block_slicing_decorator)
|
||||||
|
|
24
cura/CuraView.py
Normal file
24
cura/CuraView.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
from PyQt5.QtCore import pyqtProperty, QUrl
|
||||||
|
|
||||||
|
from UM.View.View import View
|
||||||
|
|
||||||
|
|
||||||
|
# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
|
||||||
|
# to indicate this.
|
||||||
|
# MainComponent works in the same way the MainComponent of a stage.
|
||||||
|
# the stageMenuComponent returns an item that should be used somehwere in the stage menu. It's up to the active stage
|
||||||
|
# to actually do something with this.
|
||||||
|
class CuraView(View):
|
||||||
|
def __init__(self, parent = None) -> None:
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
@pyqtProperty(QUrl, constant = True)
|
||||||
|
def mainComponent(self) -> QUrl:
|
||||||
|
return self.getDisplayComponent("main")
|
||||||
|
|
||||||
|
@pyqtProperty(QUrl, constant = True)
|
||||||
|
def stageMenuComponent(self) -> QUrl:
|
||||||
|
return self.getDisplayComponent("menu")
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -81,9 +81,14 @@ class AuthorizationHelpers:
|
||||||
# \param access_token: The encoded JWT token.
|
# \param access_token: The encoded JWT token.
|
||||||
# \return: Dict containing some profile data.
|
# \return: Dict containing some profile data.
|
||||||
def parseJWT(self, access_token: str) -> Optional["UserProfile"]:
|
def parseJWT(self, access_token: str) -> Optional["UserProfile"]:
|
||||||
|
try:
|
||||||
token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = {
|
token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = {
|
||||||
"Authorization": "Bearer {}".format(access_token)
|
"Authorization": "Bearer {}".format(access_token)
|
||||||
})
|
})
|
||||||
|
except ConnectionError:
|
||||||
|
# Connection was suddenly dropped. Nothing we can do about that.
|
||||||
|
Logger.logException("e", "Something failed while attempting to parse the JWT token")
|
||||||
|
return None
|
||||||
if token_request.status_code not in (200, 201):
|
if token_request.status_code not in (200, 201):
|
||||||
Logger.log("w", "Could not retrieve token data from auth server: %s", token_request.text)
|
Logger.log("w", "Could not retrieve token data from auth server: %s", token_request.text)
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -394,21 +394,7 @@ class PrintInformation(QObject):
|
||||||
return
|
return
|
||||||
active_machine_type_name = global_container_stack.definition.getName()
|
active_machine_type_name = global_container_stack.definition.getName()
|
||||||
|
|
||||||
abbr_machine = ""
|
self._abbr_machine = self._application.getMachineManager().getAbbreviatedMachineName(active_machine_type_name)
|
||||||
for word in re.findall(r"[\w']+", active_machine_type_name):
|
|
||||||
if word.lower() == "ultimaker":
|
|
||||||
abbr_machine += "UM"
|
|
||||||
elif word.isdigit():
|
|
||||||
abbr_machine += word
|
|
||||||
else:
|
|
||||||
stripped_word = self._stripAccents(word.upper())
|
|
||||||
# - use only the first character if the word is too long (> 3 characters)
|
|
||||||
# - use the whole word if it's not too long (<= 3 characters)
|
|
||||||
if len(stripped_word) > 3:
|
|
||||||
stripped_word = stripped_word[0]
|
|
||||||
abbr_machine += stripped_word
|
|
||||||
|
|
||||||
self._abbr_machine = abbr_machine
|
|
||||||
|
|
||||||
## Utility method that strips accents from characters (eg: â -> a)
|
## Utility method that strips accents from characters (eg: â -> a)
|
||||||
def _stripAccents(self, to_strip: str) -> str:
|
def _stripAccents(self, to_strip: str) -> str:
|
||||||
|
|
|
@ -211,6 +211,11 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||||
self._unique_configurations.sort(key = lambda k: k.printerType)
|
self._unique_configurations.sort(key = lambda k: k.printerType)
|
||||||
self.uniqueConfigurationsChanged.emit()
|
self.uniqueConfigurationsChanged.emit()
|
||||||
|
|
||||||
|
# Returns the unique configurations of the printers within this output device
|
||||||
|
@pyqtProperty("QStringList", notify = uniqueConfigurationsChanged)
|
||||||
|
def uniquePrinterTypes(self) -> List[str]:
|
||||||
|
return list(set([configuration.printerType for configuration in self._unique_configurations]))
|
||||||
|
|
||||||
def _onPrintersChanged(self) -> None:
|
def _onPrintersChanged(self) -> None:
|
||||||
for printer in self._printers:
|
for printer in self._printers:
|
||||||
printer.configurationChanged.connect(self._updateUniqueConfigurations)
|
printer.configurationChanged.connect(self._updateUniqueConfigurations)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -63,7 +63,7 @@ class ExtruderManager(QObject):
|
||||||
if not self._application.getGlobalContainerStack():
|
if not self._application.getGlobalContainerStack():
|
||||||
return None # No active machine, so no active extruder.
|
return None # No active machine, so no active extruder.
|
||||||
try:
|
try:
|
||||||
return self._extruder_trains[self._application.getGlobalContainerStack().getId()][str(self._active_extruder_index)].getId()
|
return self._extruder_trains[self._application.getGlobalContainerStack().getId()][str(self.activeExtruderIndex)].getId()
|
||||||
except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong.
|
except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong.
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -144,7 +145,7 @@ class ExtruderManager(QObject):
|
||||||
|
|
||||||
@pyqtSlot(result = QObject)
|
@pyqtSlot(result = QObject)
|
||||||
def getActiveExtruderStack(self) -> Optional["ExtruderStack"]:
|
def getActiveExtruderStack(self) -> Optional["ExtruderStack"]:
|
||||||
return self.getExtruderStack(self._active_extruder_index)
|
return self.getExtruderStack(self.activeExtruderIndex)
|
||||||
|
|
||||||
## Get an extruder stack by index
|
## Get an extruder stack by index
|
||||||
def getExtruderStack(self, index) -> Optional["ExtruderStack"]:
|
def getExtruderStack(self, index) -> Optional["ExtruderStack"]:
|
||||||
|
@ -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.
|
||||||
|
|
|
@ -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 "enabled" not in self._metadata:
|
if self.getMetaDataEntry("enabled", True) == enabled: # No change.
|
||||||
self.setMetaDataEntry("enabled", "True")
|
return # Don't emit a signal then.
|
||||||
self.setMetaDataEntry("enabled", str(enabled))
|
self.setMetaDataEntry("enabled", str(enabled))
|
||||||
self.enabledChanged.emit()
|
self.enabledChanged.emit()
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, pyqtProperty, QTimer
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, pyqtProperty, QTimer
|
||||||
|
@ -24,8 +24,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
|
|
||||||
## Human-readable name of the extruder.
|
## Human-readable name of the extruder.
|
||||||
NameRole = Qt.UserRole + 2
|
NameRole = Qt.UserRole + 2
|
||||||
## Is the extruder enabled?
|
|
||||||
EnabledRole = Qt.UserRole + 9
|
|
||||||
|
|
||||||
## Colour of the material loaded in the extruder.
|
## Colour of the material loaded in the extruder.
|
||||||
ColorRole = Qt.UserRole + 3
|
ColorRole = Qt.UserRole + 3
|
||||||
|
@ -47,6 +45,12 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
VariantRole = Qt.UserRole + 7
|
VariantRole = Qt.UserRole + 7
|
||||||
StackRole = Qt.UserRole + 8
|
StackRole = Qt.UserRole + 8
|
||||||
|
|
||||||
|
MaterialBrandRole = Qt.UserRole + 9
|
||||||
|
ColorNameRole = Qt.UserRole + 10
|
||||||
|
|
||||||
|
## Is the extruder enabled?
|
||||||
|
EnabledRole = Qt.UserRole + 11
|
||||||
|
|
||||||
## List of colours to display if there is no material or the material has no known
|
## List of colours to display if there is no material or the material has no known
|
||||||
# colour.
|
# colour.
|
||||||
defaultColors = ["#ffc924", "#86ec21", "#22eeee", "#245bff", "#9124ff", "#ff24c8"]
|
defaultColors = ["#ffc924", "#86ec21", "#22eeee", "#245bff", "#9124ff", "#ff24c8"]
|
||||||
|
@ -67,7 +71,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
self.addRoleName(self.MaterialRole, "material")
|
self.addRoleName(self.MaterialRole, "material")
|
||||||
self.addRoleName(self.VariantRole, "variant")
|
self.addRoleName(self.VariantRole, "variant")
|
||||||
self.addRoleName(self.StackRole, "stack")
|
self.addRoleName(self.StackRole, "stack")
|
||||||
|
self.addRoleName(self.MaterialBrandRole, "material_brand")
|
||||||
|
self.addRoleName(self.ColorNameRole, "color_name")
|
||||||
self._update_extruder_timer = QTimer()
|
self._update_extruder_timer = QTimer()
|
||||||
self._update_extruder_timer.setInterval(100)
|
self._update_extruder_timer.setInterval(100)
|
||||||
self._update_extruder_timer.setSingleShot(True)
|
self._update_extruder_timer.setSingleShot(True)
|
||||||
|
@ -160,7 +165,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
def __updateExtruders(self):
|
def __updateExtruders(self):
|
||||||
extruders_changed = False
|
extruders_changed = False
|
||||||
|
|
||||||
if self.rowCount() != 0:
|
if self.count != 0:
|
||||||
extruders_changed = True
|
extruders_changed = True
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
|
@ -172,7 +177,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value")
|
machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value")
|
||||||
|
|
||||||
for extruder in Application.getInstance().getExtruderManager().getActiveExtruderStacks():
|
for extruder in Application.getInstance().getExtruderManager().getActiveExtruderStacks():
|
||||||
position = extruder.getMetaDataEntry("position", default = "0") # Get the position
|
position = extruder.getMetaDataEntry("position", default = "0")
|
||||||
try:
|
try:
|
||||||
position = int(position)
|
position = int(position)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -183,7 +188,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
|
|
||||||
default_color = self.defaultColors[position] if 0 <= position < len(self.defaultColors) else self.defaultColors[0]
|
default_color = self.defaultColors[position] if 0 <= position < len(self.defaultColors) else self.defaultColors[0]
|
||||||
color = extruder.material.getMetaDataEntry("color_code", default = default_color) if extruder.material else default_color
|
color = extruder.material.getMetaDataEntry("color_code", default = default_color) if extruder.material else default_color
|
||||||
|
material_brand = extruder.material.getMetaDataEntry("brand", default = "generic")
|
||||||
|
color_name = extruder.material.getMetaDataEntry("color_name")
|
||||||
# construct an item with only the relevant information
|
# construct an item with only the relevant information
|
||||||
item = {
|
item = {
|
||||||
"id": extruder.getId(),
|
"id": extruder.getId(),
|
||||||
|
@ -195,6 +201,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
"material": extruder.material.getName() if extruder.material else "",
|
"material": extruder.material.getName() if extruder.material else "",
|
||||||
"variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core
|
"variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core
|
||||||
"stack": extruder,
|
"stack": extruder,
|
||||||
|
"material_brand": material_brand,
|
||||||
|
"color_name": color_name
|
||||||
}
|
}
|
||||||
|
|
||||||
items.append(item)
|
items.append(item)
|
||||||
|
@ -216,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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import time
|
import time
|
||||||
|
import re
|
||||||
|
import unicodedata
|
||||||
from typing import Any, Callable, List, Dict, TYPE_CHECKING, Optional, cast
|
from typing import Any, Callable, List, Dict, TYPE_CHECKING, Optional, cast
|
||||||
|
|
||||||
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
||||||
|
@ -1534,9 +1536,32 @@ 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
|
||||||
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
||||||
self.updateMaterialWithVariant(None)
|
self.updateMaterialWithVariant(None)
|
||||||
self._updateQualityWithMaterial()
|
self._updateQualityWithMaterial()
|
||||||
|
|
||||||
|
## This function will translate any printer type name to an abbreviated printer type name
|
||||||
|
@pyqtSlot(str, result = str)
|
||||||
|
def getAbbreviatedMachineName(self, machine_type_name: str) -> str:
|
||||||
|
abbr_machine = ""
|
||||||
|
for word in re.findall(r"[\w']+", machine_type_name):
|
||||||
|
if word.lower() == "ultimaker":
|
||||||
|
abbr_machine += "UM"
|
||||||
|
elif word.isdigit():
|
||||||
|
abbr_machine += word
|
||||||
|
else:
|
||||||
|
stripped_word = "".join(char for char in unicodedata.normalize("NFD", word.upper()) if unicodedata.category(char) != "Mn")
|
||||||
|
# - use only the first character if the word is too long (> 3 characters)
|
||||||
|
# - use the whole word if it's not too long (<= 3 characters)
|
||||||
|
if len(stripped_word) > 3:
|
||||||
|
stripped_word = stripped_word[0]
|
||||||
|
abbr_machine += stripped_word
|
||||||
|
|
||||||
|
return abbr_machine
|
||||||
|
|
|
@ -1,23 +1,33 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtProperty, QUrl
|
from PyQt5.QtCore import pyqtProperty, QUrl
|
||||||
|
|
||||||
from UM.Stage import Stage
|
from UM.Stage import Stage
|
||||||
|
|
||||||
|
|
||||||
|
# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
|
||||||
|
# to indicate this.
|
||||||
|
# * The StageMenuComponent is the horizontal area below the stage bar. This should be used to show stage specific
|
||||||
|
# buttons and elements. This component will be drawn over the bar & main component.
|
||||||
|
# * The MainComponent is the component that will be drawn starting from the bottom of the stageBar and fills the rest
|
||||||
|
# of the screen.
|
||||||
class CuraStage(Stage):
|
class CuraStage(Stage):
|
||||||
|
def __init__(self, parent = None) -> None:
|
||||||
def __init__(self, parent = None):
|
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def stageId(self):
|
def stageId(self) -> str:
|
||||||
return self.getPluginId()
|
return self.getPluginId()
|
||||||
|
|
||||||
@pyqtProperty(QUrl, constant = True)
|
@pyqtProperty(QUrl, constant = True)
|
||||||
def mainComponent(self):
|
def mainComponent(self) -> QUrl:
|
||||||
return self.getDisplayComponent("main")
|
return self.getDisplayComponent("main")
|
||||||
|
|
||||||
@pyqtProperty(QUrl, constant = True)
|
@pyqtProperty(QUrl, constant = True)
|
||||||
def sidebarComponent(self):
|
def sidebarComponent(self) -> QUrl:
|
||||||
return self.getDisplayComponent("sidebar")
|
return self.getDisplayComponent("sidebar")
|
||||||
|
|
||||||
|
@pyqtProperty(QUrl, constant = True)
|
||||||
|
def stageMenuComponent(self) -> QUrl:
|
||||||
|
return self.getDisplayComponent("menu")
|
|
@ -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.
|
||||||
|
|
|
@ -195,7 +195,7 @@ class ProcessSlicedLayersJob(Job):
|
||||||
if extruders:
|
if extruders:
|
||||||
material_color_map = numpy.zeros((len(extruders), 4), dtype=numpy.float32)
|
material_color_map = numpy.zeros((len(extruders), 4), dtype=numpy.float32)
|
||||||
for extruder in extruders:
|
for extruder in extruders:
|
||||||
position = int(extruder.getMetaDataEntry("position", default="0")) # Get the position
|
position = int(extruder.getMetaDataEntry("position", default = "0"))
|
||||||
try:
|
try:
|
||||||
default_color = ExtrudersModel.defaultColors[position]
|
default_color = ExtrudersModel.defaultColors[position]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2016 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
|
@ -23,7 +23,7 @@ Cura.MachineAction
|
||||||
target: base.extrudersModel
|
target: base.extrudersModel
|
||||||
onModelChanged:
|
onModelChanged:
|
||||||
{
|
{
|
||||||
var extruderCount = base.extrudersModel.rowCount();
|
var extruderCount = base.extrudersModel.count;
|
||||||
base.extruderTabsCount = extruderCount;
|
base.extruderTabsCount = extruderCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -33,7 +35,6 @@ 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;
|
||||||
sourceSize.width: width;
|
|
||||||
sourceSize.height: width;
|
sourceSize.height: width;
|
||||||
color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene");
|
color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene");
|
||||||
source: "model_checker.svg"
|
source: "model_checker.svg"
|
||||||
|
|
|
@ -1,26 +1,21 @@
|
||||||
// Copyright (c) 2017 Ultimaker B.V.
|
// Copyright (c) 2017 Ultimaker B.V.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.10
|
||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.4
|
||||||
|
|
||||||
import UM 1.3 as UM
|
import UM 1.3 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
// parent could be undefined as this component is not visible at all times
|
|
||||||
width: parent ? parent.width : 0
|
|
||||||
height: parent ? parent.height : 0
|
|
||||||
|
|
||||||
// We show a nice overlay on the 3D viewer when the current output device has no monitor view
|
// We show a nice overlay on the 3D viewer when the current output device has no monitor view
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
id: viewportOverlay
|
id: viewportOverlay
|
||||||
|
|
||||||
color: UM.Theme.getColor("viewport_overlay")
|
color: UM.Theme.getColor("viewport_overlay")
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
height: parent.height
|
|
||||||
|
|
||||||
MouseArea
|
MouseArea
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -33,13 +28,13 @@ Item
|
||||||
{
|
{
|
||||||
id: monitorViewComponent
|
id: monitorViewComponent
|
||||||
|
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
|
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
property real maximumWidth: parent.width
|
property real maximumWidth: parent.width
|
||||||
property real maximumHeight: parent.height
|
property real maximumHeight: parent.height
|
||||||
|
|
||||||
sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null
|
sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null
|
||||||
visible: sourceComponent != null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
23
plugins/MonitorStage/MonitorMenu.qml
Normal file
23
plugins/MonitorStage/MonitorMenu.qml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
|
import UM 1.3 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
signal showTooltip(Item item, point location, string text)
|
||||||
|
signal hideTooltip()
|
||||||
|
|
||||||
|
Cura.MachineSelector
|
||||||
|
{
|
||||||
|
id: machineSelection
|
||||||
|
headerCornerSide: Cura.RoundedRectangle.Direction.All
|
||||||
|
width: UM.Theme.getSize("machine_selector_widget").width
|
||||||
|
height: parent.height
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,15 +65,10 @@ class MonitorStage(CuraStage):
|
||||||
# We can only connect now, as we need to be sure that everything is loaded (plugins get created quite early)
|
# We can only connect now, as we need to be sure that everything is loaded (plugins get created quite early)
|
||||||
Application.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
|
Application.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
|
||||||
self._onOutputDevicesChanged()
|
self._onOutputDevicesChanged()
|
||||||
self._updateMainOverlay()
|
|
||||||
self._updateSidebar()
|
|
||||||
|
|
||||||
def _updateMainOverlay(self):
|
plugin_path = Application.getInstance().getPluginRegistry().getPluginPath(self.getPluginId())
|
||||||
main_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("MonitorStage"),
|
if plugin_path is not None:
|
||||||
"MonitorMainView.qml")
|
menu_component_path = os.path.join(plugin_path, "MonitorMenu.qml")
|
||||||
|
main_component_path = os.path.join(plugin_path, "MonitorMain.qml")
|
||||||
|
self.addDisplayComponent("menu", menu_component_path)
|
||||||
self.addDisplayComponent("main", main_component_path)
|
self.addDisplayComponent("main", main_component_path)
|
||||||
|
|
||||||
def _updateSidebar(self):
|
|
||||||
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
|
|
||||||
"MonitorSidebar.qml")
|
|
||||||
self.addDisplayComponent("sidebar", sidebar_component_path)
|
|
||||||
|
|
|
@ -7,14 +7,16 @@ from . import MonitorStage
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
i18n_catalog = i18nCatalog("cura")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
def getMetaData():
|
def getMetaData():
|
||||||
return {
|
return {
|
||||||
"stage": {
|
"stage": {
|
||||||
"name": i18n_catalog.i18nc("@item:inmenu", "Monitor"),
|
"name": i18n_catalog.i18nc("@item:inmenu", "Monitor"),
|
||||||
"weight": 1
|
"weight": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
return {
|
return {
|
||||||
"stage": MonitorStage.MonitorStage()
|
"stage": MonitorStage.MonitorStage()
|
||||||
|
|
|
@ -265,7 +265,6 @@ Item {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: width
|
height: width
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: width
|
sourceSize.height: width
|
||||||
color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
|
color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
|
||||||
source: UM.Theme.getIcon("minus")
|
source: UM.Theme.getIcon("minus")
|
||||||
|
|
|
@ -141,7 +141,6 @@ UM.Dialog
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: Math.round(control.width / 2.7)
|
width: Math.round(control.width / 2.7)
|
||||||
height: Math.round(control.height / 2.7)
|
height: Math.round(control.height / 2.7)
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: width
|
sourceSize.height: width
|
||||||
color: palette.text
|
color: palette.text
|
||||||
source: UM.Theme.getIcon("cross1")
|
source: UM.Theme.getIcon("cross1")
|
||||||
|
@ -176,7 +175,6 @@ UM.Dialog
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: Math.round(control.width / 2.5)
|
width: Math.round(control.width / 2.5)
|
||||||
height: Math.round(control.height / 2.5)
|
height: Math.round(control.height / 2.5)
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: width
|
sourceSize.height: width
|
||||||
color: control.enabled ? palette.text : disabledPalette.text
|
color: control.enabled ? palette.text : disabledPalette.text
|
||||||
source: UM.Theme.getIcon("arrow_bottom")
|
source: UM.Theme.getIcon("arrow_bottom")
|
||||||
|
@ -211,7 +209,6 @@ UM.Dialog
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: Math.round(control.width / 2.5)
|
width: Math.round(control.width / 2.5)
|
||||||
height: Math.round(control.height / 2.5)
|
height: Math.round(control.height / 2.5)
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: width
|
sourceSize.height: width
|
||||||
color: control.enabled ? palette.text : disabledPalette.text
|
color: control.enabled ? palette.text : disabledPalette.text
|
||||||
source: UM.Theme.getIcon("arrow_top")
|
source: UM.Theme.getIcon("arrow_top")
|
||||||
|
@ -260,7 +257,7 @@ UM.Dialog
|
||||||
|
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
color: UM.Theme.getColor("sidebar")
|
color: UM.Theme.getColor("main_background")
|
||||||
anchors.left: activeScripts.right
|
anchors.left: activeScripts.right
|
||||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
@ -415,7 +412,7 @@ UM.Dialog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cura.SidebarTooltip
|
Cura.PrintSetupTooltip
|
||||||
{
|
{
|
||||||
id: tooltip
|
id: tooltip
|
||||||
}
|
}
|
||||||
|
@ -498,7 +495,6 @@ UM.Dialog
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: Math.round(parent.width / 2)
|
width: Math.round(parent.width / 2)
|
||||||
height: Math.round(parent.height / 2)
|
height: Math.round(parent.height / 2)
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: height
|
sourceSize.height: height
|
||||||
color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") :
|
color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") :
|
||||||
control.pressed ? UM.Theme.getColor("action_button_active_text") :
|
control.pressed ? UM.Theme.getColor("action_button_active_text") :
|
||||||
|
|
134
plugins/PrepareStage/PrepareMenu.qml
Normal file
134
plugins/PrepareStage/PrepareMenu.qml
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
|
import UM 1.3 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
import QtGraphicalEffects 1.0 // For the dropshadow
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: prepareMenu
|
||||||
|
|
||||||
|
UM.I18nCatalog
|
||||||
|
{
|
||||||
|
id: catalog
|
||||||
|
name: "cura"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item to ensure that all of the buttons are nicely centered.
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: openFileButton.width + itemRow.width + UM.Theme.getSize("default_margin").width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
id: itemRow
|
||||||
|
|
||||||
|
anchors.left: openFileButton.right
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
width: Math.round(0.9 * prepareMenu.width)
|
||||||
|
height: parent.height
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Cura.MachineSelector
|
||||||
|
{
|
||||||
|
id: machineSelection
|
||||||
|
headerCornerSide: Cura.RoundedRectangle.Direction.Left
|
||||||
|
Layout.minimumWidth: UM.Theme.getSize("machine_selector_widget").width
|
||||||
|
Layout.maximumWidth: UM.Theme.getSize("machine_selector_widget").width
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: parent.height
|
||||||
|
width: UM.Theme.getSize("default_lining").width
|
||||||
|
color: UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.ConfigurationMenu
|
||||||
|
{
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredWidth: itemRow.width - machineSelection.width - printSetupSelectorItem.width - 2 * UM.Theme.getSize("default_lining").width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: parent.height
|
||||||
|
width: UM.Theme.getSize("default_lining").width
|
||||||
|
color: UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: printSetupSelectorItem
|
||||||
|
// This is a work around to prevent the printSetupSelector from having to be re-loaded every time
|
||||||
|
// a stage switch is done.
|
||||||
|
children: [printSetupSelector]
|
||||||
|
height: childrenRect.height
|
||||||
|
width: childrenRect.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: openFileButton
|
||||||
|
height: UM.Theme.getSize("stage_menu").height
|
||||||
|
width: UM.Theme.getSize("stage_menu").height
|
||||||
|
onClicked: Cura.Actions.open.trigger()
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
contentItem: Item
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: buttonIcon
|
||||||
|
anchors.centerIn: parent
|
||||||
|
source: UM.Theme.getIcon("load")
|
||||||
|
width: UM.Theme.getSize("button_icon").width
|
||||||
|
height: UM.Theme.getSize("button_icon").height
|
||||||
|
color: UM.Theme.getColor("toolbar_button_text")
|
||||||
|
|
||||||
|
sourceSize.height: height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
id: background
|
||||||
|
height: UM.Theme.getSize("stage_menu").height
|
||||||
|
width: UM.Theme.getSize("stage_menu").height
|
||||||
|
|
||||||
|
radius: UM.Theme.getSize("default_radius").width
|
||||||
|
color: openFileButton.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
|
||||||
|
}
|
||||||
|
|
||||||
|
DropShadow
|
||||||
|
{
|
||||||
|
id: shadow
|
||||||
|
// Don't blur the shadow
|
||||||
|
radius: 0
|
||||||
|
anchors.fill: background
|
||||||
|
source: background
|
||||||
|
verticalOffset: 2
|
||||||
|
visible: true
|
||||||
|
color: UM.Theme.getColor("action_button_shadow")
|
||||||
|
// Should always be drawn behind the background.
|
||||||
|
z: background.z - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,13 +2,14 @@
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
import os.path
|
import os.path
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
from UM.PluginRegistry import PluginRegistry
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
from cura.Stages.CuraStage import CuraStage
|
from cura.Stages.CuraStage import CuraStage
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Stage for preparing model (slicing).
|
## Stage for preparing model (slicing).
|
||||||
class PrepareStage(CuraStage):
|
class PrepareStage(CuraStage):
|
||||||
|
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
Application.getInstance().engineCreatedSignal.connect(self._engineCreated)
|
Application.getInstance().engineCreatedSignal.connect(self._engineCreated)
|
||||||
|
@ -16,4 +17,7 @@ class PrepareStage(CuraStage):
|
||||||
def _engineCreated(self):
|
def _engineCreated(self):
|
||||||
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
|
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
|
||||||
"PrepareSidebar.qml")
|
"PrepareSidebar.qml")
|
||||||
|
|
||||||
|
menu_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMenu.qml")
|
||||||
|
self.addDisplayComponent("menu", menu_component_path)
|
||||||
self.addDisplayComponent("sidebar", sidebar_component_path)
|
self.addDisplayComponent("sidebar", sidebar_component_path)
|
||||||
|
|
18
plugins/PreviewStage/PreviewMain.qml
Normal file
18
plugins/PreviewStage/PreviewMain.qml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.4
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Controls.Styles 1.1
|
||||||
|
|
||||||
|
import UM 1.0 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
|
||||||
|
Loader
|
||||||
|
{
|
||||||
|
id: previewMain
|
||||||
|
|
||||||
|
source: UM.Controller.activeView != null && UM.Controller.activeView.mainComponent != null ? UM.Controller.activeView.mainComponent : ""
|
||||||
|
}
|
74
plugins/PreviewStage/PreviewMenu.qml
Normal file
74
plugins/PreviewStage/PreviewMenu.qml
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
|
import UM 1.3 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: previewMenu
|
||||||
|
|
||||||
|
property real itemHeight: height - 2 * UM.Theme.getSize("default_lining").width
|
||||||
|
|
||||||
|
UM.I18nCatalog
|
||||||
|
{
|
||||||
|
id: catalog
|
||||||
|
name: "cura"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: stageMenuRow
|
||||||
|
anchors.centerIn: parent
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
Cura.ViewsSelector
|
||||||
|
{
|
||||||
|
id: viewsSelector
|
||||||
|
height: parent.height
|
||||||
|
width: UM.Theme.getSize("views_selector").width
|
||||||
|
headerCornerSide: Cura.RoundedRectangle.Direction.Left
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: parent.height
|
||||||
|
// If there is no viewPanel, we only need a single spacer, so hide this one.
|
||||||
|
visible: viewPanel.source != ""
|
||||||
|
width: visible ? UM.Theme.getSize("default_lining").width : 0
|
||||||
|
|
||||||
|
color: UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader
|
||||||
|
{
|
||||||
|
id: viewPanel
|
||||||
|
height: parent.height
|
||||||
|
width: childrenRect.width
|
||||||
|
source: UM.Controller.activeView != null && UM.Controller.activeView.stageMenuComponent != null ? UM.Controller.activeView.stageMenuComponent : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: parent.height
|
||||||
|
width: UM.Theme.getSize("default_lining").width
|
||||||
|
color: UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: printSetupSelectorItem
|
||||||
|
// This is a work around to prevent the printSetupSelector from having to be re-loaded every time
|
||||||
|
// a stage switch is done.
|
||||||
|
children: [printSetupSelector]
|
||||||
|
height: childrenRect.height
|
||||||
|
width: childrenRect.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
plugins/PreviewStage/PreviewStage.py
Normal file
51
plugins/PreviewStage/PreviewStage.py
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from UM.Qt.QtApplication import QtApplication
|
||||||
|
from cura.Stages.CuraStage import CuraStage
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from UM.View.View import View
|
||||||
|
|
||||||
|
|
||||||
|
## Displays a preview of what you're about to print.
|
||||||
|
#
|
||||||
|
# The Python component of this stage just loads PreviewMain.qml for display
|
||||||
|
# when the stage is selected, and makes sure that it reverts to the previous
|
||||||
|
# view when the previous stage is activated.
|
||||||
|
class PreviewStage(CuraStage):
|
||||||
|
def __init__(self, application: QtApplication, parent = None) -> None:
|
||||||
|
super().__init__(parent)
|
||||||
|
self._application = application
|
||||||
|
self._application.engineCreatedSignal.connect(self._engineCreated)
|
||||||
|
self._previously_active_view = None # type: Optional[View]
|
||||||
|
|
||||||
|
## When selecting the stage, remember which was the previous view so that
|
||||||
|
# we can revert to that view when we go out of the stage later.
|
||||||
|
def onStageSelected(self) -> None:
|
||||||
|
self._previously_active_view = self._application.getController().getActiveView()
|
||||||
|
|
||||||
|
## Called when going to a different stage (away from the Preview Stage).
|
||||||
|
#
|
||||||
|
# When going to a different stage, the view should be reverted to what it
|
||||||
|
# was before. Normally, that just reverts it to solid view.
|
||||||
|
def onStageDeselected(self) -> None:
|
||||||
|
if self._previously_active_view is not None:
|
||||||
|
self._application.getController().setActiveView(self._previously_active_view.getPluginId())
|
||||||
|
self._previously_active_view = None
|
||||||
|
|
||||||
|
## Delayed load of the QML files.
|
||||||
|
#
|
||||||
|
# We need to make sure that the QML engine is running before we can load
|
||||||
|
# these.
|
||||||
|
def _engineCreated(self) -> None:
|
||||||
|
plugin_path = self._application.getPluginRegistry().getPluginPath(self.getPluginId())
|
||||||
|
if plugin_path is not None:
|
||||||
|
menu_component_path = os.path.join(plugin_path, "PreviewMenu.qml")
|
||||||
|
main_component_path = os.path.join(plugin_path, "PreviewMain.qml")
|
||||||
|
self.addDisplayComponent("menu", menu_component_path)
|
||||||
|
self.addDisplayComponent("main", main_component_path)
|
22
plugins/PreviewStage/__init__.py
Normal file
22
plugins/PreviewStage/__init__.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
from . import PreviewStage
|
||||||
|
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
|
def getMetaData():
|
||||||
|
return {
|
||||||
|
"stage": {
|
||||||
|
"name": i18n_catalog.i18nc("@item:inmenu", "Preview"),
|
||||||
|
"weight": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def register(app):
|
||||||
|
return {
|
||||||
|
"stage": PreviewStage.PreviewStage(app)
|
||||||
|
}
|
8
plugins/PreviewStage/plugin.json
Normal file
8
plugins/PreviewStage/plugin.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "Preview Stage",
|
||||||
|
"author": "Ultimaker B.V.",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Provides a preview stage in Cura.",
|
||||||
|
"api": 5,
|
||||||
|
"i18n-catalog": "cura"
|
||||||
|
}
|
|
@ -13,23 +13,20 @@ Item
|
||||||
{
|
{
|
||||||
id: sliderRoot
|
id: sliderRoot
|
||||||
|
|
||||||
// handle properties
|
// Handle properties
|
||||||
property real handleSize: 10
|
property real handleSize: UM.Theme.getSize("slider_handle").width
|
||||||
property real handleRadius: handleSize / 2
|
property real handleRadius: handleSize / 2
|
||||||
property real minimumRangeHandleSize: handleSize / 2
|
property real minimumRangeHandleSize: handleSize / 2
|
||||||
property color upperHandleColor: "black"
|
property color upperHandleColor: UM.Theme.getColor("slider_handle")
|
||||||
property color lowerHandleColor: "black"
|
property color lowerHandleColor: UM.Theme.getColor("slider_handle")
|
||||||
property color rangeHandleColor: "black"
|
property color rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
|
||||||
property color handleActiveColor: "white"
|
property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
||||||
property real handleLabelWidth: width
|
|
||||||
property var activeHandle: upperHandle
|
property var activeHandle: upperHandle
|
||||||
|
|
||||||
// track properties
|
// Track properties
|
||||||
property real trackThickness: 4 // width of the slider track
|
property real trackThickness: UM.Theme.getSize("slider_groove").width // width of the slider track
|
||||||
property real trackRadius: trackThickness / 2
|
property real trackRadius: UM.Theme.getSize("slider_groove_radius").width
|
||||||
property color trackColor: "white"
|
property color trackColor: UM.Theme.getColor("slider_groove")
|
||||||
property real trackBorderWidth: 1 // width of the slider track border
|
|
||||||
property color trackBorderColor: "black"
|
|
||||||
|
|
||||||
// value properties
|
// value properties
|
||||||
property real maximumValue: 100
|
property real maximumValue: 100
|
||||||
|
@ -80,7 +77,7 @@ Item
|
||||||
return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue)
|
return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// slider track
|
// Slider track
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
id: track
|
id: track
|
||||||
|
@ -90,8 +87,6 @@ Item
|
||||||
radius: sliderRoot.trackRadius
|
radius: sliderRoot.trackRadius
|
||||||
anchors.centerIn: sliderRoot
|
anchors.centerIn: sliderRoot
|
||||||
color: sliderRoot.trackColor
|
color: sliderRoot.trackColor
|
||||||
border.width: sliderRoot.trackBorderWidth
|
|
||||||
border.color: sliderRoot.trackBorderColor
|
|
||||||
visible: sliderRoot.layersVisible
|
visible: sliderRoot.layersVisible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +101,7 @@ Item
|
||||||
anchors.horizontalCenter: sliderRoot.horizontalCenter
|
anchors.horizontalCenter: sliderRoot.horizontalCenter
|
||||||
visible: sliderRoot.layersVisible
|
visible: sliderRoot.layersVisible
|
||||||
|
|
||||||
// set the new value when dragging
|
// Set the new value when dragging
|
||||||
function onHandleDragged()
|
function onHandleDragged()
|
||||||
{
|
{
|
||||||
sliderRoot.manuallyChanged = true
|
sliderRoot.manuallyChanged = true
|
||||||
|
@ -140,9 +135,10 @@ Item
|
||||||
|
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
width: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth
|
width: sliderRoot.trackThickness
|
||||||
height: parent.height + sliderRoot.handleSize
|
height: parent.height + sliderRoot.handleSize
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
radius: sliderRoot.trackRadius
|
||||||
color: sliderRoot.rangeHandleColor
|
color: sliderRoot.rangeHandleColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,9 +163,9 @@ Item
|
||||||
id: rangleHandleLabel
|
id: rangleHandleLabel
|
||||||
|
|
||||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
x: parent.x + parent.width + UM.Theme.getSize("default_margin").width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
target: Qt.point(sliderRoot.width, y + height / 2)
|
target: Qt.point(sliderRoot.width + width, y + height / 2)
|
||||||
visible: sliderRoot.activeHandle == parent
|
visible: sliderRoot.activeHandle == parent
|
||||||
|
|
||||||
// custom properties
|
// custom properties
|
||||||
|
@ -275,7 +271,7 @@ Item
|
||||||
id: upperHandleLabel
|
id: upperHandleLabel
|
||||||
|
|
||||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
x: parent.x - parent.width - width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
target: Qt.point(sliderRoot.width, y + height / 2)
|
target: Qt.point(sliderRoot.width, y + height / 2)
|
||||||
visible: sliderRoot.activeHandle == parent
|
visible: sliderRoot.activeHandle == parent
|
||||||
|
@ -385,9 +381,9 @@ Item
|
||||||
id: lowerHandleLabel
|
id: lowerHandleLabel
|
||||||
|
|
||||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
x: parent.x - parent.width - width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
target: Qt.point(sliderRoot.width, y + height / 2)
|
target: Qt.point(sliderRoot.width + width, y + height / 2)
|
||||||
visible: sliderRoot.activeHandle == parent
|
visible: sliderRoot.activeHandle == parent
|
||||||
|
|
||||||
// custom properties
|
// custom properties
|
||||||
|
|
|
@ -14,19 +14,17 @@ Item
|
||||||
id: sliderRoot
|
id: sliderRoot
|
||||||
|
|
||||||
// handle properties
|
// handle properties
|
||||||
property real handleSize: 10
|
property real handleSize: UM.Theme.getSize("slider_handle").width
|
||||||
property real handleRadius: handleSize / 2
|
property real handleRadius: handleSize / 2
|
||||||
property color handleColor: "black"
|
property color handleColor: UM.Theme.getColor("slider_handle")
|
||||||
property color handleActiveColor: "white"
|
property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
||||||
property color rangeColor: "black"
|
property color rangeColor: UM.Theme.getColor("slider_groove_fill")
|
||||||
property real handleLabelWidth: width
|
property real handleLabelWidth: width
|
||||||
|
|
||||||
// track properties
|
// track properties
|
||||||
property real trackThickness: 4 // width of the slider track
|
property real trackThickness: UM.Theme.getSize("slider_groove").width
|
||||||
property real trackRadius: trackThickness / 2
|
property real trackRadius: UM.Theme.getSize("slider_groove_radius").width
|
||||||
property color trackColor: "white"
|
property color trackColor: UM.Theme.getColor("slider_groove")
|
||||||
property real trackBorderWidth: 1 // width of the slider track border
|
|
||||||
property color trackBorderColor: "black"
|
|
||||||
|
|
||||||
// value properties
|
// value properties
|
||||||
property real maximumValue: 100
|
property real maximumValue: 100
|
||||||
|
@ -68,8 +66,6 @@ Item
|
||||||
radius: sliderRoot.trackRadius
|
radius: sliderRoot.trackRadius
|
||||||
anchors.centerIn: sliderRoot
|
anchors.centerIn: sliderRoot
|
||||||
color: sliderRoot.trackColor
|
color: sliderRoot.trackColor
|
||||||
border.width: sliderRoot.trackBorderWidth
|
|
||||||
border.color: sliderRoot.trackBorderColor
|
|
||||||
visible: sliderRoot.pathsVisible
|
visible: sliderRoot.pathsVisible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,9 +82,10 @@ Item
|
||||||
|
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
height: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth
|
height: sliderRoot.trackThickness
|
||||||
width: parent.width + sliderRoot.handleSize
|
width: parent.width + sliderRoot.handleSize
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
radius: sliderRoot.trackRadius
|
||||||
color: sliderRoot.rangeColor
|
color: sliderRoot.rangeColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ from UM.Mesh.MeshBuilder import MeshBuilder
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from UM.Platform import Platform
|
from UM.Platform import Platform
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
from UM.Qt.QtApplication import QtApplication
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||||
|
|
||||||
|
@ -26,8 +27,8 @@ from UM.View.GL.OpenGL import OpenGL
|
||||||
from UM.View.GL.OpenGLContext import OpenGLContext
|
from UM.View.GL.OpenGLContext import OpenGLContext
|
||||||
from UM.View.GL.ShaderProgram import ShaderProgram
|
from UM.View.GL.ShaderProgram import ShaderProgram
|
||||||
|
|
||||||
from UM.View.View import View
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
from cura.CuraView import CuraView
|
||||||
from cura.Scene.ConvexHullNode import ConvexHullNode
|
from cura.Scene.ConvexHullNode import ConvexHullNode
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
|
|
||||||
|
@ -48,15 +49,15 @@ catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
## View used to display g-code paths.
|
## View used to display g-code paths.
|
||||||
class SimulationView(View):
|
class SimulationView(CuraView):
|
||||||
# Must match SimulationView.qml
|
# Must match SimulationView.qml
|
||||||
LAYER_VIEW_TYPE_MATERIAL_TYPE = 0
|
LAYER_VIEW_TYPE_MATERIAL_TYPE = 0
|
||||||
LAYER_VIEW_TYPE_LINE_TYPE = 1
|
LAYER_VIEW_TYPE_LINE_TYPE = 1
|
||||||
LAYER_VIEW_TYPE_FEEDRATE = 2
|
LAYER_VIEW_TYPE_FEEDRATE = 2
|
||||||
LAYER_VIEW_TYPE_THICKNESS = 3
|
LAYER_VIEW_TYPE_THICKNESS = 3
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self, parent = None) -> None:
|
||||||
super().__init__()
|
super().__init__(parent)
|
||||||
|
|
||||||
self._max_layers = 0
|
self._max_layers = 0
|
||||||
self._current_layer_num = 0
|
self._current_layer_num = 0
|
||||||
|
@ -113,6 +114,16 @@ class SimulationView(View):
|
||||||
self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled"),
|
self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled"),
|
||||||
title = catalog.i18nc("@info:title", "Simulation View"))
|
title = catalog.i18nc("@info:title", "Simulation View"))
|
||||||
|
|
||||||
|
QtApplication.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
|
||||||
|
|
||||||
|
def _onEngineCreated(self) -> None:
|
||||||
|
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
|
||||||
|
if plugin_path:
|
||||||
|
self.addDisplayComponent("main", os.path.join(plugin_path, "SimulationViewMainComponent.qml"))
|
||||||
|
self.addDisplayComponent("menu", os.path.join(plugin_path, "SimulationViewMenuComponent.qml"))
|
||||||
|
else:
|
||||||
|
Logger.log("e", "Unable to find the path for %s", self.getPluginId())
|
||||||
|
|
||||||
def _evaluateCompatibilityMode(self) -> bool:
|
def _evaluateCompatibilityMode(self) -> bool:
|
||||||
return OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode"))
|
return OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode"))
|
||||||
|
|
||||||
|
|
|
@ -1,808 +0,0 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.4
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Controls.Styles 1.1
|
|
||||||
|
|
||||||
import UM 1.0 as UM
|
|
||||||
import Cura 1.0 as Cura
|
|
||||||
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
id: base
|
|
||||||
width:
|
|
||||||
{
|
|
||||||
if (UM.SimulationView.compatibilityMode)
|
|
||||||
{
|
|
||||||
return UM.Theme.getSize("layerview_menu_size_compatibility").width;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return UM.Theme.getSize("layerview_menu_size").width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
height: {
|
|
||||||
if (viewSettings.collapsed)
|
|
||||||
{
|
|
||||||
if (UM.SimulationView.compatibilityMode)
|
|
||||||
{
|
|
||||||
return UM.Theme.getSize("layerview_menu_size_compatibility_collapsed").height;
|
|
||||||
}
|
|
||||||
return UM.Theme.getSize("layerview_menu_size_collapsed").height;
|
|
||||||
}
|
|
||||||
else if (UM.SimulationView.compatibilityMode)
|
|
||||||
{
|
|
||||||
return UM.Theme.getSize("layerview_menu_size_compatibility").height;
|
|
||||||
}
|
|
||||||
else if (UM.Preferences.getValue("layerview/layer_view_type") == 0)
|
|
||||||
{
|
|
||||||
return UM.Theme.getSize("layerview_menu_size_material_color_mode").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return UM.Theme.getSize("layerview_menu_size").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on height { NumberAnimation { duration: 100 } }
|
|
||||||
|
|
||||||
property var buttonTarget:
|
|
||||||
{
|
|
||||||
if(parent != null)
|
|
||||||
{
|
|
||||||
var force_binding = parent.y; // ensure this gets reevaluated when the panel moves
|
|
||||||
return base.mapFromItem(parent.parent, parent.buttonTarget.x, parent.buttonTarget.y)
|
|
||||||
}
|
|
||||||
return Qt.point(0,0)
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
id: layerViewMenu
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
clip: true
|
|
||||||
z: layerSlider.z - 1
|
|
||||||
color: UM.Theme.getColor("tool_panel_background")
|
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
|
||||||
border.color: UM.Theme.getColor("lining")
|
|
||||||
|
|
||||||
Button {
|
|
||||||
id: collapseButton
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: Math.round(UM.Theme.getSize("default_margin").height + (UM.Theme.getSize("layerview_row").height - UM.Theme.getSize("default_margin").height) / 2)
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
|
||||||
|
|
||||||
width: UM.Theme.getSize("standard_arrow").width
|
|
||||||
height: UM.Theme.getSize("standard_arrow").height
|
|
||||||
|
|
||||||
onClicked: viewSettings.collapsed = !viewSettings.collapsed
|
|
||||||
|
|
||||||
style: ButtonStyle
|
|
||||||
{
|
|
||||||
background: UM.RecolorImage
|
|
||||||
{
|
|
||||||
width: control.width
|
|
||||||
height: control.height
|
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: width
|
|
||||||
color: UM.Theme.getColor("setting_control_text")
|
|
||||||
source: viewSettings.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom")
|
|
||||||
}
|
|
||||||
label: Label{ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout
|
|
||||||
{
|
|
||||||
id: viewSettings
|
|
||||||
|
|
||||||
property bool collapsed: false
|
|
||||||
property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
|
|
||||||
property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
|
|
||||||
property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
|
|
||||||
property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
|
|
||||||
property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
|
|
||||||
// if we are in compatibility mode, we only show the "line type"
|
|
||||||
property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1
|
|
||||||
property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3
|
|
||||||
property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2
|
|
||||||
property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3
|
|
||||||
property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
|
|
||||||
property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
|
||||||
spacing: UM.Theme.getSize("layerview_row_spacing").height
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: layerViewTypesLabel
|
|
||||||
anchors.left: parent.left
|
|
||||||
text: catalog.i18nc("@label","Color scheme")
|
|
||||||
font: UM.Theme.getFont("default");
|
|
||||||
visible: !UM.SimulationView.compatibilityMode
|
|
||||||
Layout.fillWidth: true
|
|
||||||
color: UM.Theme.getColor("setting_control_text")
|
|
||||||
}
|
|
||||||
|
|
||||||
ListModel // matches SimulationView.py
|
|
||||||
{
|
|
||||||
id: layerViewTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted:
|
|
||||||
{
|
|
||||||
layerViewTypes.append({
|
|
||||||
text: catalog.i18nc("@label:listbox", "Material Color"),
|
|
||||||
type_id: 0
|
|
||||||
})
|
|
||||||
layerViewTypes.append({
|
|
||||||
text: catalog.i18nc("@label:listbox", "Line Type"),
|
|
||||||
type_id: 1
|
|
||||||
})
|
|
||||||
layerViewTypes.append({
|
|
||||||
text: catalog.i18nc("@label:listbox", "Feedrate"),
|
|
||||||
type_id: 2
|
|
||||||
})
|
|
||||||
layerViewTypes.append({
|
|
||||||
text: catalog.i18nc("@label:listbox", "Layer thickness"),
|
|
||||||
type_id: 3 // these ids match the switching in the shader
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
ComboBox
|
|
||||||
{
|
|
||||||
id: layerTypeCombobox
|
|
||||||
anchors.left: parent.left
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
|
||||||
model: layerViewTypes
|
|
||||||
visible: !UM.SimulationView.compatibilityMode
|
|
||||||
style: UM.Theme.styles.combobox
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
onActivated:
|
|
||||||
{
|
|
||||||
UM.Preferences.setValue("layerview/layer_view_type", index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted:
|
|
||||||
{
|
|
||||||
currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
|
|
||||||
updateLegends(currentIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateLegends(type_id)
|
|
||||||
{
|
|
||||||
// update visibility of legends
|
|
||||||
viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
|
|
||||||
viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3);
|
|
||||||
viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2);
|
|
||||||
viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: compatibilityModeLabel
|
|
||||||
anchors.left: parent.left
|
|
||||||
text: catalog.i18nc("@label","Compatibility Mode")
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
color: UM.Theme.getColor("text")
|
|
||||||
visible: UM.SimulationView.compatibilityMode
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
|
|
||||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
|
||||||
}
|
|
||||||
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
height: Math.round(UM.Theme.getSize("default_margin").width / 2)
|
|
||||||
width: width
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections
|
|
||||||
{
|
|
||||||
target: UM.Preferences
|
|
||||||
onPreferenceChanged:
|
|
||||||
{
|
|
||||||
layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
|
|
||||||
layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex);
|
|
||||||
playButton.pauseSimulation();
|
|
||||||
viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|");
|
|
||||||
viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves");
|
|
||||||
viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers");
|
|
||||||
viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin");
|
|
||||||
viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill");
|
|
||||||
viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers");
|
|
||||||
viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater
|
|
||||||
{
|
|
||||||
model: Cura.ExtrudersModel{}
|
|
||||||
CheckBox
|
|
||||||
{
|
|
||||||
id: extrudersModelCheckBox
|
|
||||||
checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == ""
|
|
||||||
onClicked:
|
|
||||||
{
|
|
||||||
viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0
|
|
||||||
UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|"));
|
|
||||||
}
|
|
||||||
visible: !UM.SimulationView.compatibilityMode
|
|
||||||
enabled: index + 1 <= 4
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.right: extrudersModelCheckBox.right
|
|
||||||
width: UM.Theme.getSize("layerview_legend_size").width
|
|
||||||
height: UM.Theme.getSize("layerview_legend_size").height
|
|
||||||
color: model.color
|
|
||||||
radius: Math.round(width / 2)
|
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
|
||||||
border.color: UM.Theme.getColor("lining")
|
|
||||||
visible: !viewSettings.show_legend & !viewSettings.show_gradient
|
|
||||||
}
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
|
||||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
|
||||||
style: UM.Theme.styles.checkbox
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: model.name
|
|
||||||
elide: Text.ElideRight
|
|
||||||
color: UM.Theme.getColor("setting_control_text")
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.left: extrudersModelCheckBox.left;
|
|
||||||
anchors.right: extrudersModelCheckBox.right;
|
|
||||||
anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2)
|
|
||||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater
|
|
||||||
{
|
|
||||||
model: ListModel
|
|
||||||
{
|
|
||||||
id: typesLegendModel
|
|
||||||
Component.onCompleted:
|
|
||||||
{
|
|
||||||
typesLegendModel.append({
|
|
||||||
label: catalog.i18nc("@label", "Show Travels"),
|
|
||||||
initialValue: viewSettings.show_travel_moves,
|
|
||||||
preference: "layerview/show_travel_moves",
|
|
||||||
colorId: "layerview_move_combing"
|
|
||||||
});
|
|
||||||
typesLegendModel.append({
|
|
||||||
label: catalog.i18nc("@label", "Show Helpers"),
|
|
||||||
initialValue: viewSettings.show_helpers,
|
|
||||||
preference: "layerview/show_helpers",
|
|
||||||
colorId: "layerview_support"
|
|
||||||
});
|
|
||||||
typesLegendModel.append({
|
|
||||||
label: catalog.i18nc("@label", "Show Shell"),
|
|
||||||
initialValue: viewSettings.show_skin,
|
|
||||||
preference: "layerview/show_skin",
|
|
||||||
colorId: "layerview_inset_0"
|
|
||||||
});
|
|
||||||
typesLegendModel.append({
|
|
||||||
label: catalog.i18nc("@label", "Show Infill"),
|
|
||||||
initialValue: viewSettings.show_infill,
|
|
||||||
preference: "layerview/show_infill",
|
|
||||||
colorId: "layerview_infill"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox
|
|
||||||
{
|
|
||||||
id: legendModelCheckBox
|
|
||||||
checked: model.initialValue
|
|
||||||
onClicked:
|
|
||||||
{
|
|
||||||
UM.Preferences.setValue(model.preference, checked);
|
|
||||||
}
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.right: legendModelCheckBox.right
|
|
||||||
width: UM.Theme.getSize("layerview_legend_size").width
|
|
||||||
height: UM.Theme.getSize("layerview_legend_size").height
|
|
||||||
color: UM.Theme.getColor(model.colorId)
|
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
|
||||||
border.color: UM.Theme.getColor("lining")
|
|
||||||
visible: viewSettings.show_legend
|
|
||||||
}
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
|
||||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
|
||||||
style: UM.Theme.styles.checkbox
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: label
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
elide: Text.ElideRight
|
|
||||||
color: UM.Theme.getColor("setting_control_text")
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.left: legendModelCheckBox.left;
|
|
||||||
anchors.right: legendModelCheckBox.right;
|
|
||||||
anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2)
|
|
||||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox
|
|
||||||
{
|
|
||||||
checked: viewSettings.only_show_top_layers
|
|
||||||
onClicked:
|
|
||||||
{
|
|
||||||
UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0);
|
|
||||||
}
|
|
||||||
text: catalog.i18nc("@label", "Only Show Top Layers")
|
|
||||||
visible: UM.SimulationView.compatibilityMode
|
|
||||||
style: UM.Theme.styles.checkbox
|
|
||||||
}
|
|
||||||
CheckBox
|
|
||||||
{
|
|
||||||
checked: viewSettings.top_layer_count == 5
|
|
||||||
onClicked:
|
|
||||||
{
|
|
||||||
UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1);
|
|
||||||
}
|
|
||||||
text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
|
|
||||||
visible: UM.SimulationView.compatibilityMode
|
|
||||||
style: UM.Theme.styles.checkbox
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater
|
|
||||||
{
|
|
||||||
model: ListModel
|
|
||||||
{
|
|
||||||
id: typesLegendModelNoCheck
|
|
||||||
Component.onCompleted:
|
|
||||||
{
|
|
||||||
typesLegendModelNoCheck.append({
|
|
||||||
label: catalog.i18nc("@label", "Top / Bottom"),
|
|
||||||
colorId: "layerview_skin",
|
|
||||||
});
|
|
||||||
typesLegendModelNoCheck.append({
|
|
||||||
label: catalog.i18nc("@label", "Inner Wall"),
|
|
||||||
colorId: "layerview_inset_x",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: label
|
|
||||||
visible: viewSettings.show_legend
|
|
||||||
id: typesLegendModelLabel
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.right: typesLegendModelLabel.right
|
|
||||||
width: UM.Theme.getSize("layerview_legend_size").width
|
|
||||||
height: UM.Theme.getSize("layerview_legend_size").height
|
|
||||||
color: UM.Theme.getColor(model.colorId)
|
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
|
||||||
border.color: UM.Theme.getColor("lining")
|
|
||||||
visible: viewSettings.show_legend
|
|
||||||
}
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
|
||||||
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
|
|
||||||
color: UM.Theme.getColor("setting_control_text")
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text for the minimum, maximum and units for the feedrates and layer thickness
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
id: gradientLegend
|
|
||||||
visible: viewSettings.show_gradient
|
|
||||||
width: parent.width
|
|
||||||
height: UM.Theme.getSize("layerview_row").height
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
topMargin: UM.Theme.getSize("slider_layerview_margin").height
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: minText()
|
|
||||||
anchors.left: parent.left
|
|
||||||
color: UM.Theme.getColor("setting_control_text")
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
|
|
||||||
function minText()
|
|
||||||
{
|
|
||||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
|
||||||
{
|
|
||||||
// Feedrate selected
|
|
||||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
|
||||||
{
|
|
||||||
return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
|
|
||||||
}
|
|
||||||
// Layer thickness selected
|
|
||||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
|
||||||
{
|
|
||||||
return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return catalog.i18nc("@label","min")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: unitsText()
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
color: UM.Theme.getColor("setting_control_text")
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
|
|
||||||
function unitsText()
|
|
||||||
{
|
|
||||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
|
||||||
{
|
|
||||||
// Feedrate selected
|
|
||||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
|
||||||
{
|
|
||||||
return "mm/s"
|
|
||||||
}
|
|
||||||
// Layer thickness selected
|
|
||||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
|
||||||
{
|
|
||||||
return "mm"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: maxText()
|
|
||||||
anchors.right: parent.right
|
|
||||||
color: UM.Theme.getColor("setting_control_text")
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
|
|
||||||
function maxText()
|
|
||||||
{
|
|
||||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
|
||||||
{
|
|
||||||
// Feedrate selected
|
|
||||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
|
||||||
{
|
|
||||||
return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
|
|
||||||
}
|
|
||||||
// Layer thickness selected
|
|
||||||
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
|
||||||
{
|
|
||||||
return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return catalog.i18nc("@label","max")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gradient colors for feedrate
|
|
||||||
Rectangle
|
|
||||||
{ // In QML 5.9 can be changed by LinearGradient
|
|
||||||
// Invert values because then the bar is rotated 90 degrees
|
|
||||||
id: feedrateGradient
|
|
||||||
visible: viewSettings.show_feedrate_gradient
|
|
||||||
anchors.left: parent.right
|
|
||||||
height: parent.width
|
|
||||||
width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
|
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
|
||||||
border.color: UM.Theme.getColor("lining")
|
|
||||||
transform: Rotation {origin.x: 0; origin.y: 0; angle: 90}
|
|
||||||
gradient: Gradient
|
|
||||||
{
|
|
||||||
GradientStop
|
|
||||||
{
|
|
||||||
position: 0.000
|
|
||||||
color: Qt.rgba(1, 0.5, 0, 1)
|
|
||||||
}
|
|
||||||
GradientStop
|
|
||||||
{
|
|
||||||
position: 0.625
|
|
||||||
color: Qt.rgba(0.375, 0.5, 0, 1)
|
|
||||||
}
|
|
||||||
GradientStop
|
|
||||||
{
|
|
||||||
position: 0.75
|
|
||||||
color: Qt.rgba(0.25, 1, 0, 1)
|
|
||||||
}
|
|
||||||
GradientStop
|
|
||||||
{
|
|
||||||
position: 1.0
|
|
||||||
color: Qt.rgba(0, 0, 1, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gradient colors for layer thickness (similar to parula colormap)
|
|
||||||
Rectangle // In QML 5.9 can be changed by LinearGradient
|
|
||||||
{
|
|
||||||
// Invert values because then the bar is rotated 90 degrees
|
|
||||||
id: thicknessGradient
|
|
||||||
visible: viewSettings.show_thickness_gradient
|
|
||||||
anchors.left: parent.right
|
|
||||||
height: parent.width
|
|
||||||
width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
|
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
|
||||||
border.color: UM.Theme.getColor("lining")
|
|
||||||
transform: Rotation {origin.x: 0; origin.y: 0; angle: 90}
|
|
||||||
gradient: Gradient
|
|
||||||
{
|
|
||||||
GradientStop
|
|
||||||
{
|
|
||||||
position: 0.000
|
|
||||||
color: Qt.rgba(1, 1, 0, 1)
|
|
||||||
}
|
|
||||||
GradientStop
|
|
||||||
{
|
|
||||||
position: 0.25
|
|
||||||
color: Qt.rgba(1, 0.75, 0.25, 1)
|
|
||||||
}
|
|
||||||
GradientStop
|
|
||||||
{
|
|
||||||
position: 0.5
|
|
||||||
color: Qt.rgba(0, 0.75, 0.5, 1)
|
|
||||||
}
|
|
||||||
GradientStop
|
|
||||||
{
|
|
||||||
position: 0.75
|
|
||||||
color: Qt.rgba(0, 0.375, 0.75, 1)
|
|
||||||
}
|
|
||||||
GradientStop
|
|
||||||
{
|
|
||||||
position: 1.0
|
|
||||||
color: Qt.rgba(0, 0, 0.5, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
id: slidersBox
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
|
|
||||||
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
top: parent.bottom
|
|
||||||
topMargin: UM.Theme.getSize("slider_layerview_margin").height
|
|
||||||
left: parent.left
|
|
||||||
}
|
|
||||||
|
|
||||||
PathSlider
|
|
||||||
{
|
|
||||||
id: pathSlider
|
|
||||||
|
|
||||||
height: UM.Theme.getSize("slider_handle").width
|
|
||||||
anchors.left: playButton.right
|
|
||||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
|
||||||
anchors.right: parent.right
|
|
||||||
visible: !UM.SimulationView.compatibilityMode
|
|
||||||
|
|
||||||
// custom properties
|
|
||||||
handleValue: UM.SimulationView.currentPath
|
|
||||||
maximumValue: UM.SimulationView.numPaths
|
|
||||||
handleSize: UM.Theme.getSize("slider_handle").width
|
|
||||||
trackThickness: UM.Theme.getSize("slider_groove").width
|
|
||||||
trackColor: UM.Theme.getColor("slider_groove")
|
|
||||||
trackBorderColor: UM.Theme.getColor("slider_groove_border")
|
|
||||||
handleColor: UM.Theme.getColor("slider_handle")
|
|
||||||
handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
|
||||||
rangeColor: UM.Theme.getColor("slider_groove_fill")
|
|
||||||
|
|
||||||
// update values when layer data changes
|
|
||||||
Connections
|
|
||||||
{
|
|
||||||
target: UM.SimulationView
|
|
||||||
onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
|
||||||
onCurrentPathChanged:
|
|
||||||
{
|
|
||||||
// Only pause the simulation when the layer was changed manually, not when the simulation is running
|
|
||||||
if (pathSlider.manuallyChanged)
|
|
||||||
{
|
|
||||||
playButton.pauseSimulation()
|
|
||||||
}
|
|
||||||
pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the slider handlers show the correct value after switching views
|
|
||||||
Component.onCompleted:
|
|
||||||
{
|
|
||||||
pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerSlider
|
|
||||||
{
|
|
||||||
id: layerSlider
|
|
||||||
|
|
||||||
width: UM.Theme.getSize("slider_handle").width
|
|
||||||
height: UM.Theme.getSize("layerview_menu_size").height
|
|
||||||
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
top: !UM.SimulationView.compatibilityMode ? pathSlider.bottom : parent.top
|
|
||||||
topMargin: !UM.SimulationView.compatibilityMode ? UM.Theme.getSize("default_margin").height : 0
|
|
||||||
right: parent.right
|
|
||||||
rightMargin: UM.Theme.getSize("slider_layerview_margin").width
|
|
||||||
}
|
|
||||||
|
|
||||||
// custom properties
|
|
||||||
upperValue: UM.SimulationView.currentLayer
|
|
||||||
lowerValue: UM.SimulationView.minimumLayer
|
|
||||||
maximumValue: UM.SimulationView.numLayers
|
|
||||||
handleSize: UM.Theme.getSize("slider_handle").width
|
|
||||||
trackThickness: UM.Theme.getSize("slider_groove").width
|
|
||||||
trackColor: UM.Theme.getColor("slider_groove")
|
|
||||||
trackBorderColor: UM.Theme.getColor("slider_groove_border")
|
|
||||||
upperHandleColor: UM.Theme.getColor("slider_handle")
|
|
||||||
lowerHandleColor: UM.Theme.getColor("slider_handle")
|
|
||||||
rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
|
|
||||||
handleActiveColor: UM.Theme.getColor("slider_handle_active")
|
|
||||||
handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width
|
|
||||||
|
|
||||||
// update values when layer data changes
|
|
||||||
Connections
|
|
||||||
{
|
|
||||||
target: UM.SimulationView
|
|
||||||
onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
|
||||||
onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
|
|
||||||
onCurrentLayerChanged:
|
|
||||||
{
|
|
||||||
// Only pause the simulation when the layer was changed manually, not when the simulation is running
|
|
||||||
if (layerSlider.manuallyChanged)
|
|
||||||
{
|
|
||||||
playButton.pauseSimulation()
|
|
||||||
}
|
|
||||||
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the slider handlers show the correct value after switching views
|
|
||||||
Component.onCompleted:
|
|
||||||
{
|
|
||||||
layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
|
|
||||||
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Play simulation button
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
id: playButton
|
|
||||||
iconSource: "./resources/simulation_resume.svg"
|
|
||||||
style: UM.Theme.styles.small_tool_button
|
|
||||||
visible: !UM.SimulationView.compatibilityMode
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
verticalCenter: pathSlider.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
property var status: 0 // indicates if it's stopped (0) or playing (1)
|
|
||||||
|
|
||||||
onClicked:
|
|
||||||
{
|
|
||||||
switch(status)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
resumeSimulation()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
pauseSimulation()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function pauseSimulation()
|
|
||||||
{
|
|
||||||
UM.SimulationView.setSimulationRunning(false)
|
|
||||||
iconSource = "./resources/simulation_resume.svg"
|
|
||||||
simulationTimer.stop()
|
|
||||||
status = 0
|
|
||||||
layerSlider.manuallyChanged = true
|
|
||||||
pathSlider.manuallyChanged = true
|
|
||||||
}
|
|
||||||
|
|
||||||
function resumeSimulation()
|
|
||||||
{
|
|
||||||
UM.SimulationView.setSimulationRunning(true)
|
|
||||||
iconSource = "./resources/simulation_pause.svg"
|
|
||||||
simulationTimer.start()
|
|
||||||
layerSlider.manuallyChanged = false
|
|
||||||
pathSlider.manuallyChanged = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer
|
|
||||||
{
|
|
||||||
id: simulationTimer
|
|
||||||
interval: 100
|
|
||||||
running: false
|
|
||||||
repeat: true
|
|
||||||
onTriggered:
|
|
||||||
{
|
|
||||||
var currentPath = UM.SimulationView.currentPath
|
|
||||||
var numPaths = UM.SimulationView.numPaths
|
|
||||||
var currentLayer = UM.SimulationView.currentLayer
|
|
||||||
var numLayers = UM.SimulationView.numLayers
|
|
||||||
// When the user plays the simulation, if the path slider is at the end of this layer, we start
|
|
||||||
// the simulation at the beginning of the current layer.
|
|
||||||
if (playButton.status == 0)
|
|
||||||
{
|
|
||||||
if (currentPath >= numPaths)
|
|
||||||
{
|
|
||||||
UM.SimulationView.setCurrentPath(0)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UM.SimulationView.setCurrentPath(currentPath+1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the simulation is already playing and we reach the end of a layer, then it automatically
|
|
||||||
// starts at the beginning of the next layer.
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (currentPath >= numPaths)
|
|
||||||
{
|
|
||||||
// At the end of the model, the simulation stops
|
|
||||||
if (currentLayer >= numLayers)
|
|
||||||
{
|
|
||||||
playButton.pauseSimulation()
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UM.SimulationView.setCurrentLayer(currentLayer+1)
|
|
||||||
UM.SimulationView.setCurrentPath(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UM.SimulationView.setCurrentPath(currentPath+1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// The status must be set here instead of in the resumeSimulation function otherwise it won't work
|
|
||||||
// correctly, because part of the logic is in this trigger function.
|
|
||||||
playButton.status = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FontMetrics
|
|
||||||
{
|
|
||||||
id: fontMetrics
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
}
|
|
||||||
}
|
|
211
plugins/SimulationView/SimulationViewMainComponent.qml
Normal file
211
plugins/SimulationView/SimulationViewMainComponent.qml
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.4
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Controls.Styles 1.1
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
property bool is_simulation_playing: false
|
||||||
|
visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
|
||||||
|
|
||||||
|
PathSlider
|
||||||
|
{
|
||||||
|
id: pathSlider
|
||||||
|
height: UM.Theme.getSize("slider_handle").width
|
||||||
|
width: UM.Theme.getSize("slider_layerview_size").height
|
||||||
|
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
visible: !UM.SimulationView.compatibilityMode
|
||||||
|
|
||||||
|
// Custom properties
|
||||||
|
handleValue: UM.SimulationView.currentPath
|
||||||
|
maximumValue: UM.SimulationView.numPaths
|
||||||
|
|
||||||
|
// Update values when layer data changes.
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: UM.SimulationView
|
||||||
|
onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
||||||
|
onCurrentPathChanged:
|
||||||
|
{
|
||||||
|
// Only pause the simulation when the layer was changed manually, not when the simulation is running
|
||||||
|
if (pathSlider.manuallyChanged)
|
||||||
|
{
|
||||||
|
playButton.pauseSimulation()
|
||||||
|
}
|
||||||
|
pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the slider handlers show the correct value after switching views.
|
||||||
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
pathSlider.setHandleValue(UM.SimulationView.currentPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.SimpleButton
|
||||||
|
{
|
||||||
|
id: playButton
|
||||||
|
iconSource: !is_simulation_playing ? "./resources/simulation_resume.svg": "./resources/simulation_pause.svg"
|
||||||
|
width: UM.Theme.getSize("small_button").width
|
||||||
|
height: UM.Theme.getSize("small_button").height
|
||||||
|
hoverColor: UM.Theme.getColor("slider_handle_active")
|
||||||
|
color: UM.Theme.getColor("slider_handle")
|
||||||
|
iconMargin: UM.Theme.getSize("thick_lining").width
|
||||||
|
visible: !UM.SimulationView.compatibilityMode
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: UM.Preferences
|
||||||
|
onPreferenceChanged:
|
||||||
|
{
|
||||||
|
playButton.pauseSimulation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: pathSlider.left
|
||||||
|
verticalCenter: pathSlider.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
if(is_simulation_playing)
|
||||||
|
{
|
||||||
|
pauseSimulation()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resumeSimulation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pauseSimulation()
|
||||||
|
{
|
||||||
|
UM.SimulationView.setSimulationRunning(false)
|
||||||
|
simulationTimer.stop()
|
||||||
|
is_simulation_playing = false
|
||||||
|
layerSlider.manuallyChanged = true
|
||||||
|
pathSlider.manuallyChanged = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeSimulation()
|
||||||
|
{
|
||||||
|
UM.SimulationView.setSimulationRunning(true)
|
||||||
|
simulationTimer.start()
|
||||||
|
layerSlider.manuallyChanged = false
|
||||||
|
pathSlider.manuallyChanged = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer
|
||||||
|
{
|
||||||
|
id: simulationTimer
|
||||||
|
interval: 100
|
||||||
|
running: false
|
||||||
|
repeat: true
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
var currentPath = UM.SimulationView.currentPath
|
||||||
|
var numPaths = UM.SimulationView.numPaths
|
||||||
|
var currentLayer = UM.SimulationView.currentLayer
|
||||||
|
var numLayers = UM.SimulationView.numLayers
|
||||||
|
|
||||||
|
// When the user plays the simulation, if the path slider is at the end of this layer, we start
|
||||||
|
// the simulation at the beginning of the current layer.
|
||||||
|
if (!is_simulation_playing)
|
||||||
|
{
|
||||||
|
if (currentPath >= numPaths)
|
||||||
|
{
|
||||||
|
UM.SimulationView.setCurrentPath(0)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UM.SimulationView.setCurrentPath(currentPath + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the simulation is already playing and we reach the end of a layer, then it automatically
|
||||||
|
// starts at the beginning of the next layer.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (currentPath >= numPaths)
|
||||||
|
{
|
||||||
|
// At the end of the model, the simulation stops
|
||||||
|
if (currentLayer >= numLayers)
|
||||||
|
{
|
||||||
|
playButton.pauseSimulation()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UM.SimulationView.setCurrentLayer(currentLayer + 1)
|
||||||
|
UM.SimulationView.setCurrentPath(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UM.SimulationView.setCurrentPath(currentPath + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The status must be set here instead of in the resumeSimulation function otherwise it won't work
|
||||||
|
// correctly, because part of the logic is in this trigger function.
|
||||||
|
is_simulation_playing = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerSlider
|
||||||
|
{
|
||||||
|
id: layerSlider
|
||||||
|
|
||||||
|
width: UM.Theme.getSize("slider_handle").width
|
||||||
|
height: UM.Theme.getSize("slider_layerview_size").height
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom properties
|
||||||
|
upperValue: UM.SimulationView.currentLayer
|
||||||
|
lowerValue: UM.SimulationView.minimumLayer
|
||||||
|
maximumValue: UM.SimulationView.numLayers
|
||||||
|
|
||||||
|
// Update values when layer data changes
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: UM.SimulationView
|
||||||
|
onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
||||||
|
onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
|
||||||
|
onCurrentLayerChanged:
|
||||||
|
{
|
||||||
|
// Only pause the simulation when the layer was changed manually, not when the simulation is running
|
||||||
|
if (layerSlider.manuallyChanged)
|
||||||
|
{
|
||||||
|
playButton.pauseSimulation()
|
||||||
|
}
|
||||||
|
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the slider handlers show the correct value after switching views
|
||||||
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
|
||||||
|
layerSlider.setUpperValue(UM.SimulationView.currentLayer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
530
plugins/SimulationView/SimulationViewMenuComponent.qml
Normal file
530
plugins/SimulationView/SimulationViewMenuComponent.qml
Normal file
|
@ -0,0 +1,530 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.4
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Controls.Styles 1.1
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
|
||||||
|
import UM 1.0 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
|
||||||
|
Cura.ExpandableComponent
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
|
||||||
|
width: UM.Theme.getSize("layerview_menu_size").width
|
||||||
|
contentHeaderTitle: catalog.i18nc("@label", "Color scheme")
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: UM.Preferences
|
||||||
|
onPreferenceChanged:
|
||||||
|
{
|
||||||
|
layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type")
|
||||||
|
layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex)
|
||||||
|
viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|")
|
||||||
|
viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves")
|
||||||
|
viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers")
|
||||||
|
viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin")
|
||||||
|
viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill")
|
||||||
|
viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers")
|
||||||
|
viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
headerItem: Label
|
||||||
|
{
|
||||||
|
id: layerViewTypesLabel
|
||||||
|
text: catalog.i18nc("@label", "Color scheme")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("setting_control_text")
|
||||||
|
height: base.height
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Column
|
||||||
|
{
|
||||||
|
id: viewSettings
|
||||||
|
|
||||||
|
property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
|
||||||
|
property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
|
||||||
|
property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
|
||||||
|
property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
|
||||||
|
property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
|
||||||
|
|
||||||
|
// If we are in compatibility mode, we only show the "line type"
|
||||||
|
property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1
|
||||||
|
property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3
|
||||||
|
property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2
|
||||||
|
property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3
|
||||||
|
property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
|
||||||
|
property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
|
||||||
|
|
||||||
|
width: UM.Theme.getSize("layerview_menu_size").width - 2 * UM.Theme.getSize("default_margin").width
|
||||||
|
height: implicitHeight
|
||||||
|
|
||||||
|
spacing: UM.Theme.getSize("layerview_row_spacing").height
|
||||||
|
|
||||||
|
ListModel // matches SimulationView.py
|
||||||
|
{
|
||||||
|
id: layerViewTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
layerViewTypes.append({
|
||||||
|
text: catalog.i18nc("@label:listbox", "Material Color"),
|
||||||
|
type_id: 0
|
||||||
|
})
|
||||||
|
layerViewTypes.append({
|
||||||
|
text: catalog.i18nc("@label:listbox", "Line Type"),
|
||||||
|
type_id: 1
|
||||||
|
})
|
||||||
|
layerViewTypes.append({
|
||||||
|
text: catalog.i18nc("@label:listbox", "Feedrate"),
|
||||||
|
type_id: 2
|
||||||
|
})
|
||||||
|
layerViewTypes.append({
|
||||||
|
text: catalog.i18nc("@label:listbox", "Layer thickness"),
|
||||||
|
type_id: 3 // these ids match the switching in the shader
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox
|
||||||
|
{
|
||||||
|
id: layerTypeCombobox
|
||||||
|
width: parent.width
|
||||||
|
model: layerViewTypes
|
||||||
|
visible: !UM.SimulationView.compatibilityMode
|
||||||
|
style: UM.Theme.styles.combobox
|
||||||
|
|
||||||
|
onActivated:
|
||||||
|
{
|
||||||
|
UM.Preferences.setValue("layerview/layer_view_type", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
|
||||||
|
updateLegends(currentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateLegends(type_id)
|
||||||
|
{
|
||||||
|
// Update the visibility of the legends.
|
||||||
|
viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
|
||||||
|
viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3);
|
||||||
|
viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2);
|
||||||
|
viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: compatibilityModeLabel
|
||||||
|
text: catalog.i18nc("@label","Compatibility Mode")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
visible: UM.SimulationView.compatibilityMode
|
||||||
|
height: UM.Theme.getSize("layerview_row").height
|
||||||
|
width: parent.width
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
Item // Spacer
|
||||||
|
{
|
||||||
|
height: Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||||
|
width: width
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
model: Cura.ExtrudersModel{}
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
{
|
||||||
|
id: extrudersModelCheckBox
|
||||||
|
checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == ""
|
||||||
|
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
||||||
|
width: parent.width
|
||||||
|
visible: !UM.SimulationView.compatibilityMode
|
||||||
|
enabled: index < 4
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0
|
||||||
|
UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|"));
|
||||||
|
}
|
||||||
|
|
||||||
|
style: UM.Theme.styles.checkbox
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: extrudersModelCheckBox.right
|
||||||
|
width: UM.Theme.getSize("layerview_legend_size").width
|
||||||
|
height: UM.Theme.getSize("layerview_legend_size").height
|
||||||
|
color: model.color
|
||||||
|
radius: Math.round(width / 2)
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: UM.Theme.getColor("lining")
|
||||||
|
visible: !viewSettings.show_legend && !viewSettings.show_gradient
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: model.name
|
||||||
|
elide: Text.ElideRight
|
||||||
|
color: UM.Theme.getColor("setting_control_text")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: extrudersModelCheckBox.left
|
||||||
|
right: extrudersModelCheckBox.right
|
||||||
|
leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||||
|
rightMargin: UM.Theme.getSize("default_margin").width * 2
|
||||||
|
}
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
model: ListModel
|
||||||
|
{
|
||||||
|
id: typesLegendModel
|
||||||
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
typesLegendModel.append({
|
||||||
|
label: catalog.i18nc("@label", "Show Travels"),
|
||||||
|
initialValue: viewSettings.show_travel_moves,
|
||||||
|
preference: "layerview/show_travel_moves",
|
||||||
|
colorId: "layerview_move_combing"
|
||||||
|
});
|
||||||
|
typesLegendModel.append({
|
||||||
|
label: catalog.i18nc("@label", "Show Helpers"),
|
||||||
|
initialValue: viewSettings.show_helpers,
|
||||||
|
preference: "layerview/show_helpers",
|
||||||
|
colorId: "layerview_support"
|
||||||
|
});
|
||||||
|
typesLegendModel.append({
|
||||||
|
label: catalog.i18nc("@label", "Show Shell"),
|
||||||
|
initialValue: viewSettings.show_skin,
|
||||||
|
preference: "layerview/show_skin",
|
||||||
|
colorId: "layerview_inset_0"
|
||||||
|
});
|
||||||
|
typesLegendModel.append({
|
||||||
|
label: catalog.i18nc("@label", "Show Infill"),
|
||||||
|
initialValue: viewSettings.show_infill,
|
||||||
|
preference: "layerview/show_infill",
|
||||||
|
colorId: "layerview_infill"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
{
|
||||||
|
id: legendModelCheckBox
|
||||||
|
checked: model.initialValue
|
||||||
|
onClicked: UM.Preferences.setValue(model.preference, checked)
|
||||||
|
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
style: UM.Theme.styles.checkbox
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: legendModelCheckBox.right
|
||||||
|
width: UM.Theme.getSize("layerview_legend_size").width
|
||||||
|
height: UM.Theme.getSize("layerview_legend_size").height
|
||||||
|
color: UM.Theme.getColor(model.colorId)
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: UM.Theme.getColor("lining")
|
||||||
|
visible: viewSettings.show_legend
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: label
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
elide: Text.ElideRight
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
color: UM.Theme.getColor("setting_control_text")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: legendModelCheckBox.left
|
||||||
|
anchors.right: legendModelCheckBox.right
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2)
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
{
|
||||||
|
checked: viewSettings.only_show_top_layers
|
||||||
|
onClicked: UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0)
|
||||||
|
text: catalog.i18nc("@label", "Only Show Top Layers")
|
||||||
|
visible: UM.SimulationView.compatibilityMode
|
||||||
|
style: UM.Theme.styles.checkbox
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
{
|
||||||
|
checked: viewSettings.top_layer_count == 5
|
||||||
|
onClicked: UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1)
|
||||||
|
text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
|
||||||
|
width: parent.width
|
||||||
|
visible: UM.SimulationView.compatibilityMode
|
||||||
|
style: UM.Theme.styles.checkbox
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
model: ListModel
|
||||||
|
{
|
||||||
|
id: typesLegendModelNoCheck
|
||||||
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
typesLegendModelNoCheck.append({
|
||||||
|
label: catalog.i18nc("@label", "Top / Bottom"),
|
||||||
|
colorId: "layerview_skin",
|
||||||
|
});
|
||||||
|
typesLegendModelNoCheck.append({
|
||||||
|
label: catalog.i18nc("@label", "Inner Wall"),
|
||||||
|
colorId: "layerview_inset_x",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: label
|
||||||
|
visible: viewSettings.show_legend
|
||||||
|
id: typesLegendModelLabel
|
||||||
|
|
||||||
|
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
|
||||||
|
width: parent.width
|
||||||
|
color: UM.Theme.getColor("setting_control_text")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: typesLegendModelLabel.right
|
||||||
|
|
||||||
|
width: UM.Theme.getSize("layerview_legend_size").width
|
||||||
|
height: UM.Theme.getSize("layerview_legend_size").height
|
||||||
|
|
||||||
|
color: UM.Theme.getColor(model.colorId)
|
||||||
|
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text for the minimum, maximum and units for the feedrates and layer thickness
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: gradientLegend
|
||||||
|
visible: viewSettings.show_gradient
|
||||||
|
width: parent.width
|
||||||
|
height: UM.Theme.getSize("layerview_row").height
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text:
|
||||||
|
{
|
||||||
|
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||||
|
{
|
||||||
|
// Feedrate selected
|
||||||
|
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
||||||
|
{
|
||||||
|
return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
|
||||||
|
}
|
||||||
|
// Layer thickness selected
|
||||||
|
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
||||||
|
{
|
||||||
|
return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return catalog.i18nc("@label","min")
|
||||||
|
}
|
||||||
|
anchors.left: parent.left
|
||||||
|
color: UM.Theme.getColor("setting_control_text")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: {
|
||||||
|
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||||
|
{
|
||||||
|
// Feedrate selected
|
||||||
|
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
||||||
|
{
|
||||||
|
return "mm/s"
|
||||||
|
}
|
||||||
|
// Layer thickness selected
|
||||||
|
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
||||||
|
{
|
||||||
|
return "mm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
color: UM.Theme.getColor("setting_control_text")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: {
|
||||||
|
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||||
|
{
|
||||||
|
// Feedrate selected
|
||||||
|
if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
|
||||||
|
{
|
||||||
|
return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
|
||||||
|
}
|
||||||
|
// Layer thickness selected
|
||||||
|
if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
|
||||||
|
{
|
||||||
|
return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return catalog.i18nc("@label","max")
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
color: UM.Theme.getColor("setting_control_text")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gradient colors for feedrate
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: feedrateGradient
|
||||||
|
visible: viewSettings.show_feedrate_gradient
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: UM.Theme.getColor("lining")
|
||||||
|
|
||||||
|
LinearGradient
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: UM.Theme.getSize("default_lining").width
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: UM.Theme.getSize("default_lining").width
|
||||||
|
top: parent.top
|
||||||
|
topMargin: UM.Theme.getSize("default_lining").width
|
||||||
|
bottom: parent.bottom
|
||||||
|
bottomMargin: UM.Theme.getSize("default_lining").width
|
||||||
|
}
|
||||||
|
start: Qt.point(0, 0)
|
||||||
|
end: Qt.point(parent.width, 0)
|
||||||
|
gradient: Gradient
|
||||||
|
{
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.000
|
||||||
|
color: Qt.rgba(0, 0, 1, 1)
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.25
|
||||||
|
color: Qt.rgba(0.25, 1, 0, 1)
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.375
|
||||||
|
color: Qt.rgba(0.375, 0.5, 0, 1)
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 1.0
|
||||||
|
color: Qt.rgba(1, 0.5, 0, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gradient colors for layer thickness (similar to parula colormap)
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: thicknessGradient
|
||||||
|
visible: viewSettings.show_thickness_gradient
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: UM.Theme.getColor("lining")
|
||||||
|
|
||||||
|
LinearGradient
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: UM.Theme.getSize("default_lining").width
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: UM.Theme.getSize("default_lining").width
|
||||||
|
top: parent.top
|
||||||
|
topMargin: UM.Theme.getSize("default_lining").width
|
||||||
|
bottom: parent.bottom
|
||||||
|
bottomMargin: UM.Theme.getSize("default_lining").width
|
||||||
|
}
|
||||||
|
start: Qt.point(0, 0)
|
||||||
|
end: Qt.point(parent.width, 0)
|
||||||
|
gradient: Gradient
|
||||||
|
{
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.000
|
||||||
|
color: Qt.rgba(0, 0, 0.5, 1)
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.25
|
||||||
|
color: Qt.rgba(0, 0.375, 0.75, 1)
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.5
|
||||||
|
color: Qt.rgba(0, 0.75, 0.5, 1)
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.75
|
||||||
|
color: Qt.rgba(1, 0.75, 0.25, 1)
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 1.0
|
||||||
|
color: Qt.rgba(1, 1, 0, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FontMetrics
|
||||||
|
{
|
||||||
|
id: fontMetrics
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,19 +8,21 @@ from . import SimulationViewProxy, SimulationView
|
||||||
|
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
def getMetaData():
|
def getMetaData():
|
||||||
return {
|
return {
|
||||||
"view": {
|
"view": {
|
||||||
"name": catalog.i18nc("@item:inlistbox", "Layer view"),
|
"name": catalog.i18nc("@item:inlistbox", "Layer view"),
|
||||||
"view_panel": "SimulationView.qml",
|
"weight": 0
|
||||||
"weight": 2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def createSimulationViewProxy(engine, script_engine):
|
def createSimulationViewProxy(engine, script_engine):
|
||||||
return SimulationViewProxy.SimulationViewProxy()
|
return SimulationViewProxy.SimulationViewProxy()
|
||||||
|
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
simulation_view = SimulationView.SimulationView()
|
simulation_view = SimulationView.SimulationView()
|
||||||
qmlRegisterSingletonType(SimulationViewProxy.SimulationViewProxy, "UM", 1, 0, "SimulationView", simulation_view.getProxy)
|
qmlRegisterSingletonType(SimulationViewProxy.SimulationViewProxy, "UM", 1, 0, "SimulationView", simulation_view.getProxy)
|
||||||
return { "view": SimulationView.SimulationView()}
|
return { "view": simulation_view}
|
||||||
|
|
|
@ -10,7 +10,8 @@ def getMetaData():
|
||||||
return {
|
return {
|
||||||
"view": {
|
"view": {
|
||||||
"name": i18n_catalog.i18nc("@item:inmenu", "Solid view"),
|
"name": i18n_catalog.i18nc("@item:inmenu", "Solid view"),
|
||||||
"weight": 0
|
"weight": 0,
|
||||||
|
"visible": False
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ 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
|
||||||
maximumHeight: minimumHeight
|
maximumHeight: minimumHeight
|
||||||
color: UM.Theme.getColor("sidebar")
|
color: UM.Theme.getColor("main_background")
|
||||||
UM.I18nCatalog
|
UM.I18nCatalog
|
||||||
{
|
{
|
||||||
id: catalog
|
id: catalog
|
||||||
|
@ -95,6 +95,7 @@ Window
|
||||||
licenseDialog.show();
|
licenseDialog.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolboxLicenseDialog
|
ToolboxLicenseDialog
|
||||||
{
|
{
|
||||||
id: licenseDialog
|
id: licenseDialog
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -86,14 +88,16 @@ Item
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@label", "Website") + ":"
|
text: catalog.i18nc("@label", "Website") + ":"
|
||||||
font: UM.Theme.getFont("very_small")
|
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("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column
|
Column
|
||||||
|
@ -118,10 +122,11 @@ Item
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
font: UM.Theme.getFont("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
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
|
||||||
|
@ -134,10 +139,11 @@ Item
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
font: UM.Theme.getFont("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -90,7 +91,7 @@ Item
|
||||||
model: packageData.supported_configs
|
model: packageData.supported_configs
|
||||||
headerDelegate: Rectangle
|
headerDelegate: Rectangle
|
||||||
{
|
{
|
||||||
color: UM.Theme.getColor("sidebar")
|
color: UM.Theme.getColor("main_background")
|
||||||
height: UM.Theme.getSize("toolbox_chart_row").height
|
height: UM.Theme.getSize("toolbox_chart_row").height
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,9 +233,10 @@ Item
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
font: UM.Theme.getFont("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -26,10 +26,19 @@ Item
|
||||||
}
|
}
|
||||||
height: childrenRect.height + 2 * UM.Theme.getSize("wide_margin").height
|
height: childrenRect.height + 2 * UM.Theme.getSize("wide_margin").height
|
||||||
spacing: UM.Theme.getSize("default_margin").height
|
spacing: UM.Theme.getSize("default_margin").height
|
||||||
|
|
||||||
Repeater
|
Repeater
|
||||||
{
|
{
|
||||||
model: toolbox.packagesModel
|
model: toolbox.packagesModel
|
||||||
delegate: ToolboxDetailTile {}
|
delegate: Loader
|
||||||
|
{
|
||||||
|
// 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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -37,7 +37,7 @@ Item
|
||||||
leftMargin: UM.Theme.getSize("wide_margin").width
|
leftMargin: UM.Theme.getSize("wide_margin").width
|
||||||
topMargin: UM.Theme.getSize("wide_margin").height
|
topMargin: UM.Theme.getSize("wide_margin").height
|
||||||
}
|
}
|
||||||
color: white //Always a white background for image (regardless of theme).
|
color: "white" //Always a white background for image (regardless of theme).
|
||||||
Image
|
Image
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -65,6 +65,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
|
||||||
}
|
}
|
||||||
|
|
||||||
Column
|
Column
|
||||||
|
@ -82,26 +83,30 @@ Item
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@label", "Version") + ":"
|
text: catalog.i18nc("@label", "Version") + ":"
|
||||||
font: UM.Theme.getFont("very_small")
|
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("very_small")
|
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("very_small")
|
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("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column
|
Column
|
||||||
|
@ -119,8 +124,9 @@ Item
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: details === null ? "" : (details.version || catalog.i18nc("@label", "Unknown"))
|
text: details === null ? "" : (details.version || catalog.i18nc("@label", "Unknown"))
|
||||||
font: UM.Theme.getFont("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
@ -133,8 +139,9 @@ Item
|
||||||
var date = new Date(details.last_updated)
|
var date = new Date(details.last_updated)
|
||||||
return date.toLocaleString(UM.Preferences.getValue("general/language"))
|
return date.toLocaleString(UM.Preferences.getValue("general/language"))
|
||||||
}
|
}
|
||||||
font: UM.Theme.getFont("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
@ -149,16 +156,18 @@ Item
|
||||||
return "<a href=\"" + details.website + "\">" + details.author_name + "</a>"
|
return "<a href=\"" + details.website + "\">" + details.author_name + "</a>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font: UM.Theme.getFont("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
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("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rectangle
|
Rectangle
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,69 @@
|
||||||
// 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
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
Column
|
Column
|
||||||
{
|
{
|
||||||
property bool installed: toolbox.isInstalled(model.id)
|
property bool installed: toolbox.isInstalled(model.id)
|
||||||
property bool canUpdate: toolbox.canUpdate(model.id)
|
property bool canUpdate: toolbox.canUpdate(model.id)
|
||||||
|
property bool loginRequired: model.login_required && !Cura.API.account.isLoggedIn
|
||||||
|
|
||||||
width: UM.Theme.getSize("toolbox_action_button").width
|
width: UM.Theme.getSize("toolbox_action_button").width
|
||||||
spacing: UM.Theme.getSize("narrow_margin").height
|
spacing: UM.Theme.getSize("narrow_margin").height
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
width: installButton.width
|
||||||
|
height: installButton.height
|
||||||
ToolboxProgressButton
|
ToolboxProgressButton
|
||||||
{
|
{
|
||||||
id: installButton
|
id: installButton
|
||||||
active: toolbox.isDownloading && toolbox.activePackage == model
|
active: toolbox.isDownloading && toolbox.activePackage == model
|
||||||
complete: installed
|
onReadyAction:
|
||||||
readyAction: function()
|
|
||||||
{
|
{
|
||||||
toolbox.activePackage = model
|
toolbox.activePackage = model
|
||||||
toolbox.startDownload(model.download_url)
|
toolbox.startDownload(model.download_url)
|
||||||
}
|
}
|
||||||
activeAction: function()
|
onActiveAction: toolbox.cancelDownload()
|
||||||
{
|
|
||||||
toolbox.cancelDownload()
|
|
||||||
}
|
|
||||||
completeAction: function()
|
|
||||||
{
|
|
||||||
toolbox.viewCategory = "installed"
|
|
||||||
}
|
|
||||||
// Don't allow installing while another download is running
|
// Don't allow installing while another download is running
|
||||||
enabled: installed || !(toolbox.isDownloading && toolbox.activePackage != model)
|
enabled: installed || (!(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired)
|
||||||
opacity: enabled ? 1.0 : 0.5
|
opacity: enabled ? 1.0 : 0.5
|
||||||
visible: !updateButton.visible // Don't show when the update button is visible
|
visible: !updateButton.visible && !installed// Don't show when the update button is visible
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.SecondaryButton
|
||||||
|
{
|
||||||
|
visible: installed
|
||||||
|
onClicked: toolbox.viewCategory = "installed"
|
||||||
|
text: catalog.i18nc("@action:button", "Installed")
|
||||||
|
fixedWidthMode: true
|
||||||
|
width: installButton.width
|
||||||
|
height: installButton.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: catalog.i18nc("@label:The string between <a href=> and </a> is the highlighted link", "<a href='%1'>Log in</a> is required to install or update")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
linkColor: UM.Theme.getColor("text_link")
|
||||||
|
visible: loginRequired
|
||||||
|
width: installButton.width
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: Cura.API.account.login()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolboxProgressButton
|
ToolboxProgressButton
|
||||||
|
@ -44,20 +73,19 @@ Column
|
||||||
readyLabel: catalog.i18nc("@action:button", "Update")
|
readyLabel: catalog.i18nc("@action:button", "Update")
|
||||||
activeLabel: catalog.i18nc("@action:button", "Updating")
|
activeLabel: catalog.i18nc("@action:button", "Updating")
|
||||||
completeLabel: catalog.i18nc("@action:button", "Updated")
|
completeLabel: catalog.i18nc("@action:button", "Updated")
|
||||||
readyAction: function()
|
|
||||||
|
onReadyAction:
|
||||||
{
|
{
|
||||||
toolbox.activePackage = model
|
toolbox.activePackage = model
|
||||||
toolbox.update(model.id)
|
toolbox.update(model.id)
|
||||||
}
|
}
|
||||||
activeAction: function()
|
onActiveAction: toolbox.cancelDownload()
|
||||||
{
|
|
||||||
toolbox.cancelDownload()
|
|
||||||
}
|
|
||||||
// Don't allow installing while another download is running
|
// Don't allow installing while another download is running
|
||||||
enabled: !(toolbox.isDownloading && toolbox.activePackage != model)
|
enabled: !(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired
|
||||||
opacity: enabled ? 1.0 : 0.5
|
opacity: enabled ? 1.0 : 0.5
|
||||||
visible: canUpdate
|
visible: canUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections
|
Connections
|
||||||
{
|
{
|
||||||
target: toolbox
|
target: toolbox
|
||||||
|
|
|
@ -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,8 +23,9 @@ 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
|
||||||
}
|
}
|
||||||
GridLayout
|
Grid
|
||||||
{
|
{
|
||||||
id: grid
|
id: grid
|
||||||
width: parent.width - 2 * parent.padding
|
width: parent.width - 2 * parent.padding
|
||||||
|
@ -34,10 +35,12 @@ Column
|
||||||
Repeater
|
Repeater
|
||||||
{
|
{
|
||||||
model: gridArea.model
|
model: gridArea.model
|
||||||
delegate: ToolboxDownloadsGridTile
|
delegate: Loader
|
||||||
{
|
{
|
||||||
Layout.preferredWidth: (grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns
|
asynchronous: true
|
||||||
Layout.preferredHeight: UM.Theme.getSize("toolbox_thumbnail_small").height
|
width: Math.round((grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns)
|
||||||
|
height: UM.Theme.getSize("toolbox_thumbnail_small").height
|
||||||
|
source: "ToolboxDownloadsGridTile.qml"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -52,7 +52,6 @@ Item
|
||||||
bottom: parent.bottom
|
bottom: parent.bottom
|
||||||
right: parent.right
|
right: parent.right
|
||||||
}
|
}
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: height
|
sourceSize.height: height
|
||||||
visible: installedPackages != 0
|
visible: installedPackages != 0
|
||||||
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
||||||
|
@ -63,6 +62,8 @@ Item
|
||||||
{
|
{
|
||||||
width: parent.width - thumbnail.width - parent.spacing
|
width: parent.width - thumbnail.width - parent.spacing
|
||||||
spacing: Math.floor(UM.Theme.getSize("narrow_margin").width)
|
spacing: Math.floor(UM.Theme.getSize("narrow_margin").width)
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: name
|
id: name
|
||||||
|
@ -71,6 +72,7 @@ Item
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
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
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
@ -81,7 +83,8 @@ Item
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
font: UM.Theme.getFont("very_small")
|
font: UM.Theme.getFont("default")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,19 +24,19 @@ 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
|
||||||
{
|
{
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
spacing: UM.Theme.getSize("wide_margin").width
|
spacing: UM.Theme.getSize("wide_margin").width
|
||||||
columns: 3
|
columns: 3
|
||||||
anchors
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
{
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
Repeater
|
Repeater
|
||||||
{
|
{
|
||||||
model: {
|
model:
|
||||||
|
{
|
||||||
if (toolbox.viewCategory == "plugin")
|
if (toolbox.viewCategory == "plugin")
|
||||||
{
|
{
|
||||||
return toolbox.pluginsShowcaseModel
|
return toolbox.pluginsShowcaseModel
|
||||||
|
@ -46,7 +46,11 @@ Rectangle
|
||||||
return toolbox.materialsShowcaseModel
|
return toolbox.materialsShowcaseModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delegate: ToolboxDownloadsShowcaseTile {}
|
delegate: Loader
|
||||||
|
{
|
||||||
|
asynchronous: true
|
||||||
|
source: "ToolboxDownloadsShowcaseTile.qml"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -48,8 +48,6 @@ Rectangle
|
||||||
right: parent.right
|
right: parent.right
|
||||||
bottomMargin: UM.Theme.getSize("default_lining").width
|
bottomMargin: UM.Theme.getSize("default_lining").width
|
||||||
}
|
}
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: height
|
|
||||||
visible: installedPackages != 0
|
visible: installedPackages != 0
|
||||||
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
||||||
source: "../images/installed_check.svg"
|
source: "../images/installed_check.svg"
|
||||||
|
@ -81,6 +79,7 @@ Rectangle
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
color: UM.Theme.getColor("button_text")
|
color: UM.Theme.getColor("button_text")
|
||||||
font: UM.Theme.getFont("medium_bold")
|
font: UM.Theme.getFont("medium_bold")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseArea
|
MouseArea
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -21,44 +21,40 @@ ScrollView
|
||||||
Column
|
Column
|
||||||
{
|
{
|
||||||
spacing: UM.Theme.getSize("default_margin").height
|
spacing: UM.Theme.getSize("default_margin").height
|
||||||
|
visible: toolbox.pluginsInstalledModel.items.length > 0
|
||||||
|
height: childrenRect.height + 4 * UM.Theme.getSize("default_margin").height
|
||||||
|
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
right: parent.right
|
right: parent.right
|
||||||
left: parent.left
|
left: parent.left
|
||||||
leftMargin: UM.Theme.getSize("wide_margin").width
|
margins: UM.Theme.getSize("default_margin").width
|
||||||
topMargin: UM.Theme.getSize("wide_margin").height
|
|
||||||
bottomMargin: UM.Theme.getSize("wide_margin").height
|
|
||||||
top: parent.top
|
top: parent.top
|
||||||
}
|
}
|
||||||
height: childrenRect.height + 4 * UM.Theme.getSize("default_margin").height
|
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
visible: toolbox.pluginsInstalledModel.items.length > 0
|
width: page.width
|
||||||
width: parent.width
|
|
||||||
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
|
||||||
{
|
{
|
||||||
visible: toolbox.pluginsInstalledModel.items.length > 0
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: childrenRect.height + 1 * UM.Theme.getSize("default_lining").width
|
height: childrenRect.height + UM.Theme.getSize("default_margin").width
|
||||||
border.color: UM.Theme.getColor("lining")
|
border.color: UM.Theme.getColor("lining")
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
Column
|
Column
|
||||||
{
|
{
|
||||||
height: childrenRect.height
|
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: parent.top
|
top: parent.top
|
||||||
right: parent.right
|
right: parent.right
|
||||||
left: parent.left
|
left: parent.left
|
||||||
leftMargin: UM.Theme.getSize("default_margin").width
|
margins: UM.Theme.getSize("default_margin").width
|
||||||
rightMargin: UM.Theme.getSize("default_margin").width
|
|
||||||
topMargin: UM.Theme.getSize("default_lining").width
|
|
||||||
bottomMargin: UM.Theme.getSize("default_lining").width
|
|
||||||
}
|
}
|
||||||
Repeater
|
Repeater
|
||||||
{
|
{
|
||||||
|
@ -70,32 +66,27 @@ ScrollView
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
visible: toolbox.materialsInstalledModel.items.length > 0
|
|
||||||
width: page.width
|
|
||||||
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
|
||||||
{
|
{
|
||||||
visible: toolbox.materialsInstalledModel.items.length > 0
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: childrenRect.height + 1 * UM.Theme.getSize("default_lining").width
|
height: childrenRect.height + UM.Theme.getSize("default_margin").width
|
||||||
border.color: UM.Theme.getColor("lining")
|
border.color: UM.Theme.getColor("lining")
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
Column
|
Column
|
||||||
{
|
{
|
||||||
height: Math.max( UM.Theme.getSize("wide_margin").height, childrenRect.height)
|
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: parent.top
|
top: parent.top
|
||||||
right: parent.right
|
right: parent.right
|
||||||
left: parent.left
|
left: parent.left
|
||||||
leftMargin: UM.Theme.getSize("default_margin").width
|
margins: UM.Theme.getSize("default_margin").width
|
||||||
rightMargin: UM.Theme.getSize("default_margin").width
|
|
||||||
topMargin: UM.Theme.getSize("default_lining").width
|
|
||||||
bottomMargin: UM.Theme.getSize("default_lining").width
|
|
||||||
}
|
}
|
||||||
Repeater
|
Repeater
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
Column
|
Column
|
||||||
{
|
{
|
||||||
property bool canUpdate: false
|
property bool canUpdate: false
|
||||||
property bool canDowngrade: false
|
property bool canDowngrade: false
|
||||||
|
property bool loginRequired: model.login_required && !Cura.API.account.isLoggedIn
|
||||||
width: UM.Theme.getSize("toolbox_action_button").width
|
width: UM.Theme.getSize("toolbox_action_button").width
|
||||||
spacing: UM.Theme.getSize("narrow_margin").height
|
spacing: UM.Theme.getSize("narrow_margin").height
|
||||||
|
|
||||||
|
@ -21,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
|
||||||
|
@ -30,59 +34,49 @@ Column
|
||||||
readyLabel: catalog.i18nc("@action:button", "Update")
|
readyLabel: catalog.i18nc("@action:button", "Update")
|
||||||
activeLabel: catalog.i18nc("@action:button", "Updating")
|
activeLabel: catalog.i18nc("@action:button", "Updating")
|
||||||
completeLabel: catalog.i18nc("@action:button", "Updated")
|
completeLabel: catalog.i18nc("@action:button", "Updated")
|
||||||
readyAction: function()
|
onReadyAction:
|
||||||
{
|
{
|
||||||
toolbox.activePackage = model
|
toolbox.activePackage = model
|
||||||
toolbox.update(model.id)
|
toolbox.update(model.id)
|
||||||
}
|
}
|
||||||
activeAction: function()
|
onActiveAction: toolbox.cancelDownload()
|
||||||
{
|
|
||||||
toolbox.cancelDownload()
|
|
||||||
}
|
|
||||||
// Don't allow installing while another download is running
|
// Don't allow installing while another download is running
|
||||||
enabled: !(toolbox.isDownloading && toolbox.activePackage != model)
|
enabled: !(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired
|
||||||
opacity: enabled ? 1.0 : 0.5
|
opacity: enabled ? 1.0 : 0.5
|
||||||
visible: canUpdate
|
visible: canUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
Button
|
Label
|
||||||
|
{
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: catalog.i18nc("@label:The string between <a href=> and </a> is the highlighted link", "<a href='%1'>Log in</a> is required to update")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
linkColor: UM.Theme.getColor("text_link")
|
||||||
|
visible: loginRequired
|
||||||
|
width: updateButton.width
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: Cura.API.account.login()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.SecondaryButton
|
||||||
{
|
{
|
||||||
id: removeButton
|
id: removeButton
|
||||||
text: canDowngrade ? catalog.i18nc("@action:button", "Downgrade") : catalog.i18nc("@action:button", "Uninstall")
|
text: canDowngrade ? catalog.i18nc("@action:button", "Downgrade") : catalog.i18nc("@action:button", "Uninstall")
|
||||||
visible: !model.is_bundled && model.is_installed
|
visible: !model.is_bundled && model.is_installed
|
||||||
enabled: !toolbox.isDownloading
|
enabled: !toolbox.isDownloading
|
||||||
style: ButtonStyle
|
|
||||||
{
|
width: UM.Theme.getSize("toolbox_action_button").width
|
||||||
background: Rectangle
|
height: UM.Theme.getSize("toolbox_action_button").height
|
||||||
{
|
|
||||||
implicitWidth: UM.Theme.getSize("toolbox_action_button").width
|
fixedWidthMode: true
|
||||||
implicitHeight: UM.Theme.getSize("toolbox_action_button").height
|
|
||||||
color: "transparent"
|
|
||||||
border
|
|
||||||
{
|
|
||||||
width: UM.Theme.getSize("default_lining").width
|
|
||||||
color:
|
|
||||||
{
|
|
||||||
if (control.hovered)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("primary_hover")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("lining")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
label: Label
|
|
||||||
{
|
|
||||||
text: control.text
|
|
||||||
color: UM.Theme.getColor("text")
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onClicked: toolbox.checkPackageUsageAndUninstall(model.id)
|
onClicked: toolbox.checkPackageUsageAndUninstall(model.id)
|
||||||
Connections
|
Connections
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import QtQuick 2.2
|
||||||
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
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
|
||||||
Item
|
Item
|
||||||
|
@ -18,16 +19,19 @@ Item
|
||||||
property var activeLabel: catalog.i18nc("@action:button", "Cancel")
|
property var activeLabel: catalog.i18nc("@action:button", "Cancel")
|
||||||
property var completeLabel: catalog.i18nc("@action:button", "Installed")
|
property var completeLabel: catalog.i18nc("@action:button", "Installed")
|
||||||
|
|
||||||
property var readyAction: null // Action when button is ready and clicked (likely install)
|
signal readyAction() // Action when button is ready and clicked (likely install)
|
||||||
property var activeAction: null // Action when button is active and clicked (likely cancel)
|
signal activeAction() // Action when button is active and clicked (likely cancel)
|
||||||
property var completeAction: null // Action when button is complete and clicked (likely go to installed)
|
signal completeAction() // Action when button is complete and clicked (likely go to installed)
|
||||||
|
|
||||||
width: UM.Theme.getSize("toolbox_action_button").width
|
width: UM.Theme.getSize("toolbox_action_button").width
|
||||||
height: UM.Theme.getSize("toolbox_action_button").height
|
height: UM.Theme.getSize("toolbox_action_button").height
|
||||||
|
|
||||||
Button
|
Cura.PrimaryButton
|
||||||
{
|
{
|
||||||
id: button
|
id: button
|
||||||
|
width: UM.Theme.getSize("toolbox_action_button").width
|
||||||
|
height: UM.Theme.getSize("toolbox_action_button").height
|
||||||
|
fixedWidthMode: true
|
||||||
text:
|
text:
|
||||||
{
|
{
|
||||||
if (complete)
|
if (complete)
|
||||||
|
@ -47,101 +51,15 @@ Item
|
||||||
{
|
{
|
||||||
if (complete)
|
if (complete)
|
||||||
{
|
{
|
||||||
return completeAction()
|
completeAction()
|
||||||
}
|
}
|
||||||
else if (active)
|
else if (active)
|
||||||
{
|
{
|
||||||
return activeAction()
|
activeAction()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return readyAction()
|
readyAction()
|
||||||
}
|
|
||||||
}
|
|
||||||
style: ButtonStyle
|
|
||||||
{
|
|
||||||
background: Rectangle
|
|
||||||
{
|
|
||||||
implicitWidth: UM.Theme.getSize("toolbox_action_button").width
|
|
||||||
implicitHeight: UM.Theme.getSize("toolbox_action_button").height
|
|
||||||
color:
|
|
||||||
{
|
|
||||||
if (base.complete)
|
|
||||||
{
|
|
||||||
return "transparent"
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (control.hovered)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("primary_hover")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("primary")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
border
|
|
||||||
{
|
|
||||||
width:
|
|
||||||
{
|
|
||||||
if (base.complete)
|
|
||||||
{
|
|
||||||
UM.Theme.getSize("default_lining").width
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
color:
|
|
||||||
{
|
|
||||||
if (control.hovered)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("primary_hover")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("lining")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
label: Label
|
|
||||||
{
|
|
||||||
text: control.text
|
|
||||||
color:
|
|
||||||
{
|
|
||||||
if (base.complete)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("text")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (control.hovered)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("button_text_hover")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("button_text")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
font:
|
|
||||||
{
|
|
||||||
if (base.complete)
|
|
||||||
{
|
|
||||||
return UM.Theme.getFont("default")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return UM.Theme.getFont("default_bold")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +1,51 @@
|
||||||
// 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 2.3
|
||||||
import QtQuick.Controls.Styles 1.4
|
|
||||||
import UM 1.1 as UM
|
import UM 1.1 as UM
|
||||||
|
|
||||||
Button
|
Button
|
||||||
{
|
{
|
||||||
|
id: control
|
||||||
property bool active: false
|
property bool active: false
|
||||||
style: ButtonStyle
|
hoverEnabled: true
|
||||||
|
|
||||||
|
background: Item
|
||||||
{
|
{
|
||||||
background: Rectangle
|
|
||||||
{
|
|
||||||
color: "transparent"
|
|
||||||
implicitWidth: UM.Theme.getSize("toolbox_header_tab").width
|
implicitWidth: UM.Theme.getSize("toolbox_header_tab").width
|
||||||
implicitHeight: UM.Theme.getSize("toolbox_header_tab").height
|
implicitHeight: UM.Theme.getSize("toolbox_header_tab").height
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
visible: control.active
|
visible: control.active
|
||||||
color: UM.Theme.getColor("sidebar_header_highlight_hover")
|
color: UM.Theme.getColor("primary")
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: UM.Theme.getSize("sidebar_header_highlight").height
|
height: UM.Theme.getSize("toolbox_header_highlight").height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
label: Label
|
contentItem: Label
|
||||||
{
|
{
|
||||||
|
id: label
|
||||||
text: control.text
|
text: control.text
|
||||||
color:
|
color:
|
||||||
{
|
{
|
||||||
if(control.hovered)
|
if(control.hovered)
|
||||||
{
|
{
|
||||||
return UM.Theme.getColor("topbar_button_text_hovered");
|
return UM.Theme.getColor("toolbox_header_button_text_hovered");
|
||||||
}
|
}
|
||||||
if(control.active)
|
if(control.active)
|
||||||
{
|
{
|
||||||
return UM.Theme.getColor("topbar_button_text_active");
|
return UM.Theme.getColor("toolbox_header_button_text_active");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return UM.Theme.getColor("topbar_button_text_inactive");
|
return UM.Theme.getColor("toolbox_header_button_text_inactive");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic")
|
font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic")
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
}
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,18 +2,19 @@
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import Dict
|
from typing import Dict, List, Optional, Union
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal
|
from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal
|
||||||
|
|
||||||
from UM.Qt.ListModel import ListModel
|
from UM.Qt.ListModel import ListModel
|
||||||
|
|
||||||
|
|
||||||
## Model that holds cura packages. By setting the filter property the instances held by this model can be changed.
|
## Model that holds cura packages. By setting the filter property the instances held by this model can be changed.
|
||||||
class AuthorsModel(ListModel):
|
class AuthorsModel(ListModel):
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self._metadata = None
|
self._metadata = None # type: Optional[List[Dict[str, Union[str, List[str], int]]]]
|
||||||
|
|
||||||
self.addRoleName(Qt.UserRole + 1, "id")
|
self.addRoleName(Qt.UserRole + 1, "id")
|
||||||
self.addRoleName(Qt.UserRole + 2, "name")
|
self.addRoleName(Qt.UserRole + 2, "name")
|
||||||
|
@ -27,37 +28,38 @@ class AuthorsModel(ListModel):
|
||||||
# List of filters for queries. The result is the union of the each list of results.
|
# List of filters for queries. The result is the union of the each list of results.
|
||||||
self._filter = {} # type: Dict[str, str]
|
self._filter = {} # type: Dict[str, str]
|
||||||
|
|
||||||
def setMetadata(self, data):
|
def setMetadata(self, data: List[Dict[str, Union[str, List[str], int]]]):
|
||||||
|
if self._metadata != data:
|
||||||
self._metadata = data
|
self._metadata = data
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
def _update(self):
|
def _update(self) -> None:
|
||||||
items = []
|
items = [] # type: List[Dict[str, Union[str, List[str], int, None]]]
|
||||||
if not self._metadata:
|
if not self._metadata:
|
||||||
self.setItems([])
|
self.setItems(items)
|
||||||
return
|
return
|
||||||
|
|
||||||
for author in self._metadata:
|
for author in self._metadata:
|
||||||
items.append({
|
items.append({
|
||||||
"id": author["author_id"],
|
"id": author.get("author_id"),
|
||||||
"name": author["display_name"],
|
"name": author.get("display_name"),
|
||||||
"email": author["email"] if "email" in author else None,
|
"email": author.get("email"),
|
||||||
"website": author["website"],
|
"website": author.get("website"),
|
||||||
"package_count": author["package_count"] if "package_count" in author else 0,
|
"package_count": author.get("package_count", 0),
|
||||||
"package_types": author["package_types"] if "package_types" in author else [],
|
"package_types": author.get("package_types", []),
|
||||||
"icon_url": author["icon_url"] if "icon_url" in author else None,
|
"icon_url": author.get("icon_url"),
|
||||||
"description": "Material and quality profiles from {author_name}".format(author_name = author["display_name"])
|
"description": "Material and quality profiles from {author_name}".format(author_name = author.get("display_name", ""))
|
||||||
})
|
})
|
||||||
|
|
||||||
# Filter on all the key-word arguments.
|
# Filter on all the key-word arguments.
|
||||||
for key, value in self._filter.items():
|
for key, value in self._filter.items():
|
||||||
if key is "package_types":
|
if key is "package_types":
|
||||||
key_filter = lambda item, value = value: value in item["package_types"]
|
key_filter = lambda item, value = value: value in item["package_types"] # type: ignore
|
||||||
elif "*" in value:
|
elif "*" in value:
|
||||||
key_filter = lambda item, key = key, value = value: self._matchRegExp(item, key, value)
|
key_filter = lambda item, key = key, value = value: self._matchRegExp(item, key, value) # type: ignore
|
||||||
else:
|
else:
|
||||||
key_filter = lambda item, key = key, value = value: self._matchString(item, key, value)
|
key_filter = lambda item, key = key, value = value: self._matchString(item, key, value) # type: ignore
|
||||||
items = filter(key_filter, items)
|
items = filter(key_filter, items) # type: ignore
|
||||||
|
|
||||||
# Execute all filters.
|
# Execute all filters.
|
||||||
filtered_items = list(items)
|
filtered_items = list(items)
|
||||||
|
|
|
@ -40,11 +40,13 @@ class PackagesModel(ListModel):
|
||||||
self.addRoleName(Qt.UserRole + 19, "tags")
|
self.addRoleName(Qt.UserRole + 19, "tags")
|
||||||
self.addRoleName(Qt.UserRole + 20, "links")
|
self.addRoleName(Qt.UserRole + 20, "links")
|
||||||
self.addRoleName(Qt.UserRole + 21, "website")
|
self.addRoleName(Qt.UserRole + 21, "website")
|
||||||
|
self.addRoleName(Qt.UserRole + 22, "login_required")
|
||||||
|
|
||||||
# List of filters for queries. The result is the union of the each list of results.
|
# List of filters for queries. The result is the union of the each list of results.
|
||||||
self._filter = {} # type: Dict[str, str]
|
self._filter = {} # type: Dict[str, str]
|
||||||
|
|
||||||
def setMetadata(self, data):
|
def setMetadata(self, data):
|
||||||
|
if self._metadata != data:
|
||||||
self._metadata = data
|
self._metadata = data
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
|
@ -99,6 +101,7 @@ class PackagesModel(ListModel):
|
||||||
"tags": package["tags"] if "tags" in package else [],
|
"tags": package["tags"] if "tags" in package else [],
|
||||||
"links": links_dict,
|
"links": links_dict,
|
||||||
"website": package["website"] if "website" in package else None,
|
"website": package["website"] if "website" in package else None,
|
||||||
|
"login_required": "login-required" in package.get("tags", [])
|
||||||
})
|
})
|
||||||
|
|
||||||
# Filter on all the key-word arguments.
|
# Filter on all the key-word arguments.
|
||||||
|
|
|
@ -67,31 +67,26 @@ class Toolbox(QObject, Extension):
|
||||||
self._old_plugin_ids = set() # type: Set[str]
|
self._old_plugin_ids = set() # type: Set[str]
|
||||||
self._old_plugin_metadata = dict() # type: Dict[str, Dict[str, Any]]
|
self._old_plugin_metadata = dict() # type: Dict[str, Dict[str, Any]]
|
||||||
|
|
||||||
# Data:
|
# The responses as given by the server parsed to a list.
|
||||||
self._metadata = {
|
self._server_response_data = {
|
||||||
"authors": [],
|
"authors": [],
|
||||||
"packages": [],
|
"packages": []
|
||||||
"plugins_showcase": [],
|
|
||||||
"plugins_available": [],
|
|
||||||
"plugins_installed": [],
|
|
||||||
"materials_showcase": [],
|
|
||||||
"materials_available": [],
|
|
||||||
"materials_installed": [],
|
|
||||||
"materials_generic": []
|
|
||||||
} # type: Dict[str, List[Any]]
|
} # type: Dict[str, List[Any]]
|
||||||
|
|
||||||
# Models:
|
# Models:
|
||||||
self._models = {
|
self._models = {
|
||||||
"authors": AuthorsModel(self),
|
"authors": AuthorsModel(self),
|
||||||
"packages": PackagesModel(self),
|
"packages": PackagesModel(self),
|
||||||
"plugins_showcase": PackagesModel(self),
|
} # type: Dict[str, Union[AuthorsModel, PackagesModel]]
|
||||||
"plugins_available": PackagesModel(self),
|
|
||||||
"plugins_installed": PackagesModel(self),
|
self._plugins_showcase_model = PackagesModel(self)
|
||||||
"materials_showcase": AuthorsModel(self),
|
self._plugins_available_model = PackagesModel(self)
|
||||||
"materials_available": AuthorsModel(self),
|
self._plugins_installed_model = PackagesModel(self)
|
||||||
"materials_installed": PackagesModel(self),
|
|
||||||
"materials_generic": PackagesModel(self)
|
self._materials_showcase_model = AuthorsModel(self)
|
||||||
} # type: Dict[str, ListModel]
|
self._materials_available_model = AuthorsModel(self)
|
||||||
|
self._materials_installed_model = PackagesModel(self)
|
||||||
|
self._materials_generic_model = PackagesModel(self)
|
||||||
|
|
||||||
# These properties are for keeping track of the UI state:
|
# These properties are for keeping track of the UI state:
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
@ -176,12 +171,7 @@ class Toolbox(QObject, Extension):
|
||||||
)
|
)
|
||||||
self._request_urls = {
|
self._request_urls = {
|
||||||
"authors": QUrl("{base_url}/authors".format(base_url = self._api_url)),
|
"authors": QUrl("{base_url}/authors".format(base_url = self._api_url)),
|
||||||
"packages": QUrl("{base_url}/packages".format(base_url = self._api_url)),
|
"packages": QUrl("{base_url}/packages".format(base_url = self._api_url))
|
||||||
"plugins_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)),
|
|
||||||
"plugins_available": QUrl("{base_url}/packages?package_type=plugin".format(base_url = self._api_url)),
|
|
||||||
"materials_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)),
|
|
||||||
"materials_available": QUrl("{base_url}/packages?package_type=material".format(base_url = self._api_url)),
|
|
||||||
"materials_generic": QUrl("{base_url}/packages?package_type=material&tags=generic".format(base_url = self._api_url))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
@ -199,12 +189,6 @@ class Toolbox(QObject, Extension):
|
||||||
# Make remote requests:
|
# Make remote requests:
|
||||||
self._makeRequestByType("packages")
|
self._makeRequestByType("packages")
|
||||||
self._makeRequestByType("authors")
|
self._makeRequestByType("authors")
|
||||||
# TODO: Uncomment in the future when the tag-filtered api calls work in the cloud server
|
|
||||||
# self._makeRequestByType("plugins_showcase")
|
|
||||||
# self._makeRequestByType("plugins_available")
|
|
||||||
# self._makeRequestByType("materials_showcase")
|
|
||||||
# self._makeRequestByType("materials_available")
|
|
||||||
# self._makeRequestByType("materials_generic")
|
|
||||||
|
|
||||||
# Gather installed packages:
|
# Gather installed packages:
|
||||||
self._updateInstalledModels()
|
self._updateInstalledModels()
|
||||||
|
@ -249,7 +233,7 @@ class Toolbox(QObject, Extension):
|
||||||
"description": plugin_data["plugin"]["description"]
|
"description": plugin_data["plugin"]["description"]
|
||||||
}
|
}
|
||||||
return formatted
|
return formatted
|
||||||
except:
|
except KeyError:
|
||||||
Logger.log("w", "Unable to convert plugin meta data %s", str(plugin_data))
|
Logger.log("w", "Unable to convert plugin meta data %s", str(plugin_data))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -287,13 +271,10 @@ class Toolbox(QObject, Extension):
|
||||||
if plugin_id not in all_plugin_package_ids)
|
if plugin_id not in all_plugin_package_ids)
|
||||||
self._old_plugin_metadata = {k: v for k, v in self._old_plugin_metadata.items() if k in self._old_plugin_ids}
|
self._old_plugin_metadata = {k: v for k, v in self._old_plugin_metadata.items() if k in self._old_plugin_ids}
|
||||||
|
|
||||||
self._metadata["plugins_installed"] = all_packages["plugin"] + list(self._old_plugin_metadata.values())
|
self._plugins_installed_model.setMetadata(all_packages["plugin"] + list(self._old_plugin_metadata.values()))
|
||||||
self._models["plugins_installed"].setMetadata(self._metadata["plugins_installed"])
|
|
||||||
self.metadataChanged.emit()
|
self.metadataChanged.emit()
|
||||||
if "material" in all_packages:
|
if "material" in all_packages:
|
||||||
self._metadata["materials_installed"] = all_packages["material"]
|
self._materials_installed_model.setMetadata(all_packages["material"])
|
||||||
# TODO: ADD MATERIALS HERE ONCE MATERIALS PORTION OF TOOLBOX IS LIVE
|
|
||||||
self._models["materials_installed"].setMetadata(self._metadata["materials_installed"])
|
|
||||||
self.metadataChanged.emit()
|
self.metadataChanged.emit()
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
|
@ -447,7 +428,7 @@ class Toolbox(QObject, Extension):
|
||||||
def getRemotePackage(self, package_id: str) -> Optional[Dict]:
|
def getRemotePackage(self, package_id: str) -> Optional[Dict]:
|
||||||
# TODO: make the lookup in a dict, not a loop. canUpdate is called for every item.
|
# TODO: make the lookup in a dict, not a loop. canUpdate is called for every item.
|
||||||
remote_package = None
|
remote_package = None
|
||||||
for package in self._metadata["packages"]:
|
for package in self._server_response_data["packages"]:
|
||||||
if package["package_id"] == package_id:
|
if package["package_id"] == package_id:
|
||||||
remote_package = package
|
remote_package = package
|
||||||
break
|
break
|
||||||
|
@ -459,11 +440,8 @@ class Toolbox(QObject, Extension):
|
||||||
def canUpdate(self, package_id: str) -> bool:
|
def canUpdate(self, package_id: str) -> bool:
|
||||||
local_package = self._package_manager.getInstalledPackageInfo(package_id)
|
local_package = self._package_manager.getInstalledPackageInfo(package_id)
|
||||||
if local_package is None:
|
if local_package is None:
|
||||||
Logger.log("i", "Could not find package [%s] as installed in the package manager, fall back to check the old plugins",
|
|
||||||
package_id)
|
|
||||||
local_package = self.getOldPluginPackageMetadata(package_id)
|
local_package = self.getOldPluginPackageMetadata(package_id)
|
||||||
if local_package is None:
|
if local_package is None:
|
||||||
Logger.log("i", "Could not find package [%s] in the old plugins", package_id)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
remote_package = self.getRemotePackage(package_id)
|
remote_package = self.getRemotePackage(package_id)
|
||||||
|
@ -513,8 +491,8 @@ class Toolbox(QObject, Extension):
|
||||||
@pyqtSlot(str, result = int)
|
@pyqtSlot(str, result = int)
|
||||||
def getNumberOfInstalledPackagesByAuthor(self, author_id: str) -> int:
|
def getNumberOfInstalledPackagesByAuthor(self, author_id: str) -> int:
|
||||||
count = 0
|
count = 0
|
||||||
for package in self._metadata["materials_installed"]:
|
for package in self._materials_installed_model.items:
|
||||||
if package["author"]["author_id"] == author_id:
|
if package["author_id"] == author_id:
|
||||||
count += 1
|
count += 1
|
||||||
return count
|
return count
|
||||||
|
|
||||||
|
@ -522,7 +500,7 @@ class Toolbox(QObject, Extension):
|
||||||
@pyqtSlot(str, result = int)
|
@pyqtSlot(str, result = int)
|
||||||
def getTotalNumberOfMaterialPackagesByAuthor(self, author_id: str) -> int:
|
def getTotalNumberOfMaterialPackagesByAuthor(self, author_id: str) -> int:
|
||||||
count = 0
|
count = 0
|
||||||
for package in self._metadata["packages"]:
|
for package in self._server_response_data["packages"]:
|
||||||
if package["package_type"] == "material":
|
if package["package_type"] == "material":
|
||||||
if package["author"]["author_id"] == author_id:
|
if package["author"]["author_id"] == author_id:
|
||||||
count += 1
|
count += 1
|
||||||
|
@ -536,34 +514,30 @@ class Toolbox(QObject, Extension):
|
||||||
|
|
||||||
# Check for plugins that were installed with the old plugin browser
|
# Check for plugins that were installed with the old plugin browser
|
||||||
def isOldPlugin(self, plugin_id: str) -> bool:
|
def isOldPlugin(self, plugin_id: str) -> bool:
|
||||||
if plugin_id in self._old_plugin_ids:
|
return plugin_id in self._old_plugin_ids
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def getOldPluginPackageMetadata(self, plugin_id: str) -> Optional[Dict[str, Any]]:
|
def getOldPluginPackageMetadata(self, plugin_id: str) -> Optional[Dict[str, Any]]:
|
||||||
return self._old_plugin_metadata.get(plugin_id)
|
return self._old_plugin_metadata.get(plugin_id)
|
||||||
|
|
||||||
def loadingComplete(self) -> bool:
|
def isLoadingComplete(self) -> bool:
|
||||||
populated = 0
|
populated = 0
|
||||||
for list in self._metadata.items():
|
for metadata_list in self._server_response_data.items():
|
||||||
if len(list) > 0:
|
if metadata_list:
|
||||||
populated += 1
|
populated += 1
|
||||||
if populated == len(self._metadata.items()):
|
return populated == len(self._server_response_data.items())
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Make API Calls
|
# Make API Calls
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
def _makeRequestByType(self, type: str) -> None:
|
def _makeRequestByType(self, request_type: str) -> None:
|
||||||
Logger.log("i", "Marketplace: Requesting %s metadata from server.", type)
|
Logger.log("i", "Requesting %s metadata from server.", request_type)
|
||||||
request = QNetworkRequest(self._request_urls[type])
|
request = QNetworkRequest(self._request_urls[request_type])
|
||||||
request.setRawHeader(*self._request_header)
|
request.setRawHeader(*self._request_header)
|
||||||
if self._network_manager:
|
if self._network_manager:
|
||||||
self._network_manager.get(request)
|
self._network_manager.get(request)
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def startDownload(self, url: str) -> None:
|
def startDownload(self, url: str) -> None:
|
||||||
Logger.log("i", "Marketplace: Attempting to download & install package from %s.", url)
|
Logger.log("i", "Attempting to download & install package from %s.", url)
|
||||||
url = QUrl(url)
|
url = QUrl(url)
|
||||||
self._download_request = QNetworkRequest(url)
|
self._download_request = QNetworkRequest(url)
|
||||||
if hasattr(QNetworkRequest, "FollowRedirectsAttribute"):
|
if hasattr(QNetworkRequest, "FollowRedirectsAttribute"):
|
||||||
|
@ -580,7 +554,7 @@ class Toolbox(QObject, Extension):
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def cancelDownload(self) -> None:
|
def cancelDownload(self) -> None:
|
||||||
Logger.log("i", "Marketplace: User cancelled the download of a package.")
|
Logger.log("i", "User cancelled the download of a package.")
|
||||||
self.resetDownload()
|
self.resetDownload()
|
||||||
|
|
||||||
def resetDownload(self) -> None:
|
def resetDownload(self) -> None:
|
||||||
|
@ -614,22 +588,8 @@ class Toolbox(QObject, Extension):
|
||||||
self.resetDownload()
|
self.resetDownload()
|
||||||
return
|
return
|
||||||
|
|
||||||
# HACK: These request are not handled independently at this moment, but together from the "packages" call
|
|
||||||
do_not_handle = [
|
|
||||||
"materials_available",
|
|
||||||
"materials_showcase",
|
|
||||||
"materials_generic",
|
|
||||||
"plugins_available",
|
|
||||||
"plugins_showcase",
|
|
||||||
]
|
|
||||||
|
|
||||||
if reply.operation() == QNetworkAccessManager.GetOperation:
|
if reply.operation() == QNetworkAccessManager.GetOperation:
|
||||||
for type, url in self._request_urls.items():
|
for response_type, url in self._request_urls.items():
|
||||||
|
|
||||||
# HACK: Do nothing because we'll handle these from the "packages" call
|
|
||||||
if type in do_not_handle:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if reply.url() == url:
|
if reply.url() == url:
|
||||||
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200:
|
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200:
|
||||||
try:
|
try:
|
||||||
|
@ -642,38 +602,32 @@ class Toolbox(QObject, Extension):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Create model and apply metadata:
|
# Create model and apply metadata:
|
||||||
if not self._models[type]:
|
if not self._models[response_type]:
|
||||||
Logger.log("e", "Could not find the %s model.", type)
|
Logger.log("e", "Could not find the %s model.", response_type)
|
||||||
break
|
break
|
||||||
|
|
||||||
self._metadata[type] = json_data["data"]
|
self._server_response_data[response_type] = json_data["data"]
|
||||||
self._models[type].setMetadata(self._metadata[type])
|
self._models[response_type].setMetadata(self._server_response_data[response_type])
|
||||||
|
|
||||||
# Do some auto filtering
|
if response_type is "packages":
|
||||||
# TODO: Make multiple API calls in the future to handle this
|
self._models[response_type].setFilter({"type": "plugin"})
|
||||||
if type is "packages":
|
self.reBuildMaterialsModels()
|
||||||
self._models[type].setFilter({"type": "plugin"})
|
self.reBuildPluginsModels()
|
||||||
self.buildMaterialsModels()
|
elif response_type is "authors":
|
||||||
self.buildPluginsModels()
|
self._models[response_type].setFilter({"package_types": "material"})
|
||||||
if type is "authors":
|
self._models[response_type].setFilter({"tags": "generic"})
|
||||||
self._models[type].setFilter({"package_types": "material"})
|
|
||||||
if type is "materials_generic":
|
|
||||||
self._models[type].setFilter({"tags": "generic"})
|
|
||||||
|
|
||||||
self.metadataChanged.emit()
|
self.metadataChanged.emit()
|
||||||
|
|
||||||
if self.loadingComplete() is True:
|
if self.isLoadingComplete():
|
||||||
self.setViewPage("overview")
|
self.setViewPage("overview")
|
||||||
|
|
||||||
return
|
|
||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
Logger.log("w", "Marketplace: Received invalid JSON for %s.", type)
|
Logger.log("w", "Received invalid JSON for %s.", response_type)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.setViewPage("errored")
|
self.setViewPage("errored")
|
||||||
self.resetDownload()
|
self.resetDownload()
|
||||||
return
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Ignore any operation that is not a get operation
|
# Ignore any operation that is not a get operation
|
||||||
pass
|
pass
|
||||||
|
@ -684,7 +638,13 @@ 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
|
||||||
|
if self._download_reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
|
||||||
|
Logger.log("w", "Failed to download package. The following error was returned: %s", json.loads(bytes(self._download_reply.readAll()).decode("utf-8")))
|
||||||
|
return
|
||||||
# Must not delete the temporary file on Windows
|
# Must not delete the temporary file on Windows
|
||||||
self._temp_plugin_file = tempfile.NamedTemporaryFile(mode = "w+b", suffix = ".curapackage", delete = False)
|
self._temp_plugin_file = tempfile.NamedTemporaryFile(mode = "w+b", suffix = ".curapackage", delete = False)
|
||||||
file_path = self._temp_plugin_file.name
|
file_path = self._temp_plugin_file.name
|
||||||
|
@ -694,10 +654,10 @@ class Toolbox(QObject, Extension):
|
||||||
self._onDownloadComplete(file_path)
|
self._onDownloadComplete(file_path)
|
||||||
|
|
||||||
def _onDownloadComplete(self, file_path: str) -> None:
|
def _onDownloadComplete(self, file_path: str) -> None:
|
||||||
Logger.log("i", "Marketplace: Download complete.")
|
Logger.log("i", "Download complete.")
|
||||||
package_info = self._package_manager.getPackageInfo(file_path)
|
package_info = self._package_manager.getPackageInfo(file_path)
|
||||||
if not package_info:
|
if not package_info:
|
||||||
Logger.log("w", "Marketplace: Package file [%s] was not a valid CuraPackage.", file_path)
|
Logger.log("w", "Package file [%s] was not a valid CuraPackage.", file_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
license_content = self._package_manager.getPackageLicense(file_path)
|
license_content = self._package_manager.getPackageLicense(file_path)
|
||||||
|
@ -706,7 +666,6 @@ class Toolbox(QObject, Extension):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.install(file_path)
|
self.install(file_path)
|
||||||
return
|
|
||||||
|
|
||||||
# Getter & Setters for Properties:
|
# Getter & Setters for Properties:
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
@ -729,6 +688,7 @@ class Toolbox(QObject, Extension):
|
||||||
return self._is_downloading
|
return self._is_downloading
|
||||||
|
|
||||||
def setActivePackage(self, package: Dict[str, Any]) -> None:
|
def setActivePackage(self, package: Dict[str, Any]) -> None:
|
||||||
|
if self._active_package != package:
|
||||||
self._active_package = package
|
self._active_package = package
|
||||||
self.activePackageChanged.emit()
|
self.activePackageChanged.emit()
|
||||||
|
|
||||||
|
@ -738,6 +698,7 @@ class Toolbox(QObject, Extension):
|
||||||
return self._active_package
|
return self._active_package
|
||||||
|
|
||||||
def setViewCategory(self, category: str = "plugin") -> None:
|
def setViewCategory(self, category: str = "plugin") -> None:
|
||||||
|
if self._view_category != category:
|
||||||
self._view_category = category
|
self._view_category = category
|
||||||
self.viewChanged.emit()
|
self.viewChanged.emit()
|
||||||
|
|
||||||
|
@ -746,6 +707,7 @@ class Toolbox(QObject, Extension):
|
||||||
return self._view_category
|
return self._view_category
|
||||||
|
|
||||||
def setViewPage(self, page: str = "overview") -> None:
|
def setViewPage(self, page: str = "overview") -> None:
|
||||||
|
if self._view_page != page:
|
||||||
self._view_page = page
|
self._view_page = page
|
||||||
self.viewChanged.emit()
|
self.viewChanged.emit()
|
||||||
|
|
||||||
|
@ -755,48 +717,48 @@ class Toolbox(QObject, Extension):
|
||||||
|
|
||||||
# Exposed Models:
|
# Exposed Models:
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
@pyqtProperty(QObject, notify = metadataChanged)
|
@pyqtProperty(QObject, constant=True)
|
||||||
def authorsModel(self) -> AuthorsModel:
|
def authorsModel(self) -> AuthorsModel:
|
||||||
return cast(AuthorsModel, self._models["authors"])
|
return cast(AuthorsModel, self._models["authors"])
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = metadataChanged)
|
@pyqtProperty(QObject, constant=True)
|
||||||
def packagesModel(self) -> PackagesModel:
|
def packagesModel(self) -> PackagesModel:
|
||||||
return cast(PackagesModel, self._models["packages"])
|
return cast(PackagesModel, self._models["packages"])
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = metadataChanged)
|
@pyqtProperty(QObject, constant=True)
|
||||||
def pluginsShowcaseModel(self) -> PackagesModel:
|
def pluginsShowcaseModel(self) -> PackagesModel:
|
||||||
return cast(PackagesModel, self._models["plugins_showcase"])
|
return self._plugins_showcase_model
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = metadataChanged)
|
@pyqtProperty(QObject, constant=True)
|
||||||
def pluginsAvailableModel(self) -> PackagesModel:
|
def pluginsAvailableModel(self) -> PackagesModel:
|
||||||
return cast(PackagesModel, self._models["plugins_available"])
|
return self._plugins_available_model
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = metadataChanged)
|
@pyqtProperty(QObject, constant=True)
|
||||||
def pluginsInstalledModel(self) -> PackagesModel:
|
def pluginsInstalledModel(self) -> PackagesModel:
|
||||||
return cast(PackagesModel, self._models["plugins_installed"])
|
return self._plugins_installed_model
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = metadataChanged)
|
@pyqtProperty(QObject, constant=True)
|
||||||
def materialsShowcaseModel(self) -> AuthorsModel:
|
def materialsShowcaseModel(self) -> AuthorsModel:
|
||||||
return cast(AuthorsModel, self._models["materials_showcase"])
|
return self._materials_showcase_model
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = metadataChanged)
|
@pyqtProperty(QObject, constant=True)
|
||||||
def materialsAvailableModel(self) -> AuthorsModel:
|
def materialsAvailableModel(self) -> AuthorsModel:
|
||||||
return cast(AuthorsModel, self._models["materials_available"])
|
return self._materials_available_model
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = metadataChanged)
|
@pyqtProperty(QObject, constant=True)
|
||||||
def materialsInstalledModel(self) -> PackagesModel:
|
def materialsInstalledModel(self) -> PackagesModel:
|
||||||
return cast(PackagesModel, self._models["materials_installed"])
|
return self._materials_installed_model
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify=metadataChanged)
|
@pyqtProperty(QObject, constant=True)
|
||||||
def materialsGenericModel(self) -> PackagesModel:
|
def materialsGenericModel(self) -> PackagesModel:
|
||||||
return cast(PackagesModel, self._models["materials_generic"])
|
return self._materials_generic_model
|
||||||
|
|
||||||
# Filter Models:
|
# Filter Models:
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
@pyqtSlot(str, str, str)
|
@pyqtSlot(str, str, str)
|
||||||
def filterModelByProp(self, model_type: str, filter_type: str, parameter: str) -> None:
|
def filterModelByProp(self, model_type: str, filter_type: str, parameter: str) -> None:
|
||||||
if not self._models[model_type]:
|
if not self._models[model_type]:
|
||||||
Logger.log("w", "Marketplace: Couldn't filter %s model because it doesn't exist.", model_type)
|
Logger.log("w", "Couldn't filter %s model because it doesn't exist.", model_type)
|
||||||
return
|
return
|
||||||
self._models[model_type].setFilter({filter_type: parameter})
|
self._models[model_type].setFilter({filter_type: parameter})
|
||||||
self.filterChanged.emit()
|
self.filterChanged.emit()
|
||||||
|
@ -804,7 +766,7 @@ class Toolbox(QObject, Extension):
|
||||||
@pyqtSlot(str, "QVariantMap")
|
@pyqtSlot(str, "QVariantMap")
|
||||||
def setFilters(self, model_type: str, filter_dict: dict) -> None:
|
def setFilters(self, model_type: str, filter_dict: dict) -> None:
|
||||||
if not self._models[model_type]:
|
if not self._models[model_type]:
|
||||||
Logger.log("w", "Marketplace: Couldn't filter %s model because it doesn't exist.", model_type)
|
Logger.log("w", "Couldn't filter %s model because it doesn't exist.", model_type)
|
||||||
return
|
return
|
||||||
self._models[model_type].setFilter(filter_dict)
|
self._models[model_type].setFilter(filter_dict)
|
||||||
self.filterChanged.emit()
|
self.filterChanged.emit()
|
||||||
|
@ -812,21 +774,21 @@ class Toolbox(QObject, Extension):
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def removeFilters(self, model_type: str) -> None:
|
def removeFilters(self, model_type: str) -> None:
|
||||||
if not self._models[model_type]:
|
if not self._models[model_type]:
|
||||||
Logger.log("w", "Marketplace: Couldn't remove filters on %s model because it doesn't exist.", model_type)
|
Logger.log("w", "Couldn't remove filters on %s model because it doesn't exist.", model_type)
|
||||||
return
|
return
|
||||||
self._models[model_type].setFilter({})
|
self._models[model_type].setFilter({})
|
||||||
self.filterChanged.emit()
|
self.filterChanged.emit()
|
||||||
|
|
||||||
# HACK(S):
|
# HACK(S):
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
def buildMaterialsModels(self) -> None:
|
def reBuildMaterialsModels(self) -> None:
|
||||||
self._metadata["materials_showcase"] = []
|
materials_showcase_metadata = []
|
||||||
self._metadata["materials_available"] = []
|
materials_available_metadata = []
|
||||||
self._metadata["materials_generic"] = []
|
materials_generic_metadata = []
|
||||||
|
|
||||||
processed_authors = [] # type: List[str]
|
processed_authors = [] # type: List[str]
|
||||||
|
|
||||||
for item in self._metadata["packages"]:
|
for item in self._server_response_data["packages"]:
|
||||||
if item["package_type"] == "material":
|
if item["package_type"] == "material":
|
||||||
|
|
||||||
author = item["author"]
|
author = item["author"]
|
||||||
|
@ -835,30 +797,29 @@ class Toolbox(QObject, Extension):
|
||||||
|
|
||||||
# Generic materials to be in the same section
|
# Generic materials to be in the same section
|
||||||
if "generic" in item["tags"]:
|
if "generic" in item["tags"]:
|
||||||
self._metadata["materials_generic"].append(item)
|
materials_generic_metadata.append(item)
|
||||||
else:
|
else:
|
||||||
if "showcase" in item["tags"]:
|
if "showcase" in item["tags"]:
|
||||||
self._metadata["materials_showcase"].append(author)
|
materials_showcase_metadata.append(author)
|
||||||
else:
|
else:
|
||||||
self._metadata["materials_available"].append(author)
|
materials_available_metadata.append(author)
|
||||||
|
|
||||||
processed_authors.append(author["author_id"])
|
processed_authors.append(author["author_id"])
|
||||||
|
|
||||||
self._models["materials_showcase"].setMetadata(self._metadata["materials_showcase"])
|
self._materials_showcase_model.setMetadata(materials_showcase_metadata)
|
||||||
self._models["materials_available"].setMetadata(self._metadata["materials_available"])
|
self._materials_available_model.setMetadata(materials_available_metadata)
|
||||||
self._models["materials_generic"].setMetadata(self._metadata["materials_generic"])
|
self._materials_generic_model.setMetadata(materials_generic_metadata)
|
||||||
|
|
||||||
def buildPluginsModels(self) -> None:
|
def reBuildPluginsModels(self) -> None:
|
||||||
self._metadata["plugins_showcase"] = []
|
plugins_showcase_metadata = []
|
||||||
self._metadata["plugins_available"] = []
|
plugins_available_metadata = []
|
||||||
|
|
||||||
for item in self._metadata["packages"]:
|
for item in self._server_response_data["packages"]:
|
||||||
if item["package_type"] == "plugin":
|
if item["package_type"] == "plugin":
|
||||||
|
|
||||||
if "showcase" in item["tags"]:
|
if "showcase" in item["tags"]:
|
||||||
self._metadata["plugins_showcase"].append(item)
|
plugins_showcase_metadata.append(item)
|
||||||
else:
|
else:
|
||||||
self._metadata["plugins_available"].append(item)
|
plugins_available_metadata.append(item)
|
||||||
|
|
||||||
self._models["plugins_showcase"].setMetadata(self._metadata["plugins_showcase"])
|
self._plugins_showcase_model.setMetadata(plugins_showcase_metadata)
|
||||||
self._models["plugins_available"].setMetadata(self._metadata["plugins_available"])
|
self._plugins_available_model.setMetadata(plugins_available_metadata)
|
||||||
|
|
|
@ -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("sidebar");
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -64,6 +64,7 @@ Cura.MachineAction
|
||||||
width: parent.width
|
width: parent.width
|
||||||
text: catalog.i18nc("@title:window", "Connect to Networked Printer")
|
text: catalog.i18nc("@title:window", "Connect to Networked Printer")
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
font.pointSize: 18
|
font.pointSize: 18
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +73,7 @@ Cura.MachineAction
|
||||||
id: pageDescription
|
id: pageDescription
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
text: catalog.i18nc("@label", "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n\nSelect your printer from the list below:")
|
text: catalog.i18nc("@label", "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n\nSelect your printer from the list below:")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +184,7 @@ Cura.MachineAction
|
||||||
text: listview.model[index].name
|
text: listview.model[index].name
|
||||||
color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text
|
color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea
|
MouseArea
|
||||||
|
@ -204,6 +207,7 @@ Cura.MachineAction
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
text: catalog.i18nc("@label", "If your printer is not listed, read the <a href='%1'>network printing troubleshooting guide</a>").arg("https://ultimaker.com/en/troubleshooting");
|
text: catalog.i18nc("@label", "If your printer is not listed, read the <a href='%1'>network printing troubleshooting guide</a>").arg("https://ultimaker.com/en/troubleshooting");
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
onLinkActivated: Qt.openUrlExternally(link)
|
||||||
}
|
}
|
||||||
|
@ -221,6 +225,7 @@ Cura.MachineAction
|
||||||
text: base.selectedDevice ? base.selectedDevice.name : ""
|
text: base.selectedDevice ? base.selectedDevice.name : ""
|
||||||
font: UM.Theme.getFont("large")
|
font: UM.Theme.getFont("large")
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Grid
|
Grid
|
||||||
{
|
{
|
||||||
|
@ -231,12 +236,14 @@ Cura.MachineAction
|
||||||
{
|
{
|
||||||
width: Math.round(parent.width * 0.5)
|
width: Math.round(parent.width * 0.5)
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
text: catalog.i18nc("@label", "Type")
|
text: catalog.i18nc("@label", "Type")
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
width: Math.round(parent.width * 0.5)
|
width: Math.round(parent.width * 0.5)
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
text:
|
text:
|
||||||
{
|
{
|
||||||
if(base.selectedDevice)
|
if(base.selectedDevice)
|
||||||
|
@ -268,24 +275,28 @@ Cura.MachineAction
|
||||||
{
|
{
|
||||||
width: Math.round(parent.width * 0.5)
|
width: Math.round(parent.width * 0.5)
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
text: catalog.i18nc("@label", "Firmware version")
|
text: catalog.i18nc("@label", "Firmware version")
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
width: Math.round(parent.width * 0.5)
|
width: Math.round(parent.width * 0.5)
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
text: base.selectedDevice ? base.selectedDevice.firmwareVersion : ""
|
text: base.selectedDevice ? base.selectedDevice.firmwareVersion : ""
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
width: Math.round(parent.width * 0.5)
|
width: Math.round(parent.width * 0.5)
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
text: catalog.i18nc("@label", "Address")
|
text: catalog.i18nc("@label", "Address")
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
width: Math.round(parent.width * 0.5)
|
width: Math.round(parent.width * 0.5)
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
text: base.selectedDevice ? base.selectedDevice.ipAddress : ""
|
text: base.selectedDevice ? base.selectedDevice.ipAddress : ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,6 +305,7 @@ Cura.MachineAction
|
||||||
{
|
{
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
text:{
|
text:{
|
||||||
// The property cluster size does not exist for older UM3 devices.
|
// The property cluster size does not exist for older UM3 devices.
|
||||||
if(!base.selectedDevice || base.selectedDevice.clusterSize == null || base.selectedDevice.clusterSize == 1)
|
if(!base.selectedDevice || base.selectedDevice.clusterSize == null || base.selectedDevice.clusterSize == 1)
|
||||||
|
@ -315,6 +327,7 @@ Cura.MachineAction
|
||||||
{
|
{
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
visible: base.selectedDevice != null && !base.completeProperties
|
visible: base.selectedDevice != null && !base.completeProperties
|
||||||
text: catalog.i18nc("@label", "The printer at this address has not yet responded." )
|
text: catalog.i18nc("@label", "The printer at this address has not yet responded." )
|
||||||
}
|
}
|
||||||
|
@ -361,6 +374,7 @@ Cura.MachineAction
|
||||||
text: catalog.i18nc("@alabel", "Enter the IP address or hostname of your printer on the network.")
|
text: catalog.i18nc("@alabel", "Enter the IP address or hostname of your printer on the network.")
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField
|
TextField
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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.
|
||||||
|
@ -52,7 +52,7 @@ Item
|
||||||
id: buildplateLabel
|
id: buildplateLabel
|
||||||
color: "#191919" // TODO: Theme!
|
color: "#191919" // TODO: Theme!
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font: UM.Theme.getFont("very_small") // 12pt, regular
|
font: UM.Theme.getFont("default") // 12pt, regular
|
||||||
text: ""
|
text: ""
|
||||||
|
|
||||||
// FIXED-LINE-HEIGHT:
|
// FIXED-LINE-HEIGHT:
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,7 +49,7 @@ Item
|
||||||
}
|
}
|
||||||
color: "#191919" // TODO: Theme!
|
color: "#191919" // TODO: Theme!
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font: UM.Theme.getFont("very_small") // 12pt, regular
|
font: UM.Theme.getFont("default") // 12pt, regular
|
||||||
text: ""
|
text: ""
|
||||||
|
|
||||||
// FIXED-LINE-HEIGHT:
|
// FIXED-LINE-HEIGHT:
|
||||||
|
@ -66,7 +66,7 @@ Item
|
||||||
}
|
}
|
||||||
color: "#191919" // TODO: Theme!
|
color: "#191919" // TODO: Theme!
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font: UM.Theme.getFont("small") // 12pt, bold
|
font: UM.Theme.getFont("default_bold") // 12pt, bold
|
||||||
text: ""
|
text: ""
|
||||||
|
|
||||||
// FIXED-LINE-HEIGHT:
|
// FIXED-LINE-HEIGHT:
|
||||||
|
|
|
@ -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!
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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":
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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")
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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: "";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,7 +650,8 @@ 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" \
|
||||||
|
else i18n_catalog.i18nc("@label:material", "Unknown")
|
||||||
return MaterialOutputModel(guid = material_data["guid"], type = material_type,
|
return MaterialOutputModel(guid = material_data["guid"], type = material_type,
|
||||||
brand = brand, color = color, name = name)
|
brand = brand, color = color, name = name)
|
||||||
|
|
||||||
|
|
46
plugins/USBPrinting/MonitorItem.qml
Normal file
46
plugins/USBPrinting/MonitorItem.qml
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: parent.width * 0.3
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
Cura.PrintMonitor
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: footerSeparator
|
||||||
|
width: parent.width
|
||||||
|
height: UM.Theme.getSize("wide_lining").height
|
||||||
|
color: UM.Theme.getColor("wide_lining")
|
||||||
|
anchors.bottom: monitorButton.top
|
||||||
|
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
|
||||||
|
}
|
||||||
|
|
||||||
|
// MonitorButton is actually the bottom footer panel.
|
||||||
|
Cura.MonitorButton
|
||||||
|
{
|
||||||
|
id: monitorButton
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
import os
|
||||||
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
@ -64,7 +65,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._accepts_commands = True
|
self._accepts_commands = True
|
||||||
|
|
||||||
self._paused = False
|
self._paused = False
|
||||||
self._printer_busy = False # when printer is preheating and waiting (M190/M109), or when waiting for action on the printer
|
self._printer_busy = False # When printer is preheating and waiting (M190/M109), or when waiting for action on the printer
|
||||||
|
|
||||||
self.setConnectionText(catalog.i18nc("@info:status", "Connected via USB"))
|
self.setConnectionText(catalog.i18nc("@info:status", "Connected via USB"))
|
||||||
|
|
||||||
|
@ -77,6 +78,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._firmware_name_requested = False
|
self._firmware_name_requested = False
|
||||||
self._firmware_updater = AvrFirmwareUpdater(self)
|
self._firmware_updater = AvrFirmwareUpdater(self)
|
||||||
|
|
||||||
|
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "MonitorItem.qml")
|
||||||
|
|
||||||
CuraApplication.getInstance().getOnExitCallbackManager().addCallback(self._checkActivePrintingUponAppExit)
|
CuraApplication.getInstance().getOnExitCallbackManager().addCallback(self._checkActivePrintingUponAppExit)
|
||||||
|
|
||||||
# This is a callback function that checks if there is any printing in progress via USB when the application tries
|
# This is a callback function that checks if there is any printing in progress via USB when the application tries
|
||||||
|
|
|
@ -373,6 +373,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"PreviewStage": {
|
||||||
|
"package_info": {
|
||||||
|
"package_id": "PreviewStage",
|
||||||
|
"package_type": "plugin",
|
||||||
|
"display_name": "Preview Stage",
|
||||||
|
"description": "Provides a preview stage in Cura.",
|
||||||
|
"package_version": "1.0.0",
|
||||||
|
"sdk_version": 5,
|
||||||
|
"website": "https://ultimaker.com",
|
||||||
|
"author": {
|
||||||
|
"author_id": "UltimakerPackages",
|
||||||
|
"display_name": "Ultimaker B.V.",
|
||||||
|
"email": "plugins@ultimaker.com",
|
||||||
|
"website": "https://ultimaker.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"RemovableDriveOutputDevice": {
|
"RemovableDriveOutputDevice": {
|
||||||
"package_info": {
|
"package_info": {
|
||||||
"package_id": "RemovableDriveOutputDevice",
|
"package_id": "RemovableDriveOutputDevice",
|
||||||
|
|
|
@ -1,170 +0,0 @@
|
||||||
// Copyright (c) 2015 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
import UM 1.1 as UM
|
|
||||||
|
|
||||||
UM.Dialog
|
|
||||||
{
|
|
||||||
id: base
|
|
||||||
|
|
||||||
//: About dialog title
|
|
||||||
title: catalog.i18nc("@title:window","About Cura")
|
|
||||||
|
|
||||||
minimumWidth: 500 * screenScaleFactor
|
|
||||||
minimumHeight: 650 * screenScaleFactor
|
|
||||||
width: minimumWidth
|
|
||||||
height: minimumHeight
|
|
||||||
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
width: parent.width + 2 * margin // margin from Dialog.qml
|
|
||||||
height: version.y + version.height + margin
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: - margin
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
color: UM.Theme.getColor("viewport_background")
|
|
||||||
}
|
|
||||||
|
|
||||||
Image
|
|
||||||
{
|
|
||||||
id: logo
|
|
||||||
width: (base.minimumWidth * 0.85) | 0
|
|
||||||
height: (width * (1/4.25)) | 0
|
|
||||||
|
|
||||||
source: UM.Theme.getImage("logo")
|
|
||||||
|
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: height
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: ((base.minimumWidth - width) / 2) | 0
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: version
|
|
||||||
|
|
||||||
text: catalog.i18nc("@label","version: %1").arg(UM.Application.version)
|
|
||||||
font: UM.Theme.getFont("large")
|
|
||||||
color: UM.Theme.getColor("text")
|
|
||||||
anchors.right : logo.right
|
|
||||||
anchors.top: logo.bottom
|
|
||||||
anchors.topMargin: (UM.Theme.getSize("default_margin").height / 2) | 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: description
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
//: About dialog application description
|
|
||||||
text: catalog.i18nc("@label","End-to-end solution for fused filament 3D printing.")
|
|
||||||
font: UM.Theme.getFont("system")
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
anchors.top: version.bottom
|
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: creditsNotes
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
//: About dialog application author note
|
|
||||||
text: catalog.i18nc("@info:credit","Cura is developed by Ultimaker B.V. in cooperation with the community.\nCura proudly uses the following open source projects:")
|
|
||||||
font: UM.Theme.getFont("system")
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
anchors.top: description.bottom
|
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollView
|
|
||||||
{
|
|
||||||
id: credits
|
|
||||||
anchors.top: creditsNotes.bottom
|
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height)
|
|
||||||
|
|
||||||
ListView
|
|
||||||
{
|
|
||||||
id: projectsList
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
delegate: Row
|
|
||||||
{
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: "<a href='%1' title='%2'>%2</a>".arg(model.url).arg(model.name)
|
|
||||||
width: (projectsList.width * 0.25) | 0
|
|
||||||
elide: Text.ElideRight
|
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
|
||||||
}
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: model.description
|
|
||||||
elide: Text.ElideRight
|
|
||||||
width: (projectsList.width * 0.6) | 0
|
|
||||||
}
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: model.license
|
|
||||||
elide: Text.ElideRight
|
|
||||||
width: (projectsList.width * 0.15) | 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
model: ListModel
|
|
||||||
{
|
|
||||||
id: projectsModel
|
|
||||||
}
|
|
||||||
Component.onCompleted:
|
|
||||||
{
|
|
||||||
projectsModel.append({ name:"Cura", description: catalog.i18nc("@label", "Graphical user interface"), license: "LGPLv3", url: "https://github.com/Ultimaker/Cura" });
|
|
||||||
projectsModel.append({ name:"Uranium", description: catalog.i18nc("@label", "Application framework"), license: "LGPLv3", url: "https://github.com/Ultimaker/Uranium" });
|
|
||||||
projectsModel.append({ name:"CuraEngine", description: catalog.i18nc("@label", "G-code generator"), license: "AGPLv3", url: "https://github.com/Ultimaker/CuraEngine" });
|
|
||||||
projectsModel.append({ name:"libArcus", description: catalog.i18nc("@label", "Interprocess communication library"), license: "LGPLv3", url: "https://github.com/Ultimaker/libArcus" });
|
|
||||||
|
|
||||||
projectsModel.append({ name:"Python", description: catalog.i18nc("@label", "Programming language"), license: "Python", url: "http://python.org/" });
|
|
||||||
projectsModel.append({ name:"Qt5", description: catalog.i18nc("@label", "GUI framework"), license: "LGPLv3", url: "https://www.qt.io/" });
|
|
||||||
projectsModel.append({ name:"PyQt", description: catalog.i18nc("@label", "GUI framework bindings"), license: "GPL", url: "https://riverbankcomputing.com/software/pyqt" });
|
|
||||||
projectsModel.append({ name:"SIP", description: catalog.i18nc("@label", "C/C++ Binding library"), license: "GPL", url: "https://riverbankcomputing.com/software/sip" });
|
|
||||||
projectsModel.append({ name:"Protobuf", description: catalog.i18nc("@label", "Data interchange format"), license: "BSD", url: "https://developers.google.com/protocol-buffers" });
|
|
||||||
projectsModel.append({ name:"SciPy", description: catalog.i18nc("@label", "Support library for scientific computing"), license: "BSD-new", url: "https://www.scipy.org/" });
|
|
||||||
projectsModel.append({ name:"NumPy", description: catalog.i18nc("@label", "Support library for faster math"), license: "BSD", url: "http://www.numpy.org/" });
|
|
||||||
projectsModel.append({ name:"NumPy-STL", description: catalog.i18nc("@label", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" });
|
|
||||||
projectsModel.append({ name:"Shapely", description: catalog.i18nc("@label", "Support library for handling planar objects"), license: "BSD", url: "https://github.com/Toblerity/Shapely" });
|
|
||||||
projectsModel.append({ name:"Trimesh", description: catalog.i18nc("@label", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" });
|
|
||||||
projectsModel.append({ name:"NetworkX", description: catalog.i18nc("@label", "Support library for analysis of complex networks"), license: "3-clause BSD", url: "https://networkx.github.io/" });
|
|
||||||
projectsModel.append({ name:"libSavitar", description: catalog.i18nc("@label", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" });
|
|
||||||
projectsModel.append({ name:"libCharon", description: catalog.i18nc("@label", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" });
|
|
||||||
projectsModel.append({ name:"PySerial", description: catalog.i18nc("@label", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" });
|
|
||||||
projectsModel.append({ name:"python-zeroconf", description: catalog.i18nc("@label", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" });
|
|
||||||
projectsModel.append({ name:"Clipper", description: catalog.i18nc("@label", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" });
|
|
||||||
projectsModel.append({ name:"Requests", description: catalog.i18nc("@Label", "Python HTTP library"), license: "GPL", url: "http://docs.python-requests.org" });
|
|
||||||
|
|
||||||
projectsModel.append({ name:"Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" });
|
|
||||||
projectsModel.append({ name:"Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" });
|
|
||||||
projectsModel.append({ name:"AppImageKit", description: catalog.i18nc("@label", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rightButtons: Button
|
|
||||||
{
|
|
||||||
//: Close about dialog button
|
|
||||||
id: closeButton
|
|
||||||
text: catalog.i18nc("@action:button","Close");
|
|
||||||
|
|
||||||
onClicked: base.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
69
resources/qml/Account/AccountDetails.qml
Normal file
69
resources/qml/Account/AccountDetails.qml
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Column
|
||||||
|
{
|
||||||
|
property var profile: null
|
||||||
|
property var loggedIn: false
|
||||||
|
property var profileImage: ""
|
||||||
|
|
||||||
|
padding: UM.Theme.getSize("wide_margin").height
|
||||||
|
spacing: UM.Theme.getSize("wide_margin").height
|
||||||
|
|
||||||
|
AvatarImage
|
||||||
|
{
|
||||||
|
id: avatar
|
||||||
|
width: UM.Theme.getSize("avatar_image").width
|
||||||
|
height: UM.Theme.getSize("avatar_image").height
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
source:
|
||||||
|
{
|
||||||
|
if(loggedIn)
|
||||||
|
{
|
||||||
|
if(profileImage)
|
||||||
|
{
|
||||||
|
return profileImage
|
||||||
|
}
|
||||||
|
return UM.Theme.getImage("avatar_no_user")
|
||||||
|
}
|
||||||
|
return UM.Theme.getImage("avatar_no_user")
|
||||||
|
}
|
||||||
|
outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: information
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
text: loggedIn ? profile["username"] : catalog.i18nc("@label", "Please log in or create an account to\nenjoy all features of Ultimaker Cura.")
|
||||||
|
font: loggedIn ? UM.Theme.getFont("large") : UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader
|
||||||
|
{
|
||||||
|
id: accountOperations
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
sourceComponent: loggedIn ? userOperations : generalOperations
|
||||||
|
}
|
||||||
|
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
id: userOperations
|
||||||
|
UserOperations { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
id: generalOperations
|
||||||
|
GeneralOperations { }
|
||||||
|
}
|
||||||
|
}
|
76
resources/qml/Account/AccountWidget.qml
Normal file
76
resources/qml/Account/AccountWidget.qml
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: accountWidget
|
||||||
|
property var profile: Cura.API.account.userProfile
|
||||||
|
property var loggedIn: Cura.API.account.isLoggedIn
|
||||||
|
|
||||||
|
implicitHeight: UM.Theme.getSize("main_window_header").height
|
||||||
|
implicitWidth: UM.Theme.getSize("main_window_header").height
|
||||||
|
|
||||||
|
background: AvatarImage
|
||||||
|
{
|
||||||
|
id: avatar
|
||||||
|
|
||||||
|
width: Math.round(0.8 * accountWidget.width)
|
||||||
|
height: Math.round(0.8 * accountWidget.height)
|
||||||
|
anchors.verticalCenter: accountWidget.verticalCenter
|
||||||
|
anchors.horizontalCenter: accountWidget.horizontalCenter
|
||||||
|
|
||||||
|
source:
|
||||||
|
{
|
||||||
|
if(loggedIn)
|
||||||
|
{
|
||||||
|
if(profile["profile_image_url"])
|
||||||
|
{
|
||||||
|
return profile["profile_image_url"]
|
||||||
|
}
|
||||||
|
return UM.Theme.getImage("avatar_no_user")
|
||||||
|
}
|
||||||
|
return UM.Theme.getImage("avatar_no_user")
|
||||||
|
}
|
||||||
|
outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining")
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: popup.opened ? popup.close() : popup.open()
|
||||||
|
|
||||||
|
Popup
|
||||||
|
{
|
||||||
|
id: popup
|
||||||
|
|
||||||
|
y: parent.height + UM.Theme.getSize("default_arrow").height
|
||||||
|
x: parent.width - width
|
||||||
|
|
||||||
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||||
|
|
||||||
|
opacity: opened ? 1 : 0
|
||||||
|
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||||
|
|
||||||
|
contentItem: AccountDetails
|
||||||
|
{
|
||||||
|
id: panel
|
||||||
|
profile: Cura.API.account.userProfile
|
||||||
|
loggedIn: Cura.API.account.isLoggedIn
|
||||||
|
profileImage: Cura.API.account.profileImageUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
background: UM.PointingRectangle
|
||||||
|
{
|
||||||
|
color: UM.Theme.getColor("tool_panel_background")
|
||||||
|
borderColor: UM.Theme.getColor("lining")
|
||||||
|
borderWidth: UM.Theme.getSize("default_lining").width
|
||||||
|
|
||||||
|
target: Qt.point(width - (accountWidget.width / 2), -10)
|
||||||
|
|
||||||
|
arrowSize: UM.Theme.getSize("default_arrow").width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
resources/qml/Account/AvatarImage.qml
Normal file
56
resources/qml/Account/AvatarImage.qml
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
|
||||||
|
import UM 1.4 as UM
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
// This item shows the provided image while applying a round mask to it.
|
||||||
|
// It also shows a round border around it. The color is defined by the outlineColor property.
|
||||||
|
|
||||||
|
id: avatar
|
||||||
|
|
||||||
|
property alias source: profileImage.source
|
||||||
|
property alias outlineColor: profileImageOutline.color
|
||||||
|
|
||||||
|
Image
|
||||||
|
{
|
||||||
|
id: profileImage
|
||||||
|
anchors.fill: parent
|
||||||
|
source: UM.Theme.getImage("avatar_default")
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
visible: false
|
||||||
|
mipmap: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: profileImageMask
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: width
|
||||||
|
}
|
||||||
|
|
||||||
|
OpacityMask
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
source: profileImage
|
||||||
|
maskSource: profileImageMask
|
||||||
|
cached: true
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: profileImageOutline
|
||||||
|
anchors.centerIn: parent
|
||||||
|
// Make it a bit bigger than it has to, otherwise it sometimes shows a white border.
|
||||||
|
width: parent.width + 2
|
||||||
|
height: parent.height + 2
|
||||||
|
source: UM.Theme.getIcon("circle_outline")
|
||||||
|
sourceSize: Qt.size(parent.width, parent.height)
|
||||||
|
color: UM.Theme.getColor("account_widget_ouline_active")
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue