Connecting C++ widget to Python

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
chennes
Veteran
Posts: 3906
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Connecting C++ widget to Python

Post by chennes »

I'd like to add a Python interface to the Gui part of Spreadsheet (mostly for unit testing purposes) -- in particular, right now what I want is a new Python function that accesses the QTableView of the sheet. In my binding code, how do I take a QTableView * in C++ and construct a PyObject * that I can return to the Python?
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Connecting C++ widget to Python

Post by openBrain »

Not sure to well understand why you are talking about C++.
If a spreadsheet is open in the MDI view, you can access it by

Code: Select all

Gui.getMainWindow().centralWidget().activeSubWindow().widget().findChild(QtWidgets.QTableView)
User avatar
chennes
Veteran
Posts: 3906
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Connecting C++ widget to Python

Post by chennes »

That's what I tried first, and it works fine on the console, but when I use that strategy in the unit tests I get an error that the object has been deleted.
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Connecting C++ widget to Python

Post by openBrain »

Hmm. Have to check later when I'm with a computer.
Just for completeness of my answer, when I dealt the first time with exposing to Python API, I also imagined to expose/return a Qt object from the "FreeCAD" API going through C++. I don't remember exactly for what reason, but I was discouraged to do so by @wmayer.
The only function that I know in FreeCAD that do something like this is 'Gui.getMainWindow()'. Maybe it's worth looking at it.
User avatar
chennes
Veteran
Posts: 3906
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Connecting C++ widget to Python

Post by chennes »

In my C++ PySide wrapper for ViewProviderSpreadsheet I have:

Code: Select all

PyObject*  ViewProviderSpreadsheetPy::getView(PyObject *args)
{
    if (!PyArg_ParseTuple(args, ""))
        return nullptr;
    // Here I can easily get a QTableView * ... I need to "convert" it/reference it in such a way that
    // I can return it as a PyObject*
}
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
User avatar
chennes
Veteran
Posts: 3906
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Connecting C++ widget to Python

Post by chennes »

openBrain wrote: Wed Nov 10, 2021 8:33 pm I don't remember exactly for what reason, but I was discouraged to do so by @wmayer.
I can easily refactor this idea to go the other direction: what I really need right now is a way to tell the QTableView to select a cell or range of cells. I was going to do all that in the Python, but I could instead have the Python send a QItemSelection into the C++. Then I can do the work of sending that to the selection model in the C++.
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
wmayer
Founder
Posts: 20302
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Connecting C++ widget to Python

Post by wmayer »

There is sometimes an odd behaviour with the reference counting of shiboken-wrapped objects that they got destroyed and I am not sure why. But to avoid this kind of problems it's best to assign the needed object to a variable so that the reference counter of the wrapper won't become zero. (At least when doing it this way I was never aware of a case where it failed.)

Code: Select all

from PySide2 import QtWidgets

mw=Gui.getMainWindow()
view=mw.findChild(QtWidgets.QTableView)
wmayer
Founder
Posts: 20302
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Connecting C++ widget to Python

Post by wmayer »

chennes wrote: Wed Nov 10, 2021 8:37 pm In my C++ PySide wrapper for ViewProviderSpreadsheet I have:

Code: Select all

#include <Gui/PythonWrapper.h>

PyObject*  ViewProviderSpreadsheetPy::getView(PyObject *args)
{
    if (!PyArg_ParseTuple(args, ""))
        return nullptr;
    // Here I can easily get a QTableView * ... I need to "convert" it/reference it in such a way that
    // I can return it as a PyObject*
    QTableView * table = ...
    Gui::PythonWrapper wrap;
    wrap.loadWidgetsModule();
    return Py::new_reference_to(wrap.fromQWidget(table));
}
The code is not tested but that's roughly the idea how to wrap the QTableView
User avatar
chennes
Veteran
Posts: 3906
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Connecting C++ widget to Python

Post by chennes »

wmayer wrote: Wed Nov 10, 2021 8:45 pm But to avoid this kind of problems it's best to assign the needed object to a variable so that the reference counter of the wrapper won't become zero. (At least when doing it this way I was never aware of a case where it failed.)
I still can't get the plain Python to work. I wrote this function:

Code: Select all

    def getTableView(self):
        # Window code from mwganson
        mw = FreeCADGui.getMainWindow()
        mdiarea = mw.findChild(QtGui.QMdiArea)
        subw = mdiarea.subWindowList()
        sheetView = None
        for i in subw:
            if i.widget().metaObject().className() == "SpreadsheetGui::SheetView":
                sheetView = i.widget()
        if sheetView is None:
            print ("ERROR: Could not locate SpreadsheetGui::SheetView")
            return None
        tableView = sheetView.findChild(QtGui.QTableView)
        return tableView
When I try to use the tableView returned there, I'm told it was deleted, even if I don't close or unload the document or anything.Thanks for the C++ snippet, I'll give that a try now.
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Connecting C++ widget to Python

Post by openBrain »

chennes wrote: Wed Nov 10, 2021 9:16 pm I still can't get the plain Python to work
@chennes, did you finally succeed or is this still open topic ?
Post Reply