Core: Expose Placement dialog to Python

This commit is contained in:
wmayer
2024-09-05 18:17:08 +02:00
parent 6f245c0103
commit df67720eac
3 changed files with 268 additions and 0 deletions

View File

@@ -81,6 +81,7 @@
#include "PythonDebugger.h"
#include "MainWindowPy.h"
#include "MDIViewPy.h"
#include "Placement.h"
#include "SoFCDB.h"
#include "Selection.h"
#include "SelectionFilterPy.h"
@@ -359,6 +360,7 @@ struct PyMethodDef FreeCADGui_methods[] = {
} // namespace Gui
// clang-format off
Application::Application(bool GUIenabled)
{
// App::GetApplication().Attach(this);
@@ -452,6 +454,10 @@ Application::Application(bool GUIenabled)
Base::Interpreter().addType(UiLoaderPy::type_object(), module, "UiLoader");
PyResource::init_type();
Gui::Dialog::TaskPlacementPy::init_type();
Base::Interpreter().addType(Gui::Dialog::TaskPlacementPy::type_object(),
module, "TaskPlacement");
// PySide additions
PyModule_AddObject(module, "PySideUic", Base::Interpreter().addModule(new PySideUicModule));
@@ -555,6 +561,7 @@ Application::Application(bool GUIenabled)
MacroCommand::load();
}
}
// clang-format on
Application::~Application()
{

View File

@@ -32,13 +32,16 @@
#include <App/ComplexGeoData.h>
#include <App/Document.h>
#include <App/DocumentObjectPy.h>
#include <App/GeoFeature.h>
#include <Base/Console.h>
#include <Base/PlacementPy.h>
#include <Base/Tools.h>
#include <Gui/Application.h>
#include <Gui/Command.h>
#include <Gui/DockWindowManager.h>
#include <Gui/Document.h>
#include <Gui/PythonWrapper.h>
#include <Gui/Selection.h>
#include <Gui/ViewProvider.h>
#include <Gui/Window.h>
@@ -1152,4 +1155,227 @@ void TaskPlacement::clicked(int id)
}
}
// ----------------------------------------------
void TaskPlacementPy::init_type()
{
behaviors().name("TaskPlacement");
behaviors().doc("TaskPlacement");
behaviors().set_tp_new(PyMake);
// you must have overwritten the virtual functions
behaviors().supportRepr();
behaviors().supportGetattr();
behaviors().supportSetattr();
// clang-format off
add_varargs_method("setPropertyName",&TaskPlacementPy::setPropertyName,"setPropertyName(string)");
add_varargs_method("setPlacement",&TaskPlacementPy::setPlacement,"setPlacement(Placement)");
add_varargs_method("setSelection",&TaskPlacementPy::setSelection,"setSelection(list)");
add_varargs_method("bindObject",&TaskPlacementPy::bindObject,"bindObject()");
add_varargs_method("showDefaultButtons",&TaskPlacementPy::showDefaultButtons, "showDefaultButtons(bool)");
add_varargs_method("accept",&TaskPlacementPy::accept,"accept()");
add_varargs_method("reject",&TaskPlacementPy::reject,"reject()");
add_varargs_method("clicked",&TaskPlacementPy::clicked,"clicked()");
add_varargs_method("open",&TaskPlacementPy::open,"open()");
add_varargs_method("isAllowedAlterDocument",&TaskPlacementPy::isAllowedAlterDocument,"isAllowedAlterDocument()");
add_varargs_method("isAllowedAlterView",&TaskPlacementPy::isAllowedAlterView,"isAllowedAlterView()");
add_varargs_method("isAllowedAlterSelection",&TaskPlacementPy::isAllowedAlterSelection,"isAllowedAlterSelection()");
add_varargs_method("getStandardButtons",&TaskPlacementPy::getStandardButtons,"getStandardButtons()");
// clang-format on
}
PyObject* TaskPlacementPy::PyMake(struct _typeobject * type, PyObject * args, PyObject * kwds)
{
Q_UNUSED(type)
Q_UNUSED(kwds)
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
return new TaskPlacementPy();
}
TaskPlacementPy::TaskPlacementPy()
: widget{new Placement}
{
}
TaskPlacementPy::~TaskPlacementPy() = default;
Py::Object TaskPlacementPy::repr()
{
return Py::String("TaskPlacement");
}
Py::Object TaskPlacementPy::getattr(const char * name)
{
if (strcmp(name, "form") == 0) {
Gui::PythonWrapper wrap;
wrap.loadWidgetsModule();
return wrap.fromQWidget(widget, "QDialog");
}
return BaseType::getattr(name);
}
int TaskPlacementPy::setattr(const char* name, const Py::Object& attr)
{
if (strcmp(name, "form") == 0 && attr.isNone()) {
delete widget;
widget = nullptr;
return {};
}
return BaseType::setattr(name, attr);
}
Py::Object TaskPlacementPy::setPropertyName(const Py::Tuple& args)
{
const char* propname {};
if (!PyArg_ParseTuple(args.ptr(), "s", &propname)) {
throw Py::Exception();
}
if (widget) {
widget->setPropertyName(propname);
}
return Py::None();
}
Py::Object TaskPlacementPy::setPlacement(const Py::Tuple& args)
{
PyObject* plm {};
if (!PyArg_ParseTuple(args.ptr(), "O!", &Base::PlacementPy::Type, &plm)) {
throw Py::Exception();
}
if (widget) {
widget->setPlacement(*static_cast<Base::PlacementPy*>(plm)->getPlacementPtr());
}
return Py::None();
}
Py::Object TaskPlacementPy::setSelection(const Py::Tuple& args)
{
std::vector<Gui::SelectionObject> sel;
Py::Sequence list(args[0]);
for (const auto& obj : list) {
if (PyObject_TypeCheck(obj.ptr(), &App::DocumentObjectPy::Type)) {
auto doc = static_cast<App::DocumentObjectPy*>(obj.ptr());
sel.emplace_back(doc->getDocumentObjectPtr());
}
}
if (widget) {
widget->setSelection(sel);
}
return Py::None();
}
Py::Object TaskPlacementPy::bindObject(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), "")) {
throw Py::Exception();
}
if (widget) {
widget->bindObject();
}
return Py::None();
}
Py::Object TaskPlacementPy::showDefaultButtons(const Py::Tuple& args)
{
if (widget) {
widget->showDefaultButtons(Py::Boolean(args[0]));
}
return Py::None();
}
Py::Object TaskPlacementPy::accept(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), "")) {
throw Py::Exception();
}
bool res = true;
if (widget) {
widget->accept();
res = widget->result() == QDialog::Accepted;
}
return Py::Boolean(res);
}
Py::Object TaskPlacementPy::reject(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), "")) {
throw Py::Exception();
}
bool res = true;
if (widget) {
widget->reject();
res = widget->result() == QDialog::Rejected;
}
return Py::Boolean(res);
}
Py::Object TaskPlacementPy::clicked(const Py::Tuple& args)
{
int index {};
if (!PyArg_ParseTuple(args.ptr(), "i", &index)) {
throw Py::Exception();
}
if (widget && index == QDialogButtonBox::Apply) {
widget->onApplyButtonClicked();
}
return Py::None();
}
Py::Object TaskPlacementPy::open(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), "")) {
throw Py::Exception();
}
if (widget) {
widget->open();
}
return Py::None();
}
Py::Object TaskPlacementPy::isAllowedAlterDocument(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), "")) {
throw Py::Exception();
}
return Py::Boolean(true);
}
Py::Object TaskPlacementPy::isAllowedAlterView(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), "")) {
throw Py::Exception();
}
return Py::Boolean(true);
}
Py::Object TaskPlacementPy::isAllowedAlterSelection(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), "")) {
throw Py::Exception();
}
return Py::Boolean(true);
}
Py::Object TaskPlacementPy::getStandardButtons(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), "")) {
throw Py::Exception();
}
auto buttons = QDialogButtonBox::Ok|
QDialogButtonBox::Cancel|
QDialogButtonBox::Apply;
return Py::Long(static_cast<int>(buttons));
}
#include "moc_Placement.cpp"

View File

@@ -212,6 +212,41 @@ private:
Placement* widget;
};
class TaskPlacementPy: public Py::PythonExtension<TaskPlacementPy>
{
public:
using BaseType = Py::PythonExtension<TaskPlacementPy>;
static void init_type();
TaskPlacementPy();
~TaskPlacementPy() override;
Py::Object repr() override;
Py::Object getattr(const char* name) override;
int setattr(const char* name, const Py::Object&) override;
Py::Object setPropertyName(const Py::Tuple&);
Py::Object setPlacement(const Py::Tuple&);
Py::Object setSelection(const Py::Tuple&);
Py::Object bindObject(const Py::Tuple&);
Py::Object showDefaultButtons(const Py::Tuple&);
Py::Object accept(const Py::Tuple&);
Py::Object reject(const Py::Tuple&);
Py::Object clicked(const Py::Tuple&);
Py::Object open(const Py::Tuple&);
Py::Object isAllowedAlterDocument(const Py::Tuple&);
Py::Object isAllowedAlterView(const Py::Tuple&);
Py::Object isAllowedAlterSelection(const Py::Tuple&);
Py::Object getStandardButtons(const Py::Tuple&);
private:
static PyObject* PyMake(struct _typeobject*, PyObject*, PyObject*);
private:
QPointer<Placement> widget;
};
} // namespace Dialog
} // namespace Gui