mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-04-22 13:49:39 +08:00
Convert doxygen to rst for Toolbox, TrimeshReader
This commit is contained in:
parent
8e347c1034
commit
d96359f208
@ -9,8 +9,12 @@ from PyQt5.QtCore import Qt, pyqtProperty
|
||||
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 AuthorsModel(ListModel):
|
||||
"""Model that holds cura packages.
|
||||
|
||||
By setting the filter property the instances held by this model can be changed.
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
@ -67,9 +71,11 @@ class AuthorsModel(ListModel):
|
||||
filtered_items.sort(key = lambda k: k["name"])
|
||||
self.setItems(filtered_items)
|
||||
|
||||
## 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:
|
||||
"""Set the filter of this model based on a string.
|
||||
|
||||
:param filter_dict: Dictionary to do the filtering by.
|
||||
"""
|
||||
if filter_dict != self._filter:
|
||||
self._filter = filter_dict
|
||||
self._update()
|
||||
|
@ -20,9 +20,9 @@ class CloudApiModel:
|
||||
cloud_api_version=cloud_api_version,
|
||||
)
|
||||
|
||||
## https://api.ultimaker.com/cura-packages/v1/user/packages/{package_id}
|
||||
@classmethod
|
||||
def userPackageUrl(cls, package_id: str) -> str:
|
||||
"""https://api.ultimaker.com/cura-packages/v1/user/packages/{package_id}"""
|
||||
|
||||
return (CloudApiModel.api_url_user_packages + "/{package_id}").format(
|
||||
package_id=package_id
|
||||
|
@ -8,9 +8,11 @@ from UM.Signal import Signal
|
||||
from .SubscribedPackagesModel import SubscribedPackagesModel
|
||||
|
||||
|
||||
## Shows a list of packages to be added or removed. The user can select which packages to (un)install. The user's
|
||||
# choices are emitted on the `packageMutations` Signal.
|
||||
class DiscrepanciesPresenter(QObject):
|
||||
"""Shows a list of packages to be added or removed. The user can select which packages to (un)install. The user's
|
||||
|
||||
choices are emitted on the `packageMutations` Signal.
|
||||
"""
|
||||
|
||||
def __init__(self, app: QtApplication) -> None:
|
||||
super().__init__(app)
|
||||
|
@ -16,9 +16,11 @@ from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope
|
||||
from .SubscribedPackagesModel import SubscribedPackagesModel
|
||||
|
||||
|
||||
## Downloads a set of packages from the Ultimaker Cloud Marketplace
|
||||
# use download() exactly once: should not be used for multiple sets of downloads since this class contains state
|
||||
class DownloadPresenter:
|
||||
"""Downloads a set of packages from the Ultimaker Cloud Marketplace
|
||||
|
||||
use download() exactly once: should not be used for multiple sets of downloads since this class contains state
|
||||
"""
|
||||
|
||||
DISK_WRITE_BUFFER_SIZE = 256 * 1024 # 256 KB
|
||||
|
||||
|
@ -43,10 +43,12 @@ class LicensePresenter(QObject):
|
||||
|
||||
self._compatibility_dialog_path = "resources/qml/dialogs/ToolboxLicenseDialog.qml"
|
||||
|
||||
## Show a license dialog for multiple packages where users can read a license and accept or decline them
|
||||
# \param plugin_path: Root directory of the Toolbox plugin
|
||||
# \param packages: Dict[package id, file path]
|
||||
def present(self, plugin_path: str, packages: Dict[str, Dict[str, str]]) -> None:
|
||||
"""Show a license dialog for multiple packages where users can read a license and accept or decline them
|
||||
|
||||
:param plugin_path: Root directory of the Toolbox plugin
|
||||
:param packages: Dict[package id, file path]
|
||||
"""
|
||||
if self._presented:
|
||||
Logger.error("{clazz} is single-use. Create a new {clazz} instead", clazz=self.__class__.__name__)
|
||||
return
|
||||
|
@ -3,9 +3,11 @@ from UM.Message import Message
|
||||
from cura.CuraApplication import CuraApplication
|
||||
|
||||
|
||||
## Presents a dialog telling the user that a restart is required to apply changes
|
||||
# Since we cannot restart Cura, the app is closed instead when the button is clicked
|
||||
class RestartApplicationPresenter:
|
||||
"""Presents a dialog telling the user that a restart is required to apply changes
|
||||
|
||||
Since we cannot restart Cura, the app is closed instead when the button is clicked
|
||||
"""
|
||||
def __init__(self, app: CuraApplication) -> None:
|
||||
self._app = app
|
||||
self._i18n_catalog = i18nCatalog("cura")
|
||||
|
@ -16,20 +16,23 @@ from .RestartApplicationPresenter import RestartApplicationPresenter
|
||||
from .SubscribedPackagesModel import SubscribedPackagesModel
|
||||
|
||||
|
||||
## Orchestrates the synchronizing of packages from the user account to the installed packages
|
||||
# Example flow:
|
||||
# - CloudPackageChecker compares a list of packages the user `subscribed` to in their account
|
||||
# If there are `discrepancies` between the account and locally installed packages, they are emitted
|
||||
# - DiscrepanciesPresenter shows a list of packages to be added or removed to the user. It emits the `packageMutations`
|
||||
# the user selected to be performed
|
||||
# - The SyncOrchestrator uses PackageManager to remove local packages the users wants to see removed
|
||||
# - The DownloadPresenter shows a download progress dialog. It emits A tuple of succeeded and failed downloads
|
||||
# - The LicensePresenter extracts licenses from the downloaded packages and presents a license for each package to
|
||||
# be installed. It emits the `licenseAnswers` signal for accept or declines
|
||||
# - The CloudApiClient removes the declined packages from the account
|
||||
# - The SyncOrchestrator uses PackageManager to install the downloaded packages and delete temp files.
|
||||
# - The RestartApplicationPresenter notifies the user that a restart is required for changes to take effect
|
||||
class SyncOrchestrator(Extension):
|
||||
"""Orchestrates the synchronizing of packages from the user account to the installed packages
|
||||
|
||||
Example flow:
|
||||
|
||||
- CloudPackageChecker compares a list of packages the user `subscribed` to in their account
|
||||
If there are `discrepancies` between the account and locally installed packages, they are emitted
|
||||
- DiscrepanciesPresenter shows a list of packages to be added or removed to the user. It emits the `packageMutations`
|
||||
the user selected to be performed
|
||||
- The SyncOrchestrator uses PackageManager to remove local packages the users wants to see removed
|
||||
- The DownloadPresenter shows a download progress dialog. It emits A tuple of succeeded and failed downloads
|
||||
- The LicensePresenter extracts licenses from the downloaded packages and presents a license for each package to
|
||||
be installed. It emits the `licenseAnswers` signal for accept or declines
|
||||
- The CloudApiClient removes the declined packages from the account
|
||||
- The SyncOrchestrator uses PackageManager to install the downloaded packages and delete temp files.
|
||||
- The RestartApplicationPresenter notifies the user that a restart is required for changes to take effect
|
||||
"""
|
||||
|
||||
def __init__(self, app: CuraApplication) -> None:
|
||||
super().__init__()
|
||||
@ -63,10 +66,12 @@ class SyncOrchestrator(Extension):
|
||||
self._download_presenter.done.connect(self._onDownloadFinished)
|
||||
self._download_presenter.download(mutations)
|
||||
|
||||
## Called when a set of packages have finished downloading
|
||||
# \param success_items: Dict[package_id, Dict[str, str]]
|
||||
# \param error_items: List[package_id]
|
||||
def _onDownloadFinished(self, success_items: Dict[str, Dict[str, str]], error_items: List[str]) -> None:
|
||||
"""Called when a set of packages have finished downloading
|
||||
|
||||
:param success_items:: Dict[package_id, Dict[str, str]]
|
||||
:param error_items:: List[package_id]
|
||||
"""
|
||||
if error_items:
|
||||
message = i18n_catalog.i18nc("@info:generic", "{} plugins failed to download".format(len(error_items)))
|
||||
self._showErrorMessage(message)
|
||||
@ -96,7 +101,8 @@ class SyncOrchestrator(Extension):
|
||||
if has_changes:
|
||||
self._restart_presenter.present()
|
||||
|
||||
## Logs an error and shows it to the user
|
||||
def _showErrorMessage(self, text: str):
|
||||
"""Logs an error and shows it to the user"""
|
||||
|
||||
Logger.error(text)
|
||||
Message(text, lifetime=0).show()
|
||||
|
@ -6,8 +6,9 @@ from PyQt5.QtCore import Qt
|
||||
from UM.Qt.ListModel import ListModel
|
||||
|
||||
|
||||
## Model that holds supported configurations (for material/quality packages).
|
||||
class ConfigsModel(ListModel):
|
||||
"""Model that holds supported configurations (for material/quality packages)."""
|
||||
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
|
||||
|
@ -12,8 +12,12 @@ from UM.Qt.ListModel import ListModel
|
||||
from .ConfigsModel import ConfigsModel
|
||||
|
||||
|
||||
## Model that holds Cura packages. By setting the filter property the instances held by this model can be changed.
|
||||
class PackagesModel(ListModel):
|
||||
"""Model that holds Cura packages.
|
||||
|
||||
By setting the filter property the instances held by this model can be changed.
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
|
||||
@ -131,9 +135,11 @@ class PackagesModel(ListModel):
|
||||
filtered_items.sort(key = lambda k: k["name"])
|
||||
self.setItems(filtered_items)
|
||||
|
||||
## 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:
|
||||
"""Set the filter of this model based on a string.
|
||||
|
||||
:param filter_dict: Dictionary to do the filtering by.
|
||||
"""
|
||||
if filter_dict != self._filter:
|
||||
self._filter = filter_dict
|
||||
self._update()
|
||||
|
@ -37,10 +37,10 @@ try:
|
||||
except ImportError:
|
||||
CuraMarketplaceRoot = DEFAULT_MARKETPLACE_ROOT
|
||||
|
||||
# todo Remove license and download dialog, use SyncOrchestrator instead
|
||||
|
||||
## Provides a marketplace for users to download plugins an materials
|
||||
class Toolbox(QObject, Extension):
|
||||
"""Provides a marketplace for users to download plugins an materials"""
|
||||
|
||||
def __init__(self, application: CuraApplication) -> None:
|
||||
super().__init__()
|
||||
|
||||
@ -135,8 +135,9 @@ class Toolbox(QObject, Extension):
|
||||
closeLicenseDialog = pyqtSignal()
|
||||
uninstallVariablesChanged = pyqtSignal()
|
||||
|
||||
## Go back to the start state (welcome screen or loading if no login required)
|
||||
def _restart(self):
|
||||
"""Go back to the start state (welcome screen or loading if no login required)"""
|
||||
|
||||
# For an Essentials build, login is mandatory
|
||||
if not self._application.getCuraAPI().account.isLoggedIn and ApplicationMetadata.IsEnterpriseVersion:
|
||||
self.setViewPage("welcome")
|
||||
@ -311,10 +312,13 @@ class Toolbox(QObject, Extension):
|
||||
self.restartRequiredChanged.emit()
|
||||
return package_id
|
||||
|
||||
## Check package usage and uninstall
|
||||
# If the package is in use, you'll get a confirmation dialog to set everything to default
|
||||
@pyqtSlot(str)
|
||||
def checkPackageUsageAndUninstall(self, package_id: str) -> None:
|
||||
"""Check package usage and uninstall
|
||||
|
||||
If the package is in use, you'll get a confirmation dialog to set everything to default
|
||||
"""
|
||||
|
||||
package_used_materials, package_used_qualities = self._package_manager.getMachinesUsingPackage(package_id)
|
||||
if package_used_materials or package_used_qualities:
|
||||
# Set up "uninstall variables" for resetMaterialsQualitiesAndUninstall
|
||||
@ -352,10 +356,13 @@ class Toolbox(QObject, Extension):
|
||||
if self._confirm_reset_dialog is not None:
|
||||
self._confirm_reset_dialog.close()
|
||||
|
||||
## Uses "uninstall variables" to reset qualities and materials, then uninstall
|
||||
# It's used as an action on Confirm reset on Uninstall
|
||||
@pyqtSlot()
|
||||
def resetMaterialsQualitiesAndUninstall(self) -> None:
|
||||
"""Uses "uninstall variables" to reset qualities and materials, then uninstall
|
||||
|
||||
It's used as an action on Confirm reset on Uninstall
|
||||
"""
|
||||
|
||||
application = CuraApplication.getInstance()
|
||||
machine_manager = application.getMachineManager()
|
||||
container_tree = ContainerTree.getInstance()
|
||||
@ -418,8 +425,9 @@ class Toolbox(QObject, Extension):
|
||||
self._restart_required = True
|
||||
self.restartRequiredChanged.emit()
|
||||
|
||||
## Actual update packages that are in self._to_update
|
||||
def _update(self) -> None:
|
||||
"""Actual update packages that are in self._to_update"""
|
||||
|
||||
if self._to_update:
|
||||
plugin_id = self._to_update.pop(0)
|
||||
remote_package = self.getRemotePackage(plugin_id)
|
||||
@ -433,9 +441,10 @@ class Toolbox(QObject, Extension):
|
||||
if self._to_update:
|
||||
self._application.callLater(self._update)
|
||||
|
||||
## Update a plugin by plugin_id
|
||||
@pyqtSlot(str)
|
||||
def update(self, plugin_id: str) -> None:
|
||||
"""Update a plugin by plugin_id"""
|
||||
|
||||
self._to_update.append(plugin_id)
|
||||
self._application.callLater(self._update)
|
||||
|
||||
@ -714,9 +723,10 @@ class Toolbox(QObject, Extension):
|
||||
self._active_package = package
|
||||
self.activePackageChanged.emit()
|
||||
|
||||
## The active package is the package that is currently being downloaded
|
||||
@pyqtProperty(QObject, fset = setActivePackage, notify = activePackageChanged)
|
||||
def activePackage(self) -> Optional[QObject]:
|
||||
"""The active package is the package that is currently being downloaded"""
|
||||
|
||||
return self._active_package
|
||||
|
||||
def setViewCategory(self, category: str = "plugin") -> None:
|
||||
@ -724,7 +734,7 @@ class Toolbox(QObject, Extension):
|
||||
self._view_category = category
|
||||
self.viewChanged.emit()
|
||||
|
||||
## Function explicitly defined so that it can be called through the callExtensionsMethod
|
||||
# Function explicitly defined so that it can be called through the callExtensionsMethod
|
||||
# which cannot receive arguments.
|
||||
def setViewCategoryToMaterials(self) -> None:
|
||||
self.setViewCategory("material")
|
||||
|
@ -22,8 +22,10 @@ from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator # Adde
|
||||
if TYPE_CHECKING:
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
|
||||
## Class that leverages Trimesh to import files.
|
||||
|
||||
class TrimeshReader(MeshReader):
|
||||
"""Class that leverages Trimesh to import files."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
@ -79,11 +81,13 @@ class TrimeshReader(MeshReader):
|
||||
)
|
||||
)
|
||||
|
||||
## Reads a file using Trimesh.
|
||||
# \param file_name The file path. This is assumed to be one of the file
|
||||
# types that Trimesh can read. It will not be checked again.
|
||||
# \return A scene node that contains the file's contents.
|
||||
def _read(self, file_name: str) -> Union["SceneNode", List["SceneNode"]]:
|
||||
"""Reads a file using Trimesh.
|
||||
|
||||
:param file_name: The file path. This is assumed to be one of the file
|
||||
types that Trimesh can read. It will not be checked again.
|
||||
:return: A scene node that contains the file's contents.
|
||||
"""
|
||||
# CURA-6739
|
||||
# GLTF files are essentially JSON files. If you directly give a file name to trimesh.load(), it will
|
||||
# try to figure out the format, but for GLTF, it loads it as a binary file with flags "rb", and the json.load()
|
||||
@ -130,13 +134,14 @@ class TrimeshReader(MeshReader):
|
||||
node.setParent(group_node)
|
||||
return group_node
|
||||
|
||||
## Converts a Trimesh to Uranium's MeshData.
|
||||
# \param tri_node A Trimesh containing the contents of a file that was
|
||||
# just read.
|
||||
# \param file_name The full original filename used to watch for changes
|
||||
# \return Mesh data from the Trimesh in a way that Uranium can understand
|
||||
# it.
|
||||
def _toMeshData(self, tri_node: trimesh.base.Trimesh, file_name: str = "") -> MeshData:
|
||||
"""Converts a Trimesh to Uranium's MeshData.
|
||||
|
||||
:param tri_node: A Trimesh containing the contents of a file that was just read.
|
||||
:param file_name: The full original filename used to watch for changes
|
||||
:return: Mesh data from the Trimesh in a way that Uranium can understand it.
|
||||
"""
|
||||
|
||||
tri_faces = tri_node.faces
|
||||
tri_vertices = tri_node.vertices
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user