Connecting C++ widget to Python
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
Connecting C++ widget to Python
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?
Re: Connecting C++ widget to Python
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
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)
Re: Connecting C++ widget to Python
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.
Re: Connecting C++ widget to Python
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.
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.
Re: Connecting C++ widget to Python
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*
}
Re: Connecting C++ widget to Python
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++.
Re: Connecting C++ widget to Python
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)
Re: Connecting C++ widget to Python
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));
}
Re: Connecting C++ widget to Python
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