mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-22 06:03:57 -06:00
Groundwork for installing/updating packages
Contributes to: CURA-8587
This commit is contained in:
parent
08067432c6
commit
3b3d986058
4 changed files with 73 additions and 14 deletions
|
@ -1,18 +1,21 @@
|
|||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import tempfile
|
||||
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, Qt
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
from typing import Dict, Optional, TYPE_CHECKING
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Qt.ListModel import ListModel
|
||||
from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope # To request JSON responses from the API.
|
||||
from UM.TaskManagement.HttpRequestManager import HttpRequestData # To request the package list from the API
|
||||
from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope
|
||||
from UM.TaskManagement.HttpRequestManager import HttpRequestData , HttpRequestManager
|
||||
from UM.Logger import Logger
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope # To make requests to the Ultimaker API with correct authorization.
|
||||
|
||||
from .PackageModel import PackageModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from PyQt5.QtCore import QObject
|
||||
|
||||
|
@ -24,6 +27,7 @@ class PackageList(ListModel):
|
|||
such as Packages obtained from Remote or Local source
|
||||
"""
|
||||
PackageRole = Qt.UserRole + 1
|
||||
DISK_WRITE_BUFFER_SIZE = 256 * 1024 # 256 KB
|
||||
|
||||
def __init__(self, parent: Optional["QObject"] = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
@ -33,6 +37,8 @@ class PackageList(ListModel):
|
|||
self._is_loading = False
|
||||
self._has_more = False
|
||||
self._has_footer = True
|
||||
self._to_install: Dict[str, str] = {}
|
||||
self.canInstallChanged.connect(self._install)
|
||||
|
||||
self._ongoing_request: Optional[HttpRequestData] = None
|
||||
self._scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance()))
|
||||
|
@ -105,13 +111,60 @@ class PackageList(ListModel):
|
|||
def _connectManageButtonSignals(self, package):
|
||||
package.installPackageTriggered.connect(self.installPackage)
|
||||
package.uninstallPackageTriggered.connect(self.uninstallPackage)
|
||||
package.updatePackageTriggered.connect(self.updatePackage)
|
||||
package.updatePackageTriggered.connect(self.installPackage)
|
||||
package.enablePackageTriggered.connect(self.enablePackage)
|
||||
package.disablePackageTriggered.connect(self.disablePackage)
|
||||
|
||||
def _getPackageModel(self, package_id: str) -> PackageModel:
|
||||
index = self.find("package", package_id)
|
||||
return self.getItem(index)["package"]
|
||||
|
||||
canInstallChanged = pyqtSignal(str, bool)
|
||||
|
||||
def download(self, package_id, url, update: bool = False):
|
||||
|
||||
def downloadFinished(reply: "QNetworkReply") -> None:
|
||||
self._downloadFinished(package_id, reply, update)
|
||||
|
||||
HttpRequestManager.getInstance().get(
|
||||
url,
|
||||
scope = self._scope,
|
||||
callback = downloadFinished
|
||||
)
|
||||
|
||||
def _downloadFinished(self, package_id: str, reply: "QNetworkReply", update: bool = False) -> None:
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(mode = "wb+", suffix = ".curapackage", delete = False) as temp_file:
|
||||
bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE)
|
||||
while bytes_read:
|
||||
temp_file.write(bytes_read)
|
||||
bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE)
|
||||
Logger.debug(f"Finished downloading {package_id} and stored it as {temp_file.name}")
|
||||
self._to_install[package_id] = temp_file.name
|
||||
self.canInstallChanged.emit(package_id, update)
|
||||
except IOError as e:
|
||||
Logger.logException("e", "Failed to write downloaded package to temp file", e)
|
||||
temp_file.close()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def installPackage(self, package_id):
|
||||
def installPackage(self, package_id: str) -> None:
|
||||
package = self._getPackageModel(package_id)
|
||||
url = package.download_url
|
||||
Logger.debug(f"Trying to download and install {package_id} from {url}")
|
||||
self.download(package_id, url)
|
||||
|
||||
def _install(self, package_id: str, update: bool = False) -> None:
|
||||
package_path = self._to_install.pop(package_id)
|
||||
Logger.debug(f"Installing {package_id}")
|
||||
to_be_installed = self._manager.installPackage(package_path) != None
|
||||
package = self._getPackageModel(package_id)
|
||||
if package.canUpdate and to_be_installed:
|
||||
package.canUpdate = False
|
||||
package.setManageInstallState(to_be_installed)
|
||||
if update:
|
||||
package.setIsUpdating(False)
|
||||
else:
|
||||
package.setIsInstalling(False)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def uninstallPackage(self, package_id):
|
||||
|
@ -119,7 +172,10 @@ class PackageList(ListModel):
|
|||
|
||||
@pyqtSlot(str)
|
||||
def updatePackage(self, package_id):
|
||||
Logger.debug(f"Updating {package_id}")
|
||||
package = self._getPackageModel(package_id)
|
||||
url = package.download_url
|
||||
Logger.debug(f"Trying to download and update {package_id} from {url}")
|
||||
self.download(package_id, url, True)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def enablePackage(self, package_id):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue