mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-23 06:33:55 -06:00
CURA-5137 Create the Cura Packages Model for the Toolbox.
Fetch the data from the new server and create the model for show in the toolbox.
This commit is contained in:
parent
89c27ae7f4
commit
3d452d334b
2 changed files with 101 additions and 23 deletions
71
plugins/Toolbox/Toolbox/CuraPackageModel.py
Normal file
71
plugins/Toolbox/Toolbox/CuraPackageModel.py
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal
|
||||||
|
|
||||||
|
from UM.Qt.ListModel import ListModel
|
||||||
|
|
||||||
|
## Model that holds cura packages. By setting the filter property the instances held by this model can be changed.
|
||||||
|
class CuraPackageModel(ListModel):
|
||||||
|
IdRole = Qt.UserRole + 1
|
||||||
|
TypeRole = Qt.UserRole + 2
|
||||||
|
NameRole = Qt.UserRole + 3
|
||||||
|
VersionRole = Qt.UserRole + 4
|
||||||
|
AuthorRole = Qt.UserRole + 5
|
||||||
|
DescriptionRole = Qt.UserRole + 6
|
||||||
|
IconURLRole = Qt.UserRole + 7
|
||||||
|
ImageURLsRole = Qt.UserRole + 8
|
||||||
|
|
||||||
|
def __init__(self, parent = None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self._packages_metadata = None
|
||||||
|
|
||||||
|
self.addRoleName(CuraPackageModel.IdRole, "id")
|
||||||
|
self.addRoleName(CuraPackageModel.TypeRole, "type")
|
||||||
|
self.addRoleName(CuraPackageModel.NameRole, "name")
|
||||||
|
self.addRoleName(CuraPackageModel.VersionRole, "version")
|
||||||
|
self.addRoleName(CuraPackageModel.AuthorRole, "author")
|
||||||
|
self.addRoleName(CuraPackageModel.DescriptionRole, "description")
|
||||||
|
self.addRoleName(CuraPackageModel.IconURLRole, "icon_url")
|
||||||
|
self.addRoleName(CuraPackageModel.ImageURLsRole, "image_urls")
|
||||||
|
|
||||||
|
# List of filters for queries. The result is the union of the each list of results.
|
||||||
|
self._filter = None # type: Dict[str,str]
|
||||||
|
|
||||||
|
def setPackagesMetaData(self, data):
|
||||||
|
self._packages_metadata = data
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _update(self):
|
||||||
|
items = []
|
||||||
|
|
||||||
|
for package in self._packages_metadata:
|
||||||
|
items.append({
|
||||||
|
"id": package["package_id"],
|
||||||
|
"type": package["package_type"],
|
||||||
|
"name": package["display_name"],
|
||||||
|
"version": package["package_version"],
|
||||||
|
"author": package["author"],
|
||||||
|
"description": package["description"],
|
||||||
|
"icon_url": package["icon_url"] if "icon_url" in package else None,
|
||||||
|
"image_urls": package["image_urls"]
|
||||||
|
})
|
||||||
|
|
||||||
|
items.sort(key = lambda k: k["name"])
|
||||||
|
self.setItems(items)
|
||||||
|
|
||||||
|
filterChanged = pyqtSignal()
|
||||||
|
|
||||||
|
## Set the filter of this model based on a string.
|
||||||
|
# \param filter_dict \type{Dict} Dictionary to do the filtering by.
|
||||||
|
def setFilter(self, filter_dict: Dict[str, str]) -> None:
|
||||||
|
if filter_dict != self._filter:
|
||||||
|
self._filter = filter_dict
|
||||||
|
self.filterChanged.emit()
|
||||||
|
|
||||||
|
@pyqtProperty("QVariantMap", fset = setFilter, notify = filterChanged)
|
||||||
|
def filter(self) -> Dict[str, str]:
|
||||||
|
return self._filter
|
|
@ -1,5 +1,6 @@
|
||||||
# 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
|
||||||
|
|
||||||
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
|
||||||
|
@ -21,6 +22,7 @@ import platform
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
|
from .CuraPackageModel import CuraPackageModel
|
||||||
|
|
||||||
i18n_catalog = i18nCatalog("cura")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
@ -32,16 +34,17 @@ class Toolbox(QObject, Extension):
|
||||||
self._api_version = 1
|
self._api_version = 1
|
||||||
self._api_url = "https://api-staging.ultimaker.com/cura-packages/v%s/" % self._api_version
|
self._api_url = "https://api-staging.ultimaker.com/cura-packages/v%s/" % self._api_version
|
||||||
|
|
||||||
self._plugin_list_request = None
|
self._package_list_request = None
|
||||||
self._download_plugin_request = None
|
self._download_plugin_request = None
|
||||||
|
|
||||||
self._download_plugin_reply = None
|
self._download_plugin_reply = None
|
||||||
|
|
||||||
self._network_manager = None
|
self._network_manager = None
|
||||||
self._plugin_registry = Application.getInstance().getPluginRegistry()
|
self._plugin_registry = Application.getInstance().getPluginRegistry()
|
||||||
|
self._packages_version_number = self._plugin_registry.APIVersion
|
||||||
|
|
||||||
self._plugins_metadata = []
|
self._packages_metadata = []
|
||||||
self._plugins_model = None
|
self._packages_model = None
|
||||||
|
|
||||||
# Can be 'installed' or 'available'
|
# Can be 'installed' or 'available'
|
||||||
self._view = "available"
|
self._view = "available"
|
||||||
|
@ -82,7 +85,7 @@ class Toolbox(QObject, Extension):
|
||||||
|
|
||||||
showLicenseDialog = pyqtSignal()
|
showLicenseDialog = pyqtSignal()
|
||||||
showRestartDialog = pyqtSignal()
|
showRestartDialog = pyqtSignal()
|
||||||
pluginsMetadataChanged = pyqtSignal()
|
packagesMetadataChanged = pyqtSignal()
|
||||||
onDownloadProgressChanged = pyqtSignal()
|
onDownloadProgressChanged = pyqtSignal()
|
||||||
onIsDownloadingChanged = pyqtSignal()
|
onIsDownloadingChanged = pyqtSignal()
|
||||||
restartRequiredChanged = pyqtSignal()
|
restartRequiredChanged = pyqtSignal()
|
||||||
|
@ -129,12 +132,11 @@ class Toolbox(QObject, Extension):
|
||||||
self._dialog.show()
|
self._dialog.show()
|
||||||
|
|
||||||
def requestPackageList(self):
|
def requestPackageList(self):
|
||||||
cura_version = 4
|
|
||||||
Logger.log("i", "Requesting package list")
|
Logger.log("i", "Requesting package list")
|
||||||
url = QUrl(self._api_url + "packages?cura_version={version}".format(version = cura_version))
|
url = QUrl("{base_url}packages?cura_version={version}".format(base_url = self._api_url, version = self._packages_version_number))
|
||||||
self._plugin_list_request = QNetworkRequest(url)
|
self._package_list_request = QNetworkRequest(url)
|
||||||
self._plugin_list_request.setRawHeader(*self._request_header)
|
self._package_list_request.setRawHeader(*self._request_header)
|
||||||
self._network_manager.get(self._plugin_list_request)
|
self._network_manager.get(self._package_list_request)
|
||||||
|
|
||||||
def _createDialog(self, qml_name):
|
def _createDialog(self, qml_name):
|
||||||
Logger.log("d", "Creating dialog [%s]", qml_name)
|
Logger.log("d", "Creating dialog [%s]", qml_name)
|
||||||
|
@ -218,7 +220,7 @@ class Toolbox(QObject, Extension):
|
||||||
result = PluginRegistry.getInstance().installPlugin("file://" + location)
|
result = PluginRegistry.getInstance().installPlugin("file://" + location)
|
||||||
|
|
||||||
self._newly_installed_plugin_ids.append(result["id"])
|
self._newly_installed_plugin_ids.append(result["id"])
|
||||||
self.pluginsMetadataChanged.emit()
|
self.packagesMetadataChanged.emit()
|
||||||
|
|
||||||
self.openRestartDialog(result["message"])
|
self.openRestartDialog(result["message"])
|
||||||
self._restart_required = True
|
self._restart_required = True
|
||||||
|
@ -229,7 +231,7 @@ class Toolbox(QObject, Extension):
|
||||||
result = PluginRegistry.getInstance().uninstallPlugin(plugin_id)
|
result = PluginRegistry.getInstance().uninstallPlugin(plugin_id)
|
||||||
|
|
||||||
self._newly_uninstalled_plugin_ids.append(result["id"])
|
self._newly_uninstalled_plugin_ids.append(result["id"])
|
||||||
self.pluginsMetadataChanged.emit()
|
self.packagesMetadataChanged.emit()
|
||||||
|
|
||||||
self._restart_required = True
|
self._restart_required = True
|
||||||
self.restartRequiredChanged.emit()
|
self.restartRequiredChanged.emit()
|
||||||
|
@ -239,13 +241,13 @@ class Toolbox(QObject, Extension):
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def enablePlugin(self, plugin_id):
|
def enablePlugin(self, plugin_id):
|
||||||
self._plugin_registry.enablePlugin(plugin_id)
|
self._plugin_registry.enablePlugin(plugin_id)
|
||||||
self.pluginsMetadataChanged.emit()
|
self.packagesMetadataChanged.emit()
|
||||||
Logger.log("i", "%s was set as 'active'", id)
|
Logger.log("i", "%s was set as 'active'", id)
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def disablePlugin(self, plugin_id):
|
def disablePlugin(self, plugin_id):
|
||||||
self._plugin_registry.disablePlugin(plugin_id)
|
self._plugin_registry.disablePlugin(plugin_id)
|
||||||
self.pluginsMetadataChanged.emit()
|
self.packagesMetadataChanged.emit()
|
||||||
Logger.log("i", "%s was set as 'deactive'", id)
|
Logger.log("i", "%s was set as 'deactive'", id)
|
||||||
|
|
||||||
@pyqtProperty(int, notify = onDownloadProgressChanged)
|
@pyqtProperty(int, notify = onDownloadProgressChanged)
|
||||||
|
@ -283,7 +285,7 @@ class Toolbox(QObject, Extension):
|
||||||
def setView(self, view = "available"):
|
def setView(self, view = "available"):
|
||||||
self._view = view
|
self._view = view
|
||||||
self.viewChanged.emit()
|
self.viewChanged.emit()
|
||||||
self.pluginsMetadataChanged.emit()
|
self.packagesMetadataChanged.emit()
|
||||||
|
|
||||||
@pyqtProperty(str, notify = viewChanged)
|
@pyqtProperty(str, notify = viewChanged)
|
||||||
def viewing(self):
|
def viewing(self):
|
||||||
|
@ -293,13 +295,13 @@ class Toolbox(QObject, Extension):
|
||||||
def setDetailView(self, item = ""):
|
def setDetailView(self, item = ""):
|
||||||
self._detail_view = item
|
self._detail_view = item
|
||||||
self.detailViewChanged.emit()
|
self.detailViewChanged.emit()
|
||||||
self.pluginsMetadataChanged.emit()
|
self.packagesMetadataChanged.emit()
|
||||||
|
|
||||||
@pyqtProperty(str, notify = detailViewChanged)
|
@pyqtProperty(str, notify = detailViewChanged)
|
||||||
def detailView(self):
|
def detailView(self):
|
||||||
return self._detail_view
|
return self._detail_view
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = pluginsMetadataChanged)
|
@pyqtProperty(QObject, notify = packagesMetadataChanged)
|
||||||
def pluginsModel(self):
|
def pluginsModel(self):
|
||||||
self._plugins_model = PluginsModel(None, self._view)
|
self._plugins_model = PluginsModel(None, self._view)
|
||||||
# self._plugins_model.update()
|
# self._plugins_model.update()
|
||||||
|
@ -311,20 +313,22 @@ class Toolbox(QObject, Extension):
|
||||||
if self._checkCanUpgrade(plugin["id"], plugin["version"]):
|
if self._checkCanUpgrade(plugin["id"], plugin["version"]):
|
||||||
plugin["can_upgrade"] = True
|
plugin["can_upgrade"] = True
|
||||||
|
|
||||||
for item in self._plugins_metadata:
|
for item in self._packages_metadata:
|
||||||
if item["id"] == plugin["id"]:
|
if item["id"] == plugin["id"]:
|
||||||
plugin["update_url"] = item["file_location"]
|
plugin["update_url"] = item["file_location"]
|
||||||
|
|
||||||
return self._plugins_model
|
return self._plugins_model
|
||||||
|
|
||||||
|
@pyqtProperty(QObject, notify = packagesMetadataChanged)
|
||||||
|
def packagesModel(self):
|
||||||
|
return self._packages_model
|
||||||
|
|
||||||
def _checkCanUpgrade(self, id, version):
|
def _checkCanUpgrade(self, id, version):
|
||||||
|
|
||||||
# TODO: This could maybe be done more efficiently using a dictionary...
|
# TODO: This could maybe be done more efficiently using a dictionary...
|
||||||
|
|
||||||
# Scan plugin server data for plugin with the given id:
|
# Scan plugin server data for plugin with the given id:
|
||||||
for plugin in self._plugins_metadata:
|
for plugin in self._packages_metadata:
|
||||||
if id == plugin["id"]:
|
if id == plugin["id"]:
|
||||||
reg_version = Version(version)
|
reg_version = Version(version)
|
||||||
new_version = Version(plugin["version"])
|
new_version = Version(plugin["version"])
|
||||||
|
@ -374,14 +378,17 @@ class Toolbox(QObject, Extension):
|
||||||
return
|
return
|
||||||
|
|
||||||
if reply.operation() == QNetworkAccessManager.GetOperation:
|
if reply.operation() == QNetworkAccessManager.GetOperation:
|
||||||
if reply_url == self._api_url + "plugins":
|
if reply_url == "{base_url}packages?cura_version={version}".format(base_url = self._api_url, version = self._packages_version_number):
|
||||||
try:
|
try:
|
||||||
json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))
|
json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))
|
||||||
|
|
||||||
# Add metadata to the manager:
|
# Add metadata to the manager:
|
||||||
self._plugins_metadata = json_data
|
self._packages_metadata = json_data
|
||||||
self._plugin_registry.addExternalPlugins(self._plugins_metadata)
|
if not self._packages_model:
|
||||||
self.pluginsMetadataChanged.emit()
|
self._packages_model = CuraPackageModel()
|
||||||
|
self._packages_model.setPackagesMetaData(self._packages_metadata["data"])
|
||||||
|
# self._plugin_registry.addExternalPlugins(self._packages_metadata)
|
||||||
|
self.packagesMetadataChanged.emit()
|
||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
Logger.log("w", "Received an invalid print job state message: Not valid JSON.")
|
Logger.log("w", "Received an invalid print job state message: Not valid JSON.")
|
||||||
return
|
return
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue