mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-06-04 11:14:21 +08:00
Add copy, paste, cut functionality
CURA-7913
This commit is contained in:
parent
f71f39f8bd
commit
f07faac422
@ -1,15 +1,20 @@
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Copyright (c) 2023 UltiMaker
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from PyQt6.QtCore import QObject, QUrl
|
||||
from PyQt6.QtGui import QDesktopServices
|
||||
from typing import List, cast
|
||||
|
||||
from PyQt6.QtCore import QObject, QUrl, QMimeData
|
||||
from PyQt6.QtGui import QDesktopServices
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
|
||||
import pySavitar as Savitar
|
||||
|
||||
from UM.Event import CallFunctionEvent
|
||||
from UM.FlameProfiler import pyqtSlot
|
||||
from UM.Math.Vector import Vector
|
||||
from UM.Scene.Selection import Selection
|
||||
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.Operations.GroupedOperation import GroupedOperation
|
||||
from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
|
||||
from UM.Operations.TranslateOperation import TranslateOperation
|
||||
@ -19,6 +24,7 @@ from cura.Operations.SetParentOperation import SetParentOperation
|
||||
from cura.MultiplyObjectsJob import MultiplyObjectsJob
|
||||
from cura.Settings.SetObjectExtruderOperation import SetObjectExtruderOperation
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
from cura.Arranging.Nest2DArrange import createGroupOperationForArrange
|
||||
|
||||
from cura.Operations.SetBuildPlateNumberOperation import SetBuildPlateNumberOperation
|
||||
|
||||
@ -181,5 +187,63 @@ class CuraActions(QObject):
|
||||
|
||||
Selection.clear()
|
||||
|
||||
@pyqtSlot()
|
||||
def cut(self) -> None:
|
||||
self.copy()
|
||||
self.deleteSelection()
|
||||
|
||||
@pyqtSlot()
|
||||
def copy(self) -> None:
|
||||
# Convert all selected objects to a Savitar scene
|
||||
savitar_scene = Savitar.Scene()
|
||||
mesh_writer = cura.CuraApplication.CuraApplication.getInstance().getMeshFileHandler().getWriter("3MFWriter")
|
||||
for scene_node in Selection.getAllSelectedObjects():
|
||||
savitar_node = mesh_writer._convertUMNodeToSavitarNode(scene_node)
|
||||
savitar_scene.addSceneNode(savitar_node)
|
||||
|
||||
# Convert the scene to a string
|
||||
parser = Savitar.ThreeMFParser()
|
||||
scene_string = parser.sceneToString(savitar_scene)
|
||||
|
||||
# Copy the scene to the clipboard
|
||||
QApplication.clipboard().setText(scene_string)
|
||||
|
||||
@pyqtSlot()
|
||||
def paste(self) -> None:
|
||||
application = cura.CuraApplication.CuraApplication.getInstance()
|
||||
|
||||
# Parse the scene from the clipboard
|
||||
scene_string = QApplication.clipboard().text()
|
||||
parser = Savitar.ThreeMFParser()
|
||||
scene = parser.parse(scene_string)
|
||||
|
||||
# Convert the scene to scene nodes
|
||||
nodes = []
|
||||
mesh_reader = application.getMeshFileHandler().getReaderForFile(".3mf")
|
||||
for savitar_node in scene.getSceneNodes():
|
||||
scene_node = mesh_reader._convertSavitarNodeToUMNode(savitar_node, "file_name")
|
||||
if scene_node is None:
|
||||
continue
|
||||
nodes.append(scene_node)
|
||||
|
||||
# Find all fixed nodes, these are the nodes that should be avoided when arranging
|
||||
fixed_nodes = []
|
||||
root = application.getController().getScene().getRoot()
|
||||
for node in DepthFirstIterator(root):
|
||||
# Only count sliceable objects
|
||||
if node.callDecoration("isSliceable"):
|
||||
fixed_nodes.append(node)
|
||||
# Add the new nodes to the scene, and arrange them
|
||||
group_operation, not_fit_count = createGroupOperationForArrange(nodes, application.getBuildVolume(),
|
||||
fixed_nodes, factor=10000,
|
||||
add_new_nodes_in_scene=True)
|
||||
group_operation.push()
|
||||
|
||||
# deselect currently selected nodes, and select the new nodes
|
||||
for node in Selection.getAllSelectedObjects():
|
||||
Selection.remove(node)
|
||||
for node in nodes:
|
||||
Selection.add(node)
|
||||
|
||||
def _openUrl(self, url: QUrl) -> None:
|
||||
QDesktopServices.openUrl(url)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2022 UltiMaker
|
||||
// Copyright (c) 2023 UltiMaker
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
pragma Singleton
|
||||
@ -71,6 +71,10 @@ Item
|
||||
|
||||
property alias browsePackages: browsePackagesAction
|
||||
|
||||
property alias paste: pasteAction
|
||||
property alias copy: copyAction
|
||||
property alias cut: cutAction
|
||||
|
||||
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||
|
||||
|
||||
@ -309,6 +313,33 @@ Item
|
||||
onTriggered: CuraActions.centerSelection()
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: copyAction
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit", "Copy to clipboard")
|
||||
onTriggered: CuraActions.copy()
|
||||
enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection
|
||||
shortcut: StandardKey.Copy
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: pasteAction
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit", "Paste from clipboard")
|
||||
onTriggered: CuraActions.paste()
|
||||
enabled: UM.Controller.toolsEnabled
|
||||
shortcut: StandardKey.Paste
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: cutAction
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit", "Cut")
|
||||
onTriggered: CuraActions.cut()
|
||||
enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection
|
||||
shortcut: StandardKey.Cut
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: multiplySelectionAction
|
||||
|
@ -19,6 +19,8 @@ Cura.Menu
|
||||
// Selection-related actions.
|
||||
Cura.MenuItem { action: Cura.Actions.centerSelection; }
|
||||
Cura.MenuItem { action: Cura.Actions.deleteSelection; }
|
||||
Cura.MenuItem { action: Cura.Actions.copy; }
|
||||
Cura.MenuItem { action: Cura.Actions.paste; }
|
||||
Cura.MenuItem { action: Cura.Actions.multiplySelection; }
|
||||
|
||||
// Extruder selection - only visible if there is more than 1 extruder
|
||||
|
Loading…
x
Reference in New Issue
Block a user