diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 7b588c836a..1af8380fd6 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1143,6 +1143,16 @@ class CuraApplication(QtApplication): self._build_plate_model = BuildPlateModel(self) return self._build_plate_model + @pyqtSlot() + def exportUcp(self): + writer = self.getMeshFileHandler().getWriter("3MFWriter") + + if writer is None: + Logger.warning("3mf writer is not enabled") + return + + writer.exportUcp() + def getCuraSceneController(self, *args) -> CuraSceneController: if self._cura_scene_controller is None: self._cura_scene_controller = CuraSceneController.createCuraSceneController() diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index c9692599e5..04885a961b 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -236,8 +236,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Check whether the file is a UCP, which changes some import options #FIXME Instead of this, we should just check for the presence of the user-settings file, whatever the extension - is_ucp = file_name.endswith('.3mf') - + if file_name.endswith('.3mf'): + is_ucp = True # # Read definition containers # diff --git a/plugins/3MFReader/__init__.py b/plugins/3MFReader/__init__.py index 101337f05f..5e2b68fce0 100644 --- a/plugins/3MFReader/__init__.py +++ b/plugins/3MFReader/__init__.py @@ -25,20 +25,12 @@ def getMetaData() -> Dict: { "extension": "3mf", "description": catalog.i18nc("@item:inlistbox", "3MF File") - }, - { - "extension": "ucp", - "description": catalog.i18nc("@item:inlistbox", "UCP File") } ] metaData["workspace_reader"] = [ { "extension": workspace_extension, "description": catalog.i18nc("@item:inlistbox", "3MF File") - }, - { - "extension": "ucp", - "description": catalog.i18nc("@item:inlistbox", "UCP File") } ] diff --git a/plugins/3MFWriter/ThreeMFWorkspaceWriter.py b/plugins/3MFWriter/ThreeMFWorkspaceWriter.py index c67da24569..745627ed93 100644 --- a/plugins/3MFWriter/ThreeMFWorkspaceWriter.py +++ b/plugins/3MFWriter/ThreeMFWorkspaceWriter.py @@ -15,7 +15,6 @@ from UM.Workspace.WorkspaceWriter import WorkspaceWriter from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") -from .UCPDialog import UCPDialog from .ThreeMFWriter import ThreeMFWriter from .SettingsExportModel import SettingsExportModel from .SettingsExportGroup import SettingsExportGroup @@ -32,32 +31,12 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter): self._stream = None self._nodes = None self._mode = None - self._config_dialog = None + self._is_ucp = False - #FIXME We should have proper preWrite/write methods like the readers have a preRead/read, and have them called by the global process - def _preWrite(self): - is_ucp = False - if hasattr(self._stream, 'name'): - # This only works with local file, but we don't want remote UCP files yet - is_ucp = self._stream.name.endswith('.3mf') - if is_ucp: - self._config_dialog = UCPDialog() - self._config_dialog.finished.connect(self._onUCPConfigFinished) - self._config_dialog.show() - else: - self._doWrite() - - def _onUCPConfigFinished(self, accepted: bool): - if accepted: - self._export_model = self._config_dialog.getModel() - self._doWrite() - else: - self._main_thread_lock.release() - - def _doWrite(self): - self._write() - self._main_thread_lock.release() + def setExportModel(self, model): + if self._export_model != model: + self._export_model = model def _write(self): application = Application.getInstance() @@ -153,19 +132,21 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter): #FIXME We should somehow give the information of the file type so that we know what to write, like the mode but for other files types (give mimetype ?) def write(self, stream, nodes, mode=WorkspaceWriter.OutputMode.BinaryMode): + print("Application.getInstance().getPreferences().getValue(\"local_file/last_used_type\")", Application.getInstance().getPreferences().getValue("local_file/last_used_type")) + self._success = False self._export_model = None self._stream = stream self._nodes = nodes self._mode = mode self._config_dialog = None - - self._main_thread_lock.acquire() - # Export is done in main thread because it may require a few asynchronous configuration steps - Application.getInstance().callLater(self._preWrite) - self._main_thread_lock.acquire() # Block until lock has been released, meaning the config+write is over - - self._main_thread_lock.release() + # + # self._main_thread_lock.acquire() + # # Export is done in main thread because it may require a few asynchronous configuration steps + Application.getInstance().callLater(self._write()) + # self._main_thread_lock.acquire() # Block until lock has been released, meaning the config+write is over + # + # self._main_thread_lock.release() self._export_model = None self._stream = None diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 2caa71353c..e60aae8dd9 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -23,7 +23,7 @@ from cura.Snapshot import Snapshot from PyQt6.QtCore import QBuffer import pySavitar as Savitar - +from .UCPDialog import UCPDialog import numpy import datetime @@ -61,6 +61,7 @@ class ThreeMFWriter(MeshWriter): self._unit_matrix_string = ThreeMFWriter._convertMatrixToString(Matrix()) self._archive: Optional[zipfile.ZipFile] = None self._store_archive = False + self._is_ucp = False @staticmethod def _convertMatrixToString(matrix): @@ -433,3 +434,8 @@ class ThreeMFWriter(MeshWriter): extra_settings[group.category_details] = exported_model_settings return extra_settings + + def exportUcp(self): + self._is_ucp = True + self._config_dialog = UCPDialog() + self._config_dialog.show() diff --git a/plugins/3MFWriter/UCPDialog.py b/plugins/3MFWriter/UCPDialog.py index fb214aded0..ecffb64338 100644 --- a/plugins/3MFWriter/UCPDialog.py +++ b/plugins/3MFWriter/UCPDialog.py @@ -4,6 +4,8 @@ import os from PyQt6.QtCore import pyqtSignal, QObject + +import UM from UM.FlameProfiler import pyqtSlot from UM.i18n import i18nCatalog @@ -44,6 +46,16 @@ class UCPDialog(QObject): @pyqtSlot() def _onAccepted(self): self._accepted = True + mesh_writer = CuraApplication.getInstance().getMeshFileHandler().getWriter("3MFWriter") + mesh_writer.custom_data = "My custom data" + + device = CuraApplication.getInstance().getOutputDeviceManager().getOutputDevice("local_file") + file_handler = UM.Qt.QtApplication.QtApplication.getInstance().getWorkspaceFileHandler() + nodes = [CuraApplication.getInstance().getController().getScene().getRoot()] + device.requestWrite(nodes, "test.3mf", ["application/x-ucp"], file_handler, + preferred_mimetype_list="application/x-ucp") + #TODO: update _export_model in threeMFWorkspacewriter and set is_ucp is true + # = self._config_dialog.getModel() self._onFinished() @pyqtSlot() diff --git a/resources/qml/Menus/FileMenu.qml b/resources/qml/Menus/FileMenu.qml index 4f7734cb11..bc0d1e6aef 100644 --- a/resources/qml/Menus/FileMenu.qml +++ b/resources/qml/Menus/FileMenu.qml @@ -74,14 +74,10 @@ Cura.Menu { id: saveUCPMenu text: catalog.i18nc("@title:menu menubar:file", "&Save Universal Cura Project...") - enabled: UM.WorkspaceFileHandler.enabled + enabled: UM.WorkspaceFileHandler.enabled && CuraApplication.getPackageManager().allEnabledPackages.includes("3MFWriter") onTriggered: { - var args = { "filter_by_machine": false, - "file_type": "workspace", - "preferred_mimetypes": "application/x-ucp", - "limit_mimetypes": "application/x-ucp"}; - UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args) + CuraApplication.exportUcp() } }