mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-25 15:44:04 -06:00
Merge branch '4.0' into CURA-6004_missing_tooltips
This commit is contained in:
commit
17cddac024
214 changed files with 2873 additions and 5497 deletions
|
@ -44,7 +44,7 @@ class Account(QObject):
|
||||||
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_drive_plugin",
|
CLIENT_ID="um----------------------------ultimaker_cura",
|
||||||
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.
|
||||||
|
@ -479,6 +488,8 @@ class BuildVolume(SceneNode):
|
||||||
maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - disallowed_area_size + bed_adhesion_size - 1)
|
maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - disallowed_area_size + bed_adhesion_size - 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds
|
||||||
|
|
||||||
self.updateNodeBoundaryCheck()
|
self.updateNodeBoundaryCheck()
|
||||||
|
|
||||||
def getBoundingBox(self) -> AxisAlignedBox:
|
def getBoundingBox(self) -> AxisAlignedBox:
|
||||||
|
@ -524,8 +535,11 @@ class BuildVolume(SceneNode):
|
||||||
if extra_z != self._extra_z_clearance:
|
if extra_z != self._extra_z_clearance:
|
||||||
self._extra_z_clearance = extra_z
|
self._extra_z_clearance = extra_z
|
||||||
|
|
||||||
## Update the build volume visualization
|
|
||||||
def _onStackChanged(self):
|
def _onStackChanged(self):
|
||||||
|
self._stack_change_timer.start()
|
||||||
|
|
||||||
|
## Update the build volume visualization
|
||||||
|
def _onStackChangeTimerFinished(self):
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
|
self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
|
||||||
extruders = ExtruderManager.getInstance().getActiveExtruderStacks()
|
extruders = ExtruderManager.getInstance().getActiveExtruderStacks()
|
||||||
|
|
|
@ -36,18 +36,14 @@ else:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
CuraDebugMode = False # [CodeStyle: Reflecting imported value]
|
CuraDebugMode = False # [CodeStyle: Reflecting imported value]
|
||||||
|
|
||||||
# List of exceptions that should be considered "fatal" and abort the program.
|
# List of exceptions that should not be considered "fatal" and abort the program.
|
||||||
# These are primarily some exception types that we simply cannot really recover from
|
# These are primarily some exception types that we simply skip
|
||||||
# (MemoryError and SystemError) and exceptions that indicate grave errors in the
|
skip_exception_types = [
|
||||||
# code that cause the Python interpreter to fail (SyntaxError, ImportError).
|
SystemExit,
|
||||||
fatal_exception_types = [
|
KeyboardInterrupt,
|
||||||
MemoryError,
|
GeneratorExit
|
||||||
SyntaxError,
|
|
||||||
ImportError,
|
|
||||||
SystemError,
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class CrashHandler:
|
class CrashHandler:
|
||||||
crash_url = "https://stats.ultimaker.com/api/cura"
|
crash_url = "https://stats.ultimaker.com/api/cura"
|
||||||
|
|
||||||
|
@ -70,7 +66,7 @@ class CrashHandler:
|
||||||
# If Cura has fully started, we only show fatal errors.
|
# If Cura has fully started, we only show fatal errors.
|
||||||
# If Cura has not fully started yet, we always show the early crash dialog. Otherwise, Cura will just crash
|
# If Cura has not fully started yet, we always show the early crash dialog. Otherwise, Cura will just crash
|
||||||
# without any information.
|
# without any information.
|
||||||
if has_started and exception_type not in fatal_exception_types:
|
if has_started and exception_type in skip_exception_types:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not has_started:
|
if not has_started:
|
||||||
|
@ -387,7 +383,7 @@ class CrashHandler:
|
||||||
Application.getInstance().callLater(self._show)
|
Application.getInstance().callLater(self._show)
|
||||||
|
|
||||||
def _show(self):
|
def _show(self):
|
||||||
# When the exception is not in the fatal_exception_types list, the dialog is not created, so we don't need to show it
|
# When the exception is in the skip_exception_types list, the dialog is not created, so we don't need to show it
|
||||||
if self.dialog:
|
if self.dialog:
|
||||||
self.dialog.exec_()
|
self.dialog.exec_()
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
|
|
|
@ -134,7 +134,7 @@ except ImportError:
|
||||||
CuraVersion = "master" # [CodeStyle: Reflecting imported value]
|
CuraVersion = "master" # [CodeStyle: Reflecting imported value]
|
||||||
CuraBuildType = ""
|
CuraBuildType = ""
|
||||||
CuraDebugMode = False
|
CuraDebugMode = False
|
||||||
CuraSDKVersion = "5.0.0"
|
CuraSDKVersion = "6.0.0"
|
||||||
|
|
||||||
|
|
||||||
class CuraApplication(QtApplication):
|
class CuraApplication(QtApplication):
|
||||||
|
@ -181,7 +181,6 @@ class CuraApplication(QtApplication):
|
||||||
# Variables set from CLI
|
# Variables set from CLI
|
||||||
self._files_to_open = []
|
self._files_to_open = []
|
||||||
self._use_single_instance = False
|
self._use_single_instance = False
|
||||||
self._trigger_early_crash = False # For debug only
|
|
||||||
|
|
||||||
self._single_instance = None
|
self._single_instance = None
|
||||||
|
|
||||||
|
@ -206,6 +205,8 @@ class CuraApplication(QtApplication):
|
||||||
self._container_manager = None
|
self._container_manager = None
|
||||||
|
|
||||||
self._object_manager = None
|
self._object_manager = None
|
||||||
|
self._extruders_model = None
|
||||||
|
self._extruders_model_with_optional = None
|
||||||
self._build_plate_model = None
|
self._build_plate_model = None
|
||||||
self._multi_build_plate_model = None
|
self._multi_build_plate_model = None
|
||||||
self._setting_visibility_presets_model = None
|
self._setting_visibility_presets_model = None
|
||||||
|
@ -292,7 +293,10 @@ class CuraApplication(QtApplication):
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
self._use_single_instance = self._cli_args.single_instance
|
self._use_single_instance = self._cli_args.single_instance
|
||||||
self._trigger_early_crash = self._cli_args.trigger_early_crash
|
# FOR TESTING ONLY
|
||||||
|
if self._cli_args.trigger_early_crash:
|
||||||
|
assert not "This crash is triggered by the trigger_early_crash command line argument."
|
||||||
|
|
||||||
for filename in self._cli_args.file:
|
for filename in self._cli_args.file:
|
||||||
self._files_to_open.append(os.path.abspath(filename))
|
self._files_to_open.append(os.path.abspath(filename))
|
||||||
|
|
||||||
|
@ -860,6 +864,19 @@ class CuraApplication(QtApplication):
|
||||||
self._object_manager = ObjectsModel.createObjectsModel()
|
self._object_manager = ObjectsModel.createObjectsModel()
|
||||||
return self._object_manager
|
return self._object_manager
|
||||||
|
|
||||||
|
@pyqtSlot(result = QObject)
|
||||||
|
def getExtrudersModel(self, *args) -> "ExtrudersModel":
|
||||||
|
if self._extruders_model is None:
|
||||||
|
self._extruders_model = ExtrudersModel(self)
|
||||||
|
return self._extruders_model
|
||||||
|
|
||||||
|
@pyqtSlot(result = QObject)
|
||||||
|
def getExtrudersModelWithOptional(self, *args) -> "ExtrudersModel":
|
||||||
|
if self._extruders_model_with_optional is None:
|
||||||
|
self._extruders_model_with_optional = ExtrudersModel(self)
|
||||||
|
self._extruders_model_with_optional.setAddOptionalExtruder(True)
|
||||||
|
return self._extruders_model_with_optional
|
||||||
|
|
||||||
@pyqtSlot(result = QObject)
|
@pyqtSlot(result = QObject)
|
||||||
def getMultiBuildPlateModel(self, *args) -> MultiBuildPlateModel:
|
def getMultiBuildPlateModel(self, *args) -> MultiBuildPlateModel:
|
||||||
if self._multi_build_plate_model is None:
|
if self._multi_build_plate_model is None:
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,6 @@ class NozzleModel(ListModel):
|
||||||
def _update(self):
|
def _update(self):
|
||||||
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
|
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
|
||||||
|
|
||||||
self.items.clear()
|
|
||||||
|
|
||||||
global_stack = self._machine_manager.activeMachine
|
global_stack = self._machine_manager.activeMachine
|
||||||
if global_stack is None:
|
if global_stack is None:
|
||||||
self.setItems([])
|
self.setItems([])
|
||||||
|
|
|
@ -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"]:
|
||||||
token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = {
|
try:
|
||||||
"Authorization": "Bearer {}".format(access_token)
|
token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = {
|
||||||
})
|
"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
|
||||||
|
|
|
@ -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:
|
||||||
points = numpy.append(points, child_hull.getPoints(), axis = 0)
|
try:
|
||||||
|
points = numpy.append(points, child_hull.getPoints(), axis = 0)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
if points.size < 3:
|
if points.size < 3:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -83,8 +83,9 @@ 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:
|
||||||
self._active_extruder_index = index
|
if self._active_extruder_index != index:
|
||||||
self.activeExtruderChanged.emit()
|
self._active_extruder_index = index
|
||||||
|
self.activeExtruderChanged.emit()
|
||||||
|
|
||||||
@pyqtProperty(int, notify = activeExtruderChanged)
|
@pyqtProperty(int, notify = activeExtruderChanged)
|
||||||
def activeExtruderIndex(self) -> int:
|
def activeExtruderIndex(self) -> int:
|
||||||
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, pyqtProperty, QTimer
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
@ -78,8 +78,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
self._update_extruder_timer.setSingleShot(True)
|
self._update_extruder_timer.setSingleShot(True)
|
||||||
self._update_extruder_timer.timeout.connect(self.__updateExtruders)
|
self._update_extruder_timer.timeout.connect(self.__updateExtruders)
|
||||||
|
|
||||||
self._simple_names = False
|
|
||||||
|
|
||||||
self._active_machine_extruders = [] # type: Iterable[ExtruderStack]
|
self._active_machine_extruders = [] # type: Iterable[ExtruderStack]
|
||||||
self._add_optional_extruder = False
|
self._add_optional_extruder = False
|
||||||
|
|
||||||
|
@ -101,21 +99,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
def addOptionalExtruder(self):
|
def addOptionalExtruder(self):
|
||||||
return self._add_optional_extruder
|
return self._add_optional_extruder
|
||||||
|
|
||||||
## Set the simpleNames property.
|
|
||||||
def setSimpleNames(self, simple_names):
|
|
||||||
if simple_names != self._simple_names:
|
|
||||||
self._simple_names = simple_names
|
|
||||||
self.simpleNamesChanged.emit()
|
|
||||||
self._updateExtruders()
|
|
||||||
|
|
||||||
## Emitted when the simpleNames property changes.
|
|
||||||
simpleNamesChanged = pyqtSignal()
|
|
||||||
|
|
||||||
## Whether or not the model should show all definitions regardless of visibility.
|
|
||||||
@pyqtProperty(bool, fset = setSimpleNames, notify = simpleNamesChanged)
|
|
||||||
def simpleNames(self):
|
|
||||||
return self._simple_names
|
|
||||||
|
|
||||||
## Links to the stack-changed signal of the new extruders when an extruder
|
## Links to the stack-changed signal of the new extruders when an extruder
|
||||||
# is swapped out or added in the current machine.
|
# is swapped out or added in the current machine.
|
||||||
#
|
#
|
||||||
|
@ -221,9 +204,14 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
||||||
"enabled": True,
|
"enabled": True,
|
||||||
"color": "#ffffff",
|
"color": "#ffffff",
|
||||||
"index": -1,
|
"index": -1,
|
||||||
"definition": ""
|
"definition": "",
|
||||||
|
"material": "",
|
||||||
|
"variant": "",
|
||||||
|
"stack": None,
|
||||||
|
"material_brand": "",
|
||||||
|
"color_name": "",
|
||||||
}
|
}
|
||||||
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
|
||||||
|
|
|
@ -88,12 +88,14 @@ class MachineManager(QObject):
|
||||||
|
|
||||||
self._onGlobalContainerChanged()
|
self._onGlobalContainerChanged()
|
||||||
|
|
||||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
|
extruder_manager = self._application.getExtruderManager()
|
||||||
|
|
||||||
|
extruder_manager.activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
|
||||||
self._onActiveExtruderStackChanged()
|
self._onActiveExtruderStackChanged()
|
||||||
|
|
||||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeMaterialChanged)
|
extruder_manager.activeExtruderChanged.connect(self.activeMaterialChanged)
|
||||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeVariantChanged)
|
extruder_manager.activeExtruderChanged.connect(self.activeVariantChanged)
|
||||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeQualityChanged)
|
extruder_manager.activeExtruderChanged.connect(self.activeQualityChanged)
|
||||||
|
|
||||||
self.globalContainerChanged.connect(self.activeStackChanged)
|
self.globalContainerChanged.connect(self.activeStackChanged)
|
||||||
self.globalValueChanged.connect(self.activeStackValueChanged)
|
self.globalValueChanged.connect(self.activeStackValueChanged)
|
||||||
|
@ -1527,6 +1529,10 @@ class MachineManager(QObject):
|
||||||
def activeQualityChangesGroup(self) -> Optional["QualityChangesGroup"]:
|
def activeQualityChangesGroup(self) -> Optional["QualityChangesGroup"]:
|
||||||
return self._current_quality_changes_group
|
return self._current_quality_changes_group
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify = activeQualityChangesGroupChanged)
|
||||||
|
def hasCustomQuality(self) -> bool:
|
||||||
|
return self._current_quality_changes_group is not None
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeQualityGroupChanged)
|
@pyqtProperty(str, notify = activeQualityGroupChanged)
|
||||||
def activeQualityOrQualityChangesName(self) -> str:
|
def activeQualityOrQualityChangesName(self) -> str:
|
||||||
name = empty_quality_container.getName()
|
name = empty_quality_container.getName()
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2017 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 Set
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
|
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
|
||||||
|
@ -16,15 +17,11 @@ class SimpleModeSettingsManager(QObject):
|
||||||
self._is_profile_user_created = False # True when profile was custom created by user
|
self._is_profile_user_created = False # True when profile was custom created by user
|
||||||
|
|
||||||
self._machine_manager.activeStackValueChanged.connect(self._updateIsProfileCustomized)
|
self._machine_manager.activeStackValueChanged.connect(self._updateIsProfileCustomized)
|
||||||
self._machine_manager.activeQualityGroupChanged.connect(self._updateIsProfileUserCreated)
|
|
||||||
self._machine_manager.activeQualityChangesGroupChanged.connect(self._updateIsProfileUserCreated)
|
|
||||||
|
|
||||||
# update on create as the activeQualityChanged signal is emitted before this manager is created when Cura starts
|
# update on create as the activeQualityChanged signal is emitted before this manager is created when Cura starts
|
||||||
self._updateIsProfileCustomized()
|
self._updateIsProfileCustomized()
|
||||||
self._updateIsProfileUserCreated()
|
|
||||||
|
|
||||||
isProfileCustomizedChanged = pyqtSignal()
|
isProfileCustomizedChanged = pyqtSignal()
|
||||||
isProfileUserCreatedChanged = pyqtSignal()
|
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = isProfileCustomizedChanged)
|
@pyqtProperty(bool, notify = isProfileCustomizedChanged)
|
||||||
def isProfileCustomized(self):
|
def isProfileCustomized(self):
|
||||||
|
@ -57,33 +54,6 @@ class SimpleModeSettingsManager(QObject):
|
||||||
self._is_profile_customized = has_customized_user_settings
|
self._is_profile_customized = has_customized_user_settings
|
||||||
self.isProfileCustomizedChanged.emit()
|
self.isProfileCustomizedChanged.emit()
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = isProfileUserCreatedChanged)
|
|
||||||
def isProfileUserCreated(self):
|
|
||||||
return self._is_profile_user_created
|
|
||||||
|
|
||||||
def _updateIsProfileUserCreated(self):
|
|
||||||
quality_changes_keys = set()
|
|
||||||
|
|
||||||
if not self._machine_manager.activeMachine:
|
|
||||||
return False
|
|
||||||
|
|
||||||
global_stack = self._machine_manager.activeMachine
|
|
||||||
|
|
||||||
# check quality changes settings in the global stack
|
|
||||||
quality_changes_keys.update(global_stack.qualityChanges.getAllKeys())
|
|
||||||
|
|
||||||
# check quality changes settings in the extruder stacks
|
|
||||||
if global_stack.extruders:
|
|
||||||
for extruder_stack in global_stack.extruders.values():
|
|
||||||
quality_changes_keys.update(extruder_stack.qualityChanges.getAllKeys())
|
|
||||||
|
|
||||||
# check if the qualityChanges container is not empty (meaning it is a user created profile)
|
|
||||||
has_quality_changes = len(quality_changes_keys) > 0
|
|
||||||
|
|
||||||
if has_quality_changes != self._is_profile_user_created:
|
|
||||||
self._is_profile_user_created = has_quality_changes
|
|
||||||
self.isProfileUserCreatedChanged.emit()
|
|
||||||
|
|
||||||
# These are the settings included in the Simple ("Recommended") Mode, so only when the other settings have been
|
# These are the settings included in the Simple ("Recommended") Mode, so only when the other settings have been
|
||||||
# changed, we consider it as a user customized profile in the Simple ("Recommended") Mode.
|
# changed, we consider it as a user customized profile in the Simple ("Recommended") Mode.
|
||||||
__ignored_custom_setting_keys = ["support_enable",
|
__ignored_custom_setting_keys = ["support_enable",
|
||||||
|
|
|
@ -24,10 +24,6 @@ class CuraStage(Stage):
|
||||||
def mainComponent(self) -> QUrl:
|
def mainComponent(self) -> QUrl:
|
||||||
return self.getDisplayComponent("main")
|
return self.getDisplayComponent("main")
|
||||||
|
|
||||||
@pyqtProperty(QUrl, constant = True)
|
|
||||||
def sidebarComponent(self) -> QUrl:
|
|
||||||
return self.getDisplayComponent("sidebar")
|
|
||||||
|
|
||||||
@pyqtProperty(QUrl, constant = True)
|
@pyqtProperty(QUrl, constant = True)
|
||||||
def stageMenuComponent(self) -> QUrl:
|
def stageMenuComponent(self) -> QUrl:
|
||||||
return self.getDisplayComponent("menu")
|
return self.getDisplayComponent("menu")
|
|
@ -17,12 +17,6 @@ parser.add_argument("--debug",
|
||||||
default = False,
|
default = False,
|
||||||
help = "Turn on the debug mode by setting this option."
|
help = "Turn on the debug mode by setting this option."
|
||||||
)
|
)
|
||||||
parser.add_argument("--trigger-early-crash",
|
|
||||||
dest = "trigger_early_crash",
|
|
||||||
action = "store_true",
|
|
||||||
default = False,
|
|
||||||
help = "FOR TESTING ONLY. Trigger an early crash to show the crash dialog."
|
|
||||||
)
|
|
||||||
known_args = vars(parser.parse_known_args()[0])
|
known_args = vars(parser.parse_known_args()[0])
|
||||||
|
|
||||||
if not known_args["debug"]:
|
if not known_args["debug"]:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "3MF Reader",
|
"name": "3MF Reader",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides support for reading 3MF files.",
|
"description": "Provides support for reading 3MF files.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "3MF Writer",
|
"name": "3MF Writer",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides support for writing 3MF files.",
|
"description": "Provides support for writing 3MF files.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Changelog",
|
"name": "Changelog",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Shows changes since latest checked version.",
|
"description": "Shows changes since latest checked version.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -323,7 +323,7 @@ class StartSliceJob(Job):
|
||||||
value = stack.getProperty(key, "value")
|
value = stack.getProperty(key, "value")
|
||||||
result[key] = value
|
result[key] = value
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
|
||||||
result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
|
result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
|
||||||
result["print_temperature"] = result["material_print_temperature"]
|
result["print_temperature"] = result["material_print_temperature"]
|
||||||
result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
|
result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "CuraEngine Backend",
|
"name": "CuraEngine Backend",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"description": "Provides the link to the CuraEngine slicing backend.",
|
"description": "Provides the link to the CuraEngine slicing backend.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Cura Profile Reader",
|
"name": "Cura Profile Reader",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides support for importing Cura profiles.",
|
"description": "Provides support for importing Cura profiles.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Cura Profile Writer",
|
"name": "Cura Profile Writer",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides support for exporting Cura profiles.",
|
"description": "Provides support for exporting Cura profiles.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog":"cura"
|
"i18n-catalog":"cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Firmware Update Checker",
|
"name": "Firmware Update Checker",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Checks for firmware updates.",
|
"description": "Checks for firmware updates.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Firmware Updater",
|
"name": "Firmware Updater",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides a machine actions for updating firmware.",
|
"description": "Provides a machine actions for updating firmware.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Compressed G-code Reader",
|
"name": "Compressed G-code Reader",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Reads g-code from a compressed archive.",
|
"description": "Reads g-code from a compressed archive.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Compressed G-code Writer",
|
"name": "Compressed G-code Writer",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Writes g-code to a compressed archive.",
|
"description": "Writes g-code to a compressed archive.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "G-code Profile Reader",
|
"name": "G-code Profile Reader",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides support for importing profiles from g-code files.",
|
"description": "Provides support for importing profiles from g-code files.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,6 +364,8 @@ class FlavorParser:
|
||||||
self._layer_type = LayerPolygon.SupportType
|
self._layer_type = LayerPolygon.SupportType
|
||||||
elif type == "FILL":
|
elif type == "FILL":
|
||||||
self._layer_type = LayerPolygon.InfillType
|
self._layer_type = LayerPolygon.InfillType
|
||||||
|
elif type == "SUPPORT-INTERFACE":
|
||||||
|
self._layer_type = LayerPolygon.SupportInterfaceType
|
||||||
else:
|
else:
|
||||||
Logger.log("w", "Encountered a unknown type (%s) while parsing g-code.", type)
|
Logger.log("w", "Encountered a unknown type (%s) while parsing g-code.", type)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "G-code Reader",
|
"name": "G-code Reader",
|
||||||
"author": "Victor Larchenko",
|
"author": "Victor Larchenko, Ultimaker",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Allows loading and displaying G-code files.",
|
"description": "Allows loading and displaying G-code files.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "G-code Writer",
|
"name": "G-code Writer",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Writes g-code to a file.",
|
"description": "Writes g-code to a file.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Image Reader",
|
"name": "Image Reader",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Enables ability to generate printable geometry from 2D image files.",
|
"description": "Enables ability to generate printable geometry from 2D image files.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Legacy Cura Profile Reader",
|
"name": "Legacy Cura Profile Reader",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides support for importing profiles from legacy Cura versions.",
|
"description": "Provides support for importing profiles from legacy Cura versions.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import Cura 1.0 as Cura
|
||||||
Cura.MachineAction
|
Cura.MachineAction
|
||||||
{
|
{
|
||||||
id: base
|
id: base
|
||||||
property var extrudersModel: Cura.ExtrudersModel{}
|
property var extrudersModel: CuraApplication.getExtrudersModel()
|
||||||
property int extruderTabsCount: 0
|
property int extruderTabsCount: 0
|
||||||
|
|
||||||
property var activeMachineId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.id : ""
|
property var activeMachineId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.id : ""
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Machine Settings action",
|
"name": "Machine Settings action",
|
||||||
"author": "fieldOfView",
|
"author": "fieldOfView",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
|
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Model Checker",
|
"name": "Model Checker",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "0.1",
|
"version": "1.0.1",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"description": "Checks models and print configuration for possible printing issues and give suggestions.",
|
"description": "Checks models and print configuration for possible printing issues and give suggestions.",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,6 @@ Item
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Monitor Stage",
|
"name": "Monitor Stage",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides a monitor stage in Cura.",
|
"description": "Provides a monitor stage in Cura.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Per Model Settings Tool",
|
"name": "Per Model Settings Tool",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides the Per Model Settings.",
|
"description": "Provides the Per Model Settings.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Post Processing",
|
"name": "Post Processing",
|
||||||
"author": "Ultimaker",
|
"author": "Ultimaker",
|
||||||
"version": "2.2",
|
"version": "2.2.1",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"description": "Extension that allows for user created scripts for post processing",
|
"description": "Extension that allows for user created scripts for post processing",
|
||||||
"catalog": "cura"
|
"catalog": "cura"
|
||||||
}
|
}
|
|
@ -100,7 +100,7 @@ Item
|
||||||
source: UM.Theme.getIcon("load")
|
source: UM.Theme.getIcon("load")
|
||||||
width: UM.Theme.getSize("button_icon").width
|
width: UM.Theme.getSize("button_icon").width
|
||||||
height: UM.Theme.getSize("button_icon").height
|
height: UM.Theme.getSize("button_icon").height
|
||||||
color: UM.Theme.getColor("toolbar_button_text")
|
color: UM.Theme.getColor("icon")
|
||||||
|
|
||||||
sourceSize.height: height
|
sourceSize.height: height
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
import os.path
|
import os.path
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
@ -15,9 +15,5 @@ class PrepareStage(CuraStage):
|
||||||
Application.getInstance().engineCreatedSignal.connect(self._engineCreated)
|
Application.getInstance().engineCreatedSignal.connect(self._engineCreated)
|
||||||
|
|
||||||
def _engineCreated(self):
|
def _engineCreated(self):
|
||||||
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
|
|
||||||
"PrepareSidebar.qml")
|
|
||||||
|
|
||||||
menu_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMenu.qml")
|
menu_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMenu.qml")
|
||||||
self.addDisplayComponent("menu", menu_component_path)
|
self.addDisplayComponent("menu", menu_component_path)
|
||||||
self.addDisplayComponent("sidebar", sidebar_component_path)
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Prepare Stage",
|
"name": "Prepare Stage",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides a prepare stage in Cura.",
|
"description": "Provides a prepare stage in Cura.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
import UM 1.3 as UM
|
import UM 1.3 as UM
|
||||||
|
@ -19,12 +20,15 @@ Item
|
||||||
name: "cura"
|
name: "cura"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Row
|
Row
|
||||||
{
|
{
|
||||||
id: stageMenuRow
|
id: stageMenuRow
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
width: childrenRect.width
|
||||||
|
|
||||||
|
// We want this row to have a preferred with equals to the 85% of the parent
|
||||||
|
property int preferredWidth: Math.round(0.85 * previewMenu.width)
|
||||||
|
|
||||||
Cura.ViewsSelector
|
Cura.ViewsSelector
|
||||||
{
|
{
|
||||||
|
@ -45,11 +49,12 @@ Item
|
||||||
color: UM.Theme.getColor("lining")
|
color: UM.Theme.getColor("lining")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This component will grow freely up to complete the preferredWidth of the row.
|
||||||
Loader
|
Loader
|
||||||
{
|
{
|
||||||
id: viewPanel
|
id: viewPanel
|
||||||
height: parent.height
|
height: parent.height
|
||||||
width: childrenRect.width
|
width: source != "" ? (stageMenuRow.preferredWidth - viewsSelector.width - printSetupSelectorItem.width - 2 * UM.Theme.getSize("default_lining").width) : 0
|
||||||
source: UM.Controller.activeView != null && UM.Controller.activeView.stageMenuComponent != null ? UM.Controller.activeView.stageMenuComponent : ""
|
source: UM.Controller.activeView != null && UM.Controller.activeView.stageMenuComponent != null ? UM.Controller.activeView.stageMenuComponent : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Preview Stage",
|
"name": "Preview Stage",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides a preview stage in Cura.",
|
"description": "Provides a preview stage in Cura.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "Removable Drive Output Device Plugin",
|
"name": "Removable Drive Output Device Plugin",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"description": "Provides removable drive hotplugging and writing support.",
|
"description": "Provides removable drive hotplugging and writing support.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ Cura.ExpandableComponent
|
||||||
{
|
{
|
||||||
id: base
|
id: base
|
||||||
|
|
||||||
width: UM.Theme.getSize("layerview_menu_size").width
|
contentHeaderTitle: catalog.i18nc("@label", "Color scheme")
|
||||||
|
|
||||||
Connections
|
Connections
|
||||||
{
|
{
|
||||||
|
@ -34,14 +34,36 @@ Cura.ExpandableComponent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
headerItem: Label
|
headerItem: Item
|
||||||
{
|
{
|
||||||
id: layerViewTypesLabel
|
Label
|
||||||
text: catalog.i18nc("@label", "Color scheme")
|
{
|
||||||
font: UM.Theme.getFont("default")
|
id: colorSchemeLabel
|
||||||
color: UM.Theme.getColor("setting_control_text")
|
text: catalog.i18nc("@label", "Color scheme")
|
||||||
height: base.height
|
verticalAlignment: Text.AlignVCenter
|
||||||
verticalAlignment: Text.AlignVCenter
|
height: parent.height
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: layerTypeCombobox.currentText
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: colorSchemeLabel.right
|
||||||
|
leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
height: parent.height
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Column
|
contentItem: Column
|
||||||
|
@ -124,7 +146,7 @@ Cura.ExpandableComponent
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: compatibilityModeLabel
|
id: compatibilityModeLabel
|
||||||
text: catalog.i18nc("@label","Compatibility Mode")
|
text: catalog.i18nc("@label", "Compatibility Mode")
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
visible: UM.SimulationView.compatibilityMode
|
visible: UM.SimulationView.compatibilityMode
|
||||||
|
@ -135,13 +157,13 @@ Cura.ExpandableComponent
|
||||||
|
|
||||||
Item // Spacer
|
Item // Spacer
|
||||||
{
|
{
|
||||||
height: Math.round(UM.Theme.getSize("default_margin").width / 2)
|
height: UM.Theme.getSize("narrow_margin").width
|
||||||
width: width
|
width: width
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater
|
Repeater
|
||||||
{
|
{
|
||||||
model: Cura.ExtrudersModel{}
|
model: CuraApplication.getExtrudersModel()
|
||||||
|
|
||||||
CheckBox
|
CheckBox
|
||||||
{
|
{
|
||||||
|
@ -160,17 +182,16 @@ Cura.ExpandableComponent
|
||||||
|
|
||||||
style: UM.Theme.styles.checkbox
|
style: UM.Theme.styles.checkbox
|
||||||
|
|
||||||
Rectangle
|
|
||||||
|
UM.RecolorImage
|
||||||
{
|
{
|
||||||
|
id: swatch
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: extrudersModelCheckBox.right
|
anchors.right: extrudersModelCheckBox.right
|
||||||
width: UM.Theme.getSize("layerview_legend_size").width
|
width: UM.Theme.getSize("layerview_legend_size").width
|
||||||
height: UM.Theme.getSize("layerview_legend_size").height
|
height: UM.Theme.getSize("layerview_legend_size").height
|
||||||
|
source: UM.Theme.getIcon("extruder_button")
|
||||||
color: model.color
|
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
|
Label
|
||||||
|
@ -200,25 +221,25 @@ Cura.ExpandableComponent
|
||||||
Component.onCompleted:
|
Component.onCompleted:
|
||||||
{
|
{
|
||||||
typesLegendModel.append({
|
typesLegendModel.append({
|
||||||
label: catalog.i18nc("@label", "Show Travels"),
|
label: catalog.i18nc("@label", "Travels"),
|
||||||
initialValue: viewSettings.show_travel_moves,
|
initialValue: viewSettings.show_travel_moves,
|
||||||
preference: "layerview/show_travel_moves",
|
preference: "layerview/show_travel_moves",
|
||||||
colorId: "layerview_move_combing"
|
colorId: "layerview_move_combing"
|
||||||
});
|
});
|
||||||
typesLegendModel.append({
|
typesLegendModel.append({
|
||||||
label: catalog.i18nc("@label", "Show Helpers"),
|
label: catalog.i18nc("@label", "Helpers"),
|
||||||
initialValue: viewSettings.show_helpers,
|
initialValue: viewSettings.show_helpers,
|
||||||
preference: "layerview/show_helpers",
|
preference: "layerview/show_helpers",
|
||||||
colorId: "layerview_support"
|
colorId: "layerview_support"
|
||||||
});
|
});
|
||||||
typesLegendModel.append({
|
typesLegendModel.append({
|
||||||
label: catalog.i18nc("@label", "Show Shell"),
|
label: catalog.i18nc("@label", "Shell"),
|
||||||
initialValue: viewSettings.show_skin,
|
initialValue: viewSettings.show_skin,
|
||||||
preference: "layerview/show_skin",
|
preference: "layerview/show_skin",
|
||||||
colorId: "layerview_inset_0"
|
colorId: "layerview_inset_0"
|
||||||
});
|
});
|
||||||
typesLegendModel.append({
|
typesLegendModel.append({
|
||||||
label: catalog.i18nc("@label", "Show Infill"),
|
label: catalog.i18nc("@label", "Infill"),
|
||||||
initialValue: viewSettings.show_infill,
|
initialValue: viewSettings.show_infill,
|
||||||
preference: "layerview/show_infill",
|
preference: "layerview/show_infill",
|
||||||
colorId: "layerview_infill"
|
colorId: "layerview_infill"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Simulation View",
|
"name": "Simulation View",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides the Simulation view.",
|
"description": "Provides the Simulation view.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Slice info",
|
"name": "Slice info",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Submits anonymous slice info. Can be disabled through preferences.",
|
"description": "Submits anonymous slice info. Can be disabled through preferences.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ from UM.Math.Color import Color
|
||||||
from UM.View.GL.OpenGL import OpenGL
|
from UM.View.GL.OpenGL import OpenGL
|
||||||
|
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
from cura.Settings.ExtrudersModel import ExtrudersModel
|
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
@ -29,13 +28,16 @@ class SolidView(View):
|
||||||
self._non_printing_shader = None
|
self._non_printing_shader = None
|
||||||
self._support_mesh_shader = None
|
self._support_mesh_shader = None
|
||||||
|
|
||||||
self._extruders_model = ExtrudersModel()
|
self._extruders_model = None
|
||||||
self._theme = None
|
self._theme = None
|
||||||
|
|
||||||
def beginRendering(self):
|
def beginRendering(self):
|
||||||
scene = self.getController().getScene()
|
scene = self.getController().getScene()
|
||||||
renderer = self.getRenderer()
|
renderer = self.getRenderer()
|
||||||
|
|
||||||
|
if not self._extruders_model:
|
||||||
|
self._extruders_model = Application.getInstance().getExtrudersModel()
|
||||||
|
|
||||||
if not self._theme:
|
if not self._theme:
|
||||||
self._theme = Application.getInstance().getTheme()
|
self._theme = Application.getInstance().getTheme()
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Solid View",
|
"name": "Solid View",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides a normal solid mesh view.",
|
"description": "Provides a normal solid mesh view.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Support Eraser",
|
"name": "Support Eraser",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Creates an eraser mesh to block the printing of support in certain places",
|
"description": "Creates an eraser mesh to block the printing of support in certain places",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "Toolbox",
|
"name": "Toolbox",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"description": "Find, manage and install new Cura packages."
|
"description": "Find, manage and install new Cura packages."
|
||||||
}
|
}
|
||||||
|
|
106
plugins/Toolbox/resources/qml/RatingWidget.qml
Normal file
106
plugins/Toolbox/resources/qml/RatingWidget.qml
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import UM 1.0 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: ratingWidget
|
||||||
|
|
||||||
|
property real rating: 0
|
||||||
|
property int indexHovered: -1
|
||||||
|
property string packageId: ""
|
||||||
|
|
||||||
|
property int userRating: 0
|
||||||
|
property bool canRate: false
|
||||||
|
|
||||||
|
signal rated(int rating)
|
||||||
|
|
||||||
|
width: contentRow.width
|
||||||
|
height: contentRow.height
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: ratingWidget.canRate
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
onExited:
|
||||||
|
{
|
||||||
|
if(ratingWidget.canRate)
|
||||||
|
{
|
||||||
|
ratingWidget.indexHovered = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: contentRow
|
||||||
|
height: childrenRect.height
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
model: 5 // We need to get 5 stars
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: control
|
||||||
|
hoverEnabled: true
|
||||||
|
onHoveredChanged:
|
||||||
|
{
|
||||||
|
if(hovered && ratingWidget.canRate)
|
||||||
|
{
|
||||||
|
indexHovered = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolTip.visible: control.hovered && !ratingWidget.canRate
|
||||||
|
ToolTip.text: !Cura.API.account.isLoggedIn ? catalog.i18nc("@label", "You need to login first before you can rate"): catalog.i18nc("@label", "You need to install the package before you can rate")
|
||||||
|
|
||||||
|
property bool isStarFilled:
|
||||||
|
{
|
||||||
|
// If the entire widget is hovered, override the actual rating.
|
||||||
|
if(ratingWidget.indexHovered >= 0)
|
||||||
|
{
|
||||||
|
return indexHovered >= index
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ratingWidget.userRating > 0)
|
||||||
|
{
|
||||||
|
return userRating >= index +1
|
||||||
|
}
|
||||||
|
|
||||||
|
return rating >= index + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Item {}
|
||||||
|
height: UM.Theme.getSize("rating_star").height
|
||||||
|
width: UM.Theme.getSize("rating_star").width
|
||||||
|
background: UM.RecolorImage
|
||||||
|
{
|
||||||
|
source: UM.Theme.getIcon(control.isStarFilled ? "star_filled" : "star_empty")
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
|
||||||
|
// Unfilled stars should always have the default color. Only filled stars should change on hover
|
||||||
|
color:
|
||||||
|
{
|
||||||
|
if(!ratingWidget.canRate)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("rating_star")
|
||||||
|
}
|
||||||
|
if((ratingWidget.indexHovered >= 0 || ratingWidget.userRating > 0) && isStarFilled)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("primary")
|
||||||
|
}
|
||||||
|
return UM.Theme.getColor("rating_star")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
if(ratingWidget.canRate)
|
||||||
|
{
|
||||||
|
rated(index + 1) // Notify anyone who cares about this.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
plugins/Toolbox/resources/qml/SmallRatingWidget.qml
Normal file
36
plugins/Toolbox/resources/qml/SmallRatingWidget.qml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import UM 1.1 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: rating
|
||||||
|
height: UM.Theme.getSize("rating_star").height
|
||||||
|
visible: model.average_rating > 0 //Has a rating at all.
|
||||||
|
spacing: UM.Theme.getSize("thick_lining").width
|
||||||
|
width: starIcon.width + spacing + numRatingsLabel.width
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: starIcon
|
||||||
|
source: UM.Theme.getIcon("star_filled")
|
||||||
|
color: model.user_rating == 0 ? UM.Theme.getColor("rating_star") : UM.Theme.getColor("primary")
|
||||||
|
height: UM.Theme.getSize("rating_star").height
|
||||||
|
width: UM.Theme.getSize("rating_star").width
|
||||||
|
sourceSize.height: height
|
||||||
|
sourceSize.width: width
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: numRatingsLabel
|
||||||
|
text: model.average_rating != undefined ? model.average_rating.toFixed(1) + " (" + model.num_ratings + " " + catalog.i18nc("@label", "ratings") + ")": ""
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
height: starIcon.height
|
||||||
|
width: contentWidth
|
||||||
|
anchors.verticalCenter: starIcon.verticalCenter
|
||||||
|
color: starIcon.color
|
||||||
|
font: UM.Theme.getFont("small")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,8 +14,8 @@ Window
|
||||||
modality: Qt.ApplicationModal
|
modality: Qt.ApplicationModal
|
||||||
flags: Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
|
flags: Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
|
||||||
|
|
||||||
width: 720 * screenScaleFactor
|
width: Math.floor(720 * screenScaleFactor)
|
||||||
height: 640 * screenScaleFactor
|
height: Math.floor(640 * screenScaleFactor)
|
||||||
minimumWidth: width
|
minimumWidth: width
|
||||||
maximumWidth: minimumWidth
|
maximumWidth: minimumWidth
|
||||||
minimumHeight: height
|
minimumHeight: height
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -88,12 +90,14 @@ Item
|
||||||
text: catalog.i18nc("@label", "Website") + ":"
|
text: catalog.i18nc("@label", "Website") + ":"
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@label", "Email") + ":"
|
text: catalog.i18nc("@label", "Email") + ":"
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column
|
Column
|
||||||
|
@ -122,6 +126,7 @@ Item
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
linkColor: UM.Theme.getColor("text_link")
|
linkColor: UM.Theme.getColor("text_link")
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
onLinkActivated: Qt.openUrlExternally(link)
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
|
|
||||||
Label
|
Label
|
||||||
|
@ -138,6 +143,7 @@ Item
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
linkColor: UM.Theme.getColor("text_link")
|
linkColor: UM.Theme.getColor("text_link")
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
onLinkActivated: Qt.openUrlExternally(link)
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rectangle
|
Rectangle
|
||||||
|
|
|
@ -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
|
||||||
|
@ -99,6 +100,7 @@ Item
|
||||||
text: styleData.value || ""
|
text: styleData.value || ""
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
font: UM.Theme.getFont("default_bold")
|
font: UM.Theme.getFont("default_bold")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
|
@ -118,6 +120,7 @@ Item
|
||||||
text: styleData.value || ""
|
text: styleData.value || ""
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
itemDelegate: Item
|
itemDelegate: Item
|
||||||
|
@ -130,6 +133,7 @@ Item
|
||||||
text: styleData.value || ""
|
text: styleData.value || ""
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +148,7 @@ Item
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,5 +237,6 @@ Item
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
linkColor: UM.Theme.getColor("text_link")
|
linkColor: UM.Theme.getColor("text_link")
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
onLinkActivated: Qt.openUrlExternally(link)
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,11 +1,13 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
id: page
|
id: page
|
||||||
|
@ -24,7 +26,7 @@ Item
|
||||||
right: parent.right
|
right: parent.right
|
||||||
rightMargin: UM.Theme.getSize("wide_margin").width
|
rightMargin: UM.Theme.getSize("wide_margin").width
|
||||||
}
|
}
|
||||||
height: UM.Theme.getSize("toolbox_detail_header").height
|
height: childrenRect.height + 3 * UM.Theme.getSize("default_margin").width
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
id: thumbnail
|
id: thumbnail
|
||||||
|
@ -37,7 +39,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: UM.Theme.getColor("main_background")
|
||||||
Image
|
Image
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -55,16 +57,21 @@ Item
|
||||||
top: thumbnail.top
|
top: thumbnail.top
|
||||||
left: thumbnail.right
|
left: thumbnail.right
|
||||||
leftMargin: UM.Theme.getSize("default_margin").width
|
leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
right: parent.right
|
|
||||||
rightMargin: UM.Theme.getSize("wide_margin").width
|
|
||||||
bottomMargin: UM.Theme.getSize("default_margin").height
|
|
||||||
}
|
}
|
||||||
text: details === null ? "" : (details.name || "")
|
text: details === null ? "" : (details.name || "")
|
||||||
font: UM.Theme.getFont("large")
|
font: UM.Theme.getFont("large")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
wrapMode: Text.WordWrap
|
width: contentWidth
|
||||||
width: parent.width
|
height: contentHeight
|
||||||
height: UM.Theme.getSize("toolbox_property_label").height
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallRatingWidget
|
||||||
|
{
|
||||||
|
anchors.left: title.right
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
anchors.verticalCenter: title.verticalCenter
|
||||||
|
property var model: details
|
||||||
}
|
}
|
||||||
|
|
||||||
Column
|
Column
|
||||||
|
@ -80,28 +87,39 @@ Item
|
||||||
width: childrenRect.width
|
width: childrenRect.width
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
Label
|
Label
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@label", "Your rating") + ":"
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@label", "Version") + ":"
|
text: catalog.i18nc("@label", "Version") + ":"
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@label", "Last updated") + ":"
|
text: catalog.i18nc("@label", "Last updated") + ":"
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@label", "Author") + ":"
|
text: catalog.i18nc("@label", "Author") + ":"
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@label", "Downloads") + ":"
|
text: catalog.i18nc("@label", "Downloads") + ":"
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text_medium")
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column
|
Column
|
||||||
|
@ -116,11 +134,54 @@ Item
|
||||||
}
|
}
|
||||||
spacing: Math.floor(UM.Theme.getSize("narrow_margin").height)
|
spacing: Math.floor(UM.Theme.getSize("narrow_margin").height)
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
|
RatingWidget
|
||||||
|
{
|
||||||
|
id: rating
|
||||||
|
visible: details.type == "plugin"
|
||||||
|
packageId: details.id != undefined ? details.id: ""
|
||||||
|
userRating: details.user_rating != undefined ? details.user_rating: 0
|
||||||
|
canRate: toolbox.isInstalled(details.id) && Cura.API.account.isLoggedIn
|
||||||
|
|
||||||
|
onRated:
|
||||||
|
{
|
||||||
|
toolbox.ratePackage(details.id, rating)
|
||||||
|
// HACK: This is a far from optimal solution, but without major refactoring, this is the best we can
|
||||||
|
// do. Since a rework of this is scheduled, it shouldn't live that long...
|
||||||
|
var index = toolbox.pluginsAvailableModel.find("id", details.id)
|
||||||
|
if(index != -1)
|
||||||
|
{
|
||||||
|
if(details.user_rating == 0) // User never rated before.
|
||||||
|
{
|
||||||
|
toolbox.pluginsAvailableModel.setProperty(index, "num_ratings", details.num_ratings + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbox.pluginsAvailableModel.setProperty(index, "user_rating", rating)
|
||||||
|
|
||||||
|
|
||||||
|
// Hack; This is because the current selection is an outdated copy, so we need to re-copy it.
|
||||||
|
base.selection = toolbox.pluginsAvailableModel.getItem(index)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
index = toolbox.pluginsShowcaseModel.find("id", details.id)
|
||||||
|
if(index != -1)
|
||||||
|
{
|
||||||
|
if(details.user_rating == 0) // User never rated before.
|
||||||
|
{
|
||||||
|
toolbox.pluginsShowcaseModel.setProperty(index, "user_rating", rating)
|
||||||
|
}
|
||||||
|
toolbox.pluginsShowcaseModel.setProperty(index, "num_ratings", details.num_ratings + 1)
|
||||||
|
|
||||||
|
// Hack; This is because the current selection is an outdated copy, so we need to re-copy it.
|
||||||
|
base.selection = toolbox.pluginsShowcaseModel.getItem(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: details === null ? "" : (details.version || catalog.i18nc("@label", "Unknown"))
|
text: details === null ? "" : (details.version || catalog.i18nc("@label", "Unknown"))
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
@ -135,6 +196,7 @@ Item
|
||||||
}
|
}
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
|
@ -153,21 +215,16 @@ Item
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
linkColor: UM.Theme.getColor("text_link")
|
linkColor: UM.Theme.getColor("text_link")
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
onLinkActivated: Qt.openUrlExternally(link)
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: details === null ? "" : (details.download_count || catalog.i18nc("@label", "Unknown"))
|
text: details === null ? "" : (details.download_count || catalog.i18nc("@label", "Unknown"))
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
color: UM.Theme.getColor("lining")
|
|
||||||
width: parent.width
|
|
||||||
height: UM.Theme.getSize("default_lining").height
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ToolboxDetailList
|
ToolboxDetailList
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
ToolboxProgressButton
|
Item
|
||||||
{
|
{
|
||||||
id: installButton
|
width: installButton.width
|
||||||
active: toolbox.isDownloading && toolbox.activePackage == model
|
height: installButton.height
|
||||||
complete: installed
|
ToolboxProgressButton
|
||||||
readyAction: function()
|
|
||||||
{
|
{
|
||||||
toolbox.activePackage = model
|
id: installButton
|
||||||
toolbox.startDownload(model.download_url)
|
active: toolbox.isDownloading && toolbox.activePackage == model
|
||||||
|
onReadyAction:
|
||||||
|
{
|
||||||
|
toolbox.activePackage = model
|
||||||
|
toolbox.startDownload(model.download_url)
|
||||||
|
}
|
||||||
|
onActiveAction: toolbox.cancelDownload()
|
||||||
|
|
||||||
|
// Don't allow installing while another download is running
|
||||||
|
enabled: installed || (!(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired)
|
||||||
|
opacity: enabled ? 1.0 : 0.5
|
||||||
|
visible: !updateButton.visible && !installed// Don't show when the update button is visible
|
||||||
}
|
}
|
||||||
activeAction: function()
|
|
||||||
|
Cura.SecondaryButton
|
||||||
{
|
{
|
||||||
toolbox.cancelDownload()
|
visible: installed
|
||||||
|
onClicked: toolbox.viewCategory = "installed"
|
||||||
|
text: catalog.i18nc("@action:button", "Installed")
|
||||||
|
fixedWidthMode: true
|
||||||
|
width: installButton.width
|
||||||
|
height: installButton.height
|
||||||
}
|
}
|
||||||
completeAction: function()
|
}
|
||||||
|
|
||||||
|
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
|
||||||
{
|
{
|
||||||
toolbox.viewCategory = "installed"
|
anchors.fill: parent
|
||||||
|
onClicked: Cura.API.account.login()
|
||||||
}
|
}
|
||||||
// Don't allow installing while another download is running
|
|
||||||
enabled: installed || !(toolbox.isDownloading && toolbox.activePackage != model)
|
|
||||||
opacity: enabled ? 1.0 : 0.5
|
|
||||||
visible: !updateButton.visible // Don't show when the update button is visible
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,11 +1,12 @@
|
||||||
// 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
|
||||||
import UM 1.1 as UM
|
import UM 1.1 as UM
|
||||||
|
import Cura 1.1 as Cura
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
|
@ -14,90 +15,13 @@ Item
|
||||||
property int installedPackages: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
|
property int installedPackages: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
id: highlight
|
|
||||||
anchors.fill: parent
|
|
||||||
opacity: 0.0
|
|
||||||
color: UM.Theme.getColor("primary")
|
|
||||||
}
|
|
||||||
Row
|
|
||||||
{
|
|
||||||
width: parent.width
|
|
||||||
height: childrenRect.height
|
|
||||||
spacing: Math.floor(UM.Theme.getSize("narrow_margin").width)
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
id: thumbnail
|
|
||||||
width: UM.Theme.getSize("toolbox_thumbnail_small").width
|
|
||||||
height: UM.Theme.getSize("toolbox_thumbnail_small").height
|
|
||||||
color: "white"
|
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
|
||||||
border.color: UM.Theme.getColor("lining")
|
|
||||||
Image
|
|
||||||
{
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: UM.Theme.getSize("toolbox_thumbnail_small").width - UM.Theme.getSize("wide_margin").width
|
|
||||||
height: UM.Theme.getSize("toolbox_thumbnail_small").height - UM.Theme.getSize("wide_margin").width
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
source: model.icon_url || "../images/logobot.svg"
|
|
||||||
mipmap: true
|
|
||||||
}
|
|
||||||
UM.RecolorImage
|
|
||||||
{
|
|
||||||
width: (parent.width * 0.4) | 0
|
|
||||||
height: (parent.height * 0.4) | 0
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
bottom: parent.bottom
|
|
||||||
right: parent.right
|
|
||||||
}
|
|
||||||
sourceSize.height: height
|
|
||||||
visible: installedPackages != 0
|
|
||||||
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
|
||||||
source: "../images/installed_check.svg"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Column
|
|
||||||
{
|
|
||||||
width: parent.width - thumbnail.width - parent.spacing
|
|
||||||
spacing: Math.floor(UM.Theme.getSize("narrow_margin").width)
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: name
|
|
||||||
text: model.name
|
|
||||||
width: parent.width
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
color: UM.Theme.getColor("text")
|
|
||||||
font: UM.Theme.getFont("default_bold")
|
|
||||||
}
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: info
|
|
||||||
text: model.description
|
|
||||||
maximumLineCount: 2
|
|
||||||
elide: Text.ElideRight
|
|
||||||
width: parent.width
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
color: UM.Theme.getColor("text_medium")
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MouseArea
|
MouseArea
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered:
|
onEntered: thumbnail.border.color = UM.Theme.getColor("primary")
|
||||||
{
|
onExited: thumbnail.border.color = UM.Theme.getColor("lining")
|
||||||
thumbnail.border.color = UM.Theme.getColor("primary")
|
|
||||||
highlight.opacity = 0.1
|
|
||||||
}
|
|
||||||
onExited:
|
|
||||||
{
|
|
||||||
thumbnail.border.color = UM.Theme.getColor("lining")
|
|
||||||
highlight.opacity = 0.0
|
|
||||||
}
|
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
base.selection = model
|
base.selection = model
|
||||||
|
@ -127,4 +51,83 @@ Item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: thumbnail
|
||||||
|
width: UM.Theme.getSize("toolbox_thumbnail_small").width
|
||||||
|
height: UM.Theme.getSize("toolbox_thumbnail_small").height
|
||||||
|
color: UM.Theme.getColor("main_background")
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: UM.Theme.getColor("lining")
|
||||||
|
|
||||||
|
Image
|
||||||
|
{
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: UM.Theme.getSize("toolbox_thumbnail_small").width - UM.Theme.getSize("wide_margin").width
|
||||||
|
height: UM.Theme.getSize("toolbox_thumbnail_small").height - UM.Theme.getSize("wide_margin").width
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: model.icon_url || "../images/logobot.svg"
|
||||||
|
mipmap: true
|
||||||
|
}
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
width: (parent.width * 0.4) | 0
|
||||||
|
height: (parent.height * 0.4) | 0
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
bottom: parent.bottom
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
sourceSize.height: height
|
||||||
|
visible: installedPackages != 0
|
||||||
|
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
||||||
|
source: "../images/installed_check.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: thumbnail.right
|
||||||
|
leftMargin: Math.floor(UM.Theme.getSize("narrow_margin").width)
|
||||||
|
right: parent.right
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: name
|
||||||
|
text: model.name
|
||||||
|
width: parent.width
|
||||||
|
elide: Text.ElideRight
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
font: UM.Theme.getFont("default_bold")
|
||||||
|
}
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: info
|
||||||
|
text: model.description
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
color: UM.Theme.getColor("text_medium")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
anchors.top: name.bottom
|
||||||
|
anchors.bottom: rating.top
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
maximumLineCount: 2
|
||||||
|
}
|
||||||
|
SmallRatingWidget
|
||||||
|
{
|
||||||
|
id: rating
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
bottom: parent.bottom
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,29 +24,33 @@ 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
|
||||||
}
|
}
|
||||||
if ( toolbox.viewCategory == "material" )
|
if (toolbox.viewCategory == "material")
|
||||||
{
|
{
|
||||||
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
|
||||||
|
@ -13,90 +13,79 @@ Rectangle
|
||||||
property int installedPackages: toolbox.viewCategory == "material" ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
|
property int installedPackages: toolbox.viewCategory == "material" ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
|
||||||
id: tileBase
|
id: tileBase
|
||||||
width: UM.Theme.getSize("toolbox_thumbnail_large").width + (2 * UM.Theme.getSize("default_lining").width)
|
width: UM.Theme.getSize("toolbox_thumbnail_large").width + (2 * UM.Theme.getSize("default_lining").width)
|
||||||
height: thumbnail.height + packageNameBackground.height + (2 * UM.Theme.getSize("default_lining").width)
|
height: thumbnail.height + packageName.height + rating.height + UM.Theme.getSize("default_margin").width
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
border.color: UM.Theme.getColor("lining")
|
border.color: UM.Theme.getColor("lining")
|
||||||
color: "transparent"
|
color: UM.Theme.getColor("main_background")
|
||||||
Rectangle
|
Image
|
||||||
{
|
{
|
||||||
id: thumbnail
|
id: thumbnail
|
||||||
color: "white"
|
height: UM.Theme.getSize("toolbox_thumbnail_large").height - 4 * UM.Theme.getSize("default_margin").height
|
||||||
width: UM.Theme.getSize("toolbox_thumbnail_large").width
|
width: UM.Theme.getSize("toolbox_thumbnail_large").height - 4 * UM.Theme.getSize("default_margin").height
|
||||||
height: UM.Theme.getSize("toolbox_thumbnail_large").height
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: model.icon_url || "../images/logobot.svg"
|
||||||
|
mipmap: true
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: parent.top
|
top: parent.top
|
||||||
|
topMargin: UM.Theme.getSize("default_margin").height
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
topMargin: UM.Theme.getSize("default_lining").width
|
|
||||||
}
|
}
|
||||||
Image
|
}
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: packageName
|
||||||
|
text: model.name
|
||||||
|
anchors
|
||||||
{
|
{
|
||||||
anchors.centerIn: parent
|
horizontalCenter: parent.horizontalCenter
|
||||||
width: UM.Theme.getSize("toolbox_thumbnail_large").width - 2 * UM.Theme.getSize("default_margin").width
|
top: thumbnail.bottom
|
||||||
height: UM.Theme.getSize("toolbox_thumbnail_large").height - 2 * UM.Theme.getSize("default_margin").height
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
source: model.icon_url || "../images/logobot.svg"
|
|
||||||
mipmap: true
|
|
||||||
}
|
}
|
||||||
UM.RecolorImage
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
height: UM.Theme.getSize("toolbox_heading_label").height
|
||||||
|
width: parent.width - UM.Theme.getSize("default_margin").width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: UM.Theme.getFont("medium_bold")
|
||||||
|
}
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
width: (parent.width * 0.20) | 0
|
||||||
|
height: width
|
||||||
|
anchors
|
||||||
{
|
{
|
||||||
width: (parent.width * 0.3) | 0
|
bottom: bottomBorder.top
|
||||||
height: (parent.height * 0.3) | 0
|
right: parent.right
|
||||||
anchors
|
|
||||||
{
|
|
||||||
bottom: parent.bottom
|
|
||||||
right: parent.right
|
|
||||||
bottomMargin: UM.Theme.getSize("default_lining").width
|
|
||||||
}
|
|
||||||
visible: installedPackages != 0
|
|
||||||
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
|
||||||
source: "../images/installed_check.svg"
|
|
||||||
}
|
}
|
||||||
|
visible: installedPackages != 0
|
||||||
|
color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
|
||||||
|
source: "../images/installed_check.svg"
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallRatingWidget
|
||||||
|
{
|
||||||
|
id: rating
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: UM.Theme.getSize("narrow_margin").height
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
id: packageNameBackground
|
id: bottomBorder
|
||||||
color: UM.Theme.getColor("primary")
|
color: UM.Theme.getColor("primary")
|
||||||
anchors
|
anchors.bottom: parent.bottom
|
||||||
{
|
|
||||||
top: thumbnail.bottom
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
height: UM.Theme.getSize("toolbox_heading_label").height
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
Label
|
height: UM.Theme.getSize("toolbox_header_highlight").height
|
||||||
{
|
|
||||||
id: packageName
|
|
||||||
text: model.name
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
height: UM.Theme.getSize("toolbox_heading_label").height
|
|
||||||
width: parent.width
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
color: UM.Theme.getColor("button_text")
|
|
||||||
font: UM.Theme.getFont("medium_bold")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea
|
MouseArea
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered:
|
onEntered: tileBase.border.color = UM.Theme.getColor("primary")
|
||||||
{
|
onExited: tileBase.border.color = UM.Theme.getColor("lining")
|
||||||
packageName.color = UM.Theme.getColor("button_text_hover")
|
|
||||||
packageNameBackground.color = UM.Theme.getColor("primary_hover")
|
|
||||||
tileBase.border.color = UM.Theme.getColor("primary_hover")
|
|
||||||
}
|
|
||||||
onExited:
|
|
||||||
{
|
|
||||||
packageName.color = UM.Theme.getColor("button_text")
|
|
||||||
packageNameBackground.color = UM.Theme.getColor("primary")
|
|
||||||
tileBase.border.color = UM.Theme.getColor("lining")
|
|
||||||
}
|
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
base.selection = model
|
base.selection = model
|
||||||
|
|
|
@ -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,22 +1,24 @@
|
||||||
// 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
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
id: footer
|
id: footer
|
||||||
width: parent.width
|
width: parent.width
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
height: visible ? Math.floor(UM.Theme.getSize("toolbox_footer").height) : 0
|
height: visible ? UM.Theme.getSize("toolbox_footer").height : 0
|
||||||
|
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@info", "You will need to restart Cura before changes in packages have effect.")
|
text: catalog.i18nc("@info", "You will need to restart Cura before changes in packages have effect.")
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
height: Math.floor(UM.Theme.getSize("toolbox_footer_button").height)
|
height: UM.Theme.getSize("toolbox_footer_button").height
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
|
@ -26,12 +28,12 @@ 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
|
|
||||||
|
Cura.PrimaryButton
|
||||||
{
|
{
|
||||||
id: restartButton
|
id: restartButton
|
||||||
text: catalog.i18nc("@info:button", "Quit Cura")
|
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: parent.top
|
top: parent.top
|
||||||
|
@ -39,26 +41,11 @@ Item
|
||||||
right: parent.right
|
right: parent.right
|
||||||
rightMargin: UM.Theme.getSize("wide_margin").width
|
rightMargin: UM.Theme.getSize("wide_margin").width
|
||||||
}
|
}
|
||||||
iconName: "dialog-restart"
|
height: UM.Theme.getSize("toolbox_footer_button").height
|
||||||
|
text: catalog.i18nc("@info:button", "Quit Cura")
|
||||||
onClicked: toolbox.restart()
|
onClicked: toolbox.restart()
|
||||||
style: ButtonStyle
|
|
||||||
{
|
|
||||||
background: Rectangle
|
|
||||||
{
|
|
||||||
implicitWidth: UM.Theme.getSize("toolbox_footer_button").width
|
|
||||||
implicitHeight: Math.floor(UM.Theme.getSize("toolbox_footer_button").height)
|
|
||||||
color: control.hovered ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary")
|
|
||||||
}
|
|
||||||
label: Label
|
|
||||||
{
|
|
||||||
color: UM.Theme.getColor("button_text")
|
|
||||||
font: UM.Theme.getFont("default_bold")
|
|
||||||
text: control.text
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolboxShadow
|
ToolboxShadow
|
||||||
{
|
{
|
||||||
visible: footer.visible
|
visible: footer.visible
|
||||||
|
|
|
@ -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
|
implicitWidth: UM.Theme.getSize("toolbox_header_tab").width
|
||||||
|
implicitHeight: UM.Theme.getSize("toolbox_header_tab").height
|
||||||
|
Rectangle
|
||||||
{
|
{
|
||||||
color: "transparent"
|
visible: control.active
|
||||||
implicitWidth: UM.Theme.getSize("toolbox_header_tab").width
|
color: UM.Theme.getColor("primary")
|
||||||
implicitHeight: UM.Theme.getSize("toolbox_header_tab").height
|
anchors.bottom: parent.bottom
|
||||||
Rectangle
|
width: parent.width
|
||||||
{
|
height: UM.Theme.getSize("toolbox_header_highlight").height
|
||||||
visible: control.active
|
|
||||||
color: UM.Theme.getColor("toolbox_header_highlight_hover")
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
width: parent.width
|
|
||||||
height: UM.Theme.getSize("toolbox_header_highlight").height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
label: Label
|
|
||||||
{
|
|
||||||
text: control.text
|
|
||||||
color:
|
|
||||||
{
|
|
||||||
if(control.hovered)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("toolbox_header_button_text_hovered");
|
|
||||||
}
|
|
||||||
if(control.active)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("toolbox_header_button_text_active");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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")
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
contentItem: Label
|
||||||
|
{
|
||||||
|
id: label
|
||||||
|
text: control.text
|
||||||
|
color:
|
||||||
|
{
|
||||||
|
if(control.hovered)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("toolbox_header_button_text_hovered");
|
||||||
|
}
|
||||||
|
if(control.active)
|
||||||
|
{
|
||||||
|
return UM.Theme.getColor("toolbox_header_button_text_active");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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")
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
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")
|
||||||
|
@ -25,39 +26,40 @@ class AuthorsModel(ListModel):
|
||||||
self.addRoleName(Qt.UserRole + 8, "description")
|
self.addRoleName(Qt.UserRole + 8, "description")
|
||||||
|
|
||||||
# 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]]]):
|
||||||
self._metadata = data
|
if self._metadata != data:
|
||||||
self._update()
|
self._metadata = data
|
||||||
|
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)
|
||||||
|
|
|
@ -33,20 +33,25 @@ class PackagesModel(ListModel):
|
||||||
self.addRoleName(Qt.UserRole + 12, "last_updated")
|
self.addRoleName(Qt.UserRole + 12, "last_updated")
|
||||||
self.addRoleName(Qt.UserRole + 13, "is_bundled")
|
self.addRoleName(Qt.UserRole + 13, "is_bundled")
|
||||||
self.addRoleName(Qt.UserRole + 14, "is_active")
|
self.addRoleName(Qt.UserRole + 14, "is_active")
|
||||||
self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed
|
self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed
|
||||||
self.addRoleName(Qt.UserRole + 16, "has_configs")
|
self.addRoleName(Qt.UserRole + 16, "has_configs")
|
||||||
self.addRoleName(Qt.UserRole + 17, "supported_configs")
|
self.addRoleName(Qt.UserRole + 17, "supported_configs")
|
||||||
self.addRoleName(Qt.UserRole + 18, "download_count")
|
self.addRoleName(Qt.UserRole + 18, "download_count")
|
||||||
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")
|
||||||
|
self.addRoleName(Qt.UserRole + 23, "average_rating")
|
||||||
|
self.addRoleName(Qt.UserRole + 24, "num_ratings")
|
||||||
|
self.addRoleName(Qt.UserRole + 25, "user_rating")
|
||||||
|
|
||||||
# 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):
|
||||||
self._metadata = data
|
if self._metadata != data:
|
||||||
self._update()
|
self._metadata = data
|
||||||
|
self._update()
|
||||||
|
|
||||||
def _update(self):
|
def _update(self):
|
||||||
items = []
|
items = []
|
||||||
|
@ -99,6 +104,10 @@ 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", []),
|
||||||
|
"average_rating": float(package.get("rating", {}).get("average", 0)),
|
||||||
|
"num_ratings": package.get("rating", {}).get("count", 0),
|
||||||
|
"user_rating": package.get("rating", {}).get("user_rating", 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
# Filter on all the key-word arguments.
|
# Filter on all the key-word arguments.
|
||||||
|
|
|
@ -13,7 +13,6 @@ from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkRepl
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
from UM.Extension import Extension
|
from UM.Extension import Extension
|
||||||
from UM.Qt.ListModel import ListModel
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
from UM.Version import Version
|
from UM.Version import Version
|
||||||
|
|
||||||
|
@ -31,8 +30,8 @@ i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
## The Toolbox class is responsible of communicating with the server through the API
|
## The Toolbox class is responsible of communicating with the server through the API
|
||||||
class Toolbox(QObject, Extension):
|
class Toolbox(QObject, Extension):
|
||||||
DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" #type: str
|
DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" # type: str
|
||||||
DEFAULT_CLOUD_API_VERSION = 1 #type: int
|
DEFAULT_CLOUD_API_VERSION = 1 # type: int
|
||||||
|
|
||||||
def __init__(self, application: CuraApplication) -> None:
|
def __init__(self, application: CuraApplication) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -50,47 +49,35 @@ class Toolbox(QObject, Extension):
|
||||||
self._download_progress = 0 # type: float
|
self._download_progress = 0 # type: float
|
||||||
self._is_downloading = False # type: bool
|
self._is_downloading = False # type: bool
|
||||||
self._network_manager = None # type: Optional[QNetworkAccessManager]
|
self._network_manager = None # type: Optional[QNetworkAccessManager]
|
||||||
self._request_header = [
|
self._request_headers = [] # type: List[Tuple[bytes, bytes]]
|
||||||
b"User-Agent",
|
self._updateRequestHeader()
|
||||||
str.encode(
|
|
||||||
"%s/%s (%s %s)" % (
|
|
||||||
self._application.getApplicationName(),
|
|
||||||
self._application.getVersion(),
|
|
||||||
platform.system(),
|
|
||||||
platform.machine(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
self._request_urls = {} # type: Dict[str, QUrl]
|
self._request_urls = {} # type: Dict[str, QUrl]
|
||||||
self._to_update = [] # type: List[str] # Package_ids that are waiting to be updated
|
self._to_update = [] # type: List[str] # Package_ids that are waiting to be updated
|
||||||
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:
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
@ -120,6 +107,7 @@ class Toolbox(QObject, Extension):
|
||||||
self._restart_dialog_message = "" # type: str
|
self._restart_dialog_message = "" # type: str
|
||||||
|
|
||||||
self._application.initializationFinished.connect(self._onAppInitialized)
|
self._application.initializationFinished.connect(self._onAppInitialized)
|
||||||
|
self._application.getCuraAPI().account.loginStateChanged.connect(self._updateRequestHeader)
|
||||||
|
|
||||||
# Signals:
|
# Signals:
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
@ -139,12 +127,38 @@ class Toolbox(QObject, Extension):
|
||||||
showLicenseDialog = pyqtSignal()
|
showLicenseDialog = pyqtSignal()
|
||||||
uninstallVariablesChanged = pyqtSignal()
|
uninstallVariablesChanged = pyqtSignal()
|
||||||
|
|
||||||
|
def _updateRequestHeader(self):
|
||||||
|
self._request_headers = [
|
||||||
|
(b"User-Agent",
|
||||||
|
str.encode(
|
||||||
|
"%s/%s (%s %s)" % (
|
||||||
|
self._application.getApplicationName(),
|
||||||
|
self._application.getVersion(),
|
||||||
|
platform.system(),
|
||||||
|
platform.machine(),
|
||||||
|
)
|
||||||
|
))
|
||||||
|
]
|
||||||
|
access_token = self._application.getCuraAPI().account.accessToken
|
||||||
|
if access_token:
|
||||||
|
self._request_headers.append((b"Authorization", "Bearer {}".format(access_token).encode()))
|
||||||
|
|
||||||
def _resetUninstallVariables(self) -> None:
|
def _resetUninstallVariables(self) -> None:
|
||||||
self._package_id_to_uninstall = None # type: Optional[str]
|
self._package_id_to_uninstall = None # type: Optional[str]
|
||||||
self._package_name_to_uninstall = ""
|
self._package_name_to_uninstall = ""
|
||||||
self._package_used_materials = [] # type: List[Tuple[GlobalStack, str, str]]
|
self._package_used_materials = [] # type: List[Tuple[GlobalStack, str, str]]
|
||||||
self._package_used_qualities = [] # type: List[Tuple[GlobalStack, str, str]]
|
self._package_used_qualities = [] # type: List[Tuple[GlobalStack, str, str]]
|
||||||
|
|
||||||
|
@pyqtSlot(str, int)
|
||||||
|
def ratePackage(self, package_id: str, rating: int) -> None:
|
||||||
|
url = QUrl("{base_url}/packages/{package_id}/ratings".format(base_url=self._api_url, package_id = package_id))
|
||||||
|
|
||||||
|
self._rate_request = QNetworkRequest(url)
|
||||||
|
for header_name, header_value in self._request_headers:
|
||||||
|
cast(QNetworkRequest, self._rate_request).setRawHeader(header_name, header_value)
|
||||||
|
data = "{\"data\": {\"cura_version\": \"%s\", \"rating\": %i}}" % (Version(self._application.getVersion()), rating)
|
||||||
|
self._rate_reply = cast(QNetworkAccessManager, self._network_manager).put(self._rate_request, data.encode())
|
||||||
|
|
||||||
@pyqtSlot(result = str)
|
@pyqtSlot(result = str)
|
||||||
def getLicenseDialogPluginName(self) -> str:
|
def getLicenseDialogPluginName(self) -> str:
|
||||||
return self._license_dialog_plugin_name
|
return self._license_dialog_plugin_name
|
||||||
|
@ -178,12 +192,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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the API root for the packages API depending on Cura version settings.
|
# Get the API root for the packages API depending on Cura version settings.
|
||||||
|
@ -192,9 +201,9 @@ class Toolbox(QObject, Extension):
|
||||||
return self.DEFAULT_CLOUD_API_ROOT
|
return self.DEFAULT_CLOUD_API_ROOT
|
||||||
if not hasattr(cura.CuraVersion, "CuraCloudAPIRoot"): # type: ignore
|
if not hasattr(cura.CuraVersion, "CuraCloudAPIRoot"): # type: ignore
|
||||||
return self.DEFAULT_CLOUD_API_ROOT
|
return self.DEFAULT_CLOUD_API_ROOT
|
||||||
if not cura.CuraVersion.CuraCloudAPIRoot: # type: ignore
|
if not cura.CuraVersion.CuraCloudAPIRoot: # type: ignore
|
||||||
return self.DEFAULT_CLOUD_API_ROOT
|
return self.DEFAULT_CLOUD_API_ROOT
|
||||||
return cura.CuraVersion.CuraCloudAPIRoot # type: ignore
|
return cura.CuraVersion.CuraCloudAPIRoot # type: ignore
|
||||||
|
|
||||||
# Get the cloud API version from CuraVersion
|
# Get the cloud API version from CuraVersion
|
||||||
def _getCloudAPIVersion(self) -> int:
|
def _getCloudAPIVersion(self) -> int:
|
||||||
|
@ -202,9 +211,9 @@ class Toolbox(QObject, Extension):
|
||||||
return self.DEFAULT_CLOUD_API_VERSION
|
return self.DEFAULT_CLOUD_API_VERSION
|
||||||
if not hasattr(cura.CuraVersion, "CuraCloudAPIVersion"): # type: ignore
|
if not hasattr(cura.CuraVersion, "CuraCloudAPIVersion"): # type: ignore
|
||||||
return self.DEFAULT_CLOUD_API_VERSION
|
return self.DEFAULT_CLOUD_API_VERSION
|
||||||
if not cura.CuraVersion.CuraCloudAPIVersion: # type: ignore
|
if not cura.CuraVersion.CuraCloudAPIVersion: # type: ignore
|
||||||
return self.DEFAULT_CLOUD_API_VERSION
|
return self.DEFAULT_CLOUD_API_VERSION
|
||||||
return cura.CuraVersion.CuraCloudAPIVersion # type: ignore
|
return cura.CuraVersion.CuraCloudAPIVersion # type: ignore
|
||||||
|
|
||||||
# Get the packages version depending on Cura version settings.
|
# Get the packages version depending on Cura version settings.
|
||||||
def _getSDKVersion(self) -> Union[int, str]:
|
def _getSDKVersion(self) -> Union[int, str]:
|
||||||
|
@ -231,12 +240,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()
|
||||||
|
@ -281,7 +284,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
|
||||||
|
|
||||||
|
@ -319,13 +322,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)
|
||||||
|
@ -479,7 +479,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
|
||||||
|
@ -491,11 +491,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)
|
||||||
|
@ -545,8 +542,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
|
||||||
|
|
||||||
|
@ -554,7 +551,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
|
||||||
|
@ -568,34 +565,31 @@ 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)
|
for header_name, header_value in self._request_headers:
|
||||||
|
request.setRawHeader(header_name, header_value)
|
||||||
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"):
|
||||||
|
@ -604,7 +598,8 @@ class Toolbox(QObject, Extension):
|
||||||
if hasattr(QNetworkRequest, "RedirectPolicyAttribute"):
|
if hasattr(QNetworkRequest, "RedirectPolicyAttribute"):
|
||||||
# Patch for Qt 5.9+
|
# Patch for Qt 5.9+
|
||||||
cast(QNetworkRequest, self._download_request).setAttribute(QNetworkRequest.RedirectPolicyAttribute, True)
|
cast(QNetworkRequest, self._download_request).setAttribute(QNetworkRequest.RedirectPolicyAttribute, True)
|
||||||
cast(QNetworkRequest, self._download_request).setRawHeader(*self._request_header)
|
for header_name, header_value in self._request_headers:
|
||||||
|
cast(QNetworkRequest, self._download_request).setRawHeader(header_name, header_value)
|
||||||
self._download_reply = cast(QNetworkAccessManager, self._network_manager).get(self._download_request)
|
self._download_reply = cast(QNetworkAccessManager, self._network_manager).get(self._download_request)
|
||||||
self.setDownloadProgress(0)
|
self.setDownloadProgress(0)
|
||||||
self.setIsDownloading(True)
|
self.setIsDownloading(True)
|
||||||
|
@ -612,15 +607,15 @@ 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:
|
||||||
if self._download_reply:
|
if self._download_reply:
|
||||||
try:
|
try:
|
||||||
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
|
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
|
||||||
except TypeError: #Raised when the method is not connected to the signal yet.
|
except TypeError: # Raised when the method is not connected to the signal yet.
|
||||||
pass #Don't need to disconnect.
|
pass # Don't need to disconnect.
|
||||||
self._download_reply.abort()
|
self._download_reply.abort()
|
||||||
self._download_reply = None
|
self._download_reply = None
|
||||||
self._download_request = None
|
self._download_request = None
|
||||||
|
@ -646,22 +641,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:
|
||||||
|
@ -674,39 +655,33 @@ 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
|
elif reply.operation() == QNetworkAccessManager.PutOperation:
|
||||||
|
|
||||||
else:
|
|
||||||
# Ignore any operation that is not a get operation
|
# Ignore any operation that is not a get operation
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -716,7 +691,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
|
||||||
|
@ -726,10 +707,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)
|
||||||
|
@ -738,7 +719,6 @@ class Toolbox(QObject, Extension):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.install(file_path)
|
self.install(file_path)
|
||||||
return
|
|
||||||
|
|
||||||
# Getter & Setters for Properties:
|
# Getter & Setters for Properties:
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
@ -761,8 +741,9 @@ 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:
|
||||||
self._active_package = package
|
if self._active_package != package:
|
||||||
self.activePackageChanged.emit()
|
self._active_package = package
|
||||||
|
self.activePackageChanged.emit()
|
||||||
|
|
||||||
## The active package is the package that is currently being downloaded
|
## The active package is the package that is currently being downloaded
|
||||||
@pyqtProperty(QObject, fset = setActivePackage, notify = activePackageChanged)
|
@pyqtProperty(QObject, fset = setActivePackage, notify = activePackageChanged)
|
||||||
|
@ -770,16 +751,18 @@ 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:
|
||||||
self._view_category = category
|
if self._view_category != category:
|
||||||
self.viewChanged.emit()
|
self._view_category = category
|
||||||
|
self.viewChanged.emit()
|
||||||
|
|
||||||
@pyqtProperty(str, fset = setViewCategory, notify = viewChanged)
|
@pyqtProperty(str, fset = setViewCategory, notify = viewChanged)
|
||||||
def viewCategory(self) -> str:
|
def viewCategory(self) -> str:
|
||||||
return self._view_category
|
return self._view_category
|
||||||
|
|
||||||
def setViewPage(self, page: str = "overview") -> None:
|
def setViewPage(self, page: str = "overview") -> None:
|
||||||
self._view_page = page
|
if self._view_page != page:
|
||||||
self.viewChanged.emit()
|
self._view_page = page
|
||||||
|
self.viewChanged.emit()
|
||||||
|
|
||||||
@pyqtProperty(str, fset = setViewPage, notify = viewChanged)
|
@pyqtProperty(str, fset = setViewPage, notify = viewChanged)
|
||||||
def viewPage(self) -> str:
|
def viewPage(self) -> str:
|
||||||
|
@ -787,48 +770,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()
|
||||||
|
@ -836,7 +819,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()
|
||||||
|
@ -844,21 +827,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"]
|
||||||
|
@ -867,30 +850,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,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "UFP Writer",
|
"name": "UFP Writer",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Provides support for writing Ultimaker Format Packages.",
|
"description": "Provides support for writing Ultimaker Format Packages.",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "UM3 Network Connection",
|
"name": "UM3 Network Connection",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"description": "Manages network connections to Ultimaker 3 printers.",
|
"description": "Manages network connections to Ultimaker 3 printers.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"api": 5,
|
"api": "6.0",
|
||||||
"i18n-catalog": "cura"
|
"i18n-catalog": "cura"
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,13 @@ import UM 1.3 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
id: base
|
||||||
property var iconSource: null;
|
property var iconSource: null;
|
||||||
color: "#0a0850" // TODO: Theme!
|
color: "#0a0850" // TODO: Theme!
|
||||||
height: width;
|
height: width;
|
||||||
radius: Math.round(0.5 * width);
|
radius: Math.round(0.5 * width);
|
||||||
width: 24 * screenScaleFactor;
|
width: 24 * screenScaleFactor;
|
||||||
|
property var enabled: true
|
||||||
|
|
||||||
UM.RecolorImage {
|
UM.RecolorImage {
|
||||||
id: icon;
|
id: icon;
|
||||||
|
@ -29,12 +31,18 @@ Rectangle {
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: clickArea;
|
id: clickArea;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
hoverEnabled: true;
|
hoverEnabled: base.enabled
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (OutputDevice.activeCameraUrl != "") {
|
if (base.enabled)
|
||||||
OutputDevice.setActiveCameraUrl("");
|
{
|
||||||
} else {
|
if (OutputDevice.activeCameraUrl != "")
|
||||||
OutputDevice.setActiveCameraUrl(modelData.cameraUrl);
|
{
|
||||||
|
OutputDevice.setActiveCameraUrl("")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OutputDevice.setActiveCameraUrl(modelData.cameraUrl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.3
|
|
||||||
import QtQuick.Controls 1.4
|
|
||||||
import QtQuick.Controls.Styles 1.3
|
|
||||||
import UM 1.3 as UM
|
|
||||||
import Cura 1.0 as Cura
|
|
||||||
|
|
||||||
Component {
|
|
||||||
Rectangle {
|
|
||||||
id: base;
|
|
||||||
property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width;
|
|
||||||
property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width;
|
|
||||||
anchors.fill: parent;
|
|
||||||
color: UM.Theme.getColor("main_background");
|
|
||||||
visible: OutputDevice != null;
|
|
||||||
|
|
||||||
UM.I18nCatalog {
|
|
||||||
id: catalog;
|
|
||||||
name: "cura";
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: printingLabel;
|
|
||||||
anchors {
|
|
||||||
left: parent.left;
|
|
||||||
leftMargin: 4 * UM.Theme.getSize("default_margin").width;
|
|
||||||
margins: 2 * UM.Theme.getSize("default_margin").width;
|
|
||||||
right: parent.right;
|
|
||||||
top: parent.top;
|
|
||||||
}
|
|
||||||
color: UM.Theme.getColor("text");
|
|
||||||
elide: Text.ElideRight;
|
|
||||||
font: UM.Theme.getFont("large");
|
|
||||||
text: catalog.i18nc("@label", "Printing");
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: managePrintersLabel;
|
|
||||||
anchors {
|
|
||||||
bottom: printingLabel.bottom;
|
|
||||||
right: printerScrollView.right;
|
|
||||||
rightMargin: 4 * UM.Theme.getSize("default_margin").width;
|
|
||||||
}
|
|
||||||
color: UM.Theme.getColor("primary"); // "Cura Blue"
|
|
||||||
font: UM.Theme.getFont("default");
|
|
||||||
linkColor: UM.Theme.getColor("primary"); // "Cura Blue"
|
|
||||||
text: catalog.i18nc("@label link to connect manager", "Manage printers");
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: managePrintersLabel;
|
|
||||||
hoverEnabled: true;
|
|
||||||
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrinterControlPanel();
|
|
||||||
onEntered: managePrintersLabel.font.underline = true;
|
|
||||||
onExited: managePrintersLabel.font.underline = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skeleton loading
|
|
||||||
Column {
|
|
||||||
id: skeletonLoader;
|
|
||||||
anchors {
|
|
||||||
left: parent.left;
|
|
||||||
leftMargin: UM.Theme.getSize("wide_margin").width;
|
|
||||||
right: parent.right;
|
|
||||||
rightMargin: UM.Theme.getSize("wide_margin").width;
|
|
||||||
top: printingLabel.bottom;
|
|
||||||
topMargin: UM.Theme.getSize("default_margin").height;
|
|
||||||
}
|
|
||||||
spacing: UM.Theme.getSize("default_margin").height - 10;
|
|
||||||
visible: printerList.count === 0;
|
|
||||||
|
|
||||||
PrinterCard {
|
|
||||||
printer: null;
|
|
||||||
}
|
|
||||||
PrinterCard {
|
|
||||||
printer: null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actual content
|
|
||||||
ScrollView {
|
|
||||||
id: printerScrollView;
|
|
||||||
anchors {
|
|
||||||
bottom: parent.bottom;
|
|
||||||
left: parent.left;
|
|
||||||
right: parent.right;
|
|
||||||
top: printingLabel.bottom;
|
|
||||||
topMargin: UM.Theme.getSize("default_margin").height;
|
|
||||||
}
|
|
||||||
style: UM.Theme.styles.scrollview;
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
id: printerList;
|
|
||||||
property var currentIndex: -1;
|
|
||||||
anchors {
|
|
||||||
fill: parent;
|
|
||||||
leftMargin: UM.Theme.getSize("wide_margin").width;
|
|
||||||
rightMargin: UM.Theme.getSize("wide_margin").width;
|
|
||||||
}
|
|
||||||
delegate: PrinterCard {
|
|
||||||
printer: modelData;
|
|
||||||
}
|
|
||||||
model: OutputDevice.printers;
|
|
||||||
spacing: UM.Theme.getSize("default_margin").height - 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,247 +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.3 as UM
|
|
||||||
import Cura 1.0 as Cura
|
|
||||||
import QtGraphicalEffects 1.0
|
|
||||||
|
|
||||||
Component
|
|
||||||
{
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
id: monitorFrame
|
|
||||||
|
|
||||||
property var emphasisColor: UM.Theme.getColor("setting_control_border_highlight")
|
|
||||||
property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width
|
|
||||||
|
|
||||||
height: maximumHeight
|
|
||||||
onVisibleChanged:
|
|
||||||
{
|
|
||||||
if (monitorFrame != null && !monitorFrame.visible)
|
|
||||||
{
|
|
||||||
OutputDevice.setActiveCameraUrl("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
width: maximumWidth
|
|
||||||
|
|
||||||
UM.I18nCatalog
|
|
||||||
{
|
|
||||||
id: catalog
|
|
||||||
name: "cura"
|
|
||||||
}
|
|
||||||
|
|
||||||
LinearGradient {
|
|
||||||
anchors.fill: parent
|
|
||||||
gradient: Gradient {
|
|
||||||
GradientStop {
|
|
||||||
position: 0.0
|
|
||||||
color: "#f6f6f6"
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 1.0
|
|
||||||
color: "#ffffff"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollView
|
|
||||||
{
|
|
||||||
id: printers
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
left: queue.left
|
|
||||||
right: queue.right
|
|
||||||
top: parent.top
|
|
||||||
topMargin: 48 * screenScaleFactor // TODO: Theme!
|
|
||||||
}
|
|
||||||
height: 264 * screenScaleFactor // TODO: Theme!
|
|
||||||
|
|
||||||
Row
|
|
||||||
{
|
|
||||||
spacing: 60 * screenScaleFactor // TODO: Theme!
|
|
||||||
|
|
||||||
Repeater
|
|
||||||
{
|
|
||||||
model: OutputDevice.printers
|
|
||||||
|
|
||||||
MonitorPrinterCard
|
|
||||||
{
|
|
||||||
printer: modelData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
id: queue
|
|
||||||
width: Math.min(834 * screenScaleFactor, maximumWidth)
|
|
||||||
|
|
||||||
anchors {
|
|
||||||
bottom: parent.bottom
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
top: printers.bottom
|
|
||||||
topMargin: 48 * screenScaleFactor // TODO: Theme!
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: queuedLabel
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
left: queuedPrintJobs.left
|
|
||||||
top: parent.top
|
|
||||||
}
|
|
||||||
color: UM.Theme.getColor("text")
|
|
||||||
font: UM.Theme.getFont("large_nonbold")
|
|
||||||
text: catalog.i18nc("@label", "Queued")
|
|
||||||
}
|
|
||||||
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
id: manageQueueLabel
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
right: queuedPrintJobs.right
|
|
||||||
verticalCenter: queuedLabel.verticalCenter
|
|
||||||
}
|
|
||||||
height: 18 * screenScaleFactor // TODO: Theme!
|
|
||||||
width: childrenRect.width
|
|
||||||
|
|
||||||
UM.RecolorImage
|
|
||||||
{
|
|
||||||
id: externalLinkIcon
|
|
||||||
anchors.verticalCenter: manageQueueLabel.verticalCenter
|
|
||||||
color: UM.Theme.getColor("primary")
|
|
||||||
source: "../svg/icons/external_link.svg"
|
|
||||||
width: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
|
|
||||||
height: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
|
|
||||||
}
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: manageQueueText
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
left: externalLinkIcon.right
|
|
||||||
leftMargin: 6 * screenScaleFactor // TODO: Theme!
|
|
||||||
verticalCenter: externalLinkIcon.verticalCenter
|
|
||||||
}
|
|
||||||
color: UM.Theme.getColor("primary")
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
linkColor: UM.Theme.getColor("primary")
|
|
||||||
text: catalog.i18nc("@label link to connect manager", "Manage queue in Cura Connect")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea
|
|
||||||
{
|
|
||||||
anchors.fill: manageQueueLabel
|
|
||||||
hoverEnabled: true
|
|
||||||
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel()
|
|
||||||
onEntered:
|
|
||||||
{
|
|
||||||
manageQueueText.font.underline = true
|
|
||||||
}
|
|
||||||
onExited:
|
|
||||||
{
|
|
||||||
manageQueueText.font.underline = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row
|
|
||||||
{
|
|
||||||
id: printJobQueueHeadings
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
left: queuedPrintJobs.left
|
|
||||||
leftMargin: 6 * screenScaleFactor // TODO: Theme!
|
|
||||||
top: queuedLabel.bottom
|
|
||||||
topMargin: 24 * screenScaleFactor // TODO: Theme!
|
|
||||||
}
|
|
||||||
spacing: 18 * screenScaleFactor // TODO: Theme!
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@label", "Print jobs")
|
|
||||||
color: "#666666"
|
|
||||||
elide: Text.ElideRight
|
|
||||||
font: UM.Theme.getFont("medium") // 14pt, regular
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: 284 * screenScaleFactor // TODO: Theme! (Should match column size)
|
|
||||||
|
|
||||||
// FIXED-LINE-HEIGHT:
|
|
||||||
height: 18 * screenScaleFactor // TODO: Theme!
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@label", "Total print time")
|
|
||||||
color: "#666666"
|
|
||||||
elide: Text.ElideRight
|
|
||||||
font: UM.Theme.getFont("medium") // 14pt, regular
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
|
|
||||||
|
|
||||||
// FIXED-LINE-HEIGHT:
|
|
||||||
height: 18 * screenScaleFactor // TODO: Theme!
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@label", "Waiting for")
|
|
||||||
color: "#666666"
|
|
||||||
elide: Text.ElideRight
|
|
||||||
font: UM.Theme.getFont("medium") // 14pt, regular
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
|
|
||||||
|
|
||||||
// FIXED-LINE-HEIGHT:
|
|
||||||
height: 18 * screenScaleFactor // TODO: Theme!
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollView
|
|
||||||
{
|
|
||||||
id: queuedPrintJobs
|
|
||||||
anchors {
|
|
||||||
bottom: parent.bottom
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
top: printJobQueueHeadings.bottom
|
|
||||||
topMargin: 12 * screenScaleFactor // TODO: Theme!
|
|
||||||
}
|
|
||||||
style: UM.Theme.styles.scrollview
|
|
||||||
visible: OutputDevice.receivedPrintJobs
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
ListView
|
|
||||||
{
|
|
||||||
id: printJobList
|
|
||||||
anchors.fill: parent
|
|
||||||
delegate: MonitorPrintJobCard
|
|
||||||
{
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
}
|
|
||||||
printJob: modelData
|
|
||||||
}
|
|
||||||
model: OutputDevice.queuedPrintJobs
|
|
||||||
spacing: 6
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PrinterVideoStream {
|
|
||||||
anchors.fill: parent
|
|
||||||
cameraUrl: OutputDevice.activeCameraUrl
|
|
||||||
visible: OutputDevice.activeCameraUrl != ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -57,7 +57,7 @@ Cura.MachineAction
|
||||||
spacing: UM.Theme.getSize("default_margin").height
|
spacing: UM.Theme.getSize("default_margin").height
|
||||||
|
|
||||||
SystemPalette { id: palette }
|
SystemPalette { id: palette }
|
||||||
UM.I18nCatalog { id: catalog; name: "cura" }
|
UM.I18nCatalog { id: catalog; name:"cura" }
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: pageTitle
|
id: pageTitle
|
||||||
|
|
|
@ -16,9 +16,9 @@ Item
|
||||||
|
|
||||||
property bool expanded: false
|
property bool expanded: false
|
||||||
property var borderWidth: 1
|
property var borderWidth: 1
|
||||||
property color borderColor: "#EAEAEC"
|
property color borderColor: "#CCCCCC"
|
||||||
property color headerBackgroundColor: "white"
|
property color headerBackgroundColor: "white"
|
||||||
property color headerHoverColor: "#f5f5f5"
|
property color headerHoverColor: "#e8f2fc"
|
||||||
property color drawerBackgroundColor: "white"
|
property color drawerBackgroundColor: "white"
|
||||||
property alias headerItem: header.children
|
property alias headerItem: header.children
|
||||||
property alias drawerItem: drawer.children
|
property alias drawerItem: drawer.children
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
251
plugins/UM3NetworkPrinting/resources/qml/MonitorCarousel.qml
Normal file
251
plugins/UM3NetworkPrinting/resources/qml/MonitorCarousel.qml
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
// 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 QtGraphicalEffects 1.0
|
||||||
|
import UM 1.3 as UM
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
|
||||||
|
property var currentIndex: 0
|
||||||
|
property var tileWidth: 834 * screenScaleFactor // TODO: Theme!
|
||||||
|
property var tileHeight: 216 * screenScaleFactor // TODO: Theme!
|
||||||
|
property var tileSpacing: 60 * screenScaleFactor // TODO: Theme!
|
||||||
|
property var maxOffset: (OutputDevice.printers.length - 1) * (tileWidth + tileSpacing)
|
||||||
|
|
||||||
|
height: centerSection.height
|
||||||
|
width: maximumWidth
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: leftHint
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: leftButton.left
|
||||||
|
rightMargin: 12 * screenScaleFactor // TODO: Theme!
|
||||||
|
left: parent.left
|
||||||
|
}
|
||||||
|
height: parent.height
|
||||||
|
z: 10
|
||||||
|
LinearGradient
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
start: Qt.point(0, 0)
|
||||||
|
end: Qt.point(leftHint.width, 0)
|
||||||
|
gradient: Gradient
|
||||||
|
{
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.0
|
||||||
|
color: "#fff6f6f6" // TODO: Theme!
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 1.0
|
||||||
|
color: "#66f6f6f6" // TODO: Theme!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: navigateTo(currentIndex - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: leftButton
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
right: centerSection.left
|
||||||
|
rightMargin: 12 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
width: 36 * screenScaleFactor // TODO: Theme!
|
||||||
|
height: 72 * screenScaleFactor // TODO: Theme!
|
||||||
|
visible: currentIndex > 0
|
||||||
|
hoverEnabled: true
|
||||||
|
z: 10
|
||||||
|
onClicked: navigateTo(currentIndex - 1)
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
color: leftButton.hovered ? "#e8f2fc" : "#ffffff" // TODO: Theme!
|
||||||
|
border.width: 1 * screenScaleFactor // TODO: Theme!
|
||||||
|
border.color: "#cccccc" // TODO: Theme!
|
||||||
|
radius: 2 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
contentItem: Item
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 18 // TODO: Theme!
|
||||||
|
height: width // TODO: Theme!
|
||||||
|
sourceSize.width: width // TODO: Theme!
|
||||||
|
sourceSize.height: width // TODO: Theme!
|
||||||
|
color: "#152950" // TODO: Theme!
|
||||||
|
source: UM.Theme.getIcon("arrow_left")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: centerSection
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
width: tileWidth
|
||||||
|
height: tiles.height
|
||||||
|
z: 1
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: tiles
|
||||||
|
height: childrenRect.height
|
||||||
|
width: 5 * tileWidth + 4 * tileSpacing // TODO: Theme!
|
||||||
|
x: 0
|
||||||
|
z: 0
|
||||||
|
Behavior on x
|
||||||
|
{
|
||||||
|
NumberAnimation
|
||||||
|
{
|
||||||
|
duration: 200
|
||||||
|
easing.type: Easing.InOutCubic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spacing: 60 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
model: OutputDevice.printers
|
||||||
|
MonitorPrinterCard
|
||||||
|
{
|
||||||
|
printer: modelData
|
||||||
|
enabled: model.index == currentIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: rightButton
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: centerSection.right
|
||||||
|
leftMargin: 12 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
width: 36 * screenScaleFactor // TODO: Theme!
|
||||||
|
height: 72 * screenScaleFactor // TODO: Theme!
|
||||||
|
z: 10
|
||||||
|
visible: currentIndex < OutputDevice.printers.length - 1
|
||||||
|
onClicked: navigateTo(currentIndex + 1)
|
||||||
|
hoverEnabled: true
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
color: rightButton.hovered ? "#e8f2fc" : "#ffffff" // TODO: Theme!
|
||||||
|
border.width: 1 * screenScaleFactor // TODO: Theme!
|
||||||
|
border.color: "#cccccc" // TODO: Theme!
|
||||||
|
radius: 2 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
contentItem: Item
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 18 // TODO: Theme!
|
||||||
|
height: width // TODO: Theme!
|
||||||
|
sourceSize.width: width // TODO: Theme!
|
||||||
|
sourceSize.height: width // TODO: Theme!
|
||||||
|
color: "#152950" // TODO: Theme!
|
||||||
|
source: UM.Theme.getIcon("arrow_right")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: rightHint
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: rightButton.right
|
||||||
|
leftMargin: 12 * screenScaleFactor // TODO: Theme!
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
height: centerSection.height
|
||||||
|
z: 10
|
||||||
|
|
||||||
|
LinearGradient
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
start: Qt.point(0, 0)
|
||||||
|
end: Qt.point(rightHint.width, 0)
|
||||||
|
gradient: Gradient
|
||||||
|
{
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 0.0
|
||||||
|
color: "#66f6f6f6" // TODO: Theme!
|
||||||
|
}
|
||||||
|
GradientStop
|
||||||
|
{
|
||||||
|
position: 1.0
|
||||||
|
color: "#fff6f6f6" // TODO: Theme!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: navigateTo(currentIndex + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: navigationDots
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
horizontalCenter: centerSection.horizontalCenter
|
||||||
|
top: centerSection.bottom
|
||||||
|
topMargin: 36 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
spacing: 8 * screenScaleFactor // TODO: Theme!
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
model: OutputDevice.printers
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
color: model.index == currentIndex ? "#777777" : "#d8d8d8" // TODO: Theme!
|
||||||
|
radius: Math.floor(width / 2)
|
||||||
|
width: 12 * screenScaleFactor // TODO: Theme!
|
||||||
|
height: width // TODO: Theme!
|
||||||
|
}
|
||||||
|
onClicked: navigateTo(model.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function navigateTo( i ) {
|
||||||
|
if (i >= 0 && i < OutputDevice.printers.length)
|
||||||
|
{
|
||||||
|
tiles.x = -1 * i * (tileWidth + tileSpacing)
|
||||||
|
currentIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ Item
|
||||||
|
|
||||||
ExpandableCard
|
ExpandableCard
|
||||||
{
|
{
|
||||||
|
borderColor: printJob.configurationChanges.length !== 0 ? "#f5a623" : "#CCCCCC" // TODO: Theme!
|
||||||
headerItem: Row
|
headerItem: Row
|
||||||
{
|
{
|
||||||
height: 48 * screenScaleFactor // TODO: Theme!
|
height: 48 * screenScaleFactor // TODO: Theme!
|
||||||
|
@ -96,6 +97,7 @@ Item
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
visible: printJob
|
visible: printJob
|
||||||
|
width: 120 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
// FIXED-LINE-HEIGHT:
|
// FIXED-LINE-HEIGHT:
|
||||||
height: 18 * screenScaleFactor // TODO: Theme!
|
height: 18 * 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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,8 +25,13 @@ Item
|
||||||
|
|
||||||
property var borderSize: 1 * screenScaleFactor // TODO: Theme, and remove from here
|
property var borderSize: 1 * screenScaleFactor // TODO: Theme, and remove from here
|
||||||
|
|
||||||
|
// If the printer card's controls are enabled. This is used by the carousel
|
||||||
|
// to prevent opening the context menu or camera while the printer card is not
|
||||||
|
// "in focus"
|
||||||
|
property var enabled: true
|
||||||
|
|
||||||
width: 834 * screenScaleFactor // TODO: Theme!
|
width: 834 * screenScaleFactor // TODO: Theme!
|
||||||
height: 216 * screenScaleFactor // TODO: Theme!
|
height: childrenRect.height
|
||||||
|
|
||||||
// Printer portion
|
// Printer portion
|
||||||
Rectangle
|
Rectangle
|
||||||
|
@ -33,7 +39,7 @@ Item
|
||||||
id: printerInfo
|
id: printerInfo
|
||||||
border
|
border
|
||||||
{
|
{
|
||||||
color: "#EAEAEC" // TODO: Theme!
|
color: "#CCCCCC" // TODO: Theme!
|
||||||
width: borderSize // TODO: Remove once themed
|
width: borderSize // TODO: Remove once themed
|
||||||
}
|
}
|
||||||
color: "white" // TODO: Theme!
|
color: "white" // TODO: Theme!
|
||||||
|
@ -66,7 +72,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
|
||||||
|
@ -123,6 +129,7 @@ Item
|
||||||
printJob: printer.activePrintJob
|
printJob: printer.activePrintJob
|
||||||
width: 36 * screenScaleFactor // TODO: Theme!
|
width: 36 * screenScaleFactor // TODO: Theme!
|
||||||
height: 36 * screenScaleFactor // TODO: Theme!
|
height: 36 * screenScaleFactor // TODO: Theme!
|
||||||
|
enabled: base.enabled
|
||||||
}
|
}
|
||||||
CameraButton
|
CameraButton
|
||||||
{
|
{
|
||||||
|
@ -135,6 +142,7 @@ Item
|
||||||
bottomMargin: 20 * screenScaleFactor // TODO: Theme!
|
bottomMargin: 20 * screenScaleFactor // TODO: Theme!
|
||||||
}
|
}
|
||||||
iconSource: "../svg/icons/camera.svg"
|
iconSource: "../svg/icons/camera.svg"
|
||||||
|
enabled: base.enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +158,7 @@ Item
|
||||||
}
|
}
|
||||||
border
|
border
|
||||||
{
|
{
|
||||||
color: "#EAEAEC" // TODO: Theme!
|
color: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? "#f5a623" : "#CCCCCC" // TODO: Theme!
|
||||||
width: borderSize // TODO: Remove once themed
|
width: borderSize // TODO: Remove once themed
|
||||||
}
|
}
|
||||||
color: "white" // TODO: Theme!
|
color: "white" // TODO: Theme!
|
||||||
|
@ -185,14 +193,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 +227,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 +256,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 +273,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: base.enabled ? overrideConfirmationDialog.open() : {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MonitorConfigOverrideDialog
|
||||||
|
{
|
||||||
|
id: overrideConfirmationDialog
|
||||||
|
printer: base.printer
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,19 @@ import UM 1.2 as UM
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
// The printer name
|
// The printer name
|
||||||
property alias text: printerNameLabel.text;
|
property var text: ""
|
||||||
|
property var tagText: {
|
||||||
|
switch(text) {
|
||||||
|
case "Ultimaker 3":
|
||||||
|
return "UM 3"
|
||||||
|
case "Ultimaker 3 Extended":
|
||||||
|
return "UM 3 EXT"
|
||||||
|
case "Ultimaker S5":
|
||||||
|
return "UM S5"
|
||||||
|
default:
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
implicitHeight: 18 * screenScaleFactor // TODO: Theme!
|
implicitHeight: 18 * screenScaleFactor // TODO: Theme!
|
||||||
implicitWidth: printerNameLabel.contentWidth + 12 // TODO: Theme!
|
implicitWidth: printerNameLabel.contentWidth + 12 // TODO: Theme!
|
||||||
|
@ -28,7 +40,7 @@ Item
|
||||||
id: printerNameLabel
|
id: printerNameLabel
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
color: "#535369" // TODO: Theme!
|
color: "#535369" // TODO: Theme!
|
||||||
text: ""
|
text: tagText
|
||||||
font.pointSize: 10
|
font.pointSize: 10
|
||||||
}
|
}
|
||||||
}
|
}
|
167
plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml
Normal file
167
plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
// 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.3 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component contains the print job queue, extracted from the primary
|
||||||
|
* MonitorStage.qml file not for reusability but simply to keep it lean and more
|
||||||
|
* readable.
|
||||||
|
*/
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: queuedLabel
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: queuedPrintJobs.left
|
||||||
|
top: parent.top
|
||||||
|
}
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
font: UM.Theme.getFont("large_nonbold")
|
||||||
|
text: catalog.i18nc("@label", "Queued")
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: manageQueueLabel
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: queuedPrintJobs.right
|
||||||
|
verticalCenter: queuedLabel.verticalCenter
|
||||||
|
}
|
||||||
|
height: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
width: childrenRect.width
|
||||||
|
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: externalLinkIcon
|
||||||
|
anchors.verticalCenter: manageQueueLabel.verticalCenter
|
||||||
|
color: UM.Theme.getColor("primary")
|
||||||
|
source: "../svg/icons/external_link.svg"
|
||||||
|
width: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
|
||||||
|
height: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
|
||||||
|
}
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: manageQueueText
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: externalLinkIcon.right
|
||||||
|
leftMargin: 6 * screenScaleFactor // TODO: Theme!
|
||||||
|
verticalCenter: externalLinkIcon.verticalCenter
|
||||||
|
}
|
||||||
|
color: UM.Theme.getColor("primary")
|
||||||
|
font: UM.Theme.getFont("default") // 12pt, regular
|
||||||
|
linkColor: UM.Theme.getColor("primary")
|
||||||
|
text: catalog.i18nc("@label link to connect manager", "Manage queue in Cura Connect")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
anchors.fill: manageQueueLabel
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel()
|
||||||
|
onEntered:
|
||||||
|
{
|
||||||
|
manageQueueText.font.underline = true
|
||||||
|
}
|
||||||
|
onExited:
|
||||||
|
{
|
||||||
|
manageQueueText.font.underline = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: printJobQueueHeadings
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: queuedPrintJobs.left
|
||||||
|
leftMargin: 6 * screenScaleFactor // TODO: Theme!
|
||||||
|
top: queuedLabel.bottom
|
||||||
|
topMargin: 24 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
spacing: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@label", "Print jobs")
|
||||||
|
color: "#666666"
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: UM.Theme.getFont("medium") // 14pt, regular
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 284 * screenScaleFactor // TODO: Theme! (Should match column size)
|
||||||
|
|
||||||
|
// FIXED-LINE-HEIGHT:
|
||||||
|
height: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@label", "Total print time")
|
||||||
|
color: "#666666"
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: UM.Theme.getFont("medium") // 14pt, regular
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
|
||||||
|
|
||||||
|
// FIXED-LINE-HEIGHT:
|
||||||
|
height: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@label", "Waiting for")
|
||||||
|
color: "#666666"
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: UM.Theme.getFont("medium") // 14pt, regular
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
|
||||||
|
|
||||||
|
// FIXED-LINE-HEIGHT:
|
||||||
|
height: 18 * screenScaleFactor // TODO: Theme!
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollView
|
||||||
|
{
|
||||||
|
id: queuedPrintJobs
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
bottom: parent.bottom
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
top: printJobQueueHeadings.bottom
|
||||||
|
topMargin: 12 * screenScaleFactor // TODO: Theme!
|
||||||
|
}
|
||||||
|
style: UM.Theme.styles.scrollview
|
||||||
|
visible: OutputDevice.receivedPrintJobs
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
ListView
|
||||||
|
{
|
||||||
|
id: printJobList
|
||||||
|
anchors.fill: parent
|
||||||
|
delegate: MonitorPrintJobCard
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
printJob: modelData
|
||||||
|
}
|
||||||
|
model: OutputDevice.queuedPrintJobs
|
||||||
|
spacing: 6 // TODO: Theme!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
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