mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-11-29 22:01:14 -07:00
Merge branch 'master' into CURA-7509_plugin_versions_on_crash
This commit is contained in:
commit
039823e68e
57 changed files with 10668 additions and 239 deletions
|
|
@ -103,6 +103,11 @@ class Account(QObject):
|
|||
self._authorization_service.accessTokenChanged.connect(self._onAccessTokenChanged)
|
||||
self._authorization_service.loadAuthDataFromPreferences()
|
||||
|
||||
|
||||
@pyqtProperty(int, notify=syncStateChanged)
|
||||
def syncState(self):
|
||||
return self._sync_state
|
||||
|
||||
def setSyncState(self, service_name: str, state: int) -> None:
|
||||
""" Can be used to register sync services and update account sync states
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
from typing import Optional
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, QTimer, pyqtProperty
|
||||
from PyQt5.QtNetwork import QNetworkReply
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
|
||||
|
||||
from UM.TaskManagement.HttpRequestManager import HttpRequestManager
|
||||
from cura.UltimakerCloud import UltimakerCloudConstants
|
||||
|
||||
|
||||
class ConnectionStatus(QObject):
|
||||
"""Status info for some web services"""
|
||||
"""Provides an estimation of whether internet is reachable
|
||||
|
||||
UPDATE_INTERVAL = 10.0 # seconds
|
||||
ULTIMAKER_CLOUD_STATUS_URL = UltimakerCloudConstants.CuraCloudAPIRoot + "/connect/v1/"
|
||||
Estimation is updated with every request through HttpRequestManager.
|
||||
Acts as a proxy to HttpRequestManager.internetReachableChanged without
|
||||
exposing the HttpRequestManager in its entirety.
|
||||
"""
|
||||
|
||||
__instance = None # type: Optional[ConnectionStatus]
|
||||
|
||||
internetReachableChanged = pyqtSignal()
|
||||
umCloudReachableChanged = pyqtSignal()
|
||||
|
||||
@classmethod
|
||||
def getInstance(cls, *args, **kwargs) -> "ConnectionStatus":
|
||||
|
|
@ -24,41 +23,19 @@ class ConnectionStatus(QObject):
|
|||
cls.__instance = cls(*args, **kwargs)
|
||||
return cls.__instance
|
||||
|
||||
def __init__(self, parent: Optional["QObject"] = None):
|
||||
def __init__(self, parent: Optional["QObject"] = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
self._http = HttpRequestManager.getInstance()
|
||||
self._statuses = {
|
||||
self.ULTIMAKER_CLOUD_STATUS_URL: True,
|
||||
"http://example.com": True
|
||||
}
|
||||
manager = HttpRequestManager.getInstance()
|
||||
self._is_internet_reachable = manager.isInternetReachable # type: bool
|
||||
manager.internetReachableChanged.connect(self._onInternetReachableChanged)
|
||||
|
||||
# Create a timer for automatic updates
|
||||
self._update_timer = QTimer()
|
||||
self._update_timer.setInterval(int(self.UPDATE_INTERVAL * 1000))
|
||||
# The timer is restarted automatically
|
||||
self._update_timer.setSingleShot(False)
|
||||
self._update_timer.timeout.connect(self._update)
|
||||
self._update_timer.start()
|
||||
|
||||
@pyqtProperty(bool, notify=internetReachableChanged)
|
||||
@pyqtProperty(bool, notify = internetReachableChanged)
|
||||
def isInternetReachable(self) -> bool:
|
||||
# Is any of the test urls reachable?
|
||||
return any(self._statuses.values())
|
||||
return self._is_internet_reachable
|
||||
|
||||
def _update(self):
|
||||
for url in self._statuses.keys():
|
||||
self._http.get(
|
||||
url = url,
|
||||
callback = self._statusCallback,
|
||||
error_callback = self._statusCallback,
|
||||
timeout = 5
|
||||
)
|
||||
|
||||
def _statusCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError = None):
|
||||
url = reply.request().url().toString()
|
||||
prev_statuses = self._statuses.copy()
|
||||
self._statuses[url] = HttpRequestManager.replyIndicatesSuccess(reply, error)
|
||||
|
||||
if any(self._statuses.values()) != any(prev_statuses.values()):
|
||||
def _onInternetReachableChanged(self, reachable: bool):
|
||||
if reachable != self._is_internet_reachable:
|
||||
self._is_internet_reachable = reachable
|
||||
self.internetReachableChanged.emit()
|
||||
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ class CuraApplication(QtApplication):
|
|||
self._first_start_machine_actions_model = None
|
||||
self._welcome_pages_model = WelcomePagesModel(self, parent = self)
|
||||
self._add_printer_pages_model = AddPrinterPagesModel(self, parent = self)
|
||||
self._add_printer_pages_model_without_cancel = AddPrinterPagesModel(self, parent = self)
|
||||
self._whats_new_pages_model = WhatsNewPagesModel(self, parent = self)
|
||||
self._text_manager = TextManager(parent = self)
|
||||
|
||||
|
|
@ -261,6 +262,10 @@ class CuraApplication(QtApplication):
|
|||
def ultimakerCloudAccountRootUrl(self) -> str:
|
||||
return UltimakerCloudConstants.CuraCloudAccountAPIRoot
|
||||
|
||||
@pyqtProperty(str, constant=True)
|
||||
def ultimakerDigitalFactoryUrl(self) -> str:
|
||||
return UltimakerCloudConstants.CuraDigitalFactoryURL
|
||||
|
||||
def addCommandLineOptions(self):
|
||||
"""Adds command line options to the command line parser.
|
||||
|
||||
|
|
@ -647,7 +652,7 @@ class CuraApplication(QtApplication):
|
|||
return self._global_container_stack
|
||||
|
||||
@override(Application)
|
||||
def setGlobalContainerStack(self, stack: "GlobalStack") -> None:
|
||||
def setGlobalContainerStack(self, stack: Optional["GlobalStack"]) -> None:
|
||||
self._setLoadingHint(self._i18n_catalog.i18nc("@info:progress", "Initializing Active Machine..."))
|
||||
super().setGlobalContainerStack(stack)
|
||||
|
||||
|
|
@ -812,6 +817,7 @@ class CuraApplication(QtApplication):
|
|||
self._output_device_manager.start()
|
||||
self._welcome_pages_model.initialize()
|
||||
self._add_printer_pages_model.initialize()
|
||||
self._add_printer_pages_model_without_cancel.initialize(cancellable = False)
|
||||
self._whats_new_pages_model.initialize()
|
||||
|
||||
# Detect in which mode to run and execute that mode
|
||||
|
|
@ -849,6 +855,7 @@ class CuraApplication(QtApplication):
|
|||
self.callLater(self._openFile, file_name)
|
||||
|
||||
initializationFinished = pyqtSignal()
|
||||
showAddPrintersUncancellableDialog = pyqtSignal() # Used to show the add printers dialog with a greyed background
|
||||
|
||||
def runWithoutGUI(self):
|
||||
"""Run Cura without GUI elements and interaction (server mode)."""
|
||||
|
|
@ -939,6 +946,10 @@ class CuraApplication(QtApplication):
|
|||
def getAddPrinterPagesModel(self, *args) -> "AddPrinterPagesModel":
|
||||
return self._add_printer_pages_model
|
||||
|
||||
@pyqtSlot(result = QObject)
|
||||
def getAddPrinterPagesModelWithoutCancel(self, *args) -> "AddPrinterPagesModel":
|
||||
return self._add_printer_pages_model_without_cancel
|
||||
|
||||
@pyqtSlot(result = QObject)
|
||||
def getWhatsNewPagesModel(self, *args) -> "WhatsNewPagesModel":
|
||||
return self._whats_new_pages_model
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ class BaseMaterialsModel(ListModel):
|
|||
|
||||
# Update the available materials (ContainerNode) for the current active machine and extruder setup.
|
||||
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
||||
if not global_stack.hasMaterials:
|
||||
if not global_stack or not global_stack.hasMaterials:
|
||||
return # There are no materials for this machine, so nothing to do.
|
||||
extruder_list = global_stack.extruderList
|
||||
if self._extruder_position > len(extruder_list):
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ from enum import IntEnum
|
|||
from threading import Thread
|
||||
from typing import Union
|
||||
|
||||
from UM.Logger import Logger
|
||||
|
||||
MYPY = False
|
||||
if MYPY:
|
||||
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
|
||||
|
|
@ -38,8 +40,10 @@ class FirmwareUpdater(QObject):
|
|||
return
|
||||
|
||||
self._setFirmwareUpdateState(FirmwareUpdateState.updating)
|
||||
|
||||
self._update_firmware_thread.start()
|
||||
try:
|
||||
self._update_firmware_thread.start()
|
||||
except RuntimeError:
|
||||
Logger.warning("Could not start the update thread, since it's still running!")
|
||||
|
||||
def _updateFirmware(self) -> None:
|
||||
raise NotImplementedError("_updateFirmware needs to be implemented")
|
||||
|
|
|
|||
|
|
@ -290,9 +290,15 @@ class MachineManager(QObject):
|
|||
self.activeStackValueChanged.emit()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def setActiveMachine(self, stack_id: str) -> None:
|
||||
def setActiveMachine(self, stack_id: Optional[str]) -> None:
|
||||
self.blurSettings.emit() # Ensure no-one has focus.
|
||||
|
||||
if not stack_id:
|
||||
self._application.setGlobalContainerStack(None)
|
||||
self.globalContainerChanged.emit()
|
||||
self._application.showAddPrintersUncancellableDialog.emit()
|
||||
return
|
||||
|
||||
container_registry = CuraContainerRegistry.getInstance()
|
||||
containers = container_registry.findContainerStacks(id = stack_id)
|
||||
if not containers:
|
||||
|
|
@ -721,6 +727,8 @@ class MachineManager(QObject):
|
|||
other_machine_stacks = [s for s in machine_stacks if s["id"] != machine_id]
|
||||
if other_machine_stacks:
|
||||
self.setActiveMachine(other_machine_stacks[0]["id"])
|
||||
else:
|
||||
self.setActiveMachine(None)
|
||||
|
||||
metadatas = CuraContainerRegistry.getInstance().findContainerStacksMetadata(id = machine_id)
|
||||
if not metadatas:
|
||||
|
|
|
|||
|
|
@ -10,12 +10,11 @@ from .WelcomePagesModel import WelcomePagesModel
|
|||
#
|
||||
class AddPrinterPagesModel(WelcomePagesModel):
|
||||
|
||||
def initialize(self) -> None:
|
||||
def initialize(self, cancellable: bool = True) -> None:
|
||||
self._pages.append({"id": "add_network_or_local_printer",
|
||||
"page_url": self._getBuiltinWelcomePagePath("AddNetworkOrLocalPrinterContent.qml"),
|
||||
"next_page_id": "machine_actions",
|
||||
"next_page_button_text": self._catalog.i18nc("@action:button", "Add"),
|
||||
"previous_page_button_text": self._catalog.i18nc("@action:button", "Cancel"),
|
||||
})
|
||||
self._pages.append({"id": "add_printer_by_ip",
|
||||
"page_url": self._getBuiltinWelcomePagePath("AddPrinterByIpContent.qml"),
|
||||
|
|
@ -30,6 +29,9 @@ class AddPrinterPagesModel(WelcomePagesModel):
|
|||
"page_url": self._getBuiltinWelcomePagePath("FirstStartMachineActionsContent.qml"),
|
||||
"should_show_function": self.shouldShowMachineActions,
|
||||
})
|
||||
if cancellable:
|
||||
self._pages[0]["previous_page_button_text"] = self._catalog.i18nc("@action:button", "Cancel")
|
||||
|
||||
self.setItems(self._pages)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" # type: str
|
||||
DEFAULT_CLOUD_API_VERSION = "1" # type: str
|
||||
DEFAULT_CLOUD_ACCOUNT_API_ROOT = "https://account.ultimaker.com" # type: str
|
||||
DEFAULT_DIGITAL_FACTORY_URL = "https://digitalfactory.ultimaker.com" # type: str
|
||||
|
||||
# Container Metadata keys
|
||||
META_UM_LINKED_TO_ACCOUNT = "um_linked_to_account"
|
||||
|
|
@ -32,3 +33,10 @@ try:
|
|||
CuraCloudAccountAPIRoot = DEFAULT_CLOUD_ACCOUNT_API_ROOT
|
||||
except ImportError:
|
||||
CuraCloudAccountAPIRoot = DEFAULT_CLOUD_ACCOUNT_API_ROOT
|
||||
|
||||
try:
|
||||
from cura.CuraVersion import CuraDigitalFactoryURL # type: ignore
|
||||
if CuraDigitalFactoryURL == "":
|
||||
CuraDigitalFactoryURL = DEFAULT_DIGITAL_FACTORY_URL
|
||||
except ImportError:
|
||||
CuraDigitalFactoryURL = DEFAULT_DIGITAL_FACTORY_URL
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue