mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-16 13:15:57 +08:00
Merge branch 'CURA-6005_cura_drive_plugin' of github.com:Ultimaker/Cura into CURA-6005_cura_drive_plugin
This commit is contained in:
commit
785f2a8a8b
@ -66,6 +66,11 @@ class Arrange:
|
||||
continue
|
||||
vertices = vertices.getMinkowskiHull(Polygon.approximatedCircle(min_offset))
|
||||
points = copy.deepcopy(vertices._points)
|
||||
|
||||
# After scaling (like up to 0.1 mm) the node might not have points
|
||||
if len(points) == 0:
|
||||
continue
|
||||
|
||||
shape_arr = ShapeArray.fromPolygon(points, scale = scale)
|
||||
arranger.place(0, 0, shape_arr)
|
||||
|
||||
|
@ -36,12 +36,12 @@ class CuraActions(QObject):
|
||||
# Starting a web browser from a signal handler connected to a menu will crash on windows.
|
||||
# So instead, defer the call to the next run of the event loop, since that does work.
|
||||
# Note that weirdly enough, only signal handlers that open a web browser fail like that.
|
||||
event = CallFunctionEvent(self._openUrl, [QUrl("http://ultimaker.com/en/support/software")], {})
|
||||
event = CallFunctionEvent(self._openUrl, [QUrl("https://ultimaker.com/en/resources/manuals/software")], {})
|
||||
cura.CuraApplication.CuraApplication.getInstance().functionEvent(event)
|
||||
|
||||
@pyqtSlot()
|
||||
def openBugReportPage(self) -> None:
|
||||
event = CallFunctionEvent(self._openUrl, [QUrl("http://github.com/Ultimaker/Cura/issues")], {})
|
||||
event = CallFunctionEvent(self._openUrl, [QUrl("https://github.com/Ultimaker/Cura/issues")], {})
|
||||
cura.CuraApplication.CuraApplication.getInstance().functionEvent(event)
|
||||
|
||||
## Reset camera position and direction to default
|
||||
|
@ -51,6 +51,7 @@ from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob
|
||||
from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob
|
||||
from cura.Arranging.ShapeArray import ShapeArray
|
||||
from cura.MultiplyObjectsJob import MultiplyObjectsJob
|
||||
from cura.GlobalStacksModel import GlobalStacksModel
|
||||
from cura.Scene.ConvexHullDecorator import ConvexHullDecorator
|
||||
from cura.Operations.SetParentOperation import SetParentOperation
|
||||
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
|
||||
@ -113,6 +114,7 @@ from cura.Settings.CuraFormulaFunctions import CuraFormulaFunctions
|
||||
|
||||
from cura.ObjectsModel import ObjectsModel
|
||||
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice
|
||||
from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage
|
||||
|
||||
from cura import ApplicationMetadata
|
||||
@ -499,7 +501,8 @@ class CuraApplication(QtApplication):
|
||||
preferences.addPreference("cura/choice_on_profile_override", "always_ask")
|
||||
preferences.addPreference("cura/choice_on_open_project", "always_ask")
|
||||
preferences.addPreference("cura/use_multi_build_plate", False)
|
||||
|
||||
preferences.addPreference("view/settings_list_height", 600)
|
||||
preferences.addPreference("view/settings_visible", False)
|
||||
preferences.addPreference("cura/currency", "€")
|
||||
preferences.addPreference("cura/material_settings", "{}")
|
||||
|
||||
@ -971,6 +974,7 @@ class CuraApplication(QtApplication):
|
||||
qmlRegisterType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel")
|
||||
qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer")
|
||||
qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
|
||||
qmlRegisterType(GlobalStacksModel, "Cura", 1, 0, "GlobalStacksModel")
|
||||
|
||||
qmlRegisterType(FavoriteMaterialsModel, "Cura", 1, 0, "FavoriteMaterialsModel")
|
||||
qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel")
|
||||
@ -992,6 +996,8 @@ class CuraApplication(QtApplication):
|
||||
qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.getInstance)
|
||||
qmlRegisterType(SidebarCustomMenuItemsModel, "Cura", 1, 0, "SidebarCustomMenuItemsModel")
|
||||
|
||||
qmlRegisterType(PrinterOutputDevice, "Cura", 1, 0, "PrinterOutputDevice")
|
||||
|
||||
from cura.API import CuraAPI
|
||||
qmlRegisterSingletonType(CuraAPI, "Cura", 1, 1, "API", self.getCuraAPI)
|
||||
|
||||
|
63
cura/GlobalStacksModel.py
Normal file
63
cura/GlobalStacksModel.py
Normal file
@ -0,0 +1,63 @@
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.Qt.ListModel import ListModel
|
||||
|
||||
from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal
|
||||
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
from UM.Settings.ContainerStack import ContainerStack
|
||||
|
||||
from cura.PrinterOutputDevice import ConnectionType
|
||||
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
|
||||
|
||||
class GlobalStacksModel(ListModel):
|
||||
NameRole = Qt.UserRole + 1
|
||||
IdRole = Qt.UserRole + 2
|
||||
HasRemoteConnectionRole = Qt.UserRole + 3
|
||||
ConnectionTypeRole = Qt.UserRole + 4
|
||||
MetaDataRole = Qt.UserRole + 5
|
||||
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
self.addRoleName(self.NameRole, "name")
|
||||
self.addRoleName(self.IdRole, "id")
|
||||
self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection")
|
||||
self.addRoleName(self.ConnectionTypeRole, "connectionType")
|
||||
self.addRoleName(self.MetaDataRole, "metadata")
|
||||
self._container_stacks = []
|
||||
|
||||
# Listen to changes
|
||||
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
|
||||
ContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
|
||||
ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
|
||||
self._filter_dict = {}
|
||||
self._update()
|
||||
|
||||
## Handler for container added/removed events from registry
|
||||
def _onContainerChanged(self, container):
|
||||
# We only need to update when the added / removed container GlobalStack
|
||||
if isinstance(container, GlobalStack):
|
||||
self._update()
|
||||
|
||||
def _update(self) -> None:
|
||||
items = []
|
||||
|
||||
container_stacks = ContainerRegistry.getInstance().findContainerStacks(type = "machine")
|
||||
|
||||
for container_stack in container_stacks:
|
||||
connection_type = int(container_stack.getMetaDataEntry("connection_type", ConnectionType.NotConnected.value))
|
||||
has_remote_connection = connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value]
|
||||
if container_stack.getMetaDataEntry("hidden", False) in ["True", True]:
|
||||
continue
|
||||
|
||||
# TODO: Remove reference to connect group name.
|
||||
items.append({"name": container_stack.getMetaDataEntry("connect_group_name", container_stack.getName()),
|
||||
"id": container_stack.getId(),
|
||||
"hasRemoteConnection": has_remote_connection,
|
||||
"connectionType": connection_type,
|
||||
"metadata": container_stack.getMetaData().copy()})
|
||||
items.sort(key=lambda i: not i["hasRemoteConnection"])
|
||||
self.setItems(items)
|
@ -302,6 +302,10 @@ class MaterialManager(QObject):
|
||||
def getMaterialGroupListByGUID(self, guid: str) -> Optional[List[MaterialGroup]]:
|
||||
return self._guid_material_groups_map.get(guid)
|
||||
|
||||
# Returns a dict of all material groups organized by root_material_id.
|
||||
def getAllMaterialGroups(self) -> Dict[str, "MaterialGroup"]:
|
||||
return self._material_group_map
|
||||
|
||||
#
|
||||
# Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup.
|
||||
#
|
||||
|
@ -106,10 +106,7 @@ class BaseMaterialsModel(ListModel):
|
||||
return False
|
||||
|
||||
extruder_stack = global_stack.extruders[extruder_position]
|
||||
available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack)
|
||||
if available_materials == self._available_materials:
|
||||
return False
|
||||
self._available_materials = available_materials
|
||||
self._available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack)
|
||||
if self._available_materials is None:
|
||||
return False
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.Logger import Logger
|
||||
from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
|
||||
|
||||
|
||||
## Model that shows the list of favorite materials.
|
||||
class FavoriteMaterialsModel(BaseMaterialsModel):
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtCore import Qt, QTimer
|
||||
|
||||
from UM.Application import Application
|
||||
from UM.Logger import Logger
|
||||
@ -39,15 +39,23 @@ class QualityProfilesDropDownMenuModel(ListModel):
|
||||
self._machine_manager = self._application.getMachineManager()
|
||||
self._quality_manager = Application.getInstance().getQualityManager()
|
||||
|
||||
self._application.globalContainerStackChanged.connect(self._update)
|
||||
self._machine_manager.activeQualityGroupChanged.connect(self._update)
|
||||
self._machine_manager.extruderChanged.connect(self._update)
|
||||
self._quality_manager.qualitiesUpdated.connect(self._update)
|
||||
self._application.globalContainerStackChanged.connect(self._onChange)
|
||||
self._machine_manager.activeQualityGroupChanged.connect(self._onChange)
|
||||
self._machine_manager.extruderChanged.connect(self._onChange)
|
||||
self._quality_manager.qualitiesUpdated.connect(self._onChange)
|
||||
|
||||
self._layer_height_unit = "" # This is cached
|
||||
|
||||
self._update_timer = QTimer() # type: QTimer
|
||||
self._update_timer.setInterval(100)
|
||||
self._update_timer.setSingleShot(True)
|
||||
self._update_timer.timeout.connect(self._update)
|
||||
|
||||
self._update()
|
||||
|
||||
def _onChange(self) -> None:
|
||||
self._update_timer.start()
|
||||
|
||||
def _update(self):
|
||||
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
|
||||
|
||||
|
@ -6,6 +6,7 @@ from typing import Optional, List
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Resources import Resources
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
@ -18,14 +19,20 @@ class SettingVisibilityPresetsModel(QObject):
|
||||
onItemsChanged = pyqtSignal()
|
||||
activePresetChanged = pyqtSignal()
|
||||
|
||||
def __init__(self, preferences, parent = None):
|
||||
def __init__(self, preferences: Preferences, parent = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
self._items = [] # type: List[SettingVisibilityPreset]
|
||||
self._custom_preset = SettingVisibilityPreset(preset_id = "custom", name = "Custom selection", weight = -100)
|
||||
|
||||
self._populate()
|
||||
|
||||
basic_item = self.getVisibilityPresetById("basic")
|
||||
basic_visibile_settings = ";".join(basic_item.settings)
|
||||
if basic_item is not None:
|
||||
basic_visibile_settings = ";".join(basic_item.settings)
|
||||
else:
|
||||
Logger.log("w", "Unable to find the basic visiblity preset.")
|
||||
basic_visibile_settings = ""
|
||||
|
||||
self._preferences = preferences
|
||||
|
||||
@ -42,7 +49,8 @@ class SettingVisibilityPresetsModel(QObject):
|
||||
visible_settings = self._preferences.getValue("general/visible_settings")
|
||||
|
||||
if not visible_settings:
|
||||
self._preferences.setValue("general/visible_settings", ";".join(self._active_preset_item.settings))
|
||||
new_visible_settings = self._active_preset_item.settings if self._active_preset_item is not None else []
|
||||
self._preferences.setValue("general/visible_settings", ";".join(new_visible_settings))
|
||||
else:
|
||||
self._onPreferencesChanged("general/visible_settings")
|
||||
|
||||
@ -59,9 +67,7 @@ class SettingVisibilityPresetsModel(QObject):
|
||||
def _populate(self) -> None:
|
||||
from cura.CuraApplication import CuraApplication
|
||||
items = [] # type: List[SettingVisibilityPreset]
|
||||
|
||||
custom_preset = SettingVisibilityPreset(preset_id="custom", name ="Custom selection", weight = -100)
|
||||
items.append(custom_preset)
|
||||
items.append(self._custom_preset)
|
||||
for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset):
|
||||
setting_visibility_preset = SettingVisibilityPreset()
|
||||
try:
|
||||
@ -77,7 +83,7 @@ class SettingVisibilityPresetsModel(QObject):
|
||||
self.setItems(items)
|
||||
|
||||
@pyqtProperty("QVariantList", notify = onItemsChanged)
|
||||
def items(self):
|
||||
def items(self) -> List[SettingVisibilityPreset]:
|
||||
return self._items
|
||||
|
||||
def setItems(self, items: List[SettingVisibilityPreset]) -> None:
|
||||
@ -87,7 +93,7 @@ class SettingVisibilityPresetsModel(QObject):
|
||||
|
||||
@pyqtSlot(str)
|
||||
def setActivePreset(self, preset_id: str) -> None:
|
||||
if preset_id == self._active_preset_item.presetId:
|
||||
if self._active_preset_item is not None and preset_id == self._active_preset_item.presetId:
|
||||
Logger.log("d", "Same setting visibility preset [%s] selected, do nothing.", preset_id)
|
||||
return
|
||||
|
||||
@ -96,7 +102,7 @@ class SettingVisibilityPresetsModel(QObject):
|
||||
Logger.log("w", "Tried to set active preset to unknown id [%s]", preset_id)
|
||||
return
|
||||
|
||||
need_to_save_to_custom = self._active_preset_item.presetId == "custom" and preset_id != "custom"
|
||||
need_to_save_to_custom = self._active_preset_item is None or (self._active_preset_item.presetId == "custom" and preset_id != "custom")
|
||||
if need_to_save_to_custom:
|
||||
# Save the current visibility settings to custom
|
||||
current_visibility_string = self._preferences.getValue("general/visible_settings")
|
||||
@ -117,7 +123,9 @@ class SettingVisibilityPresetsModel(QObject):
|
||||
|
||||
@pyqtProperty(str, notify = activePresetChanged)
|
||||
def activePreset(self) -> str:
|
||||
return self._active_preset_item.presetId
|
||||
if self._active_preset_item is not None:
|
||||
return self._active_preset_item.presetId
|
||||
return ""
|
||||
|
||||
def _onPreferencesChanged(self, name: str) -> None:
|
||||
if name != "general/visible_settings":
|
||||
@ -149,7 +157,12 @@ class SettingVisibilityPresetsModel(QObject):
|
||||
else:
|
||||
item_to_set = matching_preset_item
|
||||
|
||||
# If we didn't find a matching preset, fallback to custom.
|
||||
if item_to_set is None:
|
||||
item_to_set = self._custom_preset
|
||||
|
||||
if self._active_preset_item is None or self._active_preset_item.presetId != item_to_set.presetId:
|
||||
self._active_preset_item = item_to_set
|
||||
self._preferences.setValue("cura/active_setting_visibility_preset", self._active_preset_item.presetId)
|
||||
if self._active_preset_item is not None:
|
||||
self._preferences.setValue("cura/active_setting_visibility_preset", self._active_preset_item.presetId)
|
||||
self.activePresetChanged.emit()
|
||||
|
@ -83,9 +83,11 @@ class AuthorizationService:
|
||||
if not self.getUserProfile():
|
||||
# We check if we can get the user profile.
|
||||
# If we can't get it, that means the access token (JWT) was invalid or expired.
|
||||
Logger.log("w", "Unable to get the user profile.")
|
||||
return None
|
||||
|
||||
if self._auth_data is None:
|
||||
Logger.log("d", "No auth data to retrieve the access_token from")
|
||||
return None
|
||||
|
||||
return self._auth_data.access_token
|
||||
|
@ -6,7 +6,7 @@ from UM.Logger import Logger
|
||||
from UM.Scene.SceneNode import SceneNode #For typing.
|
||||
from cura.CuraApplication import CuraApplication
|
||||
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
|
||||
|
||||
from PyQt5.QtNetwork import QHttpMultiPart, QHttpPart, QNetworkRequest, QNetworkAccessManager, QNetworkReply, QAuthenticator
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl, QCoreApplication
|
||||
@ -28,8 +28,8 @@ class AuthState(IntEnum):
|
||||
class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
||||
authenticationStateChanged = pyqtSignal()
|
||||
|
||||
def __init__(self, device_id, address: str, properties: Dict[bytes, bytes], parent: QObject = None) -> None:
|
||||
super().__init__(device_id = device_id, parent = parent)
|
||||
def __init__(self, device_id, address: str, properties: Dict[bytes, bytes], connection_type: ConnectionType = ConnectionType.NetworkConnection, parent: QObject = None) -> None:
|
||||
super().__init__(device_id = device_id, connection_type = connection_type, parent = parent)
|
||||
self._manager = None # type: Optional[QNetworkAccessManager]
|
||||
self._last_manager_create_time = None # type: Optional[float]
|
||||
self._recreate_network_manager_time = 30
|
||||
@ -125,7 +125,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
||||
if self._connection_state_before_timeout is None:
|
||||
self._connection_state_before_timeout = self._connection_state
|
||||
|
||||
self.setConnectionState(ConnectionState.closed)
|
||||
self.setConnectionState(ConnectionState.Closed)
|
||||
|
||||
# We need to check if the manager needs to be re-created. If we don't, we get some issues when OSX goes to
|
||||
# sleep.
|
||||
@ -133,7 +133,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
||||
if self._last_manager_create_time is None or time() - self._last_manager_create_time > self._recreate_network_manager_time:
|
||||
self._createNetworkManager()
|
||||
assert(self._manager is not None)
|
||||
elif self._connection_state == ConnectionState.closed:
|
||||
elif self._connection_state == ConnectionState.Closed:
|
||||
# Go out of timeout.
|
||||
if self._connection_state_before_timeout is not None: # sanity check, but it should never be None here
|
||||
self.setConnectionState(self._connection_state_before_timeout)
|
||||
@ -285,8 +285,8 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
||||
|
||||
self._last_response_time = time()
|
||||
|
||||
if self._connection_state == ConnectionState.connecting:
|
||||
self.setConnectionState(ConnectionState.connected)
|
||||
if self._connection_state == ConnectionState.Connecting:
|
||||
self.setConnectionState(ConnectionState.Connected)
|
||||
|
||||
callback_key = reply.url().toString() + str(reply.operation())
|
||||
try:
|
||||
|
@ -4,7 +4,7 @@
|
||||
from UM.Decorators import deprecated
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.OutputDevice.OutputDevice import OutputDevice
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QTimer, QUrl
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QTimer, QUrl, Q_ENUMS
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
from UM.Logger import Logger
|
||||
@ -28,11 +28,18 @@ i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
## The current processing state of the backend.
|
||||
class ConnectionState(IntEnum):
|
||||
closed = 0
|
||||
connecting = 1
|
||||
connected = 2
|
||||
busy = 3
|
||||
error = 4
|
||||
Closed = 0
|
||||
Connecting = 1
|
||||
Connected = 2
|
||||
Busy = 3
|
||||
Error = 4
|
||||
|
||||
|
||||
class ConnectionType(IntEnum):
|
||||
NotConnected = 0
|
||||
UsbConnection = 1
|
||||
NetworkConnection = 2
|
||||
CloudConnection = 3
|
||||
|
||||
|
||||
## Printer output device adds extra interface options on top of output device.
|
||||
@ -46,6 +53,11 @@ class ConnectionState(IntEnum):
|
||||
# For all other uses it should be used in the same way as a "regular" OutputDevice.
|
||||
@signalemitter
|
||||
class PrinterOutputDevice(QObject, OutputDevice):
|
||||
|
||||
# Put ConnectionType here with Q_ENUMS() so it can be registered as a QML type and accessible via QML, and there is
|
||||
# no need to remember what those Enum integer values mean.
|
||||
Q_ENUMS(ConnectionType)
|
||||
|
||||
printersChanged = pyqtSignal()
|
||||
connectionStateChanged = pyqtSignal(str)
|
||||
acceptsCommandsChanged = pyqtSignal()
|
||||
@ -62,7 +74,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||
# Signal to indicate that the configuration of one of the printers has changed.
|
||||
uniqueConfigurationsChanged = pyqtSignal()
|
||||
|
||||
def __init__(self, device_id: str, parent: QObject = None) -> None:
|
||||
def __init__(self, device_id: str, connection_type: "ConnectionType" = ConnectionType.NotConnected, parent: QObject = None) -> None:
|
||||
super().__init__(device_id = device_id, parent = parent) # type: ignore # MyPy complains with the multiple inheritance
|
||||
|
||||
self._printers = [] # type: List[PrinterOutputModel]
|
||||
@ -83,7 +95,8 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||
self._update_timer.setSingleShot(False)
|
||||
self._update_timer.timeout.connect(self._update)
|
||||
|
||||
self._connection_state = ConnectionState.closed #type: ConnectionState
|
||||
self._connection_state = ConnectionState.Closed #type: ConnectionState
|
||||
self._connection_type = connection_type
|
||||
|
||||
self._firmware_updater = None #type: Optional[FirmwareUpdater]
|
||||
self._firmware_name = None #type: Optional[str]
|
||||
@ -110,15 +123,18 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||
callback(QMessageBox.Yes)
|
||||
|
||||
def isConnected(self) -> bool:
|
||||
return self._connection_state != ConnectionState.closed and self._connection_state != ConnectionState.error
|
||||
return self._connection_state != ConnectionState.Closed and self._connection_state != ConnectionState.Error
|
||||
|
||||
def setConnectionState(self, connection_state: ConnectionState) -> None:
|
||||
def setConnectionState(self, connection_state: "ConnectionState") -> None:
|
||||
if self._connection_state != connection_state:
|
||||
self._connection_state = connection_state
|
||||
self.connectionStateChanged.emit(self._id)
|
||||
|
||||
def getConnectionType(self) -> "ConnectionType":
|
||||
return self._connection_type
|
||||
|
||||
@pyqtProperty(str, notify = connectionStateChanged)
|
||||
def connectionState(self) -> ConnectionState:
|
||||
def connectionState(self) -> "ConnectionState":
|
||||
return self._connection_state
|
||||
|
||||
def _update(self) -> None:
|
||||
@ -174,13 +190,13 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||
|
||||
## Attempt to establish connection
|
||||
def connect(self) -> None:
|
||||
self.setConnectionState(ConnectionState.connecting)
|
||||
self.setConnectionState(ConnectionState.Connecting)
|
||||
self._update_timer.start()
|
||||
|
||||
## Attempt to close the connection
|
||||
def close(self) -> None:
|
||||
self._update_timer.stop()
|
||||
self.setConnectionState(ConnectionState.closed)
|
||||
self.setConnectionState(ConnectionState.Closed)
|
||||
|
||||
## Ensure that close gets called when object is destroyed
|
||||
def __del__(self) -> None:
|
||||
@ -214,7 +230,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||
# Returns the unique configurations of the printers within this output device
|
||||
@pyqtProperty("QStringList", notify = uniqueConfigurationsChanged)
|
||||
def uniquePrinterTypes(self) -> List[str]:
|
||||
return list(set([configuration.printerType for configuration in self._unique_configurations]))
|
||||
return list(sorted(set([configuration.printerType for configuration in self._unique_configurations])))
|
||||
|
||||
def _onPrintersChanged(self) -> None:
|
||||
for printer in self._printers:
|
||||
|
@ -23,7 +23,7 @@ from UM.Settings.SettingFunction import SettingFunction
|
||||
from UM.Signal import postponeSignals, CompressTechnique
|
||||
|
||||
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionType
|
||||
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
|
||||
from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
|
||||
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
|
||||
@ -299,6 +299,7 @@ class MachineManager(QObject):
|
||||
self.activeMaterialChanged.emit()
|
||||
|
||||
self.rootMaterialChanged.emit()
|
||||
self.numberExtrudersEnabledChanged.emit()
|
||||
|
||||
def _onContainersChanged(self, container: ContainerInterface) -> None:
|
||||
self._instance_container_timer.start()
|
||||
@ -523,7 +524,13 @@ class MachineManager(QObject):
|
||||
def printerConnected(self):
|
||||
return bool(self._printer_output_devices)
|
||||
|
||||
@pyqtProperty(str, notify = printerConnectedStatusChanged)
|
||||
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
|
||||
def activeMachineHasRemoteConnection(self) -> bool:
|
||||
if self._global_container_stack:
|
||||
connection_type = int(self._global_container_stack.getMetaDataEntry("connection_type", ConnectionType.NotConnected.value))
|
||||
return connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value]
|
||||
return False
|
||||
|
||||
def activeMachineNetworkKey(self) -> str:
|
||||
if self._global_container_stack:
|
||||
return self._global_container_stack.getMetaDataEntry("um_network_key", "")
|
||||
@ -751,7 +758,7 @@ class MachineManager(QObject):
|
||||
self.setActiveMachine(other_machine_stacks[0]["id"])
|
||||
|
||||
metadata = CuraContainerRegistry.getInstance().findContainerStacksMetadata(id = machine_id)[0]
|
||||
network_key = metadata["um_network_key"] if "um_network_key" in metadata else None
|
||||
network_key = metadata.get("um_network_key", None)
|
||||
ExtruderManager.getInstance().removeMachineExtruders(machine_id)
|
||||
containers = CuraContainerRegistry.getInstance().findInstanceContainersMetadata(type = "user", machine = machine_id)
|
||||
for container in containers:
|
||||
@ -1317,17 +1324,18 @@ class MachineManager(QObject):
|
||||
# Get the definition id corresponding to this machine name
|
||||
machine_definition_id = CuraContainerRegistry.getInstance().findDefinitionContainers(name = machine_name)[0].getId()
|
||||
# Try to find a machine with the same network key
|
||||
new_machine = self.getMachine(machine_definition_id, metadata_filter = {"um_network_key": self.activeMachineNetworkKey})
|
||||
new_machine = self.getMachine(machine_definition_id, metadata_filter = {"um_network_key": self.activeMachineNetworkKey()})
|
||||
# If there is no machine, then create a new one and set it to the non-hidden instance
|
||||
if not new_machine:
|
||||
new_machine = CuraStackBuilder.createMachine(machine_definition_id + "_sync", machine_definition_id)
|
||||
if not new_machine:
|
||||
return
|
||||
new_machine.setMetaDataEntry("um_network_key", self.activeMachineNetworkKey)
|
||||
new_machine.setMetaDataEntry("um_network_key", self.activeMachineNetworkKey())
|
||||
new_machine.setMetaDataEntry("connect_group_name", self.activeMachineNetworkGroupName)
|
||||
new_machine.setMetaDataEntry("hidden", False)
|
||||
new_machine.setMetaDataEntry("connection_type", self._global_container_stack.getMetaDataEntry("connection_type"))
|
||||
else:
|
||||
Logger.log("i", "Found a %s with the key %s. Let's use it!", machine_name, self.activeMachineNetworkKey)
|
||||
Logger.log("i", "Found a %s with the key %s. Let's use it!", machine_name, self.activeMachineNetworkKey())
|
||||
new_machine.setMetaDataEntry("hidden", False)
|
||||
|
||||
# Set the current printer instance to hidden (the metadata entry must exist)
|
||||
@ -1387,10 +1395,10 @@ class MachineManager(QObject):
|
||||
# After updating from 3.2 to 3.3 some group names may be temporary. If there is a mismatch in the name of the group
|
||||
# then all the container stacks are updated, both the current and the hidden ones.
|
||||
def checkCorrectGroupName(self, device_id: str, group_name: str) -> None:
|
||||
if self._global_container_stack and device_id == self.activeMachineNetworkKey:
|
||||
if self._global_container_stack and device_id == self.activeMachineNetworkKey():
|
||||
# Check if the connect_group_name is correct. If not, update all the containers connected to the same printer
|
||||
if self.activeMachineNetworkGroupName != group_name:
|
||||
metadata_filter = {"um_network_key": self.activeMachineNetworkKey}
|
||||
metadata_filter = {"um_network_key": self.activeMachineNetworkKey()}
|
||||
containers = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", **metadata_filter)
|
||||
for container in containers:
|
||||
container.setMetaDataEntry("connect_group_name", group_name)
|
||||
@ -1529,6 +1537,10 @@ class MachineManager(QObject):
|
||||
def activeQualityChangesGroup(self) -> Optional["QualityChangesGroup"]:
|
||||
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)
|
||||
def activeQualityOrQualityChangesName(self) -> str:
|
||||
name = empty_quality_container.getName()
|
||||
|
@ -17,15 +17,11 @@ class SimpleModeSettingsManager(QObject):
|
||||
self._is_profile_user_created = False # True when profile was custom created by user
|
||||
|
||||
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
|
||||
self._updateIsProfileCustomized()
|
||||
self.updateIsProfileUserCreated()
|
||||
|
||||
isProfileCustomizedChanged = pyqtSignal()
|
||||
isProfileUserCreatedChanged = pyqtSignal()
|
||||
|
||||
@pyqtProperty(bool, notify = isProfileCustomizedChanged)
|
||||
def isProfileCustomized(self):
|
||||
@ -58,34 +54,6 @@ class SimpleModeSettingsManager(QObject):
|
||||
self._is_profile_customized = has_customized_user_settings
|
||||
self.isProfileCustomizedChanged.emit()
|
||||
|
||||
@pyqtProperty(bool, notify = isProfileUserCreatedChanged)
|
||||
def isProfileUserCreated(self):
|
||||
return self._is_profile_user_created
|
||||
|
||||
@pyqtSlot()
|
||||
def updateIsProfileUserCreated(self) -> None:
|
||||
quality_changes_keys = set() # type: Set[str]
|
||||
|
||||
if not self._machine_manager.activeMachine:
|
||||
return
|
||||
|
||||
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
|
||||
# changed, we consider it as a user customized profile in the Simple ("Recommended") Mode.
|
||||
__ignored_custom_setting_keys = ["support_enable",
|
||||
|
@ -794,7 +794,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||
# Clear all existing containers
|
||||
quality_changes_info.global_info.container.clear()
|
||||
for container_info in quality_changes_info.extruder_info_dict.values():
|
||||
container_info.container.clear()
|
||||
if container_info.container:
|
||||
container_info.container.clear()
|
||||
|
||||
# Loop over everything and override the existing containers
|
||||
global_info = quality_changes_info.global_info
|
||||
|
@ -35,7 +35,7 @@ RowLayout
|
||||
busy: CuraDrive.isCreatingBackup
|
||||
}
|
||||
|
||||
Cura.CheckBox
|
||||
Cura.CheckBoxWithTooltip
|
||||
{
|
||||
id: autoBackupEnabled
|
||||
checked: CuraDrive.autoBackupEnabled
|
||||
|
@ -86,8 +86,8 @@ class CuraEngineBackend(QObject, Backend):
|
||||
self._layer_view_active = False #type: bool
|
||||
self._onActiveViewChanged()
|
||||
|
||||
self._stored_layer_data = [] #type: List[Arcus.PythonMessage]
|
||||
self._stored_optimized_layer_data = {} #type: Dict[int, List[Arcus.PythonMessage]] # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob
|
||||
self._stored_layer_data = [] # type: List[Arcus.PythonMessage]
|
||||
self._stored_optimized_layer_data = {} # type: Dict[int, List[Arcus.PythonMessage]] # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob
|
||||
|
||||
self._scene = self._application.getController().getScene() #type: Scene
|
||||
self._scene.sceneChanged.connect(self._onSceneChanged)
|
||||
@ -229,6 +229,7 @@ class CuraEngineBackend(QObject, Backend):
|
||||
if not self._build_plates_to_be_sliced:
|
||||
self.processingProgress.emit(1.0)
|
||||
Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.")
|
||||
self.setState(BackendState.Done)
|
||||
return
|
||||
|
||||
if self._process_layers_job:
|
||||
@ -245,7 +246,7 @@ class CuraEngineBackend(QObject, Backend):
|
||||
num_objects = self._numObjectsPerBuildPlate()
|
||||
|
||||
self._stored_layer_data = []
|
||||
self._stored_optimized_layer_data[build_plate_to_be_sliced] = []
|
||||
|
||||
|
||||
if build_plate_to_be_sliced not in num_objects or num_objects[build_plate_to_be_sliced] == 0:
|
||||
self._scene.gcode_dict[build_plate_to_be_sliced] = [] #type: ignore #Because we created this attribute above.
|
||||
@ -253,7 +254,7 @@ class CuraEngineBackend(QObject, Backend):
|
||||
if self._build_plates_to_be_sliced:
|
||||
self.slice()
|
||||
return
|
||||
|
||||
self._stored_optimized_layer_data[build_plate_to_be_sliced] = []
|
||||
if self._application.getPrintInformation() and build_plate_to_be_sliced == active_build_plate:
|
||||
self._application.getPrintInformation().setToZeroPrintInformation(build_plate_to_be_sliced)
|
||||
|
||||
@ -410,7 +411,7 @@ class CuraEngineBackend(QObject, Backend):
|
||||
|
||||
if job.getResult() == StartJobResult.NothingToSlice:
|
||||
if self._application.platformActivity:
|
||||
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 or are assigned to a disabled extruder. Please scale or rotate models to fit, or enable an extruder."),
|
||||
title = catalog.i18nc("@info:title", "Unable to slice"))
|
||||
self._error_message.show()
|
||||
self.setState(BackendState.Error)
|
||||
|
@ -13,7 +13,8 @@ import Cura 1.0 as Cura
|
||||
Cura.MachineAction
|
||||
{
|
||||
id: base
|
||||
property var extrudersModel: CuraApplication.getExtrudersModel()
|
||||
property var extrudersModel: Cura.ExtrudersModel{} // Do not retrieve the Model from a backend. Otherwise the tabs
|
||||
// in tabView will not removed/updated. Probably QML bug
|
||||
property int extruderTabsCount: 0
|
||||
|
||||
property var activeMachineId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.id : ""
|
||||
|
@ -16,12 +16,20 @@ Item
|
||||
|
||||
color: UM.Theme.getColor("viewport_overlay")
|
||||
anchors.fill: parent
|
||||
|
||||
// This mouse area is to prevent mouse clicks to be passed onto the scene.
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.AllButtons
|
||||
onWheel: wheel.accepted = true
|
||||
}
|
||||
|
||||
// Disable dropping files into Cura when the monitor page is active
|
||||
DropArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
|
||||
Loader
|
||||
|
@ -25,7 +25,7 @@ UM.Dialog
|
||||
{
|
||||
if(!visible) //Whenever the window is closed (either via the "Close" button or the X on the window frame), we want to update it in the stack.
|
||||
{
|
||||
manager.writeScriptsToStack();
|
||||
manager.writeScriptsToStack()
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,18 +61,23 @@ UM.Dialog
|
||||
anchors.leftMargin: base.textMargin
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: base.textMargin
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
ListView
|
||||
{
|
||||
id: activeScriptsList
|
||||
anchors.top: activeScriptsHeader.bottom
|
||||
anchors.topMargin: base.textMargin
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: base.textMargin
|
||||
|
||||
anchors
|
||||
{
|
||||
top: activeScriptsHeader.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
rightMargin: base.textMargin
|
||||
topMargin: base.textMargin
|
||||
leftMargin: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
|
||||
height: childrenRect.height
|
||||
model: manager.scriptList
|
||||
delegate: Item
|
||||
@ -84,8 +89,12 @@ UM.Dialog
|
||||
id: activeScriptButton
|
||||
text: manager.getScriptLabelByKey(modelData.toString())
|
||||
exclusiveGroup: selectedScriptGroup
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("setting").height
|
||||
checkable: true
|
||||
checked: {
|
||||
|
||||
checked:
|
||||
{
|
||||
if (manager.selectedScriptIndex == index)
|
||||
{
|
||||
base.activeScriptName = manager.getScriptLabelByKey(modelData.toString())
|
||||
@ -102,8 +111,7 @@ UM.Dialog
|
||||
manager.setSelectedScriptIndex(index)
|
||||
base.activeScriptName = manager.getScriptLabelByKey(modelData.toString())
|
||||
}
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("setting").height
|
||||
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Rectangle
|
||||
@ -121,6 +129,7 @@ UM.Dialog
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button
|
||||
{
|
||||
id: removeButton
|
||||
@ -249,8 +258,8 @@ UM.Dialog
|
||||
onTriggered: manager.addScriptToList(modelData.toString())
|
||||
}
|
||||
|
||||
onObjectAdded: scriptsMenu.insertItem(index, object);
|
||||
onObjectRemoved: scriptsMenu.removeItem(object);
|
||||
onObjectAdded: scriptsMenu.insertItem(index, object)
|
||||
onObjectRemoved: scriptsMenu.removeItem(object)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,26 +277,35 @@ UM.Dialog
|
||||
{
|
||||
id: scriptSpecsHeader
|
||||
text: manager.selectedScriptIndex == -1 ? catalog.i18nc("@label", "Settings") : base.activeScriptName
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: base.textMargin
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: base.textMargin
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: base.textMargin
|
||||
anchors
|
||||
{
|
||||
top: parent.top
|
||||
topMargin: base.textMargin
|
||||
left: parent.left
|
||||
leftMargin: base.textMargin
|
||||
right: parent.right
|
||||
rightMargin: base.textMargin
|
||||
}
|
||||
|
||||
elide: Text.ElideRight
|
||||
height: 20 * screenScaleFactor
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
|
||||
ScrollView
|
||||
{
|
||||
id: scrollView
|
||||
anchors.top: scriptSpecsHeader.bottom
|
||||
anchors.topMargin: settingsPanel.textMargin
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors
|
||||
{
|
||||
top: scriptSpecsHeader.bottom
|
||||
topMargin: settingsPanel.textMargin
|
||||
left: parent.left
|
||||
leftMargin: UM.Theme.getSize("default_margin").width
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
visible: manager.selectedScriptDefinitionId != ""
|
||||
style: UM.Theme.styles.scrollview;
|
||||
|
||||
@ -297,11 +315,12 @@ UM.Dialog
|
||||
spacing: UM.Theme.getSize("default_lining").height
|
||||
model: UM.SettingDefinitionsModel
|
||||
{
|
||||
id: definitionsModel;
|
||||
id: definitionsModel
|
||||
containerId: manager.selectedScriptDefinitionId
|
||||
showAll: true
|
||||
}
|
||||
delegate:Loader
|
||||
|
||||
delegate: Loader
|
||||
{
|
||||
id: settingLoader
|
||||
|
||||
@ -312,23 +331,24 @@ UM.Dialog
|
||||
{
|
||||
if(model.type != undefined)
|
||||
{
|
||||
return UM.Theme.getSize("section").height;
|
||||
return UM.Theme.getSize("section").height
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
Behavior on height { NumberAnimation { duration: 100 } }
|
||||
opacity: provider.properties.enabled == "True" ? 1 : 0
|
||||
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
enabled: opacity > 0
|
||||
|
||||
property var definition: model
|
||||
property var settingDefinitionsModel: definitionsModel
|
||||
property var propertyProvider: provider
|
||||
@ -339,11 +359,12 @@ UM.Dialog
|
||||
//causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
|
||||
asynchronous: model.type != "enum" && model.type != "extruder"
|
||||
|
||||
onLoaded: {
|
||||
onLoaded:
|
||||
{
|
||||
settingLoader.item.showRevertButton = false
|
||||
settingLoader.item.showInheritButton = false
|
||||
settingLoader.item.showLinkedSettingIcon = false
|
||||
settingLoader.item.doDepthIndentation = true
|
||||
settingLoader.item.doDepthIndentation = false
|
||||
settingLoader.item.doQualityUserSettingEmphasis = false
|
||||
}
|
||||
|
||||
@ -395,18 +416,14 @@ UM.Dialog
|
||||
|
||||
onShowTooltip:
|
||||
{
|
||||
tooltip.text = text;
|
||||
var position = settingLoader.mapToItem(settingsPanel, settingsPanel.x, 0);
|
||||
tooltip.show(position);
|
||||
tooltip.text = text
|
||||
var position = settingLoader.mapToItem(settingsPanel, settingsPanel.x, 0)
|
||||
tooltip.show(position)
|
||||
tooltip.target.x = position.x + 1
|
||||
}
|
||||
|
||||
onHideTooltip:
|
||||
{
|
||||
tooltip.hide();
|
||||
}
|
||||
onHideTooltip: tooltip.hide()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -459,6 +476,7 @@ UM.Dialog
|
||||
Cura.SettingUnknown { }
|
||||
}
|
||||
}
|
||||
|
||||
rightButtons: Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button", "Close")
|
||||
@ -466,43 +484,15 @@ UM.Dialog
|
||||
onClicked: dialog.accept()
|
||||
}
|
||||
|
||||
Button {
|
||||
Cura.SecondaryButton
|
||||
{
|
||||
objectName: "postProcessingSaveAreaButton"
|
||||
visible: activeScriptsList.count > 0
|
||||
height: UM.Theme.getSize("save_button_save_to_button").height
|
||||
width: height
|
||||
tooltip: catalog.i18nc("@info:tooltip", "Change active post-processing scripts")
|
||||
onClicked: dialog.show()
|
||||
|
||||
style: ButtonStyle {
|
||||
background: Rectangle {
|
||||
id: deviceSelectionIcon
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: !control.enabled ? UM.Theme.getColor("action_button_disabled_border") :
|
||||
control.pressed ? UM.Theme.getColor("action_button_active_border") :
|
||||
control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
|
||||
color: !control.enabled ? UM.Theme.getColor("action_button_disabled") :
|
||||
control.pressed ? UM.Theme.getColor("action_button_active") :
|
||||
control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
|
||||
Behavior on color { ColorAnimation { duration: 50; } }
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Math.round(UM.Theme.getSize("save_button_text_margin").width / 2);
|
||||
width: parent.height
|
||||
height: parent.height
|
||||
|
||||
UM.RecolorImage {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: Math.round(parent.width / 2)
|
||||
height: Math.round(parent.height / 2)
|
||||
sourceSize.height: height
|
||||
color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") :
|
||||
control.pressed ? UM.Theme.getColor("action_button_active_text") :
|
||||
control.hovered ? UM.Theme.getColor("action_button_hovered_text") : UM.Theme.getColor("action_button_text");
|
||||
source: "postprocessing.svg"
|
||||
}
|
||||
}
|
||||
label: Label{ }
|
||||
}
|
||||
iconSource: "postprocessing.svg"
|
||||
fixedWidthMode: true
|
||||
}
|
||||
}
|
@ -163,9 +163,9 @@ Item
|
||||
id: rangleHandleLabel
|
||||
|
||||
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
|
||||
x: parent.x + parent.width + UM.Theme.getSize("default_margin").width
|
||||
x: parent.x - width - UM.Theme.getSize("default_margin").width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
target: Qt.point(sliderRoot.width + width, y + height / 2)
|
||||
target: Qt.point(sliderRoot.width, y + height / 2)
|
||||
visible: sliderRoot.activeHandle == parent
|
||||
|
||||
// custom properties
|
||||
|
@ -342,12 +342,16 @@ class SimulationView(CuraView):
|
||||
return self._extruder_count
|
||||
|
||||
def getMinFeedrate(self) -> float:
|
||||
if abs(self._min_feedrate - sys.float_info.max) < 10: # Some lenience due to floating point rounding.
|
||||
return 0.0 # If it's still max-float, there are no measurements. Use 0 then.
|
||||
return self._min_feedrate
|
||||
|
||||
def getMaxFeedrate(self) -> float:
|
||||
return self._max_feedrate
|
||||
|
||||
def getMinThickness(self) -> float:
|
||||
if abs(self._min_thickness - sys.float_info.max) < 10: # Some lenience due to floating point rounding.
|
||||
return 0.0 # If it's still max-float, there are no measurements. Use 0 then.
|
||||
return self._min_thickness
|
||||
|
||||
def getMaxThickness(self) -> float:
|
||||
|
@ -43,7 +43,7 @@ Cura.ExpandableComponent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
height: parent.height
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
@ -60,7 +60,7 @@ Cura.ExpandableComponent
|
||||
}
|
||||
height: parent.height
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
@ -358,7 +358,7 @@ Cura.ExpandableComponent
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("layerview_row").height
|
||||
|
||||
Label
|
||||
Label //Minimum value.
|
||||
{
|
||||
text:
|
||||
{
|
||||
@ -383,9 +383,10 @@ Cura.ExpandableComponent
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Label
|
||||
Label //Unit in the middle.
|
||||
{
|
||||
text: {
|
||||
text:
|
||||
{
|
||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||
{
|
||||
// Feedrate selected
|
||||
@ -407,7 +408,7 @@ Cura.ExpandableComponent
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
|
||||
Label
|
||||
Label //Maximum value.
|
||||
{
|
||||
text: {
|
||||
if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
|
||||
|
@ -30,7 +30,7 @@ Row
|
||||
width: contentWidth
|
||||
anchors.verticalCenter: starIcon.verticalCenter
|
||||
color: starIcon.color
|
||||
font: UM.Theme.getFont("small")
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
}
|
@ -55,7 +55,7 @@ Item
|
||||
bottomMargin: UM.Theme.getSize("default_margin").height
|
||||
}
|
||||
text: details.name || ""
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("toolbox_property_label").height
|
||||
|
@ -61,8 +61,13 @@ Item
|
||||
id: labelStyle
|
||||
text: control.text
|
||||
color: control.enabled ? (control.hovered ? UM.Theme.getColor("primary") : UM.Theme.getColor("text")) : UM.Theme.getColor("text_inactive")
|
||||
font: UM.Theme.getFont("default_bold")
|
||||
horizontalAlignment: Text.AlignRight
|
||||
font: UM.Theme.getFont("medium_bold")
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
leftMargin: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
width: control.width
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ Item
|
||||
leftMargin: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
text: details === null ? "" : (details.name || "")
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
color: UM.Theme.getColor("text")
|
||||
width: contentWidth
|
||||
height: contentHeight
|
||||
|
@ -22,7 +22,7 @@ Column
|
||||
text: gridArea.heading
|
||||
width: parent.width
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
font: UM.Theme.getFont("medium")
|
||||
font: UM.Theme.getFont("large")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
Grid
|
||||
|
@ -112,7 +112,7 @@ Item
|
||||
elide: Text.ElideRight
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
color: UM.Theme.getColor("text")
|
||||
font: UM.Theme.getFont("default")
|
||||
anchors.top: name.bottom
|
||||
anchors.bottom: rating.top
|
||||
|
@ -23,7 +23,7 @@ Rectangle
|
||||
text: catalog.i18nc("@label", "Featured")
|
||||
width: parent.width
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
font: UM.Theme.getFont("medium")
|
||||
font: UM.Theme.getFont("large")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
Grid
|
||||
|
@ -37,7 +37,7 @@ ScrollView
|
||||
width: page.width
|
||||
text: catalog.i18nc("@title:tab", "Plugins")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
font: UM.Theme.getFont("medium")
|
||||
font: UM.Theme.getFont("large")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
Rectangle
|
||||
|
@ -49,13 +49,14 @@ Item
|
||||
width: parent.width
|
||||
height: Math.floor(UM.Theme.getSize("toolbox_property_label").height)
|
||||
wrapMode: Text.WordWrap
|
||||
font: UM.Theme.getFont("default_bold")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
color: pluginInfo.color
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
Label
|
||||
{
|
||||
text: model.description
|
||||
font: UM.Theme.getFont("default")
|
||||
maximumLineCount: 3
|
||||
elide: Text.ElideRight
|
||||
width: parent.width
|
||||
@ -82,6 +83,7 @@ Item
|
||||
return model.author_name
|
||||
}
|
||||
}
|
||||
font: UM.Theme.getFont("medium")
|
||||
width: parent.width
|
||||
height: Math.floor(UM.Theme.getSize("toolbox_property_label").height)
|
||||
wrapMode: Text.WordWrap
|
||||
@ -96,6 +98,7 @@ Item
|
||||
Label
|
||||
{
|
||||
text: model.version
|
||||
font: UM.Theme.getFont("default")
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("toolbox_property_label").height
|
||||
color: UM.Theme.getColor("text")
|
||||
|
@ -28,7 +28,7 @@ Cura.MachineAction
|
||||
// Check if there is another instance with the same key
|
||||
if (!manager.existsKey(printerKey))
|
||||
{
|
||||
manager.setKey(printerKey)
|
||||
manager.associateActiveMachineWithPrinterDevice(base.selectedDevice)
|
||||
manager.setGroupName(printerName) // TODO To change when the groups have a name
|
||||
completed()
|
||||
}
|
||||
@ -223,7 +223,7 @@ Cura.MachineAction
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
text: base.selectedDevice ? base.selectedDevice.name : ""
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
elide: Text.ElideRight
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
@ -18,6 +18,10 @@ Item
|
||||
|
||||
height: centerSection.height
|
||||
width: maximumWidth
|
||||
|
||||
// Enable keyboard navigation
|
||||
Keys.onLeftPressed: navigateTo(currentIndex - 1)
|
||||
Keys.onRightPressed: navigateTo(currentIndex + 1)
|
||||
|
||||
Item
|
||||
{
|
||||
@ -211,7 +215,7 @@ Item
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
Row
|
||||
{
|
||||
id: navigationDots
|
||||
anchors
|
||||
@ -220,23 +224,20 @@ Item
|
||||
top: centerSection.bottom
|
||||
topMargin: 36 * screenScaleFactor // TODO: Theme!
|
||||
}
|
||||
Row
|
||||
spacing: 8 * screenScaleFactor // TODO: Theme!
|
||||
Repeater
|
||||
{
|
||||
spacing: 8 * screenScaleFactor // TODO: Theme!
|
||||
Repeater
|
||||
model: OutputDevice.printers
|
||||
Button
|
||||
{
|
||||
model: OutputDevice.printers
|
||||
Button
|
||||
background: Rectangle
|
||||
{
|
||||
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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ Item
|
||||
text: printer && printer.name ? printer.name : ""
|
||||
color: "#414054" // TODO: Theme!
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("large") // 16pt, bold
|
||||
font: UM.Theme.getFont("large_bold") // 16pt, bold
|
||||
width: parent.width
|
||||
|
||||
// FIXED-LINE-HEIGHT:
|
||||
@ -185,7 +185,7 @@ Item
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
color: "#414054" // TODO: Theme!
|
||||
font: UM.Theme.getFont("large") // 16pt, bold
|
||||
font: UM.Theme.getFont("large_bold") // 16pt, bold
|
||||
text: {
|
||||
if (printer && printer.state == "disabled")
|
||||
{
|
||||
@ -236,7 +236,7 @@ Item
|
||||
id: printerJobNameLabel
|
||||
color: printer.activePrintJob && printer.activePrintJob.isActive ? "#414054" : "#babac1" // TODO: Theme!
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("large") // 16pt, bold
|
||||
font: UM.Theme.getFont("large_bold") // 16pt, bold
|
||||
text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N
|
||||
width: parent.width
|
||||
|
||||
|
@ -23,7 +23,7 @@ Item
|
||||
top: parent.top
|
||||
}
|
||||
color: UM.Theme.getColor("text")
|
||||
font: UM.Theme.getFont("large_nonbold")
|
||||
font: UM.Theme.getFont("large")
|
||||
text: catalog.i18nc("@label", "Queued")
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,11 @@ Component
|
||||
}
|
||||
}
|
||||
width: maximumWidth
|
||||
|
||||
// Enable keyboard navigation. NOTE: This is done here so that we can also potentially
|
||||
// forward to the queue items in the future. (Deleting selected print job, etc.)
|
||||
Keys.forwardTo: carousel
|
||||
Component.onCompleted: forceActiveFocus()
|
||||
|
||||
UM.I18nCatalog
|
||||
{
|
||||
@ -59,7 +64,9 @@ Component
|
||||
}
|
||||
width: parent.width
|
||||
height: 264 * screenScaleFactor // TODO: Theme!
|
||||
MonitorCarousel {}
|
||||
MonitorCarousel {
|
||||
id: carousel
|
||||
}
|
||||
}
|
||||
|
||||
MonitorQueue
|
||||
|
@ -22,6 +22,7 @@ from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationM
|
||||
from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice, AuthState
|
||||
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
||||
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
|
||||
from cura.PrinterOutputDevice import ConnectionType
|
||||
|
||||
from .ClusterUM3PrinterOutputController import ClusterUM3PrinterOutputController
|
||||
from .SendMaterialJob import SendMaterialJob
|
||||
@ -54,7 +55,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||
clusterPrintersChanged = pyqtSignal()
|
||||
|
||||
def __init__(self, device_id, address, properties, parent = None) -> None:
|
||||
super().__init__(device_id = device_id, address = address, properties=properties, parent = parent)
|
||||
super().__init__(device_id = device_id, address = address, properties=properties, connection_type = ConnectionType.NetworkConnection, parent = parent)
|
||||
self._api_prefix = "/cluster-api/v1/"
|
||||
|
||||
self._number_of_extruders = 2
|
||||
@ -619,8 +620,9 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||
if material_group_list is None:
|
||||
material_name = i18n_catalog.i18nc("@label:material", "Empty") if len(material_data.get("guid", "")) == 0 \
|
||||
else i18n_catalog.i18nc("@label:material", "Unknown")
|
||||
|
||||
return MaterialOutputModel(guid = material_data.get("guid", ""),
|
||||
type = material_data.get("type", ""),
|
||||
type = material_data.get("material", ""),
|
||||
color = material_data.get("color", ""),
|
||||
brand = material_data.get("brand", ""),
|
||||
name = material_data.get("name", material_name)
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
import os.path
|
||||
import time
|
||||
from typing import cast, Optional
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject
|
||||
|
||||
@ -16,6 +16,9 @@ from cura.MachineAction import MachineAction
|
||||
|
||||
from .UM3OutputDevicePlugin import UM3OutputDevicePlugin
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice
|
||||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
@ -116,22 +119,30 @@ class DiscoverUM3Action(MachineAction):
|
||||
# Ensure that the connection states are refreshed.
|
||||
self._network_plugin.reCheckConnections()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def setKey(self, key: str) -> None:
|
||||
Logger.log("d", "Attempting to set the network key of the active machine to %s", key)
|
||||
# Associates the currently active machine with the given printer device. The network connection information will be
|
||||
# stored into the metadata of the currently active machine.
|
||||
@pyqtSlot(QObject)
|
||||
def associateActiveMachineWithPrinterDevice(self, printer_device: Optional["PrinterOutputDevice"]) -> None:
|
||||
Logger.log("d", "Attempting to set the network key of the active machine to %s", printer_device.key)
|
||||
global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack:
|
||||
meta_data = global_container_stack.getMetaData()
|
||||
if "um_network_key" in meta_data:
|
||||
previous_network_key= meta_data["um_network_key"]
|
||||
global_container_stack.setMetaDataEntry("um_network_key", key)
|
||||
global_container_stack.setMetaDataEntry("um_network_key", printer_device.key)
|
||||
# Delete old authentication data.
|
||||
Logger.log("d", "Removing old authentication id %s for device %s", global_container_stack.getMetaDataEntry("network_authentication_id", None), key)
|
||||
Logger.log("d", "Removing old authentication id %s for device %s", global_container_stack.getMetaDataEntry("network_authentication_id", None), printer_device.key)
|
||||
global_container_stack.removeMetaDataEntry("network_authentication_id")
|
||||
global_container_stack.removeMetaDataEntry("network_authentication_key")
|
||||
CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "um_network_key", value = previous_network_key, new_value = key)
|
||||
CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "um_network_key", value = previous_network_key, new_value = printer_device.key)
|
||||
|
||||
if "connection_type" in meta_data:
|
||||
previous_connection_type = meta_data["connection_type"]
|
||||
global_container_stack.setMetaDataEntry("connection_type", printer_device.getConnectionType().value)
|
||||
CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "connection_type", value = previous_connection_type, new_value = printer_device.getConnectionType().value)
|
||||
else:
|
||||
global_container_stack.setMetaDataEntry("um_network_key", key)
|
||||
global_container_stack.setMetaDataEntry("um_network_key", printer_device.key)
|
||||
global_container_stack.setMetaDataEntry("connection_type", printer_device.getConnectionType().value)
|
||||
|
||||
if self._network_plugin:
|
||||
# Ensure that the connection states are refreshed.
|
||||
|
@ -7,6 +7,7 @@ from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutp
|
||||
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
||||
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
|
||||
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
|
||||
from cura.PrinterOutputDevice import ConnectionType
|
||||
|
||||
from cura.Settings.ContainerManager import ContainerManager
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
@ -43,7 +44,7 @@ i18n_catalog = i18nCatalog("cura")
|
||||
# 5. As a final step, we verify the authentication, as this forces the QT manager to setup the authenticator.
|
||||
class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||
def __init__(self, device_id, address: str, properties, parent = None) -> None:
|
||||
super().__init__(device_id = device_id, address = address, properties = properties, parent = parent)
|
||||
super().__init__(device_id = device_id, address = address, properties = properties, connection_type = ConnectionType.NetworkConnection, parent = parent)
|
||||
self._api_prefix = "/api/v1/"
|
||||
self._number_of_extruders = 2
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import json
|
||||
import os
|
||||
import urllib.parse
|
||||
from typing import Dict, TYPE_CHECKING, Set
|
||||
|
||||
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
|
||||
@ -10,9 +9,7 @@ from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
|
||||
from UM.Application import Application
|
||||
from UM.Job import Job
|
||||
from UM.Logger import Logger
|
||||
from UM.MimeTypeDatabase import MimeTypeDatabase
|
||||
from UM.Resources import Resources
|
||||
from cura.CuraApplication import CuraApplication
|
||||
|
||||
# Absolute imports don't work in plugins
|
||||
from .Models import ClusterMaterial, LocalMaterial
|
||||
|
||||
@ -37,7 +34,6 @@ class SendMaterialJob(Job):
|
||||
#
|
||||
# \param reply The reply from the printer, a json file.
|
||||
def _onGetRemoteMaterials(self, reply: QNetworkReply) -> None:
|
||||
|
||||
# Got an error from the HTTP request. If we did not receive a 200 something happened.
|
||||
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
|
||||
Logger.log("e", "Error fetching materials from printer: %s", reply.errorString())
|
||||
@ -52,7 +48,6 @@ class SendMaterialJob(Job):
|
||||
#
|
||||
# \param remote_materials_by_guid The remote materials by GUID.
|
||||
def _sendMissingMaterials(self, remote_materials_by_guid: Dict[str, ClusterMaterial]) -> None:
|
||||
|
||||
# Collect local materials
|
||||
local_materials_by_guid = self._getLocalMaterials()
|
||||
if len(local_materials_by_guid) == 0:
|
||||
@ -91,22 +86,22 @@ class SendMaterialJob(Job):
|
||||
#
|
||||
# \param materials_to_send A set with id's of materials that must be sent.
|
||||
def _sendMaterials(self, materials_to_send: Set[str]) -> None:
|
||||
file_paths = Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.MaterialInstanceContainer)
|
||||
container_registry = Application.getInstance().getContainerRegistry()
|
||||
material_manager = Application.getInstance().getMaterialManager()
|
||||
material_group_dict = material_manager.getAllMaterialGroups()
|
||||
|
||||
# Find all local material files and send them if needed.
|
||||
for file_path in file_paths:
|
||||
try:
|
||||
mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
|
||||
except MimeTypeDatabase.MimeTypeNotFoundError:
|
||||
continue
|
||||
|
||||
file_name = os.path.basename(file_path)
|
||||
material_id = urllib.parse.unquote_plus(mime_type.stripExtension(file_name))
|
||||
if material_id not in materials_to_send:
|
||||
for root_material_id in material_group_dict:
|
||||
if root_material_id not in materials_to_send:
|
||||
# If the material does not have to be sent we skip it.
|
||||
continue
|
||||
|
||||
self._sendMaterialFile(file_path, file_name, material_id)
|
||||
file_path = container_registry.getContainerFilePathById(root_material_id)
|
||||
if not file_path:
|
||||
Logger.log("w", "Cannot get file path for material container [%s]", root_material_id)
|
||||
continue
|
||||
|
||||
file_name = os.path.basename(file_path)
|
||||
self._sendMaterialFile(file_path, file_name, root_material_id)
|
||||
|
||||
## Send a single material file to the printer.
|
||||
#
|
||||
@ -116,7 +111,6 @@ class SendMaterialJob(Job):
|
||||
# \param file_name The name of the material file.
|
||||
# \param material_id The ID of the material in the file.
|
||||
def _sendMaterialFile(self, file_path: str, file_name: str, material_id: str) -> None:
|
||||
|
||||
parts = []
|
||||
|
||||
# Add the material file.
|
||||
@ -171,27 +165,31 @@ class SendMaterialJob(Job):
|
||||
# \return a dictionary of LocalMaterial objects by GUID
|
||||
def _getLocalMaterials(self) -> Dict[str, LocalMaterial]:
|
||||
result = {} # type: Dict[str, LocalMaterial]
|
||||
container_registry = Application.getInstance().getContainerRegistry()
|
||||
material_containers = container_registry.findContainersMetadata(type = "material")
|
||||
material_manager = Application.getInstance().getMaterialManager()
|
||||
|
||||
material_group_dict = material_manager.getAllMaterialGroups()
|
||||
|
||||
# Find the latest version of all material containers in the registry.
|
||||
for material in material_containers:
|
||||
for root_material_id, material_group in material_group_dict.items():
|
||||
material_metadata = material_group.root_material_node.getMetadata()
|
||||
|
||||
try:
|
||||
# material version must be an int
|
||||
material["version"] = int(material["version"])
|
||||
material_metadata["version"] = int(material_metadata["version"])
|
||||
|
||||
# Create a new local material
|
||||
local_material = LocalMaterial(**material)
|
||||
local_material = LocalMaterial(**material_metadata)
|
||||
local_material.id = root_material_id
|
||||
|
||||
if local_material.GUID not in result or \
|
||||
local_material.version > result.get(local_material.GUID).version:
|
||||
result[local_material.GUID] = local_material
|
||||
|
||||
except KeyError:
|
||||
Logger.logException("w", "Local material {} has missing values.".format(material["id"]))
|
||||
Logger.logException("w", "Local material {} has missing values.".format(material_metadata["id"]))
|
||||
except ValueError:
|
||||
Logger.logException("w", "Local material {} has invalid values.".format(material["id"]))
|
||||
Logger.logException("w", "Local material {} has invalid values.".format(material_metadata["id"]))
|
||||
except TypeError:
|
||||
Logger.logException("w", "Local material {} has invalid values.".format(material["id"]))
|
||||
Logger.logException("w", "Local material {} has invalid values.".format(material_metadata["id"]))
|
||||
|
||||
return result
|
||||
|
@ -283,6 +283,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack and device.getId() == global_container_stack.getMetaDataEntry("um_network_key"):
|
||||
global_container_stack.setMetaDataEntry("connection_type", device.getConnectionType().value)
|
||||
device.connect()
|
||||
device.connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
|
||||
|
||||
|
@ -1,26 +1,29 @@
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import copy
|
||||
import io
|
||||
import json
|
||||
from unittest import TestCase, mock
|
||||
from unittest.mock import patch, call
|
||||
from unittest.mock import patch, call, MagicMock
|
||||
|
||||
from PyQt5.QtCore import QByteArray
|
||||
|
||||
from UM.MimeTypeDatabase import MimeType
|
||||
from UM.Application import Application
|
||||
|
||||
from cura.Machines.MaterialGroup import MaterialGroup
|
||||
from cura.Machines.MaterialNode import MaterialNode
|
||||
|
||||
from plugins.UM3NetworkPrinting.src.SendMaterialJob import SendMaterialJob
|
||||
|
||||
_FILES_MAP = {"generic_pla_white": "/materials/generic_pla_white.xml.fdm_material",
|
||||
"generic_pla_black": "/materials/generic_pla_black.xml.fdm_material",
|
||||
}
|
||||
|
||||
|
||||
@patch("builtins.open", lambda _, __: io.StringIO("<xml></xml>"))
|
||||
@patch("UM.MimeTypeDatabase.MimeTypeDatabase.getMimeTypeForFile",
|
||||
lambda _: MimeType(name = "application/x-ultimaker-material-profile", comment = "Ultimaker Material Profile",
|
||||
suffixes = ["xml.fdm_material"]))
|
||||
@patch("UM.Resources.Resources.getAllResourcesOfType", lambda _: ["/materials/generic_pla_white.xml.fdm_material"])
|
||||
@patch("plugins.UM3NetworkPrinting.src.ClusterUM3OutputDevice")
|
||||
@patch("PyQt5.QtNetwork.QNetworkReply")
|
||||
class TestSendMaterialJob(TestCase):
|
||||
# version 1
|
||||
_LOCAL_MATERIAL_WHITE = {"type": "material", "status": "unknown", "id": "generic_pla_white",
|
||||
"base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
|
||||
"brand": "Generic", "material": "PLA", "color_name": "White",
|
||||
@ -29,6 +32,37 @@ class TestSendMaterialJob(TestCase):
|
||||
"properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
|
||||
"definition": "fdmprinter", "compatible": True}
|
||||
|
||||
# version 2
|
||||
_LOCAL_MATERIAL_WHITE_NEWER = {"type": "material", "status": "unknown", "id": "generic_pla_white",
|
||||
"base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
|
||||
"brand": "Generic", "material": "PLA", "color_name": "White",
|
||||
"GUID": "badb0ee7-87c8-4f3f-9398-938587b67dce", "version": "2",
|
||||
"color_code": "#ffffff",
|
||||
"description": "Test PLA White", "adhesion_info": "Use glue.",
|
||||
"approximate_diameter": "3",
|
||||
"properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
|
||||
"definition": "fdmprinter", "compatible": True}
|
||||
|
||||
# invalid version: "one"
|
||||
_LOCAL_MATERIAL_WHITE_INVALID_VERSION = {"type": "material", "status": "unknown", "id": "generic_pla_white",
|
||||
"base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
|
||||
"brand": "Generic", "material": "PLA", "color_name": "White",
|
||||
"GUID": "badb0ee7-87c8-4f3f-9398-938587b67dce", "version": "one",
|
||||
"color_code": "#ffffff",
|
||||
"description": "Test PLA White", "adhesion_info": "Use glue.",
|
||||
"approximate_diameter": "3",
|
||||
"properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
|
||||
"definition": "fdmprinter", "compatible": True}
|
||||
|
||||
_LOCAL_MATERIAL_WHITE_ALL_RESULT = {"generic_pla_white": MaterialGroup("generic_pla_white",
|
||||
MaterialNode(_LOCAL_MATERIAL_WHITE))}
|
||||
|
||||
_LOCAL_MATERIAL_WHITE_NEWER_ALL_RESULT = {"generic_pla_white": MaterialGroup("generic_pla_white",
|
||||
MaterialNode(_LOCAL_MATERIAL_WHITE_NEWER))}
|
||||
|
||||
_LOCAL_MATERIAL_WHITE_INVALID_VERSION_ALL_RESULT = {"generic_pla_white": MaterialGroup("generic_pla_white",
|
||||
MaterialNode(_LOCAL_MATERIAL_WHITE_INVALID_VERSION))}
|
||||
|
||||
_LOCAL_MATERIAL_BLACK = {"type": "material", "status": "unknown", "id": "generic_pla_black",
|
||||
"base_file": "generic_pla_black", "setting_version": "5", "name": "Yellow CPE",
|
||||
"brand": "Ultimaker", "material": "CPE", "color_name": "Black",
|
||||
@ -37,6 +71,9 @@ class TestSendMaterialJob(TestCase):
|
||||
"properties": {"density": "1.01", "diameter": "2.85", "weight": "750"},
|
||||
"definition": "fdmprinter", "compatible": True}
|
||||
|
||||
_LOCAL_MATERIAL_BLACK_ALL_RESULT = {"generic_pla_black": MaterialGroup("generic_pla_black",
|
||||
MaterialNode(_LOCAL_MATERIAL_BLACK))}
|
||||
|
||||
_REMOTE_MATERIAL_WHITE = {
|
||||
"guid": "badb0ee7-87c8-4f3f-9398-938587b67dce",
|
||||
"material": "PLA",
|
||||
@ -55,14 +92,17 @@ class TestSendMaterialJob(TestCase):
|
||||
"density": 1.00
|
||||
}
|
||||
|
||||
def test_run(self, device_mock, reply_mock):
|
||||
def test_run(self):
|
||||
device_mock = MagicMock()
|
||||
job = SendMaterialJob(device_mock)
|
||||
job.run()
|
||||
|
||||
# We expect the materials endpoint to be called when the job runs.
|
||||
device_mock.get.assert_called_with("materials/", on_finished = job._onGetRemoteMaterials)
|
||||
|
||||
def test__onGetRemoteMaterials_withFailedRequest(self, reply_mock, device_mock):
|
||||
def test__onGetRemoteMaterials_withFailedRequest(self):
|
||||
reply_mock = MagicMock()
|
||||
device_mock = MagicMock()
|
||||
reply_mock.attribute.return_value = 404
|
||||
job = SendMaterialJob(device_mock)
|
||||
job._onGetRemoteMaterials(reply_mock)
|
||||
@ -70,7 +110,9 @@ class TestSendMaterialJob(TestCase):
|
||||
# We expect the device not to be called for any follow up.
|
||||
self.assertEqual(0, device_mock.createFormPart.call_count)
|
||||
|
||||
def test__onGetRemoteMaterials_withWrongEncoding(self, reply_mock, device_mock):
|
||||
def test__onGetRemoteMaterials_withWrongEncoding(self):
|
||||
reply_mock = MagicMock()
|
||||
device_mock = MagicMock()
|
||||
reply_mock.attribute.return_value = 200
|
||||
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("cp500"))
|
||||
job = SendMaterialJob(device_mock)
|
||||
@ -79,7 +121,9 @@ class TestSendMaterialJob(TestCase):
|
||||
# Given that the parsing fails we do no expect the device to be called for any follow up.
|
||||
self.assertEqual(0, device_mock.createFormPart.call_count)
|
||||
|
||||
def test__onGetRemoteMaterials_withBadJsonAnswer(self, reply_mock, device_mock):
|
||||
def test__onGetRemoteMaterials_withBadJsonAnswer(self):
|
||||
reply_mock = MagicMock()
|
||||
device_mock = MagicMock()
|
||||
reply_mock.attribute.return_value = 200
|
||||
reply_mock.readAll.return_value = QByteArray(b"Six sick hicks nick six slick bricks with picks and sticks.")
|
||||
job = SendMaterialJob(device_mock)
|
||||
@ -88,7 +132,9 @@ class TestSendMaterialJob(TestCase):
|
||||
# Given that the parsing fails we do no expect the device to be called for any follow up.
|
||||
self.assertEqual(0, device_mock.createFormPart.call_count)
|
||||
|
||||
def test__onGetRemoteMaterials_withMissingGuidInRemoteMaterial(self, reply_mock, device_mock):
|
||||
def test__onGetRemoteMaterials_withMissingGuidInRemoteMaterial(self):
|
||||
reply_mock = MagicMock()
|
||||
device_mock = MagicMock()
|
||||
reply_mock.attribute.return_value = 200
|
||||
remote_material_without_guid = self._REMOTE_MATERIAL_WHITE.copy()
|
||||
del remote_material_without_guid["guid"]
|
||||
@ -99,18 +145,20 @@ class TestSendMaterialJob(TestCase):
|
||||
# Given that parsing fails we do not expect the device to be called for any follow up.
|
||||
self.assertEqual(0, device_mock.createFormPart.call_count)
|
||||
|
||||
@patch("cura.Machines.MaterialManager.MaterialManager")
|
||||
@patch("cura.Settings.CuraContainerRegistry")
|
||||
@patch("UM.Application")
|
||||
def test__onGetRemoteMaterials_withInvalidVersionInLocalMaterial(self, application_mock, container_registry_mock,
|
||||
reply_mock, device_mock):
|
||||
material_manager_mock):
|
||||
reply_mock = MagicMock()
|
||||
device_mock = MagicMock()
|
||||
application_mock.getContainerRegistry.return_value = container_registry_mock
|
||||
application_mock.getMaterialManager.return_value = material_manager_mock
|
||||
|
||||
reply_mock.attribute.return_value = 200
|
||||
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
|
||||
|
||||
localMaterialWhiteWithInvalidVersion = self._LOCAL_MATERIAL_WHITE.copy()
|
||||
localMaterialWhiteWithInvalidVersion["version"] = "one"
|
||||
container_registry_mock.findContainersMetadata.return_value = [localMaterialWhiteWithInvalidVersion]
|
||||
|
||||
application_mock.getContainerRegistry.return_value = container_registry_mock
|
||||
material_manager_mock.getAllMaterialGroups.return_value = self._LOCAL_MATERIAL_WHITE_INVALID_VERSION_ALL_RESULT.copy()
|
||||
|
||||
with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
|
||||
job = SendMaterialJob(device_mock)
|
||||
@ -118,15 +166,16 @@ class TestSendMaterialJob(TestCase):
|
||||
|
||||
self.assertEqual(0, device_mock.createFormPart.call_count)
|
||||
|
||||
@patch("cura.Settings.CuraContainerRegistry")
|
||||
@patch("UM.Application")
|
||||
def test__onGetRemoteMaterials_withNoUpdate(self, application_mock, container_registry_mock, reply_mock,
|
||||
device_mock):
|
||||
application_mock.getContainerRegistry.return_value = container_registry_mock
|
||||
@patch("UM.Application.Application.getInstance")
|
||||
def test__onGetRemoteMaterials_withNoUpdate(self, application_mock):
|
||||
reply_mock = MagicMock()
|
||||
device_mock = MagicMock()
|
||||
container_registry_mock = application_mock.getContainerRegistry.return_value
|
||||
material_manager_mock = application_mock.getMaterialManager.return_value
|
||||
|
||||
device_mock.createFormPart.return_value = "_xXx_"
|
||||
|
||||
container_registry_mock.findContainersMetadata.return_value = [self._LOCAL_MATERIAL_WHITE]
|
||||
material_manager_mock.getAllMaterialGroups.return_value = self._LOCAL_MATERIAL_WHITE_ALL_RESULT.copy()
|
||||
|
||||
reply_mock.attribute.return_value = 200
|
||||
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
|
||||
@ -138,24 +187,25 @@ class TestSendMaterialJob(TestCase):
|
||||
self.assertEqual(0, device_mock.createFormPart.call_count)
|
||||
self.assertEqual(0, device_mock.postFormWithParts.call_count)
|
||||
|
||||
@patch("cura.Settings.CuraContainerRegistry")
|
||||
@patch("UM.Application")
|
||||
def test__onGetRemoteMaterials_withUpdatedMaterial(self, application_mock, container_registry_mock, reply_mock,
|
||||
device_mock):
|
||||
application_mock.getContainerRegistry.return_value = container_registry_mock
|
||||
@patch("UM.Application.Application.getInstance")
|
||||
def test__onGetRemoteMaterials_withUpdatedMaterial(self, get_instance_mock):
|
||||
reply_mock = MagicMock()
|
||||
device_mock = MagicMock()
|
||||
application_mock = get_instance_mock.return_value
|
||||
container_registry_mock = application_mock.getContainerRegistry.return_value
|
||||
material_manager_mock = application_mock.getMaterialManager.return_value
|
||||
|
||||
container_registry_mock.getContainerFilePathById = lambda x: _FILES_MAP.get(x)
|
||||
|
||||
device_mock.createFormPart.return_value = "_xXx_"
|
||||
|
||||
localMaterialWhiteWithHigherVersion = self._LOCAL_MATERIAL_WHITE.copy()
|
||||
localMaterialWhiteWithHigherVersion["version"] = "2"
|
||||
container_registry_mock.findContainersMetadata.return_value = [localMaterialWhiteWithHigherVersion]
|
||||
material_manager_mock.getAllMaterialGroups.return_value = self._LOCAL_MATERIAL_WHITE_NEWER_ALL_RESULT.copy()
|
||||
|
||||
reply_mock.attribute.return_value = 200
|
||||
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
|
||||
|
||||
with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
|
||||
job = SendMaterialJob(device_mock)
|
||||
job._onGetRemoteMaterials(reply_mock)
|
||||
job = SendMaterialJob(device_mock)
|
||||
job._onGetRemoteMaterials(reply_mock)
|
||||
|
||||
self.assertEqual(1, device_mock.createFormPart.call_count)
|
||||
self.assertEqual(1, device_mock.postFormWithParts.call_count)
|
||||
@ -164,16 +214,21 @@ class TestSendMaterialJob(TestCase):
|
||||
call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)],
|
||||
device_mock.method_calls)
|
||||
|
||||
@patch("cura.Settings.CuraContainerRegistry")
|
||||
@patch("UM.Application")
|
||||
def test__onGetRemoteMaterials_withNewMaterial(self, application_mock, container_registry_mock, reply_mock,
|
||||
device_mock):
|
||||
application_mock.getContainerRegistry.return_value = container_registry_mock
|
||||
@patch("UM.Application.Application.getInstance")
|
||||
def test__onGetRemoteMaterials_withNewMaterial(self, application_mock):
|
||||
reply_mock = MagicMock()
|
||||
device_mock = MagicMock()
|
||||
container_registry_mock = application_mock.getContainerRegistry.return_value
|
||||
material_manager_mock = application_mock.getMaterialManager.return_value
|
||||
|
||||
container_registry_mock.getContainerFilePathById = lambda x: _FILES_MAP.get(x)
|
||||
|
||||
device_mock.createFormPart.return_value = "_xXx_"
|
||||
|
||||
container_registry_mock.findContainersMetadata.return_value = [self._LOCAL_MATERIAL_WHITE,
|
||||
self._LOCAL_MATERIAL_BLACK]
|
||||
all_results = self._LOCAL_MATERIAL_WHITE_ALL_RESULT.copy()
|
||||
for key, value in self._LOCAL_MATERIAL_BLACK_ALL_RESULT.items():
|
||||
all_results[key] = value
|
||||
material_manager_mock.getAllMaterialGroups.return_value = all_results
|
||||
|
||||
reply_mock.attribute.return_value = 200
|
||||
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_BLACK]).encode("ascii"))
|
||||
|
@ -13,6 +13,8 @@ Component
|
||||
{
|
||||
Rectangle
|
||||
{
|
||||
color: UM.Theme.getColor("main_background")
|
||||
|
||||
anchors.right: parent.right
|
||||
width: parent.width * 0.3
|
||||
anchors.top: parent.top
|
||||
|
@ -7,7 +7,7 @@ from UM.i18n import i18nCatalog
|
||||
from UM.Qt.Duration import DurationFormat
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
|
||||
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
||||
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
|
||||
from cura.PrinterOutput.GenericOutputController import GenericOutputController
|
||||
@ -29,7 +29,7 @@ catalog = i18nCatalog("cura")
|
||||
|
||||
class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||
def __init__(self, serial_port: str, baud_rate: Optional[int] = None) -> None:
|
||||
super().__init__(serial_port)
|
||||
super().__init__(serial_port, connection_type = ConnectionType.UsbConnection)
|
||||
self.setName(catalog.i18nc("@item:inmenu", "USB printing"))
|
||||
self.setShortDescription(catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print via USB"))
|
||||
self.setDescription(catalog.i18nc("@info:tooltip", "Print via USB"))
|
||||
@ -179,7 +179,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||
return
|
||||
CuraApplication.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerStackChanged)
|
||||
self._onGlobalContainerStackChanged()
|
||||
self.setConnectionState(ConnectionState.connected)
|
||||
self.setConnectionState(ConnectionState.Connected)
|
||||
self._update_thread.start()
|
||||
|
||||
def _onGlobalContainerStackChanged(self):
|
||||
@ -208,7 +208,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||
self._sendCommand(command)
|
||||
|
||||
def _sendCommand(self, command: Union[str, bytes]):
|
||||
if self._serial is None or self._connection_state != ConnectionState.connected:
|
||||
if self._serial is None or self._connection_state != ConnectionState.Connected:
|
||||
return
|
||||
|
||||
new_command = cast(bytes, command) if type(command) is bytes else cast(str, command).encode() # type: bytes
|
||||
@ -222,7 +222,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||
self._command_received.set()
|
||||
|
||||
def _update(self):
|
||||
while self._connection_state == ConnectionState.connected and self._serial is not None:
|
||||
while self._connection_state == ConnectionState.Connected and self._serial is not None:
|
||||
try:
|
||||
line = self._serial.readline()
|
||||
except:
|
||||
|
@ -66,7 +66,7 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
|
||||
return
|
||||
|
||||
changed_device = self._usb_output_devices[serial_port]
|
||||
if changed_device.connectionState == ConnectionState.connected:
|
||||
if changed_device.connectionState == ConnectionState.Connected:
|
||||
self.getOutputDeviceManager().addOutputDevice(changed_device)
|
||||
else:
|
||||
self.getOutputDeviceManager().removeOutputDevice(serial_port)
|
||||
|
@ -47,7 +47,7 @@ def getMetaData() -> Dict[str, Any]:
|
||||
},
|
||||
"user": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./user"}
|
||||
"location": {"./user", "./materials/*"}
|
||||
},
|
||||
"variant": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
|
@ -57,7 +57,7 @@
|
||||
"display_name": "Cura Backups",
|
||||
"description": "Backup and restore your configuration.",
|
||||
"package_version": "1.2.0",
|
||||
"sdk_version": 5,
|
||||
"sdk_version": 6,
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -16,7 +16,8 @@
|
||||
{
|
||||
"0": "ultimaker_original_plus_extruder_0"
|
||||
},
|
||||
"firmware_file": "MarlinUltimaker-UMOP-{baudrate}.hex"
|
||||
"firmware_file": "MarlinUltimaker-UMOP-{baudrate}.hex",
|
||||
"firmware_hbk_file": "MarlinUltimaker-UMOP-{baudrate}.hex"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
|
@ -44,7 +44,7 @@ Column
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
renderType: Text.NativeRendering
|
||||
text: loggedIn ? profile["username"] : catalog.i18nc("@label", "Please log in or create an account to\nenjoy all features of Ultimaker Cura.")
|
||||
font: loggedIn ? UM.Theme.getFont("large") : UM.Theme.getFont("default")
|
||||
font: loggedIn ? UM.Theme.getFont("large_bold") : UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ Button
|
||||
property alias iconSource: buttonIconLeft.source
|
||||
property alias textFont: buttonText.font
|
||||
property alias cornerRadius: backgroundRect.radius
|
||||
property alias tooltip: tooltip.text
|
||||
property alias tooltip: tooltip.tooltipText
|
||||
property alias cornerSide: backgroundRect.cornerSide
|
||||
|
||||
property color color: UM.Theme.getColor("primary")
|
||||
@ -33,6 +33,8 @@ Button
|
||||
property alias shadowEnabled: shadow.visible
|
||||
property alias busy: busyIndicator.visible
|
||||
|
||||
property alias toolTipContentAlignment: tooltip.contentAlignment
|
||||
|
||||
// This property is used to indicate whether the button has a fixed width or the width would depend on the contents
|
||||
// Be careful when using fixedWidthMode, the translated texts can be too long that they won't fit. In any case,
|
||||
// we elide the text to the right so the text will be cut off with the three dots at the end.
|
||||
@ -112,20 +114,17 @@ Button
|
||||
z: backgroundRect.z - 1
|
||||
}
|
||||
|
||||
ToolTip
|
||||
Cura.ToolTip
|
||||
{
|
||||
id: tooltip
|
||||
text: ""
|
||||
delay: 500
|
||||
visible: text != "" && button.hovered
|
||||
visible: button.hovered
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
BusyIndicator
|
||||
{
|
||||
id: busyIndicator
|
||||
|
||||
anchors {
|
||||
centerIn: parent
|
||||
}
|
||||
anchors.centerIn: parent
|
||||
|
||||
width: height
|
||||
height: parent.height
|
||||
|
@ -23,6 +23,7 @@ Rectangle
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
border.color: UM.Theme.getColor("lining")
|
||||
radius: UM.Theme.getSize("default_radius").width
|
||||
z: 10
|
||||
|
||||
property bool outputAvailable: UM.Backend.state == UM.Backend.Done || UM.Backend.state == UM.Backend.Disabled
|
||||
|
||||
|
@ -60,7 +60,6 @@ Item
|
||||
|
||||
leftPadding: UM.Theme.getSize("narrow_margin").width //Need more space than usual here for wide text.
|
||||
rightPadding: UM.Theme.getSize("narrow_margin").width
|
||||
tooltip: popup.opened ? "" : catalog.i18nc("@info:tooltip", "Select the active output device")
|
||||
iconSource: popup.opened ? UM.Theme.getIcon("arrow_top") : UM.Theme.getIcon("arrow_bottom")
|
||||
color: UM.Theme.getColor("action_panel_secondary")
|
||||
visible: (devicesModel.deviceCount > 1)
|
||||
@ -94,7 +93,6 @@ Item
|
||||
onClicked:
|
||||
{
|
||||
UM.OutputDeviceManager.setActiveDevice(model.id)
|
||||
widget.requestWriteToDevice()
|
||||
popup.close()
|
||||
}
|
||||
}
|
||||
|
@ -40,8 +40,7 @@ Column
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
right: printInformationPanel.left
|
||||
rightMargin: printInformationPanel.visible ? UM.Theme.getSize("thin_margin").width : 0
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
Cura.IconWithText
|
||||
@ -51,7 +50,15 @@ Column
|
||||
|
||||
text: preSlicedData ? catalog.i18nc("@label", "No time estimation available") : PrintInformation.currentPrintTime.getDisplayString(UM.DurationFormat.Long)
|
||||
source: UM.Theme.getIcon("clock")
|
||||
font: UM.Theme.getFont("default_bold")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
|
||||
PrintInformationWidget
|
||||
{
|
||||
id: printInformationPanel
|
||||
visible: !preSlicedData
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: parent.contentWidth + UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
}
|
||||
|
||||
Cura.IconWithText
|
||||
@ -84,20 +91,43 @@ Column
|
||||
return totalWeights + "g · " + totalLengths.toFixed(2) + "m"
|
||||
}
|
||||
source: UM.Theme.getIcon("spool")
|
||||
|
||||
Item
|
||||
{
|
||||
id: additionalComponents
|
||||
width: childrenRect.width
|
||||
anchors.right: parent.right
|
||||
height: parent.height
|
||||
Row
|
||||
{
|
||||
id: additionalComponentsRow
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
}
|
||||
Component.onCompleted: addAdditionalComponents("saveButton")
|
||||
|
||||
Connections
|
||||
{
|
||||
target: CuraApplication
|
||||
onAdditionalComponentsChanged: addAdditionalComponents("saveButton")
|
||||
}
|
||||
|
||||
function addAdditionalComponents (areaId)
|
||||
{
|
||||
if(areaId == "saveButton")
|
||||
{
|
||||
for (var component in CuraApplication.additionalComponents["saveButton"])
|
||||
{
|
||||
CuraApplication.additionalComponents["saveButton"][component].parent = additionalComponentsRow
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PrintInformationWidget
|
||||
{
|
||||
id: printInformationPanel
|
||||
visible: !preSlicedData
|
||||
|
||||
anchors
|
||||
{
|
||||
right: parent.right
|
||||
verticalCenter: timeAndCostsInformation.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
@ -123,11 +153,10 @@ Column
|
||||
tooltip: text
|
||||
fixedWidthMode: true
|
||||
|
||||
toolTipContentAlignment: Cura.ToolTip.ContentAlignment.AlignLeft
|
||||
|
||||
onClicked: UM.Controller.setActiveStage("PreviewStage")
|
||||
visible: UM.Controller.activeStage != null && UM.Controller.activeStage.stageId != "PreviewStage"
|
||||
|
||||
shadowEnabled: true
|
||||
shadowColor: UM.Theme.getColor("action_button_disabled_shadow")
|
||||
}
|
||||
|
||||
Cura.OutputDevicesActionButton
|
||||
|
@ -44,9 +44,9 @@ Column
|
||||
{
|
||||
id: autoSlicingLabel
|
||||
width: parent.width
|
||||
visible: prepareButtons.autoSlice && (widget.backendState == UM.Backend.Processing || widget.backendState == UM.Backend.NotStarted)
|
||||
visible: progressBar.visible
|
||||
|
||||
text: catalog.i18nc("@label:PrintjobStatus", "Auto slicing...")
|
||||
text: catalog.i18nc("@label:PrintjobStatus", "Slicing...")
|
||||
color: UM.Theme.getColor("text")
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
@ -107,8 +107,15 @@ Column
|
||||
{
|
||||
id: sliceButton
|
||||
fixedWidthMode: true
|
||||
anchors.fill: parent
|
||||
|
||||
height: parent.height
|
||||
|
||||
anchors.right: additionalComponents.left
|
||||
anchors.rightMargin: additionalComponents.width != 0 ? UM.Theme.getSize("default_margin").width : 0
|
||||
anchors.left: parent.left
|
||||
|
||||
text: catalog.i18nc("@button", "Slice")
|
||||
tooltip: catalog.i18nc("@label", "Start the slicing process")
|
||||
enabled: widget.backendState != UM.Backend.Error
|
||||
visible: widget.backendState == UM.Backend.NotStarted || widget.backendState == UM.Backend.Error
|
||||
onClicked: sliceOrStopSlicing()
|
||||
@ -118,12 +125,48 @@ Column
|
||||
{
|
||||
id: cancelButton
|
||||
fixedWidthMode: true
|
||||
anchors.fill: parent
|
||||
height: parent.height
|
||||
anchors.left: parent.left
|
||||
|
||||
anchors.right: additionalComponents.left
|
||||
anchors.rightMargin: additionalComponents.width != 0 ? UM.Theme.getSize("default_margin").width : 0
|
||||
text: catalog.i18nc("@button", "Cancel")
|
||||
enabled: sliceButton.enabled
|
||||
visible: !sliceButton.visible
|
||||
onClicked: sliceOrStopSlicing()
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: additionalComponents
|
||||
width: childrenRect.width
|
||||
anchors.right: parent.right
|
||||
height: parent.height
|
||||
Row
|
||||
{
|
||||
id: additionalComponentsRow
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
}
|
||||
}
|
||||
Component.onCompleted: prepareButtons.addAdditionalComponents("saveButton")
|
||||
|
||||
Connections
|
||||
{
|
||||
target: CuraApplication
|
||||
onAdditionalComponentsChanged: prepareButtons.addAdditionalComponents("saveButton")
|
||||
}
|
||||
|
||||
function addAdditionalComponents (areaId)
|
||||
{
|
||||
if(areaId == "saveButton")
|
||||
{
|
||||
for (var component in CuraApplication.additionalComponents["saveButton"])
|
||||
{
|
||||
CuraApplication.additionalComponents["saveButton"][component].parent = additionalComponentsRow
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -134,10 +177,13 @@ Column
|
||||
onPreferenceChanged:
|
||||
{
|
||||
var autoSlice = UM.Preferences.getValue("general/auto_slice")
|
||||
prepareButtons.autoSlice = autoSlice
|
||||
if(autoSlice)
|
||||
if(prepareButtons.autoSlice != autoSlice)
|
||||
{
|
||||
CuraApplication.backend.forceSlice()
|
||||
prepareButtons.autoSlice = autoSlice
|
||||
if(autoSlice)
|
||||
{
|
||||
CuraApplication.backend.forceSlice()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,11 +13,12 @@ CheckBox
|
||||
|
||||
property alias tooltip: tooltip.text
|
||||
|
||||
indicator: Rectangle {
|
||||
indicator: Rectangle
|
||||
{
|
||||
implicitWidth: UM.Theme.getSize("checkbox").width
|
||||
implicitHeight: UM.Theme.getSize("checkbox").height
|
||||
x: 0
|
||||
y: Math.round(parent.height / 2 - height / 2)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: UM.Theme.getColor("main_background")
|
||||
radius: UM.Theme.getSize("checkbox_radius").width
|
||||
border.width: UM.Theme.getSize("default_lining").width
|
||||
@ -37,7 +38,8 @@ CheckBox
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Label {
|
||||
contentItem: Label
|
||||
{
|
||||
anchors
|
||||
{
|
||||
left: checkbox.indicator.right
|
@ -51,7 +51,7 @@ UM.Dialog
|
||||
id: version
|
||||
|
||||
text: catalog.i18nc("@label","version: %1").arg(UM.Application.version)
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
color: UM.Theme.getColor("text")
|
||||
anchors.right : logo.right
|
||||
anchors.top: logo.bottom
|
||||
|
@ -64,7 +64,7 @@ Item
|
||||
property alias iconSize: collapseButton.height
|
||||
|
||||
// Is the "drawer" open?
|
||||
readonly property alias expanded: contentContainer.visible
|
||||
property alias expanded: contentContainer.visible
|
||||
|
||||
// What should the radius of the header be. This is also influenced by the headerCornerSide
|
||||
property alias headerRadius: background.radius
|
||||
|
@ -25,7 +25,7 @@ Cura.RoundedRectangle
|
||||
{
|
||||
id: headerLabel
|
||||
text: ""
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
renderType: Text.NativeRendering
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: UM.Theme.getColor("small_button_text")
|
||||
|
@ -48,7 +48,7 @@ Item
|
||||
id: extruderNumberText
|
||||
anchors.centerIn: parent
|
||||
text: index + 1
|
||||
font: UM.Theme.getFont("very_small")
|
||||
font: UM.Theme.getFont("small")
|
||||
color: UM.Theme.getColor("text")
|
||||
width: contentWidth
|
||||
height: contentHeight
|
||||
@ -66,7 +66,7 @@ Item
|
||||
sourceSize.height: width
|
||||
source: UM.Theme.getIcon("cross1")
|
||||
visible: !extruderEnabled
|
||||
color: "black"
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
}
|
||||
}
|
@ -97,7 +97,7 @@ Item
|
||||
style: TextFieldStyle
|
||||
{
|
||||
textColor: UM.Theme.getColor("text_scene")
|
||||
font: UM.Theme.getFont("default_bold")
|
||||
font: UM.Theme.getFont("default")
|
||||
background: Rectangle
|
||||
{
|
||||
opacity: 0
|
||||
@ -115,7 +115,7 @@ Item
|
||||
|
||||
height: UM.Theme.getSize("jobspecs_line").height
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font: UM.Theme.getFont("default_bold")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text_scene")
|
||||
text: CuraApplication.getSceneBoundingBoxString
|
||||
}
|
||||
|
@ -83,14 +83,6 @@ Item
|
||||
}
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
id: plugin_menu
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel", "&Marketplace")
|
||||
|
||||
MenuItem { action: Cura.Actions.browsePackages }
|
||||
}
|
||||
|
||||
Menu
|
||||
{
|
||||
id: preferencesMenu
|
||||
|
@ -29,6 +29,9 @@ Item
|
||||
source: UM.Theme.getImage("logo")
|
||||
width: UM.Theme.getSize("logo").width
|
||||
height: UM.Theme.getSize("logo").height
|
||||
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
}
|
||||
|
||||
Row
|
||||
@ -99,6 +102,7 @@ Item
|
||||
{
|
||||
id: label
|
||||
text: marketplaceButton.text
|
||||
font: UM.Theme.getFont("default")
|
||||
color: marketplaceButton.hovered ? UM.Theme.getColor("main_window_header_background") : UM.Theme.getColor("primary_text")
|
||||
width: contentWidth
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
@ -16,7 +16,7 @@ Item
|
||||
{
|
||||
id: header
|
||||
text: catalog.i18nc("@header", "Configurations")
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("small_button_text")
|
||||
height: contentHeight
|
||||
renderType: Text.NativeRendering
|
||||
|
@ -12,7 +12,23 @@ Button
|
||||
id: configurationItem
|
||||
|
||||
property var configuration: null
|
||||
hoverEnabled: true
|
||||
hoverEnabled: isValidMaterial
|
||||
|
||||
property bool isValidMaterial:
|
||||
{
|
||||
var extruderConfigurations = configuration.extruderConfigurations
|
||||
|
||||
for (var index in extruderConfigurations)
|
||||
{
|
||||
var name = extruderConfigurations[index].material ? extruderConfigurations[index].material.name : ""
|
||||
|
||||
if (name == "" || name == "Unknown")
|
||||
{
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
background: Rectangle
|
||||
{
|
||||
@ -40,17 +56,104 @@ Button
|
||||
right: parent.right
|
||||
rightMargin: UM.Theme.getSize("wide_margin").width
|
||||
}
|
||||
|
||||
height: childrenRect.height
|
||||
spacing: UM.Theme.getSize("default_margin").width
|
||||
|
||||
Repeater
|
||||
{
|
||||
id: repeater
|
||||
model: configuration.extruderConfigurations
|
||||
|
||||
delegate: PrintCoreConfiguration
|
||||
{
|
||||
width: Math.round(parent.width / 2)
|
||||
printCoreConfiguration: modelData
|
||||
visible: configurationItem.isValidMaterial
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown material
|
||||
Item
|
||||
{
|
||||
id: unknownMaterial
|
||||
height: unknownMaterialMessage.height + UM.Theme.getSize("thin_margin").width / 2
|
||||
width: parent.width
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: UM.Theme.getSize("thin_margin").width / 2
|
||||
|
||||
visible: !configurationItem.isValidMaterial
|
||||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: icon
|
||||
anchors.verticalCenter: unknownMaterialMessage.verticalCenter
|
||||
|
||||
source: UM.Theme.getIcon("warning")
|
||||
color: UM.Theme.getColor("warning")
|
||||
width: UM.Theme.getSize("section_icon").width
|
||||
height: width
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: unknownMaterialMessage
|
||||
text:
|
||||
{
|
||||
var extruderConfigurations = configuration.extruderConfigurations
|
||||
var unknownMaterials = []
|
||||
for (var index in extruderConfigurations)
|
||||
{
|
||||
var name = extruderConfigurations[index].material ? extruderConfigurations[index].material.name : ""
|
||||
if (name == "" || name == "Unknown")
|
||||
{
|
||||
var materialType = extruderConfigurations[index].material.type
|
||||
if (extruderConfigurations[index].material.type == "")
|
||||
{
|
||||
materialType = "Unknown"
|
||||
}
|
||||
|
||||
var brand = extruderConfigurations[index].material.brand
|
||||
if (brand == "")
|
||||
{
|
||||
brand = "Unknown"
|
||||
}
|
||||
|
||||
name = materialType + " (" + brand + ")"
|
||||
unknownMaterials.push(name)
|
||||
}
|
||||
}
|
||||
|
||||
unknownMaterials = "<b>" + unknownMaterials + "</b>"
|
||||
var draftResult = catalog.i18nc("@label", "This configuration is not available because %1 is not recognized. Please visit %2 to download the correct material profile.");
|
||||
var result = draftResult.arg(unknownMaterials).arg("<a href=' '>" + catalog.i18nc("@label","Marketplace") + "</a> ")
|
||||
|
||||
return result
|
||||
}
|
||||
width: extruderRow.width
|
||||
|
||||
anchors.left: icon.right
|
||||
anchors.right: unknownMaterial.right
|
||||
anchors.leftMargin: UM.Theme.getSize("wide_margin").height
|
||||
anchors.top: unknownMaterial.top
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
linkColor: UM.Theme.getColor("text_link")
|
||||
|
||||
onLinkActivated:
|
||||
{
|
||||
Cura.Actions.browsePackages.trigger()
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
cursorShape: unknownMaterialMessage.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,27 +187,15 @@ Button
|
||||
rightMargin: UM.Theme.getSize("wide_margin").width
|
||||
}
|
||||
height: childrenRect.height
|
||||
visible: configuration.buildplateConfiguration != ""
|
||||
visible: configuration.buildplateConfiguration != "" && false //Buildplate is disabled as long as we have no printers that properly support buildplate swapping (so we can't test).
|
||||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: buildplateIcon
|
||||
anchors.left: parent.left
|
||||
width: UM.Theme.getSize("main_window_header_button_icon").width
|
||||
height: UM.Theme.getSize("main_window_header_button_icon").height
|
||||
source: UM.Theme.getIcon("buildplate")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
|
||||
Label
|
||||
// Show the type of buildplate. The first letter is capitalized
|
||||
Cura.IconWithText
|
||||
{
|
||||
id: buildplateLabel
|
||||
anchors.left: buildplateIcon.right
|
||||
anchors.verticalCenter: buildplateIcon.verticalCenter
|
||||
anchors.leftMargin: UM.Theme.getSize("narrow_margin").height
|
||||
text: configuration.buildplateConfiguration
|
||||
renderType: Text.NativeRendering
|
||||
color: UM.Theme.getColor("text")
|
||||
source: UM.Theme.getIcon("buildplate")
|
||||
text: configuration.buildplateConfiguration.charAt(0).toUpperCase() + configuration.buildplateConfiguration.substr(1)
|
||||
anchors.left: parent.left
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -125,6 +216,9 @@ Button
|
||||
|
||||
onClicked:
|
||||
{
|
||||
Cura.MachineManager.applyRemoteConfiguration(configuration)
|
||||
if(isValidMaterial)
|
||||
{
|
||||
Cura.MachineManager.applyRemoteConfiguration(configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ Item
|
||||
anchors.left: icon.right
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||
text: catalog.i18nc("@label", "The configurations are not available because the printer is disconnected.")
|
||||
text: catalog.i18nc("@label", "Downloading the configurations from the remote printer")
|
||||
color: UM.Theme.getColor("text")
|
||||
font: UM.Theme.getFont("default")
|
||||
renderType: Text.NativeRendering
|
||||
|
@ -86,7 +86,7 @@ Cura.ExpandablePopup
|
||||
{
|
||||
text: model.material
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text")
|
||||
renderType: Text.NativeRendering
|
||||
|
||||
@ -107,7 +107,7 @@ Cura.ExpandablePopup
|
||||
{
|
||||
text: catalog.i18nc("@label", "Select configuration")
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text")
|
||||
renderType: Text.NativeRendering
|
||||
|
||||
@ -136,7 +136,7 @@ Cura.ExpandablePopup
|
||||
|
||||
onVisibleChanged:
|
||||
{
|
||||
is_connected = Cura.MachineManager.activeMachineNetworkKey !== "" && Cura.MachineManager.printerConnected // Re-evaluate.
|
||||
is_connected = Cura.MachineManager.activeMachineHasRemoteConnection && Cura.MachineManager.printerConnected //Re-evaluate.
|
||||
|
||||
// If the printer is not connected, we switch always to the custom mode. If is connected instead, the auto mode
|
||||
// or the previous state is selected
|
||||
|
@ -23,7 +23,7 @@ Item
|
||||
{
|
||||
id: header
|
||||
text: catalog.i18nc("@header", "Custom")
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("small_button_text")
|
||||
height: contentHeight
|
||||
renderType: Text.NativeRendering
|
||||
|
@ -39,7 +39,7 @@ Row
|
||||
text: printCoreConfiguration.material.brand ? printCoreConfiguration.material.name : " " //Use space so that the height is still correct.
|
||||
renderType: Text.NativeRendering
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
Label
|
||||
|
@ -7,16 +7,18 @@ import QtQuick.Controls 1.4
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Instantiator {
|
||||
model: UM.ContainerStacksModel {
|
||||
filter: {"type": "machine", "um_network_key": null}
|
||||
}
|
||||
MenuItem {
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
Instantiator
|
||||
{
|
||||
model: Cura.GlobalStacksModel {}
|
||||
|
||||
MenuItem
|
||||
{
|
||||
text: model.name
|
||||
checkable: true
|
||||
checked: Cura.MachineManager.activeMachineId == model.id
|
||||
exclusiveGroup: group;
|
||||
onTriggered: Cura.MachineManager.setActiveMachine(model.id);
|
||||
exclusiveGroup: group
|
||||
visible: !model.hasRemoteConnection
|
||||
onTriggered: Cura.MachineManager.setActiveMachine(model.id)
|
||||
}
|
||||
onObjectAdded: menu.insertItem(index, object)
|
||||
onObjectRemoved: menu.removeItem(object)
|
||||
|
@ -7,18 +7,17 @@ import QtQuick.Controls 1.4
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Instantiator {
|
||||
model: UM.ContainerStacksModel {
|
||||
filter: {"type": "machine", "um_network_key": "*", "hidden": "False"}
|
||||
}
|
||||
MenuItem {
|
||||
// TODO: Use printer_group icon when it's a cluster. Not use it for now since it doesn't look as expected
|
||||
// iconSource: UM.Theme.getIcon("printer_single")
|
||||
Instantiator
|
||||
{
|
||||
model: Cura.GlobalStacksModel {}
|
||||
MenuItem
|
||||
{
|
||||
text: model.metadata["connect_group_name"]
|
||||
checkable: true;
|
||||
checkable: true
|
||||
visible: model.hasRemoteConnection
|
||||
checked: Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["connect_group_name"]
|
||||
exclusiveGroup: group;
|
||||
onTriggered: Cura.MachineManager.setActiveMachine(model.id);
|
||||
exclusiveGroup: group
|
||||
onTriggered: Cura.MachineManager.setActiveMachine(model.id)
|
||||
}
|
||||
onObjectAdded: menu.insertItem(index, object)
|
||||
onObjectRemoved: menu.removeItem(object)
|
||||
|
@ -168,7 +168,7 @@ Item
|
||||
anchors.leftMargin: UM.Theme.getSize("thick_margin").width
|
||||
|
||||
color: base.statusColor
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
text: statusText
|
||||
}
|
||||
|
||||
@ -179,7 +179,7 @@ Item
|
||||
anchors.right: progressBar.right
|
||||
|
||||
color: base.statusColor
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
text: Math.round(progress) + "%"
|
||||
visible: showProgress
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016 Ultimaker B.V.
|
||||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
@ -70,7 +70,7 @@ UM.ManagementPage
|
||||
{
|
||||
id: machineName
|
||||
text: base.currentItem && base.currentItem.name ? base.currentItem.name : ""
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
@ -91,7 +91,7 @@ UM.ManagementPage
|
||||
|
||||
Item
|
||||
{
|
||||
width: childrenRect.width + 2 * screenScaleFactor
|
||||
width: Math.round(childrenRect.width + 2 * screenScaleFactor)
|
||||
height: childrenRect.height
|
||||
Button
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Uranium 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.Controls 1.4
|
||||
@ -10,7 +10,7 @@ import QtQuick.Dialogs 1.2
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Rectangle
|
||||
Item
|
||||
{
|
||||
id: brand_section
|
||||
|
||||
@ -69,11 +69,7 @@ Rectangle
|
||||
}
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Rectangle
|
||||
{
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
}
|
||||
background: Item { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ Item
|
||||
|
||||
Label {
|
||||
text: materialProperties.name
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Uranium 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.Controls 1.4
|
||||
@ -15,7 +15,7 @@ Rectangle
|
||||
id: materialSlot
|
||||
property var material: null
|
||||
property var hovered: false
|
||||
property var is_favorite: material != null ? material.is_favorite : false
|
||||
property var is_favorite: material != null && material.is_favorite
|
||||
|
||||
height: UM.Theme.getSize("favorites_row").height
|
||||
width: parent.width
|
||||
@ -70,24 +70,20 @@ Rectangle
|
||||
}
|
||||
onClicked:
|
||||
{
|
||||
if (materialSlot.is_favorite) {
|
||||
if (materialSlot.is_favorite)
|
||||
{
|
||||
base.materialManager.removeFavorite(material.root_material_id)
|
||||
materialSlot.is_favorite = false
|
||||
return
|
||||
}
|
||||
base.materialManager.addFavorite(material.root_material_id)
|
||||
materialSlot.is_favorite = true
|
||||
return
|
||||
}
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Rectangle
|
||||
{
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
}
|
||||
background: Item { }
|
||||
}
|
||||
UM.RecolorImage {
|
||||
UM.RecolorImage
|
||||
{
|
||||
anchors
|
||||
{
|
||||
verticalCenter: favorite_button.verticalCenter
|
||||
|
@ -10,7 +10,7 @@ import QtQuick.Dialogs 1.2
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Rectangle
|
||||
Item
|
||||
{
|
||||
id: material_type_section
|
||||
property var materialType
|
||||
|
@ -408,7 +408,7 @@ Item
|
||||
{
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.getSize("default_lining").width
|
||||
text: section == "true" ? catalog.i18nc("@label", "Protected profiles") : catalog.i18nc("@label", "Custom profiles")
|
||||
text: section == "true" ? catalog.i18nc("@label", "Default profiles") : catalog.i18nc("@label", "Custom profiles")
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
@ -471,7 +471,7 @@ Item
|
||||
|
||||
Label {
|
||||
text: base.currentItemName
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import Cura 1.0 as Cura
|
||||
import "PrinterOutput"
|
||||
|
||||
|
||||
Rectangle
|
||||
Item
|
||||
{
|
||||
id: base
|
||||
UM.I18nCatalog { id: catalog; name: "cura"}
|
||||
|
@ -11,7 +11,6 @@ import Cura 1.0 as Cura
|
||||
Item
|
||||
{
|
||||
id: customPrintSetup
|
||||
height: childrenRect.height + padding
|
||||
|
||||
property real padding: UM.Theme.getSize("default_margin").width
|
||||
property bool multipleExtruders: extrudersModel.count > 1
|
||||
@ -98,15 +97,15 @@ Item
|
||||
|
||||
Rectangle
|
||||
{
|
||||
height: UM.Theme.getSize("print_setup_widget").height
|
||||
anchors
|
||||
{
|
||||
top: tabBar.visible ? tabBar.bottom : globalProfileRow.bottom
|
||||
topMargin: -UM.Theme.getSize("default_lining").width
|
||||
left: parent.left
|
||||
leftMargin: parent.padding
|
||||
right: parent.right
|
||||
rightMargin: parent.padding
|
||||
topMargin: -UM.Theme.getSize("default_lining").width
|
||||
bottom: parent.bottom
|
||||
}
|
||||
z: tabBar.z - 1
|
||||
// Don't show the border when only one extruder
|
||||
|
@ -25,7 +25,7 @@ Item
|
||||
right: globalProfileSelection.left
|
||||
}
|
||||
text: catalog.i18nc("@label", "Profile")
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
@ -29,4 +29,7 @@ Cura.ExpandableComponent
|
||||
property var extrudersModel: CuraApplication.getExtrudersModel()
|
||||
|
||||
contentItem: PrintSetupSelectorContents {}
|
||||
|
||||
onExpandedChanged: UM.Preferences.setValue("view/settings_visible", expanded)
|
||||
Component.onCompleted: expanded = UM.Preferences.getValue("view/settings_visible")
|
||||
}
|
@ -15,7 +15,7 @@ Item
|
||||
id: content
|
||||
|
||||
width: UM.Theme.getSize("print_setup_widget").width - 2 * UM.Theme.getSize("default_margin").width
|
||||
height: childrenRect.height
|
||||
height: contents.height + buttonRow.height
|
||||
|
||||
enum Mode
|
||||
{
|
||||
@ -71,6 +71,15 @@ Item
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
}
|
||||
height: UM.Preferences.getValue("view/settings_list_height") - UM.Theme.getSize("default_margin").height
|
||||
Connections
|
||||
{
|
||||
target: UM.Preferences
|
||||
onPreferenceChanged:
|
||||
{
|
||||
customPrintSetup.height = UM.Preferences.getValue("view/settings_list_height");
|
||||
}
|
||||
}
|
||||
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom
|
||||
}
|
||||
}
|
||||
@ -94,13 +103,14 @@ Item
|
||||
|
||||
anchors
|
||||
{
|
||||
top: buttonsSeparator.bottom
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
Cura.SecondaryButton
|
||||
{
|
||||
id: recommendedButton
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.margins: parent.padding
|
||||
@ -125,5 +135,47 @@ Item
|
||||
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Recommended
|
||||
onClicked: currentModeIndex = PrintSetupSelectorContents.Mode.Custom
|
||||
}
|
||||
|
||||
//Invisible area at the bottom with which you can resize the panel.
|
||||
MouseArea
|
||||
{
|
||||
anchors
|
||||
{
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
top: recommendedButton.bottom
|
||||
topMargin: UM.Theme.getSize("default_lining").height
|
||||
}
|
||||
cursorShape: Qt.SplitVCursor
|
||||
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom
|
||||
drag
|
||||
{
|
||||
target: parent
|
||||
axis: Drag.YAxis
|
||||
}
|
||||
onMouseYChanged:
|
||||
{
|
||||
if(drag.active)
|
||||
{
|
||||
// position of mouse relative to dropdown align vertical centre of mouse area to cursor
|
||||
// v------------------------------v v------------v
|
||||
var h = mouseY + buttonRow.y + content.y - height / 2 | 0;
|
||||
if(h < 200 * screenScaleFactor) //Enforce a minimum size.
|
||||
{
|
||||
h = 200 * screenScaleFactor;
|
||||
}
|
||||
|
||||
//Absolute mouse Y position in the window, to prevent it from going outside the window.
|
||||
var mouse_absolute_y = mapToGlobal(mouseX, mouseY).y - UM.Preferences.getValue("general/window_top");
|
||||
if(mouse_absolute_y > base.height)
|
||||
{
|
||||
h -= mouse_absolute_y - base.height;
|
||||
}
|
||||
|
||||
UM.Preferences.setValue("view/settings_list_height", h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@ RowLayout
|
||||
}
|
||||
return ""
|
||||
}
|
||||
font: UM.Theme.getFont("medium")
|
||||
|
||||
UM.SettingPropertyProvider
|
||||
{
|
||||
@ -43,6 +44,7 @@ RowLayout
|
||||
{
|
||||
source: UM.Theme.getIcon("category_infill")
|
||||
text: Cura.MachineManager.activeStack ? parseInt(infillDensity.properties.value) + "%" : "0%"
|
||||
font: UM.Theme.getFont("medium")
|
||||
|
||||
UM.SettingPropertyProvider
|
||||
{
|
||||
@ -57,6 +59,7 @@ RowLayout
|
||||
{
|
||||
source: UM.Theme.getIcon("category_support")
|
||||
text: supportEnabled.properties.value == "True" ? enabledText : disabledText
|
||||
font: UM.Theme.getFont("medium")
|
||||
|
||||
UM.SettingPropertyProvider
|
||||
{
|
||||
@ -71,6 +74,7 @@ RowLayout
|
||||
{
|
||||
source: UM.Theme.getIcon("category_adhesion")
|
||||
text: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none" ? enabledText : disabledText
|
||||
font: UM.Theme.getFont("medium")
|
||||
|
||||
UM.SettingPropertyProvider
|
||||
{
|
||||
|
@ -26,6 +26,7 @@ Item
|
||||
anchors.left: parent.left
|
||||
source: UM.Theme.getIcon("category_adhesion")
|
||||
text: catalog.i18nc("@label", "Adhesion")
|
||||
font: UM.Theme.getFont("medium")
|
||||
width: labelColumnWidth
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,7 @@ Item
|
||||
anchors.left: parent.left
|
||||
source: UM.Theme.getIcon("category_infill")
|
||||
text: catalog.i18nc("@label", "Infill") + " (%)"
|
||||
font: UM.Theme.getFont("medium")
|
||||
width: labelColumnWidth
|
||||
}
|
||||
|
||||
@ -140,6 +141,7 @@ Item
|
||||
Label
|
||||
{
|
||||
text: index
|
||||
font: UM.Theme.getFont("default")
|
||||
visible: (index % 20) == 0 // Only show steps of 20%
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: UM.Theme.getSize("thin_margin").height
|
||||
|
@ -39,17 +39,6 @@ Item
|
||||
{
|
||||
target: Cura.QualityProfilesDropDownMenuModel
|
||||
onItemsChanged: qualityModel.update()
|
||||
onDataChanged:
|
||||
{
|
||||
// If a custom profile is selected and then a user decides to change any of setting the slider should show
|
||||
// the reset button. After clicking the reset button the QualityProfilesDropDownMenuModel(ListModel) is
|
||||
// updated before the property isProfileCustomized is called to update.
|
||||
if (Cura.SimpleModeSettingsManager.isProfileCustomized)
|
||||
{
|
||||
Cura.SimpleModeSettingsManager.updateIsProfileUserCreated()
|
||||
}
|
||||
qualityModel.update()
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
@ -97,7 +86,7 @@ Item
|
||||
if (Cura.MachineManager.activeQualityType == qualityItem.quality_type)
|
||||
{
|
||||
// set to -1 when switching to user created profile so all ticks are clickable
|
||||
if (Cura.SimpleModeSettingsManager.isProfileUserCreated)
|
||||
if (Cura.MachineManager.hasCustomQuality)
|
||||
{
|
||||
qualityModel.qualitySliderActiveIndex = -1
|
||||
}
|
||||
@ -184,6 +173,7 @@ Item
|
||||
id: qualityRowTitle
|
||||
source: UM.Theme.getIcon("category_layer_height")
|
||||
text: catalog.i18nc("@label", "Layer Height")
|
||||
font: UM.Theme.getFont("medium")
|
||||
anchors.left: parent.left
|
||||
anchors.right: customisedSettings.left
|
||||
}
|
||||
@ -192,7 +182,7 @@ Item
|
||||
{
|
||||
id: customisedSettings
|
||||
|
||||
visible: Cura.SimpleModeSettingsManager.isProfileCustomized || Cura.SimpleModeSettingsManager.isProfileUserCreated
|
||||
visible: Cura.SimpleModeSettingsManager.isProfileCustomized || Cura.MachineManager.hasCustomQuality
|
||||
height: visible ? UM.Theme.getSize("print_setup_icon").height : 0
|
||||
width: height
|
||||
anchors
|
||||
@ -282,6 +272,7 @@ Item
|
||||
return Math.round((settingsColumnWidth / qualityModel.totalTicks) * index - (width / 2))
|
||||
}
|
||||
}
|
||||
font: UM.Theme.getFont("default")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -358,7 +349,7 @@ Item
|
||||
{
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
enabled: !Cura.SimpleModeSettingsManager.isProfileUserCreated
|
||||
enabled: !Cura.MachineManager.hasCustomQuality
|
||||
onEntered:
|
||||
{
|
||||
var tooltipContent = catalog.i18nc("@tooltip", "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile")
|
||||
@ -417,7 +408,7 @@ Item
|
||||
implicitWidth: UM.Theme.getSize("print_setup_slider_handle").width
|
||||
implicitHeight: implicitWidth
|
||||
radius: Math.round(implicitWidth / 2)
|
||||
visible: !Cura.SimpleModeSettingsManager.isProfileCustomized && !Cura.SimpleModeSettingsManager.isProfileUserCreated && qualityModel.existingQualityProfile
|
||||
visible: !Cura.SimpleModeSettingsManager.isProfileCustomized && !Cura.MachineManager.hasCustomQuality && qualityModel.existingQualityProfile
|
||||
}
|
||||
}
|
||||
|
||||
@ -441,7 +432,7 @@ Item
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.NoButton
|
||||
enabled: !Cura.SimpleModeSettingsManager.isProfileUserCreated
|
||||
enabled: !Cura.MachineManager.hasCustomQuality
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,7 +442,7 @@ Item
|
||||
{
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
visible: Cura.SimpleModeSettingsManager.isProfileUserCreated
|
||||
visible: Cura.MachineManager.hasCustomQuality
|
||||
|
||||
onEntered:
|
||||
{
|
||||
|
@ -27,6 +27,7 @@ Item
|
||||
visible: enableSupportCheckBox.visible
|
||||
source: UM.Theme.getIcon("category_support")
|
||||
text: catalog.i18nc("@label", "Support")
|
||||
font: UM.Theme.getFont("medium")
|
||||
width: labelColumnWidth
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,7 @@
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import UM 1.0 as UM
|
||||
|
||||
@ -43,7 +41,8 @@ UM.PointingRectangle {
|
||||
base.opacity = 0;
|
||||
}
|
||||
|
||||
Label {
|
||||
Label
|
||||
{
|
||||
id: label;
|
||||
anchors {
|
||||
top: parent.top;
|
||||
@ -57,5 +56,6 @@ UM.PointingRectangle {
|
||||
textFormat: Text.RichText
|
||||
font: UM.Theme.getFont("default");
|
||||
color: UM.Theme.getColor("tooltip_text");
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ Item
|
||||
id: extruderCurrentTemperature
|
||||
text: Math.round(extruderModel.hotendTemperature) + "°C"
|
||||
color: UM.Theme.getColor("text")
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
anchors.right: extruderTargetTemperature.left
|
||||
anchors.top: parent.top
|
||||
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||
|
@ -67,7 +67,7 @@ Item
|
||||
{
|
||||
id: bedCurrentTemperature
|
||||
text: printerModel != null ? printerModel.bedTemperature + "°C" : ""
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
color: UM.Theme.getColor("text")
|
||||
anchors.right: bedTargetTemperature.left
|
||||
anchors.top: parent.top
|
||||
|
@ -31,7 +31,7 @@ Item
|
||||
Label
|
||||
{
|
||||
id: outputDeviceNameLabel
|
||||
font: UM.Theme.getFont("large")
|
||||
font: UM.Theme.getFont("large_bold")
|
||||
color: UM.Theme.getColor("text")
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
@ -11,7 +11,7 @@ Cura.ExpandablePopup
|
||||
{
|
||||
id: machineSelector
|
||||
|
||||
property bool isNetworkPrinter: Cura.MachineManager.activeMachineNetworkKey != ""
|
||||
property bool isNetworkPrinter: Cura.MachineManager.activeMachineHasRemoteConnection
|
||||
property bool isPrinterConnected: Cura.MachineManager.printerConnected
|
||||
property var outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
|
||||
|
||||
@ -93,11 +93,19 @@ Cura.ExpandablePopup
|
||||
width: scroll.width - scroll.leftPadding - scroll.rightPadding
|
||||
property real maximumHeight: UM.Theme.getSize("machine_selector_widget_content").height - buttonRow.height
|
||||
|
||||
onHeightChanged:
|
||||
// We use an extra property here, since we only want to to be informed about the content size changes.
|
||||
onContentHeightChanged:
|
||||
{
|
||||
scroll.height = Math.min(height, maximumHeight)
|
||||
scroll.height = Math.min(contentHeight, maximumHeight)
|
||||
popup.height = scroll.height + buttonRow.height
|
||||
}
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
scroll.height = Math.min(contentHeight, maximumHeight)
|
||||
popup.height = scroll.height + buttonRow.height
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,78 +7,40 @@ import QtQuick.Controls 2.3
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
Column
|
||||
ListView
|
||||
{
|
||||
id: machineSelectorList
|
||||
id: listView
|
||||
model: Cura.GlobalStacksModel {}
|
||||
section.property: "hasRemoteConnection"
|
||||
property real contentHeight: childrenRect.height
|
||||
|
||||
Label
|
||||
section.delegate: Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Connected printers")
|
||||
visible: networkedPrintersModel.items.length > 0
|
||||
text: section == "true" ? catalog.i18nc("@label", "Connected printers") : catalog.i18nc("@label", "Preset printers")
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("action_button").height
|
||||
leftPadding: UM.Theme.getSize("default_margin").width
|
||||
height: visible ? contentHeight + 2 * UM.Theme.getSize("default_margin").height : 0
|
||||
renderType: Text.NativeRendering
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Repeater
|
||||
delegate: MachineSelectorButton
|
||||
{
|
||||
id: networkedPrinters
|
||||
text: model.name
|
||||
width: listView.width
|
||||
outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
|
||||
|
||||
model: UM.ContainerStacksModel
|
||||
checked:
|
||||
{
|
||||
id: networkedPrintersModel
|
||||
filter:
|
||||
// If the machine has a remote connection
|
||||
var result = Cura.MachineManager.activeMachineId == model.id
|
||||
if (Cura.MachineManager.activeMachineHasRemoteConnection)
|
||||
{
|
||||
"type": "machine", "um_network_key": "*", "hidden": "False"
|
||||
result |= Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["connect_group_name"]
|
||||
}
|
||||
}
|
||||
|
||||
delegate: MachineSelectorButton
|
||||
{
|
||||
text: model.metadata["connect_group_name"]
|
||||
checked: Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["connect_group_name"]
|
||||
outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.MachineManager
|
||||
onActiveMachineNetworkGroupNameChanged: checked = Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["connect_group_name"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
text: catalog.i18nc("@label", "Preset printers")
|
||||
visible: virtualPrintersModel.items.length > 0
|
||||
leftPadding: UM.Theme.getSize("default_margin").width
|
||||
height: visible ? contentHeight + 2 * UM.Theme.getSize("default_margin").height : 0
|
||||
renderType: Text.NativeRendering
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Repeater
|
||||
{
|
||||
id: virtualPrinters
|
||||
|
||||
model: UM.ContainerStacksModel
|
||||
{
|
||||
id: virtualPrintersModel
|
||||
filter:
|
||||
{
|
||||
"type": "machine", "um_network_key": null
|
||||
}
|
||||
}
|
||||
|
||||
delegate: MachineSelectorButton
|
||||
{
|
||||
text: model.name
|
||||
checked: Cura.MachineManager.activeMachineId == model.id
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ Item
|
||||
{
|
||||
anchors.fill: parent
|
||||
color: UM.Theme.getColor("printer_type_label_background")
|
||||
radius: UM.Theme.getSize("checkbox_radius").width
|
||||
}
|
||||
|
||||
Label
|
||||
|
@ -73,7 +73,7 @@ Button
|
||||
text: definition.label
|
||||
textFormat: Text.PlainText
|
||||
renderType: Text.NativeRendering
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium_bold")
|
||||
color:
|
||||
{
|
||||
if (!base.enabled)
|
||||
|
63
resources/qml/ToolTip.qml
Normal file
63
resources/qml/ToolTip.qml
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import UM 1.0 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
ToolTip
|
||||
{
|
||||
enum ContentAlignment
|
||||
{
|
||||
AlignLeft,
|
||||
AlignRight
|
||||
}
|
||||
|
||||
// Defines the alignment of the content, by default to the left
|
||||
property int contentAlignment: Cura.ToolTip.ContentAlignment.AlignRight
|
||||
|
||||
property alias tooltipText: tooltip.text
|
||||
property var targetPoint: Qt.point(parent.x, y + Math.round(height/2))
|
||||
|
||||
id: tooltip
|
||||
text: ""
|
||||
delay: 500
|
||||
font: UM.Theme.getFont("default")
|
||||
|
||||
// If the text is not set, just set the height to 0 to prevent it from showing
|
||||
height: text != "" ? label.contentHeight + 2 * UM.Theme.getSize("thin_margin").width: 0
|
||||
|
||||
x:
|
||||
{
|
||||
if (contentAlignment == Cura.ToolTip.ContentAlignment.AlignLeft)
|
||||
{
|
||||
return (label.width + Math.round(UM.Theme.getSize("default_arrow").width * 1.2) + padding * 2) * -1
|
||||
}
|
||||
return parent.width + Math.round(UM.Theme.getSize("default_arrow").width * 1.2 + padding)
|
||||
}
|
||||
|
||||
y: Math.round(parent.height / 2 - label.height / 2 ) - padding
|
||||
|
||||
padding: UM.Theme.getSize("thin_margin").width
|
||||
|
||||
background: UM.PointingRectangle
|
||||
{
|
||||
id: backgroundRect
|
||||
color: UM.Theme.getColor("tooltip")
|
||||
target: Qt.point(targetPoint.x - tooltip.x, targetPoint.y - tooltip.y)
|
||||
arrowSize: UM.Theme.getSize("default_arrow").width
|
||||
}
|
||||
|
||||
contentItem: Label
|
||||
{
|
||||
id: label
|
||||
text: tooltip.text
|
||||
font: tooltip.font
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Text.RichText
|
||||
color: UM.Theme.getColor("tooltip_text")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
}
|
@ -96,4 +96,11 @@ Button
|
||||
height: UM.Theme.getSize("button_icon").height
|
||||
}
|
||||
}
|
||||
|
||||
Cura.ToolTip
|
||||
{
|
||||
id: tooltip
|
||||
tooltipText: base.text
|
||||
visible: base.hovered
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ Cura.ExpandablePopup
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
height: parent.height
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text_medium")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
@ -68,7 +68,7 @@ Cura.ExpandablePopup
|
||||
}
|
||||
height: parent.height
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("default")
|
||||
font: UM.Theme.getFont("medium")
|
||||
color: UM.Theme.getColor("text")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
@ -15,4 +15,5 @@ ViewsSelector 1.0 ViewsSelector.qml
|
||||
ToolbarButton 1.0 ToolbarButton.qml
|
||||
SettingView 1.0 SettingView.qml
|
||||
ProfileMenu 1.0 ProfileMenu.qml
|
||||
CheckBox 1.0 CheckBox.qml
|
||||
CheckBoxWithTooltip 1.0 CheckBoxWithTooltip.qml
|
||||
ToolTip 1.0 ToolTip.qml
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user