mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-08 07:27:29 -06:00
CURA-5330 Fix code style and typing in Toolbox plugin
This commit is contained in:
parent
0a21ce44b0
commit
eb65a11e18
2 changed files with 47 additions and 44 deletions
|
@ -9,4 +9,4 @@ def getMetaData():
|
||||||
|
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
return {"extension": Toolbox.Toolbox()}
|
return {"extension": Toolbox.Toolbox(app)}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Toolbox is released under the terms of the LGPLv3 or higher.
|
# Toolbox is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from typing import Dict, Optional, Union, Any
|
from typing import Dict, Optional, Union, Any, cast
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import platform
|
import platform
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrl, QObject, pyqtProperty, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import QUrl, QObject, pyqtProperty, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||||
|
@ -14,6 +15,7 @@ from UM.Application import Application
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
from UM.Extension import Extension
|
from UM.Extension import Extension
|
||||||
|
from UM.Qt.ListModel import ListModel
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
from UM.Version import Version
|
from UM.Version import Version
|
||||||
|
|
||||||
|
@ -31,40 +33,38 @@ class Toolbox(QObject, Extension):
|
||||||
DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com"
|
DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com"
|
||||||
DEFAULT_CLOUD_API_VERSION = 1
|
DEFAULT_CLOUD_API_VERSION = 1
|
||||||
|
|
||||||
def __init__(self, parent=None) -> None:
|
def __init__(self, application: Application, parent=None) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self._application = Application.getInstance()
|
self._application = application
|
||||||
self._package_manager = None
|
|
||||||
self._plugin_registry = Application.getInstance().getPluginRegistry()
|
|
||||||
|
|
||||||
self._sdk_version = None
|
self._sdk_version = None # type: Optional[int]
|
||||||
self._cloud_api_version = None
|
self._cloud_api_version = None # type: Optional[int]
|
||||||
self._cloud_api_root = None
|
self._cloud_api_root = None # type: Optional[str]
|
||||||
self._api_url = None
|
self._api_url = None # type: Optional[str]
|
||||||
|
|
||||||
# Network:
|
# Network:
|
||||||
self._get_packages_request = None
|
self._get_packages_request = None
|
||||||
self._get_showcase_request = None
|
self._get_showcase_request = None
|
||||||
self._download_request = None
|
self._download_request = None
|
||||||
self._download_reply = None
|
self._download_reply = None
|
||||||
self._download_progress = 0
|
self._download_progress = 0 # type: float
|
||||||
self._is_downloading = False
|
self._is_downloading = False
|
||||||
self._network_manager = None
|
self._network_manager = None
|
||||||
self._request_header = [
|
self._request_header = [
|
||||||
b"User-Agent",
|
b"User-Agent",
|
||||||
str.encode(
|
str.encode(
|
||||||
"%s/%s (%s %s)" % (
|
"%s/%s (%s %s)" % (
|
||||||
Application.getInstance().getApplicationName(),
|
self._application.getApplicationName(),
|
||||||
Application.getInstance().getVersion(),
|
self._application.getVersion(),
|
||||||
platform.system(),
|
platform.system(),
|
||||||
platform.machine(),
|
platform.machine(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self._request_urls = {}
|
self._request_urls = {} # type: Dict[str, QUrl]
|
||||||
self._to_update = [] # Package_ids that are waiting to be updated
|
self._to_update = [] # type: List[str] # Package_ids that are waiting to be updated
|
||||||
self._old_plugin_ids = []
|
self._old_plugin_ids = [] # type: List[str]
|
||||||
|
|
||||||
# Data:
|
# Data:
|
||||||
self._metadata = {
|
self._metadata = {
|
||||||
|
@ -76,7 +76,7 @@ class Toolbox(QObject, Extension):
|
||||||
"materials_showcase": [],
|
"materials_showcase": [],
|
||||||
"materials_available": [],
|
"materials_available": [],
|
||||||
"materials_installed": []
|
"materials_installed": []
|
||||||
}
|
} # type: Dict[str, List[Any]]
|
||||||
|
|
||||||
# Models:
|
# Models:
|
||||||
self._models = {
|
self._models = {
|
||||||
|
@ -88,7 +88,7 @@ class Toolbox(QObject, Extension):
|
||||||
"materials_showcase": AuthorsModel(self),
|
"materials_showcase": AuthorsModel(self),
|
||||||
"materials_available": PackagesModel(self),
|
"materials_available": PackagesModel(self),
|
||||||
"materials_installed": PackagesModel(self)
|
"materials_installed": PackagesModel(self)
|
||||||
}
|
} # type: Dict[str, ListModel]
|
||||||
|
|
||||||
# These properties are for keeping track of the UI state:
|
# These properties are for keeping track of the UI state:
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
@ -103,7 +103,7 @@ class Toolbox(QObject, Extension):
|
||||||
|
|
||||||
# Active package refers to which package is currently being downloaded,
|
# Active package refers to which package is currently being downloaded,
|
||||||
# installed, or otherwise modified.
|
# installed, or otherwise modified.
|
||||||
self._active_package = None
|
self._active_package = None # type: Optional[Dict[str, Any]]
|
||||||
|
|
||||||
self._dialog = None
|
self._dialog = None
|
||||||
self._restart_required = False
|
self._restart_required = False
|
||||||
|
@ -114,7 +114,7 @@ class Toolbox(QObject, Extension):
|
||||||
self._license_dialog_plugin_file_location = ""
|
self._license_dialog_plugin_file_location = ""
|
||||||
self._restart_dialog_message = ""
|
self._restart_dialog_message = ""
|
||||||
|
|
||||||
Application.getInstance().initializationFinished.connect(self._onAppInitialized)
|
self._application.initializationFinished.connect(self._onAppInitialized)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,7 +156,8 @@ class Toolbox(QObject, Extension):
|
||||||
# This is a plugin, so most of the components required are not ready when
|
# This is a plugin, so most of the components required are not ready when
|
||||||
# this is initialized. Therefore, we wait until the application is ready.
|
# this is initialized. Therefore, we wait until the application is ready.
|
||||||
def _onAppInitialized(self) -> None:
|
def _onAppInitialized(self) -> None:
|
||||||
self._package_manager = Application.getInstance().getPackageManager()
|
self._plugin_registry = self._application.getPluginRegistry()
|
||||||
|
self._package_manager = self._application.getPackageManager()
|
||||||
self._sdk_version = self._getSDKVersion()
|
self._sdk_version = self._getSDKVersion()
|
||||||
self._cloud_api_version = self._getCloudAPIVersion()
|
self._cloud_api_version = self._getCloudAPIVersion()
|
||||||
self._cloud_api_root = self._getCloudAPIRoot()
|
self._cloud_api_root = self._getCloudAPIRoot()
|
||||||
|
@ -178,31 +179,31 @@ class Toolbox(QObject, Extension):
|
||||||
def _getCloudAPIRoot(self) -> str:
|
def _getCloudAPIRoot(self) -> str:
|
||||||
if not hasattr(cura, "CuraVersion"):
|
if not hasattr(cura, "CuraVersion"):
|
||||||
return self.DEFAULT_CLOUD_API_ROOT
|
return self.DEFAULT_CLOUD_API_ROOT
|
||||||
if not hasattr(cura.CuraVersion, "CuraCloudAPIRoot"):
|
if not hasattr(cura.CuraVersion, "CuraCloudAPIRoot"): # type: ignore
|
||||||
return self.DEFAULT_CLOUD_API_ROOT
|
return self.DEFAULT_CLOUD_API_ROOT
|
||||||
if not cura.CuraVersion.CuraCloudAPIRoot:
|
if not cura.CuraVersion.CuraCloudAPIRoot: # type: ignore
|
||||||
return self.DEFAULT_CLOUD_API_ROOT
|
return self.DEFAULT_CLOUD_API_ROOT
|
||||||
return cura.CuraVersion.CuraCloudAPIRoot
|
return cura.CuraVersion.CuraCloudAPIRoot # type: ignore
|
||||||
|
|
||||||
# Get the cloud API version from CuraVersion
|
# Get the cloud API version from CuraVersion
|
||||||
def _getCloudAPIVersion(self) -> int:
|
def _getCloudAPIVersion(self) -> int:
|
||||||
if not hasattr(cura, "CuraVersion"):
|
if not hasattr(cura, "CuraVersion"):
|
||||||
return self.DEFAULT_CLOUD_API_VERSION
|
return self.DEFAULT_CLOUD_API_VERSION
|
||||||
if not hasattr(cura.CuraVersion, "CuraCloudAPIVersion"):
|
if not hasattr(cura.CuraVersion, "CuraCloudAPIVersion"): # type: ignore
|
||||||
return self.DEFAULT_CLOUD_API_VERSION
|
return self.DEFAULT_CLOUD_API_VERSION
|
||||||
if not cura.CuraVersion.CuraCloudAPIVersion:
|
if not cura.CuraVersion.CuraCloudAPIVersion: # type: ignore
|
||||||
return self.DEFAULT_CLOUD_API_VERSION
|
return self.DEFAULT_CLOUD_API_VERSION
|
||||||
return cura.CuraVersion.CuraCloudAPIVersion
|
return cura.CuraVersion.CuraCloudAPIVersion # type: ignore
|
||||||
|
|
||||||
# Get the packages version depending on Cura version settings.
|
# Get the packages version depending on Cura version settings.
|
||||||
def _getSDKVersion(self) -> int:
|
def _getSDKVersion(self) -> int:
|
||||||
if not hasattr(cura, "CuraVersion"):
|
if not hasattr(cura, "CuraVersion"):
|
||||||
return self._plugin_registry.APIVersion
|
return self._plugin_registry.APIVersion
|
||||||
if not hasattr(cura.CuraVersion, "CuraSDKVersion"):
|
if not hasattr(cura.CuraVersion, "CuraSDKVersion"): # type: ignore
|
||||||
return self._plugin_registry.APIVersion
|
return self._plugin_registry.APIVersion
|
||||||
if not cura.CuraVersion.CuraSDKVersion:
|
if not cura.CuraVersion.CuraSDKVersion: # type: ignore
|
||||||
return self._plugin_registry.APIVersion
|
return self._plugin_registry.APIVersion
|
||||||
return cura.CuraVersion.CuraSDKVersion
|
return cura.CuraVersion.CuraSDKVersion # type: ignore
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def browsePackages(self) -> None:
|
def browsePackages(self) -> None:
|
||||||
|
@ -213,6 +214,7 @@ class Toolbox(QObject, Extension):
|
||||||
self._network_manager.finished.disconnect(self._onRequestFinished)
|
self._network_manager.finished.disconnect(self._onRequestFinished)
|
||||||
self._network_manager.networkAccessibleChanged.disconnect(self._onNetworkAccessibleChanged)
|
self._network_manager.networkAccessibleChanged.disconnect(self._onNetworkAccessibleChanged)
|
||||||
self._network_manager = QNetworkAccessManager()
|
self._network_manager = QNetworkAccessManager()
|
||||||
|
assert(self._network_manager is not None)
|
||||||
self._network_manager.finished.connect(self._onRequestFinished)
|
self._network_manager.finished.connect(self._onRequestFinished)
|
||||||
self._network_manager.networkAccessibleChanged.connect(self._onNetworkAccessibleChanged)
|
self._network_manager.networkAccessibleChanged.connect(self._onNetworkAccessibleChanged)
|
||||||
|
|
||||||
|
@ -235,11 +237,11 @@ class Toolbox(QObject, Extension):
|
||||||
def _createDialog(self, qml_name: str) -> Optional[QObject]:
|
def _createDialog(self, qml_name: str) -> Optional[QObject]:
|
||||||
Logger.log("d", "Toolbox: Creating dialog [%s].", qml_name)
|
Logger.log("d", "Toolbox: Creating dialog [%s].", qml_name)
|
||||||
path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "resources", "qml", qml_name)
|
path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "resources", "qml", qml_name)
|
||||||
dialog = Application.getInstance().createQmlComponent(path, {"toolbox": self})
|
dialog = self._application.createQmlComponent(path, {"toolbox": self})
|
||||||
return dialog
|
return dialog
|
||||||
|
|
||||||
|
|
||||||
def _convertPluginMetadata(self, plugin: dict) -> dict:
|
def _convertPluginMetadata(self, plugin: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
formatted = {
|
formatted = {
|
||||||
"package_id": plugin["id"],
|
"package_id": plugin["id"],
|
||||||
"package_type": "plugin",
|
"package_type": "plugin",
|
||||||
|
@ -265,7 +267,7 @@ class Toolbox(QObject, Extension):
|
||||||
scheduled_to_remove_package_ids = self._package_manager.getToRemovePackageIDs()
|
scheduled_to_remove_package_ids = self._package_manager.getToRemovePackageIDs()
|
||||||
|
|
||||||
self._old_plugin_ids = []
|
self._old_plugin_ids = []
|
||||||
self._old_plugin_metadata = []
|
self._old_plugin_metadata = [] # type: List[Dict[str, Any]]
|
||||||
|
|
||||||
for plugin_id in old_plugin_ids:
|
for plugin_id in old_plugin_ids:
|
||||||
# Neither the installed packages nor the packages that are scheduled to remove are old plugins
|
# Neither the installed packages nor the packages that are scheduled to remove are old plugins
|
||||||
|
@ -354,7 +356,7 @@ class Toolbox(QObject, Extension):
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def restart(self):
|
def restart(self):
|
||||||
CuraApplication.getInstance().windowClosed()
|
cast(CuraApplication, self._application).windowClosed()
|
||||||
|
|
||||||
def getRemotePackage(self, package_id: str) -> Optional[Dict]:
|
def getRemotePackage(self, package_id: str) -> Optional[Dict]:
|
||||||
# TODO: make the lookup in a dict, not a loop. canUpdate is called for every item.
|
# TODO: make the lookup in a dict, not a loop. canUpdate is called for every item.
|
||||||
|
@ -432,7 +434,8 @@ class Toolbox(QObject, Extension):
|
||||||
Logger.log("i", "Toolbox: Requesting %s metadata from server.", type)
|
Logger.log("i", "Toolbox: Requesting %s metadata from server.", type)
|
||||||
request = QNetworkRequest(self._request_urls[type])
|
request = QNetworkRequest(self._request_urls[type])
|
||||||
request.setRawHeader(*self._request_header)
|
request.setRawHeader(*self._request_header)
|
||||||
self._network_manager.get(request)
|
if self._network_manager:
|
||||||
|
self._network_manager.get(request)
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def startDownload(self, url: str) -> None:
|
def startDownload(self, url: str) -> None:
|
||||||
|
@ -441,15 +444,15 @@ class Toolbox(QObject, Extension):
|
||||||
self._download_request = QNetworkRequest(url)
|
self._download_request = QNetworkRequest(url)
|
||||||
if hasattr(QNetworkRequest, "FollowRedirectsAttribute"):
|
if hasattr(QNetworkRequest, "FollowRedirectsAttribute"):
|
||||||
# Patch for Qt 5.6-5.8
|
# Patch for Qt 5.6-5.8
|
||||||
self._download_request.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True)
|
cast(QNetworkRequest, self._download_request).setAttribute(QNetworkRequest.FollowRedirectsAttribute, True)
|
||||||
if hasattr(QNetworkRequest, "RedirectPolicyAttribute"):
|
if hasattr(QNetworkRequest, "RedirectPolicyAttribute"):
|
||||||
# Patch for Qt 5.9+
|
# Patch for Qt 5.9+
|
||||||
self._download_request.setAttribute(QNetworkRequest.RedirectPolicyAttribute, True)
|
cast(QNetworkRequest, self._download_request).setAttribute(QNetworkRequest.RedirectPolicyAttribute, True)
|
||||||
self._download_request.setRawHeader(*self._request_header)
|
cast(QNetworkRequest, self._download_request).setRawHeader(*self._request_header)
|
||||||
self._download_reply = self._network_manager.get(self._download_request)
|
self._download_reply = cast(QNetworkAccessManager, self._network_manager).get(self._download_request)
|
||||||
self.setDownloadProgress(0)
|
self.setDownloadProgress(0)
|
||||||
self.setIsDownloading(True)
|
self.setIsDownloading(True)
|
||||||
self._download_reply.downloadProgress.connect(self._onDownloadProgress)
|
cast(QNetworkReply, self._download_reply).downloadProgress.connect(self._onDownloadProgress)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def cancelDownload(self) -> None:
|
def cancelDownload(self) -> None:
|
||||||
|
@ -551,12 +554,12 @@ class Toolbox(QObject, Extension):
|
||||||
self.setDownloadProgress(new_progress)
|
self.setDownloadProgress(new_progress)
|
||||||
if bytes_sent == bytes_total:
|
if bytes_sent == bytes_total:
|
||||||
self.setIsDownloading(False)
|
self.setIsDownloading(False)
|
||||||
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
|
cast(QNetworkReply, self._download_reply).downloadProgress.disconnect(self._onDownloadProgress)
|
||||||
# Must not delete the temporary file on Windows
|
# Must not delete the temporary file on Windows
|
||||||
self._temp_plugin_file = tempfile.NamedTemporaryFile(mode = "w+b", suffix = ".curapackage", delete = False)
|
self._temp_plugin_file = tempfile.NamedTemporaryFile(mode = "w+b", suffix = ".curapackage", delete = False)
|
||||||
file_path = self._temp_plugin_file.name
|
file_path = self._temp_plugin_file.name
|
||||||
# Write first and close, otherwise on Windows, it cannot read the file
|
# Write first and close, otherwise on Windows, it cannot read the file
|
||||||
self._temp_plugin_file.write(self._download_reply.readAll())
|
self._temp_plugin_file.write(cast(QNetworkReply, self._download_reply).readAll())
|
||||||
self._temp_plugin_file.close()
|
self._temp_plugin_file.close()
|
||||||
self._onDownloadComplete(file_path)
|
self._onDownloadComplete(file_path)
|
||||||
|
|
||||||
|
@ -577,13 +580,13 @@ class Toolbox(QObject, Extension):
|
||||||
|
|
||||||
# Getter & Setters for Properties:
|
# Getter & Setters for Properties:
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
def setDownloadProgress(self, progress: Union[int, float]) -> None:
|
def setDownloadProgress(self, progress: float) -> None:
|
||||||
if progress != self._download_progress:
|
if progress != self._download_progress:
|
||||||
self._download_progress = progress
|
self._download_progress = progress
|
||||||
self.onDownloadProgressChanged.emit()
|
self.onDownloadProgressChanged.emit()
|
||||||
|
|
||||||
@pyqtProperty(int, fset = setDownloadProgress, notify = onDownloadProgressChanged)
|
@pyqtProperty(int, fset = setDownloadProgress, notify = onDownloadProgressChanged)
|
||||||
def downloadProgress(self) -> int:
|
def downloadProgress(self) -> float:
|
||||||
return self._download_progress
|
return self._download_progress
|
||||||
|
|
||||||
def setIsDownloading(self, is_downloading: bool) -> None:
|
def setIsDownloading(self, is_downloading: bool) -> None:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue