mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-12 06:58:59 +08:00
Merge pull request #12531 from Ultimaker/CURA-8555_link_ufp_to_3mf_in_digital_library
Cura 8555 link ufp to 3mf in digital library
This commit is contained in:
commit
188b63703b
@ -14,6 +14,9 @@ import DigitalFactory 1.0 as DF
|
|||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
id: base
|
id: base
|
||||||
|
|
||||||
|
property variant catalog: UM.I18nCatalog { name: "cura" }
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
@ -190,53 +193,29 @@ Item
|
|||||||
text: "Save"
|
text: "Save"
|
||||||
enabled: (asProjectCheckbox.checked || asSlicedCheckbox.checked) && dfFilenameTextfield.text.length >= 1 && dfFilenameTextfield.state !== 'invalid'
|
enabled: (asProjectCheckbox.checked || asSlicedCheckbox.checked) && dfFilenameTextfield.text.length >= 1 && dfFilenameTextfield.state !== 'invalid'
|
||||||
|
|
||||||
onClicked:
|
onClicked: manager.saveFileToSelectedProject(dfFilenameTextfield.text, asProjectComboBox.currentValue)
|
||||||
{
|
|
||||||
let saveAsFormats = [];
|
|
||||||
if (asProjectCheckbox.checked)
|
|
||||||
{
|
|
||||||
saveAsFormats.push("3mf");
|
|
||||||
}
|
|
||||||
if (asSlicedCheckbox.checked)
|
|
||||||
{
|
|
||||||
saveAsFormats.push("ufp");
|
|
||||||
}
|
|
||||||
manager.saveFileToSelectedProject(dfFilenameTextfield.text, saveAsFormats);
|
|
||||||
}
|
|
||||||
busy: false
|
busy: false
|
||||||
}
|
}
|
||||||
|
|
||||||
Row
|
Cura.ComboBox
|
||||||
{
|
{
|
||||||
|
id: asProjectComboBox
|
||||||
|
|
||||||
id: saveAsFormatRow
|
width: UM.Theme.getSize("combobox_wide").width
|
||||||
|
height: saveButton.height
|
||||||
anchors.verticalCenter: saveButton.verticalCenter
|
anchors.verticalCenter: saveButton.verticalCenter
|
||||||
anchors.right: saveButton.left
|
anchors.right: saveButton.left
|
||||||
anchors.rightMargin: UM.Theme.getSize("thin_margin").height
|
anchors.rightMargin: UM.Theme.getSize("thin_margin").height
|
||||||
width: childrenRect.width
|
|
||||||
spacing: UM.Theme.getSize("default_margin").width
|
|
||||||
|
|
||||||
UM.CheckBox
|
enabled: UM.Backend.state == UM.Backend.Done
|
||||||
{
|
currentIndex: UM.Backend.state == UM.Backend.Done ? 0 : 1
|
||||||
id: asProjectCheckbox
|
textRole: "text"
|
||||||
height: UM.Theme.getSize("checkbox").height
|
valueRole: "value"
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
checked: true
|
|
||||||
text: "Save Cura project"
|
|
||||||
font: UM.Theme.getFont("medium")
|
|
||||||
}
|
|
||||||
|
|
||||||
UM.CheckBox
|
model: [
|
||||||
{
|
{ text: catalog.i18nc("@option", "Save Cura project and print file"), key: "3mf_ufp", value: ["3mf", "ufp"] },
|
||||||
id: asSlicedCheckbox
|
{ text: catalog.i18nc("@option", "Save Cura project"), key: "3mf", value: ["3mf"] },
|
||||||
height: UM.Theme.getSize("checkbox").height
|
]
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
enabled: UM.Backend.state == UM.Backend.Done
|
|
||||||
checked: UM.Backend.state == UM.Backend.Done
|
|
||||||
text: "Save print file"
|
|
||||||
font: UM.Theme.getFont("medium")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted:
|
Component.onCompleted:
|
||||||
|
@ -37,17 +37,18 @@ class DFFileExportAndUploadManager:
|
|||||||
formats: List[str],
|
formats: List[str],
|
||||||
on_upload_error: Callable[[], Any],
|
on_upload_error: Callable[[], Any],
|
||||||
on_upload_success: Callable[[], Any],
|
on_upload_success: Callable[[], Any],
|
||||||
on_upload_finished: Callable[[], Any] ,
|
on_upload_finished: Callable[[], Any],
|
||||||
on_upload_progress: Callable[[int], Any]) -> None:
|
on_upload_progress: Callable[[int], Any]) -> None:
|
||||||
|
|
||||||
self._file_handlers = file_handlers # type: Dict[str, FileHandler]
|
self._file_handlers: Dict[str, FileHandler] = file_handlers
|
||||||
self._nodes = nodes # type: List[SceneNode]
|
self._nodes: List[SceneNode] = nodes
|
||||||
self._library_project_id = library_project_id # type: str
|
self._library_project_id: str = library_project_id
|
||||||
self._library_project_name = library_project_name # type: str
|
self._library_project_name: str = library_project_name
|
||||||
self._file_name = file_name # type: str
|
self._file_name: str = file_name
|
||||||
self._upload_jobs = [] # type: List[ExportFileJob]
|
self._upload_jobs: List[ExportFileJob] = []
|
||||||
self._formats = formats # type: List[str]
|
self._formats: List[str] = formats
|
||||||
self._api = DigitalFactoryApiClient(application = CuraApplication.getInstance(), on_error = lambda error: Logger.log("e", str(error)))
|
self._api = DigitalFactoryApiClient(application = CuraApplication.getInstance(), on_error = lambda error: Logger.log("e", str(error)))
|
||||||
|
self._source_file_id: Optional[str] = None
|
||||||
|
|
||||||
# Functions of the parent class that should be called based on the upload process output
|
# Functions of the parent class that should be called based on the upload process output
|
||||||
self._on_upload_error = on_upload_error
|
self._on_upload_error = on_upload_error
|
||||||
@ -59,7 +60,7 @@ class DFFileExportAndUploadManager:
|
|||||||
# show the success message (once both upload jobs are done)
|
# show the success message (once both upload jobs are done)
|
||||||
self._message_lock = threading.Lock()
|
self._message_lock = threading.Lock()
|
||||||
|
|
||||||
self._file_upload_job_metadata = self.initializeFileUploadJobMetadata() # type: Dict[str, Dict[str, Any]]
|
self._file_upload_job_metadata: Dict[str, Dict[str, Any]] = self.initializeFileUploadJobMetadata()
|
||||||
|
|
||||||
self.progress_message = Message(
|
self.progress_message = Message(
|
||||||
title = "Uploading...",
|
title = "Uploading...",
|
||||||
@ -113,7 +114,8 @@ class DFFileExportAndUploadManager:
|
|||||||
content_type = job.getMimeType(),
|
content_type = job.getMimeType(),
|
||||||
job_name = job.getFileName(),
|
job_name = job.getFileName(),
|
||||||
file_size = len(job.getOutput()),
|
file_size = len(job.getOutput()),
|
||||||
library_project_id = self._library_project_id
|
library_project_id = self._library_project_id,
|
||||||
|
source_file_id = self._source_file_id
|
||||||
)
|
)
|
||||||
self._api.requestUploadUFP(request, on_finished = self._uploadFileData, on_error = self._onRequestUploadPrintFileFailed)
|
self._api.requestUploadUFP(request, on_finished = self._uploadFileData, on_error = self._onRequestUploadPrintFileFailed)
|
||||||
|
|
||||||
@ -125,6 +127,9 @@ class DFFileExportAndUploadManager:
|
|||||||
"""
|
"""
|
||||||
if isinstance(file_upload_response, DFLibraryFileUploadResponse):
|
if isinstance(file_upload_response, DFLibraryFileUploadResponse):
|
||||||
file_name = file_upload_response.file_name
|
file_name = file_upload_response.file_name
|
||||||
|
|
||||||
|
# store the `file_id` so it can be as `source_file_id` when uploading the print file
|
||||||
|
self._source_file_id = file_upload_response.file_id
|
||||||
elif isinstance(file_upload_response, DFPrintJobUploadResponse):
|
elif isinstance(file_upload_response, DFPrintJobUploadResponse):
|
||||||
file_name = file_upload_response.job_name if file_upload_response.job_name is not None else ""
|
file_name = file_upload_response.job_name if file_upload_response.job_name is not None else ""
|
||||||
else:
|
else:
|
||||||
@ -145,6 +150,8 @@ class DFFileExportAndUploadManager:
|
|||||||
on_progress = self._onUploadProgress,
|
on_progress = self._onUploadProgress,
|
||||||
on_error = self._onUploadError)
|
on_error = self._onUploadError)
|
||||||
|
|
||||||
|
self._handleNextUploadJob()
|
||||||
|
|
||||||
def _onUploadProgress(self, filename: str, progress: int) -> None:
|
def _onUploadProgress(self, filename: str, progress: int) -> None:
|
||||||
"""
|
"""
|
||||||
Updates the progress message according to the total progress of the two files and displays it to the user. It is
|
Updates the progress message according to the total progress of the two files and displays it to the user. It is
|
||||||
@ -325,8 +332,13 @@ class DFFileExportAndUploadManager:
|
|||||||
message.hide()
|
message.hide()
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
for job in self._upload_jobs:
|
self._handleNextUploadJob()
|
||||||
job.start()
|
|
||||||
|
def _handleNextUploadJob(self):
|
||||||
|
match self._upload_jobs:
|
||||||
|
case [job, *jobs]:
|
||||||
|
job.start()
|
||||||
|
self._upload_jobs = jobs
|
||||||
|
|
||||||
def initializeFileUploadJobMetadata(self) -> Dict[str, Any]:
|
def initializeFileUploadJobMetadata(self) -> Dict[str, Any]:
|
||||||
metadata = {}
|
metadata = {}
|
||||||
|
@ -39,8 +39,8 @@ class DFFileUploader:
|
|||||||
:param on_error: The method to be called when an error occurs.
|
:param on_error: The method to be called when an error occurs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._http = http # type: HttpRequestManager
|
self._http: HttpRequestManager = http
|
||||||
self._df_file = df_file # type: Union[DFLibraryFileUploadResponse, DFPrintJobUploadResponse]
|
self._df_file: Union[DFLibraryFileUploadResponse, DFPrintJobUploadResponse] = df_file
|
||||||
self._file_name = ""
|
self._file_name = ""
|
||||||
if isinstance(self._df_file, DFLibraryFileUploadResponse):
|
if isinstance(self._df_file, DFLibraryFileUploadResponse):
|
||||||
self._file_name = self._df_file.file_name
|
self._file_name = self._df_file.file_name
|
||||||
@ -51,7 +51,7 @@ class DFFileUploader:
|
|||||||
self._file_name = ""
|
self._file_name = ""
|
||||||
else:
|
else:
|
||||||
raise TypeError("Incorrect input type")
|
raise TypeError("Incorrect input type")
|
||||||
self._data = data # type: bytes
|
self._data: bytes = data
|
||||||
|
|
||||||
self._on_finished = on_finished
|
self._on_finished = on_finished
|
||||||
self._on_success = on_success
|
self._on_success = on_success
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
# Copyright (c) 2021 Ultimaker B.V.
|
# Copyright (c) 2021 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from .BaseModel import BaseModel
|
from .BaseModel import BaseModel
|
||||||
|
|
||||||
|
|
||||||
# Model that represents the request to upload a print job to the cloud
|
# Model that represents the request to upload a print job to the cloud
|
||||||
class DFPrintJobUploadRequest(BaseModel):
|
class DFPrintJobUploadRequest(BaseModel):
|
||||||
|
|
||||||
def __init__(self, job_name: str, file_size: int, content_type: str, library_project_id: str, **kwargs) -> None:
|
def __init__(self, job_name: str, file_size: int, content_type: str, library_project_id: str, source_file_id: str, **kwargs) -> None:
|
||||||
"""Creates a new print job upload request.
|
"""Creates a new print job upload request.
|
||||||
|
|
||||||
:param job_name: The name of the print job.
|
:param job_name: The name of the print job.
|
||||||
@ -18,4 +20,5 @@ class DFPrintJobUploadRequest(BaseModel):
|
|||||||
self.file_size = file_size
|
self.file_size = file_size
|
||||||
self.content_type = content_type
|
self.content_type = content_type
|
||||||
self.library_project_id = library_project_id
|
self.library_project_id = library_project_id
|
||||||
|
self.source_file_id = source_file_id
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
@ -40,7 +40,7 @@ class DigitalFactoryApiClient:
|
|||||||
DEFAULT_REQUEST_TIMEOUT = 10 # seconds
|
DEFAULT_REQUEST_TIMEOUT = 10 # seconds
|
||||||
|
|
||||||
# In order to avoid garbage collection we keep the callbacks in this list.
|
# In order to avoid garbage collection we keep the callbacks in this list.
|
||||||
_anti_gc_callbacks = [] # type: List[Callable[[Any], None]]
|
_anti_gc_callbacks: List[Callable[[Any], None]] = []
|
||||||
|
|
||||||
def __init__(self, application: CuraApplication, on_error: Callable[[List[CloudError]], None], projects_limit_per_page: Optional[int] = None) -> None:
|
def __init__(self, application: CuraApplication, on_error: Callable[[List[CloudError]], None], projects_limit_per_page: Optional[int] = None) -> None:
|
||||||
"""Initializes a new digital factory API client.
|
"""Initializes a new digital factory API client.
|
||||||
@ -54,7 +54,7 @@ class DigitalFactoryApiClient:
|
|||||||
self._scope = JsonDecoratorScope(UltimakerCloudScope(application))
|
self._scope = JsonDecoratorScope(UltimakerCloudScope(application))
|
||||||
self._http = HttpRequestManager.getInstance()
|
self._http = HttpRequestManager.getInstance()
|
||||||
self._on_error = on_error
|
self._on_error = on_error
|
||||||
self._file_uploader = None # type: Optional[DFFileUploader]
|
self._file_uploader: Optional[DFFileUploader] = None
|
||||||
self._library_max_private_projects: Optional[int] = None
|
self._library_max_private_projects: Optional[int] = None
|
||||||
|
|
||||||
self._projects_pagination_mgr = PaginationManager(limit = projects_limit_per_page) if projects_limit_per_page else None # type: Optional[PaginationManager]
|
self._projects_pagination_mgr = PaginationManager(limit = projects_limit_per_page) if projects_limit_per_page else None # type: Optional[PaginationManager]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user