Select All, Cut, Copy and Paste in FreeCAD Python?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
sdaau_ml
Posts: 35
Joined: Fri Dec 07, 2018 12:18 am

Select All, Cut, Copy and Paste in FreeCAD Python?

Post by sdaau_ml »

Code: Select all

OS: Ubuntu 18.04.1 LTS
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.15379 (Git)
Build type: Release
Branch: master
Hash: 3290c36d28551875f02333c2e01af80e38b8ad02
Python version: 2.7.15rc1
Qt version: 4.8.7
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/UnitedStates (en_US)
I'm asking this because of Temporarily remove object - re-add in FreeCAD Python?.

How to do Select All from Python is documented in https://www.freecadweb.org/wiki/Code_sn ... e_document (see also Select all visible objects by GUI tool - FreeCAD Forum, selection all without mouse - FreeCAD Forum):

Code: Select all

import FreeCAD
for obj in FreeCAD.ActiveDocument.Objects:
    Gui.Selection.addSelection(obj)               # select the object
However, I cannot find how to do Copy, Cut, and Paste.

For instance, this works in FreeCAD Python console:

Code: Select all

Gui.SendMsgToActiveView("ViewFit")
However, when I try:

Code: Select all

Gui.SendMsgToActiveView("Copy")
Gui.SendMsgToActiveView("Cut")
Gui.SendMsgToActiveView("Paste")
... I get in Report View:

Code: Select all

Unknown view command: Copy
Unknown view command: Cut
Unknown view command: Paste
... and that, even if FreeCAD/src/Gui/CommandDoc.cpp · GitHub has:

Code: Select all

 bool done = getGuiApplication()->sendMsgToActiveView("Copy");
... and FreeCAD/src/Gui/EditorView.cpp · GitHub lists:

Code: Select all

bool EditorView::onMsg(const char* pMsg,const char** /*ppReturn*/)
{
    if (strcmp(pMsg,"Save")==0){
        saveFile();
        return true;
    } else if (strcmp(pMsg,"SaveAs")==0){
        saveAs();
        return true;
    } else if (strcmp(pMsg,"Cut")==0){
        cut();
        return true;
    } else if (strcmp(pMsg,"Copy")==0){
        copy();
        return true;
    } else if (strcmp(pMsg,"Paste")==0){
        paste();
        return true;
    } else if (strcmp(pMsg,"Undo")==0){
        undo();
        return true;
    } else if (strcmp(pMsg,"Redo")==0){
        redo();
        return true;
    } else if (strcmp(pMsg,"ViewFit")==0){
        // just ignore this
        return true;
    }

    return false;
}
Furthermore, on Mouseover when typing Gui.SendMsgToActiveView I get this message from FreeCAD/src/Gui/ApplicationPy.cpp - GitHub:

Code: Select all

  {"SendMsgToActiveView",     (PyCFunction) Application::sSendActiveView, METH_VARARGS,
   "deprecated -- use class View"},
... and bit down:

Code: Select all

  {"activeView", (PyCFunction)Application::sActiveView, METH_VARARGS,
   "activeView() -> object or None\n\n"
   "Return the active view of the active document or None if no one exists"},
I guess, this is Gui.ActiveDocument.ActiveView in Python, it has a message() method, and it does react on Gui.ActiveDocument.ActiveView.message("ViewFit") (and it has a Gui.ActiveDocument.ActiveView.fitAll() function that does the same) - but nothing happens on Gui.ActiveDocument.ActiveView.message("Paste"), Cut, Copy etc. (and there are no such functions in Gui.ActiveDocument.ActiveView)

So, is there any kind of API, that supports calling Cut/Copy/Paste as in the GUI of FreeCAD?
sdaau_ml
Posts: 35
Joined: Fri Dec 07, 2018 12:18 am

Re: Select All, Cut, Copy and Paste in FreeCAD Python?

Post by sdaau_ml »

I really hope there is something better than the approach I'll list below - if there is, I'd love to hear about it.

I just realized, it is possible to do copy/paste in FreeCAD Python, - by emulating keypresses with PySide (see also https://www.freecadweb.org/wiki/PySide_ ... d_Examples) - here some snippets I've run in the FreeCAD Python console:

prerequisites:

Code: Select all

>>> from PySide import QtGui
>>> from PySide import QtCore
There is a QClipboard, but it seems we cannot use it for much:

Code: Select all

>>> QtGui.qApp.clipboard()
<PySide.QtGui.QClipboard object at 0x7f018005c8c0>
Here is how we can check if our simulated keypress really matches that which Qt internally considers its sequence for Paste, for instance:

Code: Select all

>>> event = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_V, QtCore.Qt.ControlModifier)
>>> event.matches(QtGui.QKeySequence.Paste)
True
... and finally, this is how to create and dispatch the "Paste" keypress event:

Code: Select all

mw = FreeCADGui.getMainWindow()
event = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_V, QtCore.Qt.ControlModifier)
QtGui.qApp.postEvent(mw, event)
Careful, if you want to test this in FreeCAD Python console - do note if you copy/paste these commands, you will change the type of clipboard contents, and then when you "paste" in this emulated fashion, nothing will happen, because the clipboard has "unpastable" (that is, text) contents. You're better off pasting once with expectation of fail; then select and copy objects from the Gui, finally re-run these commands via the console history (with up and down arrow)
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Select All, Cut, Copy and Paste in FreeCAD Python?

Post by wmayer »

The easiest would be:

Code: Select all

Gui.runCommand("Std_Copy")
Gui.runCommand("Std_Cut")
Gui.runCommand("Std_Paste")
sdaau_ml
Posts: 35
Joined: Fri Dec 07, 2018 12:18 am

Re: Select All, Cut, Copy and Paste in FreeCAD Python?

Post by sdaau_ml »

Many thanks, @wmayer:
wmayer wrote: Sat Jan 12, 2019 4:17 pm The easiest would be:

Code: Select all

Gui.runCommand("Std_Copy")
Gui.runCommand("Std_Cut")
Gui.runCommand("Std_Paste")
.... that is what I was looking for! :)

EDIT: Note that in either of these cases, the calls to Copy/Cut/Paste are asynchronous, that is, calls like .postEvent or .runCommand will return immediately, and you won't really know when they've finished in the current execution context - so you might end up with unexpected results!
Post Reply